mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
298 Commits
doc/mapper
...
d41998ec1b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d41998ec1b | ||
![]() |
f917d1597e | ||
![]() |
d474c2a47e | ||
![]() |
086d4a1c6f | ||
![]() |
65bc9ef4a8 | ||
![]() |
073268160f | ||
![]() |
40c576bc2d | ||
![]() |
0bbf7ed804 | ||
![]() |
f05fa88eec | ||
![]() |
6d67965c63 | ||
![]() |
98a24dc8fc | ||
![]() |
7fa55409ed | ||
![]() |
20f2c0460e | ||
![]() |
dc36bf96f1 | ||
![]() |
426e654f44 | ||
![]() |
6d0f93c3ce | ||
![]() |
11d3c52197 | ||
![]() |
2ee1050083 | ||
![]() |
ca00afb918 | ||
![]() |
02953a1436 | ||
![]() |
e14215c679 | ||
![]() |
c60ea0701a | ||
![]() |
de6ae1cc8f | ||
![]() |
ad24acd72f | ||
![]() |
3c0bb83032 | ||
![]() |
d5c96d74ed | ||
![]() |
43aada8ae7 | ||
![]() |
17a7c2815f | ||
![]() |
9441774a22 | ||
![]() |
d279276cc0 | ||
![]() |
c7f8a7a2eb | ||
![]() |
0fb92e000b | ||
![]() |
d70e3f71a6 | ||
![]() |
fe50ea3c01 | ||
![]() |
77f821250a | ||
![]() |
ff028ffa62 | ||
![]() |
64cc788d43 | ||
![]() |
a85668c8d9 | ||
![]() |
add042ec16 | ||
![]() |
e174136fb4 | ||
![]() |
ff8697ed71 | ||
![]() |
542a841791 | ||
![]() |
b9640f0049 | ||
![]() |
a6cc3dc85b | ||
![]() |
6083c71e0e | ||
![]() |
e844ea819b | ||
![]() |
27f0300bc7 | ||
![]() |
35cea2eaba | ||
![]() |
7c4617da99 | ||
![]() |
d6d7c5c1fb | ||
![]() |
b7f7a39aa7 | ||
![]() |
8c04771a87 | ||
![]() |
febf15b279 | ||
![]() |
a05e4b7ecc | ||
![]() |
3568a999f9 | ||
![]() |
207097bf03 | ||
![]() |
0e3d2b9570 | ||
![]() |
87fac429e8 | ||
![]() |
3b1097931b | ||
![]() |
ec7e408cd1 | ||
![]() |
f8a99b9cfa | ||
![]() |
4c7231e6ae | ||
![]() |
883d32515c | ||
![]() |
f0f3c257fa | ||
![]() |
42fce7d9ce | ||
![]() |
facac37fff | ||
![]() |
1272b601c6 | ||
![]() |
58e35cfaf5 | ||
![]() |
2befc9781b | ||
![]() |
8fb2872c36 | ||
![]() |
98033515c8 | ||
![]() |
25c02cea2e | ||
![]() |
6d5be78fec | ||
![]() |
f6e60085db | ||
![]() |
a61648af70 | ||
![]() |
2b496c6fd3 | ||
![]() |
1e984f0965 | ||
![]() |
37bed36315 | ||
![]() |
5394cc5201 | ||
![]() |
5e3dfb0e9c | ||
![]() |
f6a6c981f8 | ||
![]() |
415c1bfd2f | ||
![]() |
e4a911db25 | ||
![]() |
5fcd67d77b | ||
![]() |
86db08ac3f | ||
![]() |
8d735fc726 | ||
![]() |
1e1f4bb2a3 | ||
![]() |
d8000aca10 | ||
![]() |
a2660ff0dc | ||
![]() |
000d5785cf | ||
![]() |
9fe04712a9 | ||
![]() |
846afd9e0a | ||
![]() |
6125ff0f90 | ||
![]() |
a5428a8843 | ||
![]() |
19be45cda6 | ||
![]() |
889c97cb27 | ||
![]() |
1d83da41a9 | ||
![]() |
a65f2174eb | ||
![]() |
9db493e87e | ||
![]() |
49a3a18b51 | ||
![]() |
0489e7036b | ||
![]() |
794d5a781c | ||
![]() |
c21dfbcc1f | ||
![]() |
cc75db6d09 | ||
![]() |
48d35a50b5 | ||
![]() |
3a0888046f | ||
![]() |
7917994835 | ||
![]() |
9e2bab43f7 | ||
![]() |
7e03f47f08 | ||
![]() |
7c6137a4fc | ||
![]() |
0cbd6e2fe9 | ||
![]() |
5acc1f5560 | ||
![]() |
887693a90d | ||
![]() |
fbb985833f | ||
![]() |
1b3734ff6b | ||
![]() |
6288b30ac3 | ||
![]() |
ee435f7081 | ||
![]() |
d75b4eb2a9 | ||
![]() |
5eeb505807 | ||
![]() |
30566e35ce | ||
![]() |
e058b7f295 | ||
![]() |
902a30a9f8 | ||
![]() |
8669b94fb0 | ||
![]() |
7fb08aea62 | ||
![]() |
e7a1548b0e | ||
![]() |
bdcb6f0533 | ||
![]() |
97849ce6f1 | ||
![]() |
d1c937caf4 | ||
![]() |
5ffe6279a2 | ||
![]() |
9260e2b77a | ||
![]() |
593465e2ec | ||
![]() |
8820350760 | ||
![]() |
7e1668229a | ||
![]() |
387b96b9a0 | ||
![]() |
5f52d786c6 | ||
![]() |
e0db597f9d | ||
![]() |
41b0315ec6 | ||
![]() |
a930a4085e | ||
![]() |
d0dbbfac07 | ||
![]() |
3dc24b46f4 | ||
![]() |
8e44a357b4 | ||
![]() |
dd462310cc | ||
![]() |
a1935fa0cd | ||
![]() |
b45c57246b | ||
![]() |
c481ecd6b5 | ||
![]() |
e0898dd9b0 | ||
![]() |
5561334efa | ||
![]() |
6c4bb4f79e | ||
![]() |
8b2d2e2fe7 | ||
![]() |
49d128c964 | ||
![]() |
f24d1e0916 | ||
![]() |
9faa4c0c69 | ||
![]() |
a04b8f65db | ||
![]() |
e1cf7d23cd | ||
![]() |
b74b221844 | ||
![]() |
38affc15b4 | ||
![]() |
948488d92b | ||
![]() |
f5902d0346 | ||
![]() |
f28dc8e88a | ||
![]() |
1f41749fa3 | ||
![]() |
a4908a4d42 | ||
![]() |
aa7754e658 | ||
![]() |
58ea9387aa | ||
![]() |
775266c974 | ||
![]() |
eb9794cd1f | ||
![]() |
130732adde | ||
![]() |
7a98e73d61 | ||
![]() |
1f26b72b4b | ||
![]() |
a15ffb5b47 | ||
![]() |
1a5f72283a | ||
![]() |
0460b283ba | ||
![]() |
e212e7c780 | ||
![]() |
84100fc7cf | ||
![]() |
11a8682b07 | ||
![]() |
d3a0bbdfb1 | ||
![]() |
15f3a45d6a | ||
![]() |
f0a4f352cc | ||
![]() |
d16b3e8154 | ||
![]() |
614fb97288 | ||
![]() |
8a40d3645a | ||
![]() |
2b7dadf2a8 | ||
![]() |
c338e16e4f | ||
![]() |
aded08471d | ||
![]() |
cccb59b1c5 | ||
![]() |
3592fb7e62 | ||
![]() |
307c92991c | ||
![]() |
4b3f077669 | ||
![]() |
352bae518e | ||
![]() |
c958f4d522 | ||
![]() |
35bbb37ad2 | ||
![]() |
1d48acc841 | ||
![]() |
87702edccc | ||
![]() |
1f0ba7c19a | ||
![]() |
b4d08a99ad | ||
![]() |
8acaa06e42 | ||
![]() |
27ee85b5d4 | ||
![]() |
bbe2d1854e | ||
![]() |
d338690ff5 | ||
![]() |
571a6d8c1a | ||
![]() |
ddb5157c0a | ||
![]() |
64f01354bc | ||
![]() |
37fd99e542 | ||
![]() |
23be4a5849 | ||
![]() |
64c0ee8f98 | ||
![]() |
e5ecce3abf | ||
![]() |
5c71a4da56 | ||
![]() |
dff99b79cb | ||
![]() |
5fe46ea8ea | ||
![]() |
4a590adac4 | ||
![]() |
279d41cdb7 | ||
![]() |
5cf65a9f62 | ||
![]() |
08b05c13b6 | ||
![]() |
eb55c85f4e | ||
![]() |
8a243440db | ||
![]() |
b3e4e6b89c | ||
![]() |
a1a25f6df4 | ||
![]() |
6114a6cec1 | ||
![]() |
5058964937 | ||
![]() |
4488675540 | ||
![]() |
6a2d2c9e67 | ||
![]() |
b43c42d763 | ||
![]() |
69112183d4 | ||
![]() |
a4c2778b8d | ||
![]() |
f26e56c3bf | ||
![]() |
f5f9944fc4 | ||
![]() |
9467caf1e9 | ||
![]() |
00376f39d5 | ||
![]() |
40b6a34dc5 | ||
![]() |
17d2b8c2c2 | ||
![]() |
935af42d23 | ||
![]() |
d4a8d468cb | ||
![]() |
b16099aee0 | ||
![]() |
c17b918a43 | ||
![]() |
d58e8c7ef9 | ||
![]() |
ddd6b6e3a8 | ||
![]() |
e629c132ea | ||
![]() |
b80e03f153 | ||
![]() |
11e36ff3f1 | ||
![]() |
22de356413 | ||
![]() |
caefa04fbe | ||
![]() |
cf2e7d67d7 | ||
![]() |
685e444b2d | ||
![]() |
a9c1045afd | ||
![]() |
24e0d37583 | ||
![]() |
d44997d372 | ||
![]() |
062aa888f8 | ||
![]() |
de4c2ae4ad | ||
![]() |
29ad7308c3 | ||
![]() |
19b21c280e | ||
![]() |
fbfe8b246a | ||
![]() |
73f66eb51f | ||
![]() |
d62ba2b9a0 | ||
![]() |
323a2b6c2f | ||
![]() |
8e4cccd562 | ||
![]() |
795795ba40 | ||
![]() |
4af86b36e5 | ||
![]() |
b00632a625 | ||
![]() |
6f23f76441 | ||
![]() |
a6cd4b3c5d | ||
![]() |
81d63c41b6 | ||
![]() |
a924840228 | ||
![]() |
b013297c8e | ||
![]() |
ca77a31037 | ||
![]() |
5adb2240d5 | ||
![]() |
9d42be3362 | ||
![]() |
21201dec29 | ||
![]() |
08229cbe1d | ||
![]() |
96e9dd7c4b | ||
![]() |
7dbc687200 | ||
![]() |
7e1f2c6c97 | ||
![]() |
37cba12e4a | ||
![]() |
cdd80bca9e | ||
![]() |
3293d24c36 | ||
![]() |
bf31781d7a | ||
![]() |
f6c43b2db3 | ||
![]() |
f00156a654 | ||
![]() |
41fd1cbcee | ||
![]() |
52c807d74a | ||
![]() |
8713a496b4 | ||
![]() |
a3033f2db1 | ||
![]() |
5fb8faffc1 | ||
![]() |
a883955703 | ||
![]() |
b39d7adcbc | ||
![]() |
c577c8db71 | ||
![]() |
d7d17400dd | ||
![]() |
b219d50fd8 | ||
![]() |
88f318e6df | ||
![]() |
d12ac44b7d | ||
![]() |
7155eea716 | ||
![]() |
ca0796f131 | ||
![]() |
c4b33e2481 | ||
![]() |
ff95564b6b | ||
![]() |
cecf1ab791 | ||
![]() |
a571445e0e | ||
![]() |
89e418cd24 | ||
![]() |
896ccfcffa | ||
![]() |
d98d181755 | ||
![]() |
3c63f9b617 |
@@ -13,17 +13,18 @@ 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)
|
macos: circleci/macos@2.5.1 # For Rosetta (see below)
|
||||||
node: circleci/node@5.2.0 # For a recent npm version (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.
|
# Build the **entire** app for macOS (including the GDevelop.js library).
|
||||||
build-macos:
|
build-macos:
|
||||||
macos:
|
macos:
|
||||||
xcode: 14.2.0
|
xcode: 16.4.0
|
||||||
resource_class: macos.m1.large.gen1
|
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)
|
# 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
|
- macos/install-rosetta
|
||||||
- run: sudo sysctl net.inet.tcp.tso=0
|
# - 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
|
# 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.js v20.14.0 comes with npm v10.7.0.
|
||||||
@@ -46,9 +47,9 @@ jobs:
|
|||||||
# GDevelop.js dependencies
|
# GDevelop.js dependencies
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
|
- gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}-{{ checksum "GDJS/package-lock.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
|
||||||
@@ -69,7 +70,8 @@ jobs:
|
|||||||
- newIDE/electron-app/node_modules
|
- newIDE/electron-app/node_modules
|
||||||
- newIDE/app/node_modules
|
- newIDE/app/node_modules
|
||||||
- GDevelop.js/node_modules
|
- GDevelop.js/node_modules
|
||||||
key: gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
|
- GDJS/node_modules
|
||||||
|
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).
|
||||||
@@ -86,15 +88,37 @@ jobs:
|
|||||||
- 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: 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)/
|
command: |
|
||||||
|
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: export PATH=~/.local/bin:$PATH && aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
|
command: |
|
||||||
|
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 **entire** app for Linux.
|
# Build the app for Linux (using a pre-built GDevelop.js library).
|
||||||
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
|
||||||
@@ -107,51 +131,33 @@ jobs:
|
|||||||
- checkout
|
- checkout
|
||||||
- aws-cli/setup
|
- aws-cli/setup
|
||||||
|
|
||||||
# System dependencies (for Electron Builder and Emscripten)
|
# System dependencies (for Electron Builder)
|
||||||
- run:
|
- run:
|
||||||
name: Install dependencies for Emscripten
|
name: Update system dependencies
|
||||||
command: sudo apt-get update && sudo apt install cmake
|
command: sudo apt-get update
|
||||||
|
|
||||||
- run:
|
|
||||||
name: Install Python3 dependencies for Emscripten
|
|
||||||
command: sudo apt install python-is-python3 python3-distutils -y
|
|
||||||
|
|
||||||
- run:
|
|
||||||
name: Install Emscripten (for GDevelop.js)
|
|
||||||
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
|
|
||||||
|
|
||||||
- run:
|
- 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" }}
|
- 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" }}
|
||||||
# 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-
|
||||||
|
|
||||||
- run:
|
# GDevelop IDE dependencies (using an exact version of GDevelop.js, built previously)
|
||||||
name: Install GDevelop.js dependencies and build it
|
|
||||||
command: cd GDevelop.js && npm install && cd ..
|
|
||||||
|
|
||||||
# Build GDevelop.js (and run tests to ensure it works)
|
|
||||||
- run:
|
|
||||||
name: Build GDevelop.js
|
|
||||||
# Use "--runInBand" as it's faster and avoid deadlocks on CircleCI Linux machines (probably because limited in processes number).
|
|
||||||
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test -- --runInBand && cd ..
|
|
||||||
|
|
||||||
# GDevelop IDE dependencies (after building GDevelop.js to avoid downloading a pre-built version)
|
|
||||||
- run:
|
- run:
|
||||||
name: Install GDevelop IDE dependencies
|
name: Install GDevelop IDE dependencies
|
||||||
command: cd newIDE/app && npm install && cd ../electron-app && npm install
|
command: export REQUIRES_EXACT_LIBGD_JS_VERSION=true && 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
|
||||||
key: gd-linux-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
|
- GDJS/node_modules
|
||||||
|
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:
|
||||||
@@ -295,14 +301,203 @@ jobs:
|
|||||||
name: Deploy to S3 (specific commit)
|
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)/
|
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:
|
|
||||||
jobs:
|
|
||||||
- build-gdevelop_js-wasm-only
|
|
||||||
gdevelop_js-wasm-extra-checks:
|
gdevelop_js-wasm-extra-checks:
|
||||||
jobs:
|
jobs:
|
||||||
- build-gdevelop_js-debug-sanitizers-and-extra-checks:
|
- build-gdevelop_js-debug-sanitizers-and-extra-checks:
|
||||||
# Extra checks are resource intensive so don't all run them.
|
# Extra checks are resource intensive so don't always run them.
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
@@ -310,13 +505,36 @@ workflows:
|
|||||||
- /experimental-build.*/
|
- /experimental-build.*/
|
||||||
builds:
|
builds:
|
||||||
jobs:
|
jobs:
|
||||||
|
- 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:
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -33,3 +33,4 @@
|
|||||||
.Spotlight-V100
|
.Spotlight-V100
|
||||||
.Trashes
|
.Trashes
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
.claude
|
||||||
|
3
.vscode/tasks.json
vendored
3
.vscode/tasks.json
vendored
@@ -38,8 +38,7 @@
|
|||||||
"presentation": {
|
"presentation": {
|
||||||
"reveal": "silent"
|
"reveal": "silent"
|
||||||
},
|
},
|
||||||
"isBackground": true,
|
"isBackground": true
|
||||||
"runOptions": { "instanceLimit": 1, "runOn": "folderOpen" }
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "npm",
|
"type": "npm",
|
||||||
|
@@ -61,10 +61,12 @@ void GroupEvent::UnserializeFrom(gd::Project& project,
|
|||||||
project, events, element.GetChild("events"));
|
project, events, element.GetChild("events"));
|
||||||
|
|
||||||
parameters.clear();
|
parameters.clear();
|
||||||
gd::SerializerElement& parametersElement = element.GetChild("parameters");
|
if (element.HasChild("parameters")) {
|
||||||
parametersElement.ConsiderAsArrayOf("parameters");
|
gd::SerializerElement& parametersElement = element.GetChild("parameters");
|
||||||
for (std::size_t i = 0; i < parametersElement.GetChildrenCount(); ++i)
|
parametersElement.ConsiderAsArrayOf("parameters");
|
||||||
parameters.push_back(parametersElement.GetChild(i).GetValue().GetString());
|
for (std::size_t i = 0; i < parametersElement.GetChildrenCount(); ++i)
|
||||||
|
parameters.push_back(parametersElement.GetChild(i).GetValue().GetString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupEvent::SetBackgroundColor(unsigned int colorR_,
|
void GroupEvent::SetBackgroundColor(unsigned int colorR_,
|
||||||
|
@@ -163,6 +163,21 @@ void LinkEvent::UnserializeFrom(gd::Project& project,
|
|||||||
// end of compatibility code
|
// 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) {
|
bool LinkEvent::AcceptVisitor(gd::EventVisitor &eventVisitor) {
|
||||||
return BaseEvent::AcceptVisitor(eventVisitor) ||
|
return BaseEvent::AcceptVisitor(eventVisitor) ||
|
||||||
eventVisitor.VisitLinkEvent(*this);
|
eventVisitor.VisitLinkEvent(*this);
|
||||||
|
@@ -109,6 +109,10 @@ class GD_CORE_API LinkEvent : public gd::BaseEvent {
|
|||||||
|
|
||||||
virtual bool IsExecutable() const override { return true; };
|
virtual bool IsExecutable() const override { return true; };
|
||||||
|
|
||||||
|
virtual std::vector<gd::String> GetAllSearchableStrings() const override;
|
||||||
|
virtual bool ReplaceAllSearchableStrings(
|
||||||
|
std::vector<gd::String> newSearchableString) override;
|
||||||
|
|
||||||
virtual void SerializeTo(SerializerElement& element) const 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) override;
|
||||||
|
@@ -42,15 +42,19 @@ 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 =
|
||||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
|
instrInfos.parameters.GetParametersCount();
|
||||||
|
for (std::size_t i = startFromArgument;
|
||||||
|
i < instrInfos.parameters.GetParametersCount();
|
||||||
++i) {
|
++i) {
|
||||||
if (instrInfos.parameters.GetParameter(i).GetType() == "relationalOperator") {
|
if (instrInfos.parameters.GetParameter(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.GetParametersCount()) {
|
||||||
ReportError();
|
ReportError();
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -87,20 +91,23 @@ gd::String EventsCodeGenerator::GenerateRelationalOperation(
|
|||||||
const gd::String& relationalOperator,
|
const gd::String& relationalOperator,
|
||||||
const gd::String& lhs,
|
const gd::String& lhs,
|
||||||
const gd::String& rhs) {
|
const gd::String& rhs) {
|
||||||
return lhs + " " + GenerateRelationalOperatorCodes(relationalOperator) + " " + rhs;
|
return lhs + " " + GenerateRelationalOperatorCodes(relationalOperator) + " " +
|
||||||
|
rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gd::String EventsCodeGenerator::GenerateRelationalOperatorCodes(const gd::String &operatorString) {
|
const gd::String EventsCodeGenerator::GenerateRelationalOperatorCodes(
|
||||||
if (operatorString == "=") {
|
const gd::String& operatorString) {
|
||||||
return "==";
|
if (operatorString == "=") {
|
||||||
}
|
return "==";
|
||||||
if (operatorString != "<" && operatorString != ">" &&
|
}
|
||||||
operatorString != "<=" && operatorString != ">=" && operatorString != "!=" &&
|
if (operatorString != "<" && operatorString != ">" &&
|
||||||
operatorString != "startsWith" && operatorString != "endsWith" && operatorString != "contains") {
|
operatorString != "<=" && operatorString != ">=" &&
|
||||||
cout << "Warning: Bad relational operator: Set to == by default." << endl;
|
operatorString != "!=" && operatorString != "startsWith" &&
|
||||||
return "==";
|
operatorString != "endsWith" && operatorString != "contains") {
|
||||||
}
|
cout << "Warning: Bad relational operator: Set to == by default." << endl;
|
||||||
return operatorString;
|
return "==";
|
||||||
|
}
|
||||||
|
return operatorString;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,7 +131,8 @@ gd::String EventsCodeGenerator::GenerateOperatorCall(
|
|||||||
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.GetParametersCount();
|
||||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
|
for (std::size_t i = startFromArgument;
|
||||||
|
i < instrInfos.parameters.GetParametersCount();
|
||||||
++i) {
|
++i) {
|
||||||
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
|
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
|
||||||
operatorIndex = i;
|
operatorIndex = i;
|
||||||
@@ -195,7 +203,8 @@ gd::String EventsCodeGenerator::GenerateCompoundOperatorCall(
|
|||||||
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.GetParametersCount();
|
||||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
|
for (std::size_t i = startFromArgument;
|
||||||
|
i < instrInfos.parameters.GetParametersCount();
|
||||||
++i) {
|
++i) {
|
||||||
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
|
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
|
||||||
operatorIndex = i;
|
operatorIndex = i;
|
||||||
@@ -248,7 +257,8 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
|
|||||||
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.GetParametersCount();
|
||||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
|
for (std::size_t i = startFromArgument;
|
||||||
|
i < instrInfos.parameters.GetParametersCount();
|
||||||
++i) {
|
++i) {
|
||||||
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
|
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
|
||||||
operatorIndex = i;
|
operatorIndex = i;
|
||||||
@@ -323,83 +333,97 @@ 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.GetParametersCount()) {
|
||||||
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 mismatches 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.GetParametersCount(); ++pNb) {
|
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount();
|
||||||
if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) {
|
++pNb) {
|
||||||
|
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 =
|
const auto& expectedObjectType =
|
||||||
instrInfos.parameters.GetParameter(pNb).GetExtraInfo();
|
instrInfos.parameters.GetParameter(pNb).GetExtraInfo();
|
||||||
const auto &actualObjectType =
|
const auto& actualObjectType =
|
||||||
GetObjectsContainersList().GetTypeOfObject(objectInParameter);
|
GetObjectsContainersList().GetTypeOfObject(objectInParameter);
|
||||||
if (!GetObjectsContainersList().HasObjectOrGroupNamed(
|
if (!GetObjectsContainersList().HasObjectOrGroupNamed(
|
||||||
objectInParameter)) {
|
objectInParameter)) {
|
||||||
gd::ProjectDiagnostic projectDiagnostic(
|
gd::ProjectDiagnostic projectDiagnostic(
|
||||||
gd::ProjectDiagnostic::ErrorType::UnknownObject, "",
|
gd::ProjectDiagnostic::ErrorType::UnknownObject,
|
||||||
objectInParameter, "");
|
"",
|
||||||
|
objectInParameter,
|
||||||
|
"");
|
||||||
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
||||||
return "/* Unknown object - skipped. */";
|
return "/* Unknown object - skipped. */";
|
||||||
} else if (!expectedObjectType.empty() &&
|
} else if (!expectedObjectType.empty() &&
|
||||||
actualObjectType != expectedObjectType) {
|
actualObjectType != expectedObjectType) {
|
||||||
gd::ProjectDiagnostic projectDiagnostic(
|
gd::ProjectDiagnostic projectDiagnostic(
|
||||||
gd::ProjectDiagnostic::ErrorType::MismatchedObjectType, "",
|
gd::ProjectDiagnostic::ErrorType::MismatchedObjectType,
|
||||||
actualObjectType, expectedObjectType, objectInParameter);
|
"",
|
||||||
|
actualObjectType,
|
||||||
|
expectedObjectType,
|
||||||
|
objectInParameter);
|
||||||
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
||||||
return "/* Mismatched object type - skipped. */";
|
return "/* Mismatched object type - skipped. */";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool isAnyBehaviorMissing =
|
||||||
|
gd::EventsCodeGenerator::CheckBehaviorParameters(condition, instrInfos);
|
||||||
|
if (isAnyBehaviorMissing) {
|
||||||
|
return "/* Missing behavior - skipped. */";
|
||||||
|
}
|
||||||
|
|
||||||
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.GetParametersCount() > 0) {
|
||||||
std::vector<gd::String> realObjects =
|
std::vector<gd::String> realObjects =
|
||||||
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
GetObjectsContainersList().ExpandObjectName(
|
||||||
|
objectName, context.GetCurrentObject());
|
||||||
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 =
|
||||||
|
GetObjectsContainersList().GetTypeOfObject(realObjects[i]);
|
||||||
const ObjectMetadata& objInfo =
|
const ObjectMetadata& objInfo =
|
||||||
MetadataProvider::GetObjectMetadata(platform, objectType);
|
MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||||
|
|
||||||
AddIncludeFiles(objInfo.includeFiles);
|
AddIncludeFiles(objInfo.includeFiles);
|
||||||
context.SetCurrentObject(realObjects[i]);
|
context.SetCurrentObject(realObjects[i]);
|
||||||
context.ObjectsListNeeded(realObjects[i]);
|
context.ObjectsListNeeded(realObjects[i]);
|
||||||
|
|
||||||
// Prepare arguments and generate the condition whole code
|
// Prepare arguments and generate the condition whole code
|
||||||
vector<gd::String> arguments = GenerateParametersCodes(
|
vector<gd::String> arguments = GenerateParametersCodes(
|
||||||
condition.GetParameters(), instrInfos.parameters, context);
|
condition.GetParameters(), instrInfos.parameters, context);
|
||||||
conditionCode += GenerateObjectCondition(realObjects[i],
|
conditionCode += GenerateObjectCondition(realObjects[i],
|
||||||
objInfo,
|
objInfo,
|
||||||
arguments,
|
arguments,
|
||||||
instrInfos,
|
instrInfos,
|
||||||
returnBoolean,
|
returnBoolean,
|
||||||
condition.IsInverted(),
|
condition.IsInverted(),
|
||||||
context);
|
context);
|
||||||
|
|
||||||
context.SetNoCurrentObject();
|
context.SetNoCurrentObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (instrInfos.IsBehaviorInstruction()) {
|
} else if (instrInfos.IsBehaviorInstruction()) {
|
||||||
if (instrInfos.parameters.GetParametersCount() >= 2) {
|
if (instrInfos.parameters.GetParametersCount() >= 2) {
|
||||||
const gd::String &objectName = condition.GetParameter(0).GetPlainString();
|
const gd::String& objectName = condition.GetParameter(0).GetPlainString();
|
||||||
const gd::String &behaviorName =
|
const gd::String& behaviorName =
|
||||||
condition.GetParameter(1).GetPlainString();
|
condition.GetParameter(1).GetPlainString();
|
||||||
const gd::String &actualBehaviorType =
|
const gd::String& actualBehaviorType =
|
||||||
GetObjectsContainersList().GetTypeOfBehavior(behaviorName);
|
GetObjectsContainersList().GetTypeOfBehavior(behaviorName);
|
||||||
|
|
||||||
std::vector<gd::String> realObjects =
|
std::vector<gd::String> realObjects =
|
||||||
GetObjectsContainersList().ExpandObjectName(
|
GetObjectsContainersList().ExpandObjectName(
|
||||||
objectName, context.GetCurrentObject());
|
objectName, context.GetCurrentObject());
|
||||||
|
|
||||||
const BehaviorMetadata &autoInfo =
|
const BehaviorMetadata& autoInfo =
|
||||||
MetadataProvider::GetBehaviorMetadata(platform, actualBehaviorType);
|
MetadataProvider::GetBehaviorMetadata(platform, actualBehaviorType);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||||
@@ -411,15 +435,14 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
|||||||
// Prepare arguments and generate the whole condition code
|
// Prepare arguments and generate the whole condition code
|
||||||
vector<gd::String> arguments = GenerateParametersCodes(
|
vector<gd::String> arguments = GenerateParametersCodes(
|
||||||
condition.GetParameters(), instrInfos.parameters, context);
|
condition.GetParameters(), instrInfos.parameters, context);
|
||||||
conditionCode += GenerateBehaviorCondition(
|
conditionCode += GenerateBehaviorCondition(realObjects[i],
|
||||||
realObjects[i],
|
behaviorName,
|
||||||
behaviorName,
|
autoInfo,
|
||||||
autoInfo,
|
arguments,
|
||||||
arguments,
|
instrInfos,
|
||||||
instrInfos,
|
returnBoolean,
|
||||||
returnBoolean,
|
condition.IsInverted(),
|
||||||
condition.IsInverted(),
|
context);
|
||||||
context);
|
|
||||||
|
|
||||||
context.SetNoCurrentObject();
|
context.SetNoCurrentObject();
|
||||||
}
|
}
|
||||||
@@ -488,31 +511,50 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
|
|||||||
return outputCode;
|
return outputCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventsCodeGenerator::CheckBehaviorParameters(
|
bool EventsCodeGenerator::CheckBehaviorParameters(
|
||||||
const gd::Instruction &instruction,
|
const gd::Instruction& instruction,
|
||||||
const gd::InstructionMetadata &instrInfos) {
|
const gd::InstructionMetadata& instrInfos) {
|
||||||
gd::ParameterMetadataTools::IterateOverParameters(
|
bool isAnyBehaviorMissing = false;
|
||||||
instruction.GetParameters(), instrInfos.parameters,
|
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||||
[this](const gd::ParameterMetadata ¶meterMetadata,
|
instruction.GetParameters(),
|
||||||
const gd::Expression ¶meterValue,
|
instrInfos.parameters,
|
||||||
const gd::String &lastObjectName) {
|
[this, &isAnyBehaviorMissing, &instrInfos](
|
||||||
|
const gd::ParameterMetadata& parameterMetadata,
|
||||||
|
const gd::Expression& parameterValue,
|
||||||
|
size_t parameterIndex,
|
||||||
|
const gd::String& lastObjectName,
|
||||||
|
size_t lastObjectIndex) {
|
||||||
if (ParameterMetadata::IsBehavior(parameterMetadata.GetType())) {
|
if (ParameterMetadata::IsBehavior(parameterMetadata.GetType())) {
|
||||||
const gd::String &behaviorName = parameterValue.GetPlainString();
|
const gd::String& behaviorName = parameterValue.GetPlainString();
|
||||||
const gd::String &actualBehaviorType =
|
const gd::String& actualBehaviorType =
|
||||||
GetObjectsContainersList().GetTypeOfBehaviorInObjectOrGroup(
|
GetObjectsContainersList().GetTypeOfBehaviorInObjectOrGroup(
|
||||||
lastObjectName, behaviorName);
|
lastObjectName, behaviorName);
|
||||||
const gd::String &expectedBehaviorType =
|
const gd::String& expectedBehaviorType =
|
||||||
parameterMetadata.GetExtraInfo();
|
parameterMetadata.GetExtraInfo();
|
||||||
|
|
||||||
if (!expectedBehaviorType.empty() &&
|
if (!expectedBehaviorType.empty() &&
|
||||||
actualBehaviorType != expectedBehaviorType) {
|
actualBehaviorType != expectedBehaviorType) {
|
||||||
|
const auto& objectParameterMetadata =
|
||||||
|
instrInfos.GetParameter(lastObjectIndex);
|
||||||
|
// Event functions crash if some objects in a group are missing
|
||||||
|
// the required behaviors, since they lose reference to the original
|
||||||
|
// objects. Missing behaviors are considered "fatal" only for
|
||||||
|
// ObjectList parameters, in order to minimize side effects on
|
||||||
|
// built-in functions.
|
||||||
|
if (objectParameterMetadata.GetType() == "objectList") {
|
||||||
|
isAnyBehaviorMissing = true;
|
||||||
|
}
|
||||||
gd::ProjectDiagnostic projectDiagnostic(
|
gd::ProjectDiagnostic projectDiagnostic(
|
||||||
gd::ProjectDiagnostic::ErrorType::MissingBehavior, "",
|
gd::ProjectDiagnostic::ErrorType::MissingBehavior,
|
||||||
actualBehaviorType, expectedBehaviorType, lastObjectName);
|
"",
|
||||||
|
actualBehaviorType,
|
||||||
|
expectedBehaviorType,
|
||||||
|
lastObjectName);
|
||||||
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return isAnyBehaviorMissing;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -521,7 +563,8 @@ void EventsCodeGenerator::CheckBehaviorParameters(
|
|||||||
gd::String EventsCodeGenerator::GenerateActionCode(
|
gd::String EventsCodeGenerator::GenerateActionCode(
|
||||||
gd::Instruction& action,
|
gd::Instruction& action,
|
||||||
EventsCodeGenerationContext& context,
|
EventsCodeGenerationContext& context,
|
||||||
const gd::String& optionalAsyncCallbackName) {
|
const gd::String& optionalAsyncCallbackName,
|
||||||
|
const gd::String& optionalAsyncCallbackId) {
|
||||||
gd::String actionCode;
|
gd::String actionCode;
|
||||||
|
|
||||||
const gd::InstructionMetadata& instrInfos =
|
const gd::InstructionMetadata& instrInfos =
|
||||||
@@ -546,39 +589,51 @@ 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.GetParametersCount()) {
|
||||||
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 mismatches 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.GetParametersCount(); ++pNb) {
|
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount();
|
||||||
if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) {
|
++pNb) {
|
||||||
|
if (ParameterMetadata::IsObject(
|
||||||
|
instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||||
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
|
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
|
||||||
|
|
||||||
const auto &expectedObjectType =
|
const auto& expectedObjectType =
|
||||||
instrInfos.parameters.GetParameter(pNb).GetExtraInfo();
|
instrInfos.parameters.GetParameter(pNb).GetExtraInfo();
|
||||||
const auto &actualObjectType =
|
const auto& actualObjectType =
|
||||||
GetObjectsContainersList().GetTypeOfObject(objectInParameter);
|
GetObjectsContainersList().GetTypeOfObject(objectInParameter);
|
||||||
if (!GetObjectsContainersList().HasObjectOrGroupNamed(
|
if (!GetObjectsContainersList().HasObjectOrGroupNamed(
|
||||||
objectInParameter)) {
|
objectInParameter)) {
|
||||||
gd::ProjectDiagnostic projectDiagnostic(
|
gd::ProjectDiagnostic projectDiagnostic(
|
||||||
gd::ProjectDiagnostic::ErrorType::UnknownObject, "",
|
gd::ProjectDiagnostic::ErrorType::UnknownObject,
|
||||||
objectInParameter, "");
|
"",
|
||||||
|
objectInParameter,
|
||||||
|
"");
|
||||||
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
||||||
return "/* Unknown object - skipped. */";
|
return "/* Unknown object - skipped. */";
|
||||||
} else if (!expectedObjectType.empty() &&
|
} else if (!expectedObjectType.empty() &&
|
||||||
actualObjectType != expectedObjectType) {
|
actualObjectType != expectedObjectType) {
|
||||||
gd::ProjectDiagnostic projectDiagnostic(
|
gd::ProjectDiagnostic projectDiagnostic(
|
||||||
gd::ProjectDiagnostic::ErrorType::MismatchedObjectType, "",
|
gd::ProjectDiagnostic::ErrorType::MismatchedObjectType,
|
||||||
actualObjectType, expectedObjectType, objectInParameter);
|
"",
|
||||||
|
actualObjectType,
|
||||||
|
expectedObjectType,
|
||||||
|
objectInParameter);
|
||||||
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
||||||
return "/* Mismatched object type - skipped. */";
|
return "/* Mismatched object type - skipped. */";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool isAnyBehaviorMissing =
|
||||||
|
gd::EventsCodeGenerator::CheckBehaviorParameters(action, instrInfos);
|
||||||
|
if (isAnyBehaviorMissing) {
|
||||||
|
return "/* Missing behavior - skipped. */";
|
||||||
|
}
|
||||||
|
|
||||||
// Call free function first if available
|
// Call free function first if available
|
||||||
if (instrInfos.IsObjectInstruction()) {
|
if (instrInfos.IsObjectInstruction()) {
|
||||||
@@ -586,43 +641,46 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
|||||||
|
|
||||||
if (instrInfos.parameters.GetParametersCount() > 0) {
|
if (instrInfos.parameters.GetParametersCount() > 0) {
|
||||||
std::vector<gd::String> realObjects =
|
std::vector<gd::String> realObjects =
|
||||||
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
GetObjectsContainersList().ExpandObjectName(
|
||||||
|
objectName, context.GetCurrentObject());
|
||||||
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 =
|
||||||
|
GetObjectsContainersList().GetTypeOfObject(realObjects[i]);
|
||||||
const ObjectMetadata& objInfo =
|
const ObjectMetadata& objInfo =
|
||||||
MetadataProvider::GetObjectMetadata(platform, objectType);
|
MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||||
|
|
||||||
AddIncludeFiles(objInfo.includeFiles);
|
AddIncludeFiles(objInfo.includeFiles);
|
||||||
context.SetCurrentObject(realObjects[i]);
|
context.SetCurrentObject(realObjects[i]);
|
||||||
context.ObjectsListNeeded(realObjects[i]);
|
context.ObjectsListNeeded(realObjects[i]);
|
||||||
|
|
||||||
// Prepare arguments and generate the whole action code
|
// Prepare arguments and generate the whole action code
|
||||||
vector<gd::String> arguments = GenerateParametersCodes(
|
vector<gd::String> arguments = GenerateParametersCodes(
|
||||||
action.GetParameters(), instrInfos.parameters, context);
|
action.GetParameters(), instrInfos.parameters, context);
|
||||||
actionCode += GenerateObjectAction(realObjects[i],
|
actionCode += GenerateObjectAction(realObjects[i],
|
||||||
objInfo,
|
objInfo,
|
||||||
functionCallName,
|
functionCallName,
|
||||||
arguments,
|
arguments,
|
||||||
instrInfos,
|
instrInfos,
|
||||||
context,
|
context,
|
||||||
optionalAsyncCallbackName);
|
optionalAsyncCallbackName,
|
||||||
|
optionalAsyncCallbackId);
|
||||||
|
|
||||||
context.SetNoCurrentObject();
|
context.SetNoCurrentObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (instrInfos.IsBehaviorInstruction()) {
|
} else if (instrInfos.IsBehaviorInstruction()) {
|
||||||
if (instrInfos.parameters.GetParametersCount() >= 2) {
|
if (instrInfos.parameters.GetParametersCount() >= 2) {
|
||||||
const gd::String &objectName = action.GetParameter(0).GetPlainString();
|
const gd::String& objectName = action.GetParameter(0).GetPlainString();
|
||||||
const gd::String &behaviorName = action.GetParameter(1).GetPlainString();
|
const gd::String& behaviorName = action.GetParameter(1).GetPlainString();
|
||||||
const gd::String &actualBehaviorType =
|
const gd::String& actualBehaviorType =
|
||||||
GetObjectsContainersList().GetTypeOfBehavior(behaviorName);
|
GetObjectsContainersList().GetTypeOfBehavior(behaviorName);
|
||||||
|
|
||||||
std::vector<gd::String> realObjects =
|
std::vector<gd::String> realObjects =
|
||||||
GetObjectsContainersList().ExpandObjectName(
|
GetObjectsContainersList().ExpandObjectName(
|
||||||
objectName, context.GetCurrentObject());
|
objectName, context.GetCurrentObject());
|
||||||
|
|
||||||
const BehaviorMetadata &autoInfo =
|
const BehaviorMetadata& autoInfo =
|
||||||
MetadataProvider::GetBehaviorMetadata(platform, actualBehaviorType);
|
MetadataProvider::GetBehaviorMetadata(platform, actualBehaviorType);
|
||||||
|
|
||||||
AddIncludeFiles(autoInfo.includeFiles);
|
AddIncludeFiles(autoInfo.includeFiles);
|
||||||
@@ -634,15 +692,15 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
|||||||
// Prepare arguments and generate the whole action code
|
// Prepare arguments and generate the whole action code
|
||||||
vector<gd::String> arguments = GenerateParametersCodes(
|
vector<gd::String> arguments = GenerateParametersCodes(
|
||||||
action.GetParameters(), instrInfos.parameters, context);
|
action.GetParameters(), instrInfos.parameters, context);
|
||||||
actionCode +=
|
actionCode += GenerateBehaviorAction(realObjects[i],
|
||||||
GenerateBehaviorAction(realObjects[i],
|
behaviorName,
|
||||||
behaviorName,
|
autoInfo,
|
||||||
autoInfo,
|
functionCallName,
|
||||||
functionCallName,
|
arguments,
|
||||||
arguments,
|
instrInfos,
|
||||||
instrInfos,
|
context,
|
||||||
context,
|
optionalAsyncCallbackName,
|
||||||
optionalAsyncCallbackName);
|
optionalAsyncCallbackId);
|
||||||
|
|
||||||
context.SetNoCurrentObject();
|
context.SetNoCurrentObject();
|
||||||
}
|
}
|
||||||
@@ -654,7 +712,8 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
|||||||
arguments,
|
arguments,
|
||||||
instrInfos,
|
instrInfos,
|
||||||
context,
|
context,
|
||||||
optionalAsyncCallbackName);
|
optionalAsyncCallbackName,
|
||||||
|
optionalAsyncCallbackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return actionCode;
|
return actionCode;
|
||||||
@@ -667,8 +726,8 @@ gd::String EventsCodeGenerator::GenerateLocalVariablesStackAccessor() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gd::String EventsCodeGenerator::GenerateAnyOrSceneVariableGetter(
|
gd::String EventsCodeGenerator::GenerateAnyOrSceneVariableGetter(
|
||||||
const gd::Expression &variableExpression,
|
const gd::Expression& variableExpression,
|
||||||
EventsCodeGenerationContext &context) {
|
EventsCodeGenerationContext& context) {
|
||||||
const auto variableName = gd::ExpressionVariableNameFinder::GetVariableName(
|
const auto variableName = gd::ExpressionVariableNameFinder::GetVariableName(
|
||||||
*variableExpression.GetRootNode());
|
*variableExpression.GetRootNode());
|
||||||
|
|
||||||
@@ -679,8 +738,12 @@ gd::String EventsCodeGenerator::GenerateAnyOrSceneVariableGetter(
|
|||||||
: "scenevar";
|
: "scenevar";
|
||||||
|
|
||||||
return gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
return gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||||
*this, context, variableParameterType,
|
*this,
|
||||||
variableExpression.GetPlainString(), "", "AllowUndeclaredVariable");
|
context,
|
||||||
|
variableParameterType,
|
||||||
|
variableExpression.GetPlainString(),
|
||||||
|
"",
|
||||||
|
"AllowUndeclaredVariable");
|
||||||
}
|
}
|
||||||
|
|
||||||
const EventsCodeGenerator::CallbackDescriptor
|
const EventsCodeGenerator::CallbackDescriptor
|
||||||
@@ -727,6 +790,11 @@ EventsCodeGenerator::GenerateCallback(
|
|||||||
|
|
||||||
AddCustomCodeOutsideMain(callbackCode);
|
AddCustomCodeOutsideMain(callbackCode);
|
||||||
|
|
||||||
|
const gd::String idToCallbackMapUpdate = GetCodeNamespaceAccessor() +
|
||||||
|
"idToCallbackMap.set(" + callbackID +
|
||||||
|
", " + callbackFunctionName + ");\n";
|
||||||
|
AddCustomCodeOutsideMain(idToCallbackMapUpdate);
|
||||||
|
|
||||||
std::set<gd::String> requiredObjects;
|
std::set<gd::String> requiredObjects;
|
||||||
// Build the list of all objects required by the callback. Any object that has
|
// Build the list of all objects required by the callback. Any object that has
|
||||||
// already been declared could have gone through previous object picking, so
|
// already been declared could have gone through previous object picking, so
|
||||||
@@ -769,7 +837,7 @@ gd::String EventsCodeGenerator::GenerateActionsListCode(
|
|||||||
} else {
|
} else {
|
||||||
outputCode += actionCode;
|
outputCode += actionCode;
|
||||||
}
|
}
|
||||||
outputCode += "}";
|
outputCode += "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputCode;
|
return outputCode;
|
||||||
@@ -786,13 +854,28 @@ 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,
|
||||||
|
metadata.GetExtraInfo());
|
||||||
} 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,
|
||||||
|
metadata.GetExtraInfo());
|
||||||
} 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,
|
||||||
|
metadata.GetExtraInfo());
|
||||||
} 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.
|
||||||
@@ -827,7 +910,8 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
|||||||
metadata.GetType() == "atlasResource" ||
|
metadata.GetType() == "atlasResource" ||
|
||||||
metadata.GetType() == "spineResource" ||
|
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") {
|
||||||
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
|
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
|
||||||
} else if (metadata.GetType() == "mouse") {
|
} else if (metadata.GetType() == "mouse") {
|
||||||
@@ -977,7 +1061,8 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
|
|||||||
for (std::size_t eId = 0; eId < events.size(); ++eId) {
|
for (std::size_t eId = 0; eId < events.size(); ++eId) {
|
||||||
auto& event = events[eId];
|
auto& event = events[eId];
|
||||||
if (event.HasVariables()) {
|
if (event.HasVariables()) {
|
||||||
GetProjectScopedContainers().GetVariablesContainersList().Push(event.GetVariables());
|
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
|
||||||
@@ -1102,7 +1187,7 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
|
|||||||
instrInfos.codeExtraInformation.functionCallName);
|
instrInfos.codeExtraInformation.functionCallName);
|
||||||
} else {
|
} else {
|
||||||
predicate = instrInfos.codeExtraInformation.functionCallName + "(" +
|
predicate = instrInfos.codeExtraInformation.functionCallName + "(" +
|
||||||
GenerateArgumentsList(arguments, 0) + ")";
|
GenerateArgumentsList(arguments, 0) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add logical not if needed
|
// Add logical not if needed
|
||||||
@@ -1146,7 +1231,7 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
|
|||||||
instrInfos, arguments, objectFunctionCallNamePart, 1);
|
instrInfos, arguments, objectFunctionCallNamePart, 1);
|
||||||
} else {
|
} else {
|
||||||
predicate = objectFunctionCallNamePart + "(" +
|
predicate = objectFunctionCallNamePart + "(" +
|
||||||
GenerateArgumentsList(arguments, 1) + ")";
|
GenerateArgumentsList(arguments, 1) + ")";
|
||||||
}
|
}
|
||||||
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate);
|
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate);
|
||||||
|
|
||||||
@@ -1178,18 +1263,20 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
|
|||||||
}
|
}
|
||||||
|
|
||||||
gd::String EventsCodeGenerator::GenerateFreeAction(
|
gd::String EventsCodeGenerator::GenerateFreeAction(
|
||||||
const gd::String& functionCallName,
|
const gd::String& functionCallName,
|
||||||
const std::vector<gd::String>& arguments,
|
const std::vector<gd::String>& arguments,
|
||||||
const gd::InstructionMetadata& instrInfos,
|
const gd::InstructionMetadata& instrInfos,
|
||||||
gd::EventsCodeGenerationContext& context,
|
gd::EventsCodeGenerationContext& context,
|
||||||
const gd::String& optionalAsyncCallbackName) {
|
const gd::String& optionalAsyncCallbackName,
|
||||||
|
const gd::String& optionalAsyncCallbackId) {
|
||||||
// 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
|
// Boolean actions declared with addExpressionAndConditionAndAction uses
|
||||||
// MutatorAndOrAccessor even though they don't declare an operator parameter.
|
// MutatorAndOrAccessor even though they don't declare an operator
|
||||||
// Boolean operators are only used with SetMutators or SetCustomCodeGenerator.
|
// parameter. Boolean operators are only used with SetMutators or
|
||||||
|
// SetCustomCodeGenerator.
|
||||||
(instrInfos.codeExtraInformation.type == "boolean" &&
|
(instrInfos.codeExtraInformation.type == "boolean" &&
|
||||||
instrInfos.codeExtraInformation.accessType ==
|
instrInfos.codeExtraInformation.accessType ==
|
||||||
gd::InstructionMetadata::ExtraInformation::AccessType::Mutators)) {
|
gd::InstructionMetadata::ExtraInformation::AccessType::Mutators)) {
|
||||||
@@ -1202,23 +1289,19 @@ gd::String EventsCodeGenerator::GenerateFreeAction(
|
|||||||
instrInfos.codeExtraInformation.optionalAssociatedInstruction);
|
instrInfos.codeExtraInformation.optionalAssociatedInstruction);
|
||||||
else if (instrInfos.codeExtraInformation.accessType ==
|
else if (instrInfos.codeExtraInformation.accessType ==
|
||||||
gd::InstructionMetadata::ExtraInformation::Mutators)
|
gd::InstructionMetadata::ExtraInformation::Mutators)
|
||||||
call =
|
call = GenerateMutatorCall(instrInfos, arguments, functionCallName);
|
||||||
GenerateMutatorCall(instrInfos,
|
|
||||||
arguments,
|
|
||||||
functionCallName);
|
|
||||||
else
|
else
|
||||||
call = GenerateCompoundOperatorCall(
|
call =
|
||||||
instrInfos,
|
GenerateCompoundOperatorCall(instrInfos, arguments, functionCallName);
|
||||||
arguments,
|
|
||||||
functionCallName);
|
|
||||||
} else {
|
} else {
|
||||||
call = functionCallName + "(" +
|
call = functionCallName + "(" + GenerateArgumentsList(arguments) + ")";
|
||||||
GenerateArgumentsList(arguments) + ")";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!optionalAsyncCallbackName.empty())
|
if (!optionalAsyncCallbackName.empty() && !optionalAsyncCallbackId.empty()) {
|
||||||
call = "runtimeScene.getAsyncTasksManager().addTask(" + call + ", " +
|
call = "runtimeScene.getAsyncTasksManager().addTask(" + call + ", " +
|
||||||
optionalAsyncCallbackName + ")";
|
optionalAsyncCallbackName + ", " + optionalAsyncCallbackId +
|
||||||
|
", asyncObjectsList)";
|
||||||
|
}
|
||||||
|
|
||||||
return call + ";\n";
|
return call + ";\n";
|
||||||
}
|
}
|
||||||
@@ -1230,7 +1313,8 @@ gd::String EventsCodeGenerator::GenerateObjectAction(
|
|||||||
const std::vector<gd::String>& arguments,
|
const std::vector<gd::String>& arguments,
|
||||||
const gd::InstructionMetadata& instrInfos,
|
const gd::InstructionMetadata& instrInfos,
|
||||||
gd::EventsCodeGenerationContext& context,
|
gd::EventsCodeGenerationContext& context,
|
||||||
const gd::String& optionalAsyncCallbackName) {
|
const gd::String& optionalAsyncCallbackName,
|
||||||
|
const gd::String& optionalAsyncCallbackId) {
|
||||||
// Create call
|
// Create call
|
||||||
gd::String call;
|
gd::String call;
|
||||||
if ((instrInfos.codeExtraInformation.type == "number" ||
|
if ((instrInfos.codeExtraInformation.type == "number" ||
|
||||||
@@ -1271,7 +1355,8 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
|
|||||||
const std::vector<gd::String>& arguments,
|
const std::vector<gd::String>& arguments,
|
||||||
const gd::InstructionMetadata& instrInfos,
|
const gd::InstructionMetadata& instrInfos,
|
||||||
gd::EventsCodeGenerationContext& context,
|
gd::EventsCodeGenerationContext& context,
|
||||||
const gd::String& optionalAsyncCallbackName) {
|
const gd::String& optionalAsyncCallbackName,
|
||||||
|
const gd::String& optionalAsyncCallbackId) {
|
||||||
// Create call
|
// Create call
|
||||||
gd::String call;
|
gd::String call;
|
||||||
if ((instrInfos.codeExtraInformation.type == "number" ||
|
if ((instrInfos.codeExtraInformation.type == "number" ||
|
||||||
@@ -1286,17 +1371,13 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
|
|||||||
2);
|
2);
|
||||||
else
|
else
|
||||||
call = GenerateCompoundOperatorCall(
|
call = GenerateCompoundOperatorCall(
|
||||||
instrInfos,
|
instrInfos, arguments, functionCallName, 2);
|
||||||
arguments,
|
|
||||||
functionCallName,
|
|
||||||
2);
|
|
||||||
return "For each picked object \"" + objectName + "\", call " + call +
|
return "For each picked object \"" + objectName + "\", call " + call +
|
||||||
" for behavior \"" + behaviorName + "\".\n";
|
" for behavior \"" + behaviorName + "\".\n";
|
||||||
} else {
|
} else {
|
||||||
gd::String argumentsStr = GenerateArgumentsList(arguments, 2);
|
gd::String argumentsStr = GenerateArgumentsList(arguments, 2);
|
||||||
|
|
||||||
call = functionCallName + "(" +
|
call = functionCallName + "(" + argumentsStr + ")";
|
||||||
argumentsStr + ")";
|
|
||||||
|
|
||||||
return "For each picked object \"" + objectName + "\", call " + call + "(" +
|
return "For each picked object \"" + objectName + "\", call " + call + "(" +
|
||||||
argumentsStr + ")" + " for behavior \"" + behaviorName + "\"" +
|
argumentsStr + ")" + " for behavior \"" + behaviorName + "\"" +
|
||||||
@@ -1351,42 +1432,47 @@ gd::String EventsCodeGenerator::GenerateArgumentsList(
|
|||||||
return argumentsStr;
|
return argumentsStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
gd::String EventsCodeGenerator::GeneratePropertyGetter(const gd::PropertiesContainer& propertiesContainer,
|
gd::String EventsCodeGenerator::GeneratePropertyGetter(
|
||||||
const gd::NamedPropertyDescriptor& property,
|
const gd::PropertiesContainer& propertiesContainer,
|
||||||
const gd::String& type,
|
const gd::NamedPropertyDescriptor& property,
|
||||||
gd::EventsCodeGenerationContext& context) {
|
const gd::String& type,
|
||||||
|
gd::EventsCodeGenerationContext& context) {
|
||||||
return "getProperty" + property.GetName() + "As" + type + "()";
|
return "getProperty" + property.GetName() + "As" + type + "()";
|
||||||
}
|
}
|
||||||
|
|
||||||
gd::String EventsCodeGenerator::GeneratePropertyGetterWithoutCasting(
|
gd::String EventsCodeGenerator::GeneratePropertyGetterWithoutCasting(
|
||||||
const gd::PropertiesContainer &propertiesContainer,
|
const gd::PropertiesContainer& propertiesContainer,
|
||||||
const gd::NamedPropertyDescriptor &property) {
|
const gd::NamedPropertyDescriptor& property) {
|
||||||
return "getProperty" + property.GetName() + "()";
|
return "getProperty" + property.GetName() + "()";
|
||||||
}
|
}
|
||||||
|
|
||||||
gd::String EventsCodeGenerator::GeneratePropertySetterWithoutCasting(
|
gd::String EventsCodeGenerator::GeneratePropertySetterWithoutCasting(
|
||||||
const gd::PropertiesContainer &propertiesContainer,
|
const gd::PropertiesContainer& propertiesContainer,
|
||||||
const gd::NamedPropertyDescriptor &property,
|
const gd::NamedPropertyDescriptor& property,
|
||||||
const gd::String &operandCode) {
|
const gd::String& operandCode) {
|
||||||
return "setProperty" + property.GetName() + "(" + operandCode + ")";
|
return "setProperty" + property.GetName() + "(" + operandCode + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
gd::String EventsCodeGenerator::GenerateParameterGetter(const gd::ParameterMetadata& parameter,
|
gd::String EventsCodeGenerator::GenerateParameterGetter(
|
||||||
const gd::String& type,
|
const gd::ParameterMetadata& parameter,
|
||||||
gd::EventsCodeGenerationContext& context) {
|
const gd::String& type,
|
||||||
|
gd::EventsCodeGenerationContext& context) {
|
||||||
return "getParameter" + parameter.GetName() + "As" + type + "()";
|
return "getParameter" + parameter.GetName() + "As" + type + "()";
|
||||||
}
|
}
|
||||||
|
|
||||||
gd::String EventsCodeGenerator::GenerateParameterGetterWithoutCasting(
|
gd::String EventsCodeGenerator::GenerateParameterGetterWithoutCasting(
|
||||||
const gd::ParameterMetadata ¶meter) {
|
const gd::ParameterMetadata& parameter) {
|
||||||
return "getParameter" + parameter.GetName() + "()";
|
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)),
|
projectScopedContainers(
|
||||||
|
gd::ProjectScopedContainers::
|
||||||
|
MakeNewProjectScopedContainersForProjectAndLayout(project_,
|
||||||
|
layout)),
|
||||||
hasProjectAndLayout(true),
|
hasProjectAndLayout(true),
|
||||||
project(&project_),
|
project(&project_),
|
||||||
scene(&layout),
|
scene(&layout),
|
||||||
@@ -1395,7 +1481,7 @@ EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
|
|||||||
maxCustomConditionsDepth(0),
|
maxCustomConditionsDepth(0),
|
||||||
maxConditionsListsSize(0),
|
maxConditionsListsSize(0),
|
||||||
eventsListNextUniqueId(0),
|
eventsListNextUniqueId(0),
|
||||||
diagnosticReport(nullptr){};
|
diagnosticReport(nullptr) {};
|
||||||
|
|
||||||
EventsCodeGenerator::EventsCodeGenerator(
|
EventsCodeGenerator::EventsCodeGenerator(
|
||||||
const gd::Platform& platform_,
|
const gd::Platform& platform_,
|
||||||
@@ -1410,6 +1496,6 @@ EventsCodeGenerator::EventsCodeGenerator(
|
|||||||
maxCustomConditionsDepth(0),
|
maxCustomConditionsDepth(0),
|
||||||
maxConditionsListsSize(0),
|
maxConditionsListsSize(0),
|
||||||
eventsListNextUniqueId(0),
|
eventsListNextUniqueId(0),
|
||||||
diagnosticReport(nullptr){};
|
diagnosticReport(nullptr) {};
|
||||||
|
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
|
@@ -9,9 +9,9 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "GDCore/Events/CodeGeneration/DiagnosticReport.h"
|
||||||
#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/Project/ProjectScopedContainers.h"
|
||||||
#include "GDCore/String.h"
|
#include "GDCore/String.h"
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ class GD_CORE_API EventsCodeGenerator {
|
|||||||
EventsCodeGenerator(
|
EventsCodeGenerator(
|
||||||
const gd::Platform& platform,
|
const gd::Platform& platform,
|
||||||
const gd::ProjectScopedContainers& projectScopedContainers_);
|
const gd::ProjectScopedContainers& projectScopedContainers_);
|
||||||
virtual ~EventsCodeGenerator(){};
|
virtual ~EventsCodeGenerator() {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Preprocess an events list (replacing for example links with the
|
* \brief Preprocess an events list (replacing for example links with the
|
||||||
@@ -160,7 +160,8 @@ class GD_CORE_API EventsCodeGenerator {
|
|||||||
gd::String GenerateActionCode(
|
gd::String GenerateActionCode(
|
||||||
gd::Instruction& action,
|
gd::Instruction& action,
|
||||||
EventsCodeGenerationContext& context,
|
EventsCodeGenerationContext& context,
|
||||||
const gd::String& optionalAsyncCallbackName = "");
|
const gd::String& optionalAsyncCallbackName = "",
|
||||||
|
const gd::String& optionalAsyncCallbackId = "");
|
||||||
|
|
||||||
struct CallbackDescriptor {
|
struct CallbackDescriptor {
|
||||||
CallbackDescriptor(const gd::String functionName_,
|
CallbackDescriptor(const gd::String functionName_,
|
||||||
@@ -168,7 +169,7 @@ class GD_CORE_API EventsCodeGenerator {
|
|||||||
const std::set<gd::String> requiredObjects_)
|
const std::set<gd::String> requiredObjects_)
|
||||||
: functionName(functionName_),
|
: functionName(functionName_),
|
||||||
argumentsList(argumentsList_),
|
argumentsList(argumentsList_),
|
||||||
requiredObjects(requiredObjects_){};
|
requiredObjects(requiredObjects_) {};
|
||||||
/**
|
/**
|
||||||
* The name by which the function can be invoked.
|
* The name by which the function can be invoked.
|
||||||
*/
|
*/
|
||||||
@@ -338,9 +339,9 @@ class GD_CORE_API EventsCodeGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Give access to the project scoped containers as code generation might
|
* @brief Give access to the project scoped containers as code generation
|
||||||
* push and pop variable containers (for local variables).
|
* might push and pop variable containers (for local variables). This could be
|
||||||
* This could be passed as a parameter recursively in code generation, but this requires
|
* passed as a parameter recursively in code generation, but this requires
|
||||||
* heavy refactoring. Instead, we use this single instance.
|
* heavy refactoring. Instead, we use this single instance.
|
||||||
*/
|
*/
|
||||||
gd::ProjectScopedContainers& GetProjectScopedContainers() {
|
gd::ProjectScopedContainers& GetProjectScopedContainers() {
|
||||||
@@ -387,9 +388,7 @@ class GD_CORE_API EventsCodeGenerator {
|
|||||||
diagnosticReport = diagnosticReport_;
|
diagnosticReport = diagnosticReport_;
|
||||||
}
|
}
|
||||||
|
|
||||||
gd::DiagnosticReport* GetDiagnosticReport() {
|
gd::DiagnosticReport* GetDiagnosticReport() { return diagnosticReport; }
|
||||||
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
|
||||||
@@ -513,16 +512,16 @@ class GD_CORE_API EventsCodeGenerator {
|
|||||||
* \brief Generate an any variable getter that fallbacks on scene variable for
|
* \brief Generate an any variable getter that fallbacks on scene variable for
|
||||||
* compatibility reason.
|
* compatibility reason.
|
||||||
*/
|
*/
|
||||||
gd::String
|
gd::String GenerateAnyOrSceneVariableGetter(
|
||||||
GenerateAnyOrSceneVariableGetter(const gd::Expression &variableExpression,
|
const gd::Expression& variableExpression,
|
||||||
EventsCodeGenerationContext &context);
|
EventsCodeGenerationContext& context);
|
||||||
|
|
||||||
virtual gd::String GeneratePropertySetterWithoutCasting(
|
virtual gd::String GeneratePropertySetterWithoutCasting(
|
||||||
const gd::PropertiesContainer &propertiesContainer,
|
const gd::PropertiesContainer& propertiesContainer,
|
||||||
const gd::NamedPropertyDescriptor &property,
|
const gd::NamedPropertyDescriptor& property,
|
||||||
const gd::String &operandCode);
|
const gd::String& operandCode);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const gd::String GenerateRelationalOperatorCodes(
|
virtual const gd::String GenerateRelationalOperatorCodes(
|
||||||
const gd::String& operatorString);
|
const gd::String& operatorString);
|
||||||
|
|
||||||
@@ -643,16 +642,16 @@ protected:
|
|||||||
gd::EventsCodeGenerationContext& context);
|
gd::EventsCodeGenerationContext& context);
|
||||||
|
|
||||||
virtual gd::String GeneratePropertyGetterWithoutCasting(
|
virtual gd::String GeneratePropertyGetterWithoutCasting(
|
||||||
const gd::PropertiesContainer &propertiesContainer,
|
const gd::PropertiesContainer& propertiesContainer,
|
||||||
const gd::NamedPropertyDescriptor &property);
|
const gd::NamedPropertyDescriptor& property);
|
||||||
|
|
||||||
virtual gd::String GenerateParameterGetter(
|
virtual gd::String GenerateParameterGetter(
|
||||||
const gd::ParameterMetadata& parameter,
|
const gd::ParameterMetadata& parameter,
|
||||||
const gd::String& type,
|
const gd::String& type,
|
||||||
gd::EventsCodeGenerationContext& context);
|
gd::EventsCodeGenerationContext& context);
|
||||||
|
|
||||||
virtual gd::String
|
virtual gd::String GenerateParameterGetterWithoutCasting(
|
||||||
GenerateParameterGetterWithoutCasting(const gd::ParameterMetadata ¶meter);
|
const gd::ParameterMetadata& parameter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Generate the code to reference an object which is
|
* \brief Generate the code to reference an object which is
|
||||||
@@ -769,7 +768,8 @@ protected:
|
|||||||
const std::vector<gd::String>& arguments,
|
const std::vector<gd::String>& arguments,
|
||||||
const gd::InstructionMetadata& instrInfos,
|
const gd::InstructionMetadata& instrInfos,
|
||||||
gd::EventsCodeGenerationContext& context,
|
gd::EventsCodeGenerationContext& context,
|
||||||
const gd::String& optionalAsyncCallbackName = "");
|
const gd::String& optionalAsyncCallbackName = "",
|
||||||
|
const gd::String& optionalAsyncCallbackId = "");
|
||||||
|
|
||||||
virtual gd::String GenerateObjectAction(
|
virtual gd::String GenerateObjectAction(
|
||||||
const gd::String& objectName,
|
const gd::String& objectName,
|
||||||
@@ -778,7 +778,8 @@ protected:
|
|||||||
const std::vector<gd::String>& arguments,
|
const std::vector<gd::String>& arguments,
|
||||||
const gd::InstructionMetadata& instrInfos,
|
const gd::InstructionMetadata& instrInfos,
|
||||||
gd::EventsCodeGenerationContext& context,
|
gd::EventsCodeGenerationContext& context,
|
||||||
const gd::String& optionalAsyncCallbackName = "");
|
const gd::String& optionalAsyncCallbackName = "",
|
||||||
|
const gd::String& optionalAsyncCallbackId = "");
|
||||||
|
|
||||||
virtual gd::String GenerateBehaviorAction(
|
virtual gd::String GenerateBehaviorAction(
|
||||||
const gd::String& objectName,
|
const gd::String& objectName,
|
||||||
@@ -788,7 +789,8 @@ protected:
|
|||||||
const std::vector<gd::String>& arguments,
|
const std::vector<gd::String>& arguments,
|
||||||
const gd::InstructionMetadata& instrInfos,
|
const gd::InstructionMetadata& instrInfos,
|
||||||
gd::EventsCodeGenerationContext& context,
|
gd::EventsCodeGenerationContext& context,
|
||||||
const gd::String& optionalAsyncCallbackName = "");
|
const gd::String& optionalAsyncCallbackName = "",
|
||||||
|
const gd::String& optionalAsyncCallbackId = "");
|
||||||
|
|
||||||
gd::String GenerateRelationalOperatorCall(
|
gd::String GenerateRelationalOperatorCall(
|
||||||
const gd::InstructionMetadata& instrInfos,
|
const gd::InstructionMetadata& instrInfos,
|
||||||
@@ -837,9 +839,8 @@ protected:
|
|||||||
virtual gd::String GenerateGetBehaviorNameCode(
|
virtual gd::String GenerateGetBehaviorNameCode(
|
||||||
const gd::String& behaviorName);
|
const gd::String& behaviorName);
|
||||||
|
|
||||||
void CheckBehaviorParameters(
|
bool CheckBehaviorParameters(const gd::Instruction& instruction,
|
||||||
const gd::Instruction &instruction,
|
const gd::InstructionMetadata& instrInfos);
|
||||||
const gd::InstructionMetadata &instrInfos);
|
|
||||||
|
|
||||||
const gd::Platform& platform; ///< The platform being used.
|
const gd::Platform& platform; ///< The platform being used.
|
||||||
|
|
||||||
@@ -876,4 +877,3 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
|
|
||||||
|
@@ -286,6 +286,20 @@ class GD_CORE_API BaseEvent {
|
|||||||
* \brief True if the event should be folded in the events editor.
|
* \brief True if the event should be folded in the events editor.
|
||||||
*/
|
*/
|
||||||
bool IsFolded() const { return folded; }
|
bool IsFolded() const { return folded; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \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>
|
||||||
@@ -304,6 +318,7 @@ 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 gd::VariablesContainer badLocalVariables;
|
||||||
|
@@ -221,6 +221,8 @@ 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());
|
||||||
}
|
}
|
||||||
@@ -236,6 +238,8 @@ 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);
|
||||||
|
@@ -37,8 +37,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
.SetIcon("res/actions/position24_black.png");
|
.SetIcon("res/actions/position24_black.png");
|
||||||
extension.AddInstructionOrExpressionGroupMetadata(_("Angle"))
|
extension.AddInstructionOrExpressionGroupMetadata(_("Angle"))
|
||||||
.SetIcon("res/actions/direction24_black.png");
|
.SetIcon("res/actions/direction24_black.png");
|
||||||
extension.AddInstructionOrExpressionGroupMetadata(_("Size"))
|
extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon(
|
||||||
.SetIcon("res/actions/scale24_black.png");
|
"res/actions/scale24_black.png");
|
||||||
|
|
||||||
gd::ObjectMetadata& obj = extension.AddObject<gd::ObjectConfiguration>(
|
gd::ObjectMetadata& obj = extension.AddObject<gd::ObjectConfiguration>(
|
||||||
"", _("Base object"), _("Base object"), "res/objeticon24.png");
|
"", _("Base object"), _("Base object"), "res/objeticon24.png");
|
||||||
@@ -235,7 +235,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
|
|
||||||
obj.AddAction("SetAngle",
|
obj.AddAction("SetAngle",
|
||||||
_("Angle"),
|
_("Angle"),
|
||||||
_("Change the angle of rotation of an object (in degrees)."),
|
_("Change the angle of rotation of an object (in degrees). For "
|
||||||
|
"3D objects, this is the rotation around the Z axis."),
|
||||||
_("the angle"),
|
_("the angle"),
|
||||||
_("Angle"),
|
_("Angle"),
|
||||||
"res/actions/direction24_black.png",
|
"res/actions/direction24_black.png",
|
||||||
@@ -250,7 +251,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
obj.AddAction("Rotate",
|
obj.AddAction("Rotate",
|
||||||
_("Rotate"),
|
_("Rotate"),
|
||||||
_("Rotate an object, clockwise if the speed is positive, "
|
_("Rotate an object, clockwise if the speed is positive, "
|
||||||
"counterclockwise otherwise."),
|
"counterclockwise otherwise. For 3D objects, this is the "
|
||||||
|
"rotation around the Z axis."),
|
||||||
_("Rotate _PARAM0_ at speed _PARAM1_ deg/second"),
|
_("Rotate _PARAM0_ at speed _PARAM1_ deg/second"),
|
||||||
_("Angle"),
|
_("Angle"),
|
||||||
"res/actions/rotate24_black.png",
|
"res/actions/rotate24_black.png",
|
||||||
@@ -291,6 +293,25 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
.AddCodeOnlyParameter("currentScene", "")
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
.MarkAsAdvanced();
|
.MarkAsAdvanced();
|
||||||
|
|
||||||
|
obj.AddAction(
|
||||||
|
"RotateTowardObject",
|
||||||
|
_("Rotate toward another object"),
|
||||||
|
_("Rotate an object towards another object, with the specified speed. "
|
||||||
|
"Note that if multiple instances of the target object are picked, "
|
||||||
|
"only the first one will be used. Use a For Each event or actions "
|
||||||
|
"like \"Pick nearest object\", \"Pick a random object\" to refine "
|
||||||
|
"the choice of the target object."),
|
||||||
|
_("Rotate _PARAM0_ towards _PARAM1_ at speed _PARAM2_ deg/second"),
|
||||||
|
_("Angle"),
|
||||||
|
"res/actions/rotate24_black.png",
|
||||||
|
"res/actions/rotate_black.png")
|
||||||
|
.AddParameter("object", _("Object"))
|
||||||
|
.AddParameter("objectPtr", _("Target object"))
|
||||||
|
.AddParameter("expression", _("Angular speed (in degrees per second)"))
|
||||||
|
.SetParameterLongDescription(_("Enter 0 for an immediate rotation."))
|
||||||
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
|
.MarkAsAdvanced();
|
||||||
|
|
||||||
obj.AddAction(
|
obj.AddAction(
|
||||||
"AddForceXY",
|
"AddForceXY",
|
||||||
_("Add a force"),
|
_("Add a force"),
|
||||||
@@ -634,7 +655,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
|
|
||||||
obj.AddCondition("Angle",
|
obj.AddCondition("Angle",
|
||||||
_("Angle"),
|
_("Angle"),
|
||||||
_("Compare the angle of the specified object."),
|
_("Compare the angle, in degrees, of the specified object. "
|
||||||
|
"For 3D objects, this is the angle around the Z axis."),
|
||||||
_("the angle (in degrees)"),
|
_("the angle (in degrees)"),
|
||||||
_("Angle"),
|
_("Angle"),
|
||||||
"res/conditions/direction24_black.png",
|
"res/conditions/direction24_black.png",
|
||||||
@@ -835,14 +857,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
.MarkAsAdvanced()
|
.MarkAsAdvanced()
|
||||||
.SetRelevantForLayoutEventsOnly();
|
.SetRelevantForLayoutEventsOnly();
|
||||||
|
|
||||||
obj.AddAction(
|
obj.AddAction("PushBooleanToObjectVariable",
|
||||||
"PushBooleanToObjectVariable",
|
_("Add value to object array variable"),
|
||||||
_("Add value to object array variable"),
|
_("Adds a boolean to the end of an object array variable."),
|
||||||
_("Adds a boolean to the end of an object array variable."),
|
_("Add value _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
|
||||||
_("Add value _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
|
_("Variables ❯ Arrays and structures"),
|
||||||
_("Variables ❯ Arrays and structures"),
|
"res/actions/var24.png",
|
||||||
"res/actions/var24.png",
|
"res/actions/var.png")
|
||||||
"res/actions/var.png")
|
|
||||||
.AddParameter("object", _("Object"))
|
.AddParameter("object", _("Object"))
|
||||||
.AddParameter("objectvar", _("Array variable"))
|
.AddParameter("objectvar", _("Array variable"))
|
||||||
.AddParameter("trueorfalse", _("Boolean to add"))
|
.AddParameter("trueorfalse", _("Boolean to add"))
|
||||||
@@ -1268,7 +1289,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
|
|
||||||
obj.AddExpression("Angle",
|
obj.AddExpression("Angle",
|
||||||
_("Angle"),
|
_("Angle"),
|
||||||
_("Current angle, in degrees, of the object"),
|
_("Current angle, in degrees, of the object. For 3D "
|
||||||
|
"objects, this is the angle around the Z axis."),
|
||||||
_("Angle"),
|
_("Angle"),
|
||||||
"res/actions/direction_black.png")
|
"res/actions/direction_black.png")
|
||||||
.AddParameter("object", _("Object"));
|
.AddParameter("object", _("Object"));
|
||||||
@@ -1571,7 +1593,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
extension
|
extension
|
||||||
.AddAction("Create",
|
.AddAction("Create",
|
||||||
_("Create an object"),
|
_("Create an object"),
|
||||||
_("Create an object at specified position"),
|
_("Create an instance of the object at the specified position."
|
||||||
|
"The created object instance will be available for the next "
|
||||||
|
"actions and sub-events."),
|
||||||
_("Create object _PARAM1_ at position _PARAM2_;_PARAM3_ "
|
_("Create object _PARAM1_ at position _PARAM2_;_PARAM3_ "
|
||||||
"(layer: _PARAM4_)"),
|
"(layer: _PARAM4_)"),
|
||||||
"",
|
"",
|
||||||
@@ -1612,7 +1636,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
|
|
||||||
extension
|
extension
|
||||||
.AddAction("AjoutObjConcern",
|
.AddAction("AjoutObjConcern",
|
||||||
_("Pick all instances"),
|
_("Pick all object instances"),
|
||||||
_("Pick all instances of the specified object(s). When you "
|
_("Pick all instances of the specified object(s). When you "
|
||||||
"pick all instances, "
|
"pick all instances, "
|
||||||
"the next conditions and actions of this event work on all "
|
"the next conditions and actions of this event work on all "
|
||||||
@@ -1626,20 +1650,34 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
.MarkAsAdvanced();
|
.MarkAsAdvanced();
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddAction(
|
.AddAction("AjoutHasard",
|
||||||
"AjoutHasard",
|
_("Pick a random object"),
|
||||||
_("Pick a random object"),
|
_("Pick one instance from all the specified objects. When an "
|
||||||
_("Pick one object from all the specified objects. When an object "
|
"instance is picked, the next conditions and actions of "
|
||||||
"is picked, the next conditions and actions of this event work "
|
"this event work only on that object instance."),
|
||||||
"only on that object."),
|
_("Pick a random _PARAM1_"),
|
||||||
_("Pick a random _PARAM1_"),
|
_("Objects"),
|
||||||
_("Objects"),
|
"res/actions/ajouthasard24.png",
|
||||||
"res/actions/ajouthasard24.png",
|
"res/actions/ajouthasard.png")
|
||||||
"res/actions/ajouthasard.png")
|
|
||||||
.AddCodeOnlyParameter("objectsContext", "")
|
.AddCodeOnlyParameter("objectsContext", "")
|
||||||
.AddParameter("objectList", _("Object"))
|
.AddParameter("objectList", _("Object"))
|
||||||
.MarkAsSimple();
|
.MarkAsSimple();
|
||||||
|
|
||||||
|
extension
|
||||||
|
.AddAction(
|
||||||
|
"PickNearest",
|
||||||
|
_("Pick nearest object"),
|
||||||
|
_("Pick the instance of this object that is nearest to the specified "
|
||||||
|
"position."),
|
||||||
|
_("Pick the _PARAM0_ that is nearest to _PARAM1_;_PARAM2_"),
|
||||||
|
_("Objects"),
|
||||||
|
"res/conditions/distance24.png",
|
||||||
|
"res/conditions/distance.png")
|
||||||
|
.AddParameter("objectList", _("Object"))
|
||||||
|
.AddParameter("expression", _("X position"))
|
||||||
|
.AddParameter("expression", _("Y position"))
|
||||||
|
.MarkAsSimple();
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddAction(
|
.AddAction(
|
||||||
"MoveObjects",
|
"MoveObjects",
|
||||||
@@ -1689,11 +1727,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
extension
|
extension
|
||||||
.AddCondition(
|
.AddCondition(
|
||||||
"AjoutObjConcern",
|
"AjoutObjConcern",
|
||||||
_("Pick all objects"),
|
_("Pick all object instances"),
|
||||||
_("Pick all the specified objects. When you pick all objects, "
|
_("Pick all instances of the specified object(s). When you "
|
||||||
|
"pick all instances, "
|
||||||
"the next conditions and actions of this event work on all "
|
"the next conditions and actions of this event work on all "
|
||||||
"of them."),
|
"of them."),
|
||||||
_("Pick all _PARAM1_ objects"),
|
_("Pick all instances of _PARAM1_"),
|
||||||
_("Objects"),
|
_("Objects"),
|
||||||
"res/conditions/add24.png",
|
"res/conditions/add24.png",
|
||||||
"res/conditions/add.png")
|
"res/conditions/add.png")
|
||||||
@@ -1702,16 +1741,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
.MarkAsAdvanced();
|
.MarkAsAdvanced();
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddCondition(
|
.AddCondition("AjoutHasard",
|
||||||
"AjoutHasard",
|
_("Pick a random object"),
|
||||||
_("Pick a random object"),
|
_("Pick one instance from all the specified objects. When "
|
||||||
_("Pick one object from all the specified objects. When an object "
|
"an instance is picked, the next conditions and actions "
|
||||||
"is picked, the next conditions and actions of this event work "
|
"of this event work only on that object instance."),
|
||||||
"only on that object."),
|
_("Pick a random _PARAM1_"),
|
||||||
_("Pick a random _PARAM1_"),
|
_("Objects"),
|
||||||
_("Objects"),
|
"res/conditions/ajouthasard24.png",
|
||||||
"res/conditions/ajouthasard24.png",
|
"res/conditions/ajouthasard.png")
|
||||||
"res/conditions/ajouthasard.png")
|
|
||||||
.AddCodeOnlyParameter("objectsContext", "")
|
.AddCodeOnlyParameter("objectsContext", "")
|
||||||
.AddParameter("objectList", _("Object"))
|
.AddParameter("objectList", _("Object"))
|
||||||
.MarkAsSimple();
|
.MarkAsSimple();
|
||||||
@@ -1720,9 +1758,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
|||||||
.AddCondition(
|
.AddCondition(
|
||||||
"PickNearest",
|
"PickNearest",
|
||||||
_("Pick nearest object"),
|
_("Pick nearest object"),
|
||||||
_("Pick the object of this type that is nearest to the specified "
|
_("Pick the instance of this object that is nearest to the specified "
|
||||||
"position. If the condition is inverted, the object farthest from "
|
"position. If the condition is inverted, the instance farthest "
|
||||||
"the specified position is picked instead."),
|
"from the specified position is picked instead."),
|
||||||
_("Pick the _PARAM0_ that is nearest to _PARAM1_;_PARAM2_"),
|
_("Pick the _PARAM0_ that is nearest to _PARAM1_;_PARAM2_"),
|
||||||
_("Objects"),
|
_("Objects"),
|
||||||
"res/conditions/distance24.png",
|
"res/conditions/distance24.png",
|
||||||
|
@@ -18,21 +18,21 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAnimatableExtension(
|
|||||||
gd::PlatformExtension& extension) {
|
gd::PlatformExtension& extension) {
|
||||||
extension
|
extension
|
||||||
.SetExtensionInformation("AnimatableCapability",
|
.SetExtensionInformation("AnimatableCapability",
|
||||||
_("Animatable capability"),
|
_("Objects with animations"),
|
||||||
_("Animate objects."),
|
_("Actions and conditions for objects having animations (sprite, 3D models...)."),
|
||||||
"Florian Rival",
|
"Florian Rival",
|
||||||
"Open source (MIT License)")
|
"Open source (MIT License)")
|
||||||
.SetExtensionHelpPath("/objects");
|
.SetExtensionHelpPath("/objects");
|
||||||
extension.AddInstructionOrExpressionGroupMetadata(_("Animatable capability"))
|
extension.AddInstructionOrExpressionGroupMetadata(_("Objects with animations"))
|
||||||
.SetIcon("res/actions/animation24.png");
|
.SetIcon("res/actions/animation24.png");
|
||||||
extension.AddInstructionOrExpressionGroupMetadata(_("Animations and images"))
|
extension.AddInstructionOrExpressionGroupMetadata(_("Animations and images"))
|
||||||
.SetIcon("res/actions/animation24.png");
|
.SetIcon("res/actions/animation24.png");
|
||||||
|
|
||||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
||||||
"AnimatableBehavior",
|
"AnimatableBehavior",
|
||||||
_("Animatable capability"),
|
_("Objects with animations"),
|
||||||
"Animation",
|
"Animation",
|
||||||
_("Animate objects."),
|
_("Actions and conditions for objects having animations (sprite, 3D models...).."),
|
||||||
"",
|
"",
|
||||||
"res/actions/animation24.png",
|
"res/actions/animation24.png",
|
||||||
"AnimatableBehavior",
|
"AnimatableBehavior",
|
||||||
|
@@ -18,8 +18,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsEffectExtension(
|
|||||||
gd::PlatformExtension& extension) {
|
gd::PlatformExtension& extension) {
|
||||||
extension
|
extension
|
||||||
.SetExtensionInformation("EffectCapability",
|
.SetExtensionInformation("EffectCapability",
|
||||||
_("Effect capability"),
|
_("Objects with effects"),
|
||||||
_("Apply visual effects to objects."),
|
_("Actions/conditions to enable/disable and change parameters of visual effects applied on objects."),
|
||||||
"Florian Rival",
|
"Florian Rival",
|
||||||
"Open source (MIT License)")
|
"Open source (MIT License)")
|
||||||
.SetExtensionHelpPath("/objects");
|
.SetExtensionHelpPath("/objects");
|
||||||
@@ -28,9 +28,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsEffectExtension(
|
|||||||
|
|
||||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
||||||
"EffectBehavior",
|
"EffectBehavior",
|
||||||
_("Effect capability"),
|
_("Objects with effects"),
|
||||||
"Effect",
|
"Effect",
|
||||||
_("Apply visual effects to objects."),
|
_("Actions/conditions to enable/disable and change parameters of visual effects applied on objects."),
|
||||||
"",
|
"",
|
||||||
"res/actions/effect_black.svg",
|
"res/actions/effect_black.svg",
|
||||||
"EffectBehavior",
|
"EffectBehavior",
|
||||||
|
@@ -18,8 +18,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFlippableExtension(
|
|||||||
gd::PlatformExtension& extension) {
|
gd::PlatformExtension& extension) {
|
||||||
extension
|
extension
|
||||||
.SetExtensionInformation("FlippableCapability",
|
.SetExtensionInformation("FlippableCapability",
|
||||||
_("Flippable capability"),
|
_("Flippable objects"),
|
||||||
_("Flip objects."),
|
_("Actions/conditions for objects which can be flipped horizontally or vertically."),
|
||||||
"Florian Rival",
|
"Florian Rival",
|
||||||
"Open source (MIT License)")
|
"Open source (MIT License)")
|
||||||
.SetExtensionHelpPath("/objects");
|
.SetExtensionHelpPath("/objects");
|
||||||
@@ -28,9 +28,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFlippableExtension(
|
|||||||
|
|
||||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
||||||
"FlippableBehavior",
|
"FlippableBehavior",
|
||||||
_("Flippable capability"),
|
_("Flippable objects"),
|
||||||
"Flippable",
|
"Flippable",
|
||||||
_("Flip objects."),
|
_("Actions/conditions for objects which can be flipped horizontally or vertically."),
|
||||||
"",
|
"",
|
||||||
"res/actions/flipX24.png",
|
"res/actions/flipX24.png",
|
||||||
"FlippableBehavior",
|
"FlippableBehavior",
|
||||||
|
@@ -18,27 +18,30 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsOpacityExtension(
|
|||||||
gd::PlatformExtension& extension) {
|
gd::PlatformExtension& extension) {
|
||||||
extension
|
extension
|
||||||
.SetExtensionInformation("OpacityCapability",
|
.SetExtensionInformation("OpacityCapability",
|
||||||
_("Opacity capability"),
|
_("Objects with opacity"),
|
||||||
_("Change the object opacity."),
|
_("Action/condition/expression to change or "
|
||||||
|
"check the opacity of an object (0-255)."),
|
||||||
"Florian Rival",
|
"Florian Rival",
|
||||||
"Open source (MIT License)")
|
"Open source (MIT License)")
|
||||||
.SetExtensionHelpPath("/objects");
|
.SetExtensionHelpPath("/objects");
|
||||||
extension.AddInstructionOrExpressionGroupMetadata(_("Opacity capability"))
|
extension.AddInstructionOrExpressionGroupMetadata(_("Objects with opacity"))
|
||||||
.SetIcon("res/actions/opacity24.png");
|
.SetIcon("res/actions/opacity24.png");
|
||||||
extension.AddInstructionOrExpressionGroupMetadata(_("Visibility"))
|
extension.AddInstructionOrExpressionGroupMetadata(_("Visibility"))
|
||||||
.SetIcon("res/actions/opacity24.png");
|
.SetIcon("res/actions/opacity24.png");
|
||||||
|
|
||||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
gd::BehaviorMetadata& aut =
|
||||||
"OpacityBehavior",
|
extension
|
||||||
_("Opacity capability"),
|
.AddBehavior("OpacityBehavior",
|
||||||
"Opacity",
|
_("Objects with opacity"),
|
||||||
_("Change the object opacity."),
|
"Opacity",
|
||||||
"",
|
_("Action/condition/expression to change or check the "
|
||||||
"res/actions/opacity24.png",
|
"opacity of an object (0-255)."),
|
||||||
"OpacityBehavior",
|
"",
|
||||||
std::make_shared<gd::Behavior>(),
|
"res/actions/opacity24.png",
|
||||||
std::make_shared<gd::BehaviorsSharedData>())
|
"OpacityBehavior",
|
||||||
.SetHidden();
|
std::make_shared<gd::Behavior>(),
|
||||||
|
std::make_shared<gd::BehaviorsSharedData>())
|
||||||
|
.SetHidden();
|
||||||
|
|
||||||
aut.AddExpressionAndConditionAndAction(
|
aut.AddExpressionAndConditionAndAction(
|
||||||
"number",
|
"number",
|
||||||
@@ -52,8 +55,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsOpacityExtension(
|
|||||||
.AddParameter("object", _("Object"))
|
.AddParameter("object", _("Object"))
|
||||||
.AddParameter("behavior", _("Behavior"), "OpacityBehavior")
|
.AddParameter("behavior", _("Behavior"), "OpacityBehavior")
|
||||||
.UseStandardParameters(
|
.UseStandardParameters(
|
||||||
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
|
"number",
|
||||||
_("Opacity (0-255)")))
|
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||||
|
_("Opacity (0-255)")))
|
||||||
.SetFunctionName("setOpacity")
|
.SetFunctionName("setOpacity")
|
||||||
.SetGetter("getOpacity");
|
.SetGetter("getOpacity");
|
||||||
aut.GetAllExpressions()["Value"].SetGroup("");
|
aut.GetAllExpressions()["Value"].SetGroup("");
|
||||||
|
@@ -16,11 +16,13 @@ namespace gd {
|
|||||||
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsResizableExtension(
|
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsResizableExtension(
|
||||||
gd::PlatformExtension &extension) {
|
gd::PlatformExtension &extension) {
|
||||||
extension
|
extension
|
||||||
.SetExtensionInformation("ResizableCapability",
|
.SetExtensionInformation(
|
||||||
_("Resizable capability"),
|
"ResizableCapability",
|
||||||
_("Change the object dimensions."),
|
_("Resizable objects"),
|
||||||
"Florian Rival",
|
_("Change or compare the size (width/height) of an object which can "
|
||||||
"Open source (MIT License)")
|
"be resized (i.e: most objects)."),
|
||||||
|
"Florian Rival",
|
||||||
|
"Open source (MIT License)")
|
||||||
.SetExtensionHelpPath("/objects");
|
.SetExtensionHelpPath("/objects");
|
||||||
extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon(
|
extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon(
|
||||||
"res/actions/scale24_black.png");
|
"res/actions/scale24_black.png");
|
||||||
@@ -28,9 +30,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsResizableExtension(
|
|||||||
gd::BehaviorMetadata &aut =
|
gd::BehaviorMetadata &aut =
|
||||||
extension
|
extension
|
||||||
.AddBehavior("ResizableBehavior",
|
.AddBehavior("ResizableBehavior",
|
||||||
_("Resizable capability"),
|
_("Resizable objects"),
|
||||||
"Resizable",
|
"Resizable",
|
||||||
_("Change the object dimensions."),
|
_("Change or compare the size (width/height) of an "
|
||||||
|
"object which can be resized (i.e: most objects)."),
|
||||||
"",
|
"",
|
||||||
"res/actions/scale24_black.png",
|
"res/actions/scale24_black.png",
|
||||||
"ResizableBehavior",
|
"ResizableBehavior",
|
||||||
|
@@ -18,27 +18,30 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsScalableExtension(
|
|||||||
gd::PlatformExtension& extension) {
|
gd::PlatformExtension& extension) {
|
||||||
extension
|
extension
|
||||||
.SetExtensionInformation("ScalableCapability",
|
.SetExtensionInformation("ScalableCapability",
|
||||||
_("Scalable capability"),
|
_("Scalable objects"),
|
||||||
_("Change the object scale."),
|
_("Actions/conditions/expression to change or "
|
||||||
|
"check the scale of an object (default: 1)."),
|
||||||
"Florian Rival",
|
"Florian Rival",
|
||||||
"Open source (MIT License)")
|
"Open source (MIT License)")
|
||||||
.SetExtensionHelpPath("/objects");
|
.SetExtensionHelpPath("/objects");
|
||||||
extension.AddInstructionOrExpressionGroupMetadata(_("Scalable capability"))
|
extension.AddInstructionOrExpressionGroupMetadata(_("Scalable objects"))
|
||||||
.SetIcon("res/actions/scale24_black.png");
|
|
||||||
extension.AddInstructionOrExpressionGroupMetadata(_("Size"))
|
|
||||||
.SetIcon("res/actions/scale24_black.png");
|
.SetIcon("res/actions/scale24_black.png");
|
||||||
|
extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon(
|
||||||
|
"res/actions/scale24_black.png");
|
||||||
|
|
||||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
gd::BehaviorMetadata& aut =
|
||||||
"ScalableBehavior",
|
extension
|
||||||
_("Scalable capability"),
|
.AddBehavior("ScalableBehavior",
|
||||||
"Scale",
|
_("Scalable objects"),
|
||||||
_("Change the object scale."),
|
"Scale",
|
||||||
"",
|
_("Actions/conditions/expression to change or check the "
|
||||||
"res/actions/scale24_black.png",
|
"scale of an object (default: 1)."),
|
||||||
"ResizableBehavior",
|
"",
|
||||||
std::make_shared<gd::Behavior>(),
|
"res/actions/scale24_black.png",
|
||||||
std::make_shared<gd::BehaviorsSharedData>())
|
"ResizableBehavior",
|
||||||
.SetHidden();
|
std::make_shared<gd::Behavior>(),
|
||||||
|
std::make_shared<gd::BehaviorsSharedData>())
|
||||||
|
.SetHidden();
|
||||||
|
|
||||||
aut.AddExpressionAndConditionAndAction(
|
aut.AddExpressionAndConditionAndAction(
|
||||||
"number",
|
"number",
|
||||||
|
@@ -18,17 +18,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTextContainerExtension(
|
|||||||
gd::PlatformExtension& extension) {
|
gd::PlatformExtension& extension) {
|
||||||
extension
|
extension
|
||||||
.SetExtensionInformation("TextContainerCapability",
|
.SetExtensionInformation("TextContainerCapability",
|
||||||
_("Text capability"),
|
_("Objects containing a text"),
|
||||||
_("Allows an object to contain a text, usually shown on screen, that can be modified."),
|
_("Allows an object to contain a text, usually shown on screen, that can be modified."),
|
||||||
"Florian Rival",
|
"Florian Rival",
|
||||||
"Open source (MIT License)")
|
"Open source (MIT License)")
|
||||||
.SetExtensionHelpPath("/objects");
|
.SetExtensionHelpPath("/objects");
|
||||||
extension.AddInstructionOrExpressionGroupMetadata(_("Text capability"))
|
extension.AddInstructionOrExpressionGroupMetadata(_("Objects containing a text"))
|
||||||
.SetIcon("res/conditions/text24_black.png");
|
.SetIcon("res/conditions/text24_black.png");
|
||||||
|
|
||||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
||||||
"TextContainerBehavior",
|
"TextContainerBehavior",
|
||||||
_("Text capability"),
|
_("Objects containing a text"),
|
||||||
"Text",
|
"Text",
|
||||||
_("Allows an object to contain a text, usually shown on screen, that can be modified."),
|
_("Allows an object to contain a text, usually shown on screen, that can be modified."),
|
||||||
"",
|
"",
|
||||||
|
@@ -16,7 +16,9 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
|
|||||||
.SetExtensionInformation(
|
.SetExtensionInformation(
|
||||||
"BuiltinCommonConversions",
|
"BuiltinCommonConversions",
|
||||||
_("Conversion"),
|
_("Conversion"),
|
||||||
"Expressions to convert number, texts and quantities.",
|
"Expressions to convert numbers to string, strings to numbers, "
|
||||||
|
"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");
|
||||||
@@ -41,7 +43,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"),
|
||||||
"",
|
"",
|
||||||
@@ -72,7 +74,8 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
|
|||||||
_("Convert a variable to JSON"),
|
_("Convert a variable to JSON"),
|
||||||
_("JSON"),
|
_("JSON"),
|
||||||
"res/conditions/toujours24_black.png")
|
"res/conditions/toujours24_black.png")
|
||||||
.AddParameter("variable", _("The variable to be stringified"),
|
.AddParameter("variable",
|
||||||
|
_("The variable to be stringified"),
|
||||||
"AllowUndeclaredVariable");
|
"AllowUndeclaredVariable");
|
||||||
|
|
||||||
// Deprecated
|
// Deprecated
|
||||||
|
@@ -42,13 +42,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
|||||||
extension
|
extension
|
||||||
.AddAction(
|
.AddAction(
|
||||||
"LoadFile",
|
"LoadFile",
|
||||||
_("Load a storage in memory"),
|
_("Manually preload a storage in memory"),
|
||||||
_("This action loads the specified storage in memory, so you can "
|
_("Forces the specified storage to be loaded and kept in "
|
||||||
"write and read it.\nYou can open and write without using this "
|
"memory, allowing faster reads/writes. "
|
||||||
"action, but it will be slower.\nIf you use this action, do not "
|
"However, it requires manual management: if you use this "
|
||||||
"forget to unload the storage from memory."),
|
"action, you *must* also unload the storage manually when "
|
||||||
_("Load storage _PARAM0_ in memory"),
|
"it's no longer needed to ensure data is persisted.\n\n"
|
||||||
"",
|
"Unless you have a specific performance need, avoid using this "
|
||||||
|
"action. The system already handles loading/unloading "
|
||||||
|
"automatically."),
|
||||||
|
_("Load data storage _PARAM0_ in memory"),
|
||||||
|
_("Advanced"),
|
||||||
"res/actions/fichier24.png",
|
"res/actions/fichier24.png",
|
||||||
"res/actions/fichier.png")
|
"res/actions/fichier.png")
|
||||||
.AddParameter("string", _("Storage name"))
|
.AddParameter("string", _("Storage name"))
|
||||||
@@ -56,11 +60,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
|||||||
|
|
||||||
extension
|
extension
|
||||||
.AddAction("UnloadFile",
|
.AddAction("UnloadFile",
|
||||||
_("Close a storage"),
|
_("Manually unload and persist a storage"),
|
||||||
_("This action closes the structured data previously loaded "
|
_("Close the specified storage previously loaded "
|
||||||
"in memory, saving all changes made."),
|
"in memory, saving all changes made."),
|
||||||
_("Close structured data _PARAM0_"),
|
_("Unload and persist data storage _PARAM0_"),
|
||||||
"",
|
_("Advanced"),
|
||||||
"res/actions/fichier24.png",
|
"res/actions/fichier24.png",
|
||||||
"res/actions/fichier.png")
|
"res/actions/fichier.png")
|
||||||
.AddParameter("string", _("Storage name"))
|
.AddParameter("string", _("Storage name"))
|
||||||
|
@@ -15,10 +15,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
|
|||||||
.SetExtensionInformation(
|
.SetExtensionInformation(
|
||||||
"BuiltinKeyboard",
|
"BuiltinKeyboard",
|
||||||
_("Keyboard"),
|
_("Keyboard"),
|
||||||
_("Allows your game to respond to keyboard input. Note that this "
|
_("Conditions to check keys pressed on a keyboard. Note that this "
|
||||||
"does not work with on-screen keyboard on touch devices: use "
|
"does not work with on-screen keyboard on touch devices: use "
|
||||||
"instead conditions related to touch when making a game for "
|
"instead mouse/touch conditions when making a game for "
|
||||||
"mobile/touchscreen devices."),
|
"mobile/touchscreen devices or when making a new game from "
|
||||||
|
"scratch."),
|
||||||
"Florian Rival",
|
"Florian Rival",
|
||||||
"Open source (MIT License)")
|
"Open source (MIT License)")
|
||||||
.SetExtensionHelpPath("/all-features/keyboard")
|
.SetExtensionHelpPath("/all-features/keyboard")
|
||||||
@@ -51,10 +52,25 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
|
|||||||
.SetHidden();
|
.SetHidden();
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddCondition("KeyFromTextPressed",
|
.AddCondition(
|
||||||
_("Key pressed"),
|
"KeyFromTextPressed",
|
||||||
_("Check if a key is pressed"),
|
_("Key pressed"),
|
||||||
_("_PARAM1_ key is pressed"),
|
_("Check if a key is pressed. This stays true as long as "
|
||||||
|
"the key is held down. To check if a key was pressed during "
|
||||||
|
"the frame, use \"Key just pressed\" instead."),
|
||||||
|
_("_PARAM1_ key is pressed"),
|
||||||
|
"",
|
||||||
|
"res/conditions/keyboard24.png",
|
||||||
|
"res/conditions/keyboard.png")
|
||||||
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
|
.AddParameter("keyboardKey", _("Key to check"))
|
||||||
|
.MarkAsSimple();
|
||||||
|
|
||||||
|
extension
|
||||||
|
.AddCondition("KeyFromTextJustPressed",
|
||||||
|
_("Key just pressed"),
|
||||||
|
_("Check if a key was just pressed."),
|
||||||
|
_("_PARAM1_ key was just pressed"),
|
||||||
"",
|
"",
|
||||||
"res/conditions/keyboard24.png",
|
"res/conditions/keyboard24.png",
|
||||||
"res/conditions/keyboard.png")
|
"res/conditions/keyboard.png")
|
||||||
@@ -65,7 +81,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
|
|||||||
extension
|
extension
|
||||||
.AddCondition("KeyFromTextReleased",
|
.AddCondition("KeyFromTextReleased",
|
||||||
_("Key released"),
|
_("Key released"),
|
||||||
_("Check if a key was just released"),
|
_("Check if a key was just released."),
|
||||||
_("_PARAM1_ key is released"),
|
_("_PARAM1_ key is released"),
|
||||||
"",
|
"",
|
||||||
"res/conditions/keyboard24.png",
|
"res/conditions/keyboard24.png",
|
||||||
@@ -84,7 +100,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"),
|
||||||
|
@@ -72,7 +72,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("normalize",
|
.AddExpression("normalize",
|
||||||
_("Normalize a value between `min` and `max` to a value between 0 and 1."),
|
_("Normalize a value between `min` and `max` to a value "
|
||||||
|
"between 0 and 1."),
|
||||||
_("Remap a value between 0 and 1."),
|
_("Remap a value between 0 and 1."),
|
||||||
"",
|
"",
|
||||||
"res/mathfunction.png")
|
"res/mathfunction.png")
|
||||||
@@ -124,7 +125,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
extension
|
extension
|
||||||
.AddExpression("mod",
|
.AddExpression("mod",
|
||||||
_("Modulo"),
|
_("Modulo"),
|
||||||
_("x mod y"),
|
_("Compute \"x mod y\". GDevelop does NOT support the \% "
|
||||||
|
"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)"))
|
||||||
@@ -184,11 +186,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("asinh",
|
.AddExpression(
|
||||||
_("Arcsine"),
|
"asinh", _("Arcsine"), _("Arcsine"), "", "res/mathfunction.png")
|
||||||
_("Arcsine"),
|
|
||||||
"",
|
|
||||||
"res/mathfunction.png")
|
|
||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
@@ -218,11 +217,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("cbrt",
|
.AddExpression(
|
||||||
_("Cube root"),
|
"cbrt", _("Cube root"), _("Cube root"), "", "res/mathfunction.png")
|
||||||
_("Cube root"),
|
|
||||||
"",
|
|
||||||
"res/mathfunction.png")
|
|
||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
@@ -260,12 +256,13 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
.AddParameter("expression", _("Expression"), "", true);
|
.AddParameter("expression", _("Expression"), "", true);
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("cos",
|
.AddExpression(
|
||||||
_("Cosine"),
|
"cos",
|
||||||
_("Cosine of an angle (in radian). "
|
_("Cosine"),
|
||||||
"If you want to use degrees, use`ToRad`: `sin(ToRad(45))`."),
|
_("Cosine of an angle (in radian). "
|
||||||
"",
|
"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
|
||||||
@@ -293,29 +290,20 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("int",
|
.AddExpression(
|
||||||
_("Round"),
|
"int", _("Round"), _("Round a number"), "", "res/mathfunction.png")
|
||||||
_("Round a number"),
|
|
||||||
"",
|
|
||||||
"res/mathfunction.png")
|
|
||||||
.SetHidden()
|
.SetHidden()
|
||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("rint",
|
.AddExpression(
|
||||||
_("Round"),
|
"rint", _("Round"), _("Round a number"), "", "res/mathfunction.png")
|
||||||
_("Round a number"),
|
|
||||||
"",
|
|
||||||
"res/mathfunction.png")
|
|
||||||
.SetHidden()
|
.SetHidden()
|
||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("round",
|
.AddExpression(
|
||||||
_("Round"),
|
"round", _("Round"), _("Round a number"), "", "res/mathfunction.png")
|
||||||
_("Round a number"),
|
|
||||||
"",
|
|
||||||
"res/mathfunction.png")
|
|
||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
@@ -324,8 +312,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", _("Expression"))
|
.AddParameter("expression", _("Number to Round"))
|
||||||
.AddParameter("expression", _("Expression"), "", true);
|
.AddParameter("expression", _("Decimal Places"), "", true);
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("exp",
|
.AddExpression("exp",
|
||||||
@@ -336,19 +324,13 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("log",
|
.AddExpression(
|
||||||
_("Logarithm"),
|
"log", _("Logarithm"), _("Logarithm"), "", "res/mathfunction.png")
|
||||||
_("Logarithm"),
|
|
||||||
"",
|
|
||||||
"res/mathfunction.png")
|
|
||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("ln",
|
.AddExpression(
|
||||||
_("Logarithm"),
|
"ln", _("Logarithm"), _("Logarithm"), "", "res/mathfunction.png")
|
||||||
_("Logarithm"),
|
|
||||||
"",
|
|
||||||
"res/mathfunction.png")
|
|
||||||
.SetHidden()
|
.SetHidden()
|
||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
@@ -387,11 +369,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
.AddParameter("expression", _("The exponent (n in x^n)"));
|
.AddParameter("expression", _("The exponent (n in x^n)"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("sec",
|
.AddExpression(
|
||||||
_("Secant"),
|
"sec", _("Secant"), _("Secant"), "", "res/mathfunction.png")
|
||||||
_("Secant"),
|
|
||||||
"",
|
|
||||||
"res/mathfunction.png")
|
|
||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
@@ -403,12 +382,13 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("sin",
|
.AddExpression(
|
||||||
_("Sine"),
|
"sin",
|
||||||
_("Sine of an angle (in radian). "
|
_("Sine"),
|
||||||
"If you want to use degrees, use`ToRad`: `sin(ToRad(45))`."),
|
_("Sine of an angle (in radian). "
|
||||||
"",
|
"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
|
||||||
@@ -428,12 +408,13 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
.AddParameter("expression", _("Expression"));
|
.AddParameter("expression", _("Expression"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("tan",
|
.AddExpression(
|
||||||
_("Tangent"),
|
"tan",
|
||||||
_("Tangent of an angle (in radian). "
|
_("Tangent"),
|
||||||
"If you want to use degrees, use`ToRad`: `tan(ToRad(45))`."),
|
_("Tangent of an angle (in radian). "
|
||||||
"",
|
"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
|
||||||
@@ -463,26 +444,28 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
.AddParameter("expression", _("x (in a+(b-a)*x)"));
|
.AddParameter("expression", _("x (in a+(b-a)*x)"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("XFromAngleAndDistance",
|
.AddExpression(
|
||||||
_("X position from angle and distance"),
|
"XFromAngleAndDistance",
|
||||||
_("Compute the X position when given an angle and distance "
|
_("X position from angle and distance"),
|
||||||
"relative to the origin (0;0). This is also known as "
|
_("Compute the X position when given an angle and distance "
|
||||||
"getting the cartesian coordinates of a 2D vector, using "
|
"relative to the origin (0;0). This is also known as "
|
||||||
"its polar coordinates."),
|
"getting the cartesian coordinates of a 2D vector, using "
|
||||||
"",
|
"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("YFromAngleAndDistance",
|
.AddExpression(
|
||||||
_("Y position from angle and distance"),
|
"YFromAngleAndDistance",
|
||||||
_("Compute the Y position when given an angle and distance "
|
_("Y position from angle and distance"),
|
||||||
"relative to the origin (0;0). This is also known as "
|
_("Compute the Y position when given an angle and distance "
|
||||||
"getting the cartesian coordinates of a 2D vector, using "
|
"relative to the origin (0;0). This is also known as "
|
||||||
"its polar coordinates."),
|
"getting the cartesian coordinates of a 2D vector, using "
|
||||||
"",
|
"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"));
|
||||||
|
|
||||||
@@ -497,7 +480,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
|||||||
extension
|
extension
|
||||||
.AddExpression("lerpAngle",
|
.AddExpression("lerpAngle",
|
||||||
_("Lerp (Linear interpolation) between two angles"),
|
_("Lerp (Linear interpolation) between two angles"),
|
||||||
_("Linearly interpolates between two angles (in degrees) by taking the shortest direction around the circle."),
|
_("Linearly interpolates between two angles (in degrees) "
|
||||||
|
"by taking the shortest direction around the circle."),
|
||||||
"",
|
"",
|
||||||
"res/mathfunction.png")
|
"res/mathfunction.png")
|
||||||
.AddParameter("expression", _("Starting angle, in degrees"))
|
.AddParameter("expression", _("Starting angle, in degrees"))
|
||||||
|
@@ -16,8 +16,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
|
|||||||
.SetExtensionInformation(
|
.SetExtensionInformation(
|
||||||
"BuiltinMouse",
|
"BuiltinMouse",
|
||||||
_("Mouse and touch"),
|
_("Mouse and touch"),
|
||||||
"Conditions and actions to handle either the mouse or touches on "
|
"Conditions, actions and expressions to handle either the mouse or "
|
||||||
"touchscreen. By default, conditions related to the mouse will also "
|
"touches on a touchscreen. Notably: cursor position, mouse wheel, "
|
||||||
|
"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.",
|
||||||
@@ -273,28 +276,26 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
|
|||||||
.SetHidden();
|
.SetHidden();
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddCondition(
|
.AddCondition("MouseButtonFromTextPressed",
|
||||||
"MouseButtonFromTextPressed",
|
_("Mouse button pressed or touch held"),
|
||||||
_("Mouse button pressed or touch held"),
|
_("Check if the specified mouse button is pressed or "
|
||||||
_("Check if the specified mouse button is pressed or "
|
"if a touch is in contact with the screen."),
|
||||||
"if a touch is in contact with the screen."),
|
_("Touch or _PARAM1_ mouse button is down"),
|
||||||
_("Touch or _PARAM1_ mouse button is down"),
|
"",
|
||||||
"",
|
"res/conditions/mouse24.png",
|
||||||
"res/conditions/mouse24.png",
|
"res/conditions/mouse.png")
|
||||||
"res/conditions/mouse.png")
|
|
||||||
.AddCodeOnlyParameter("currentScene", "")
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
.AddParameter("mouseButton", _("Button to check"))
|
.AddParameter("mouseButton", _("Button to check"))
|
||||||
.MarkAsSimple();
|
.MarkAsSimple();
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddCondition(
|
.AddCondition("MouseButtonFromTextReleased",
|
||||||
"MouseButtonFromTextReleased",
|
_("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"),
|
||||||
_("Touch or _PARAM1_ mouse button is released"),
|
"",
|
||||||
"",
|
"res/conditions/mouse24.png",
|
||||||
"res/conditions/mouse24.png",
|
"res/conditions/mouse.png")
|
||||||
"res/conditions/mouse.png")
|
|
||||||
.AddCodeOnlyParameter("currentScene", "")
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
.AddParameter("mouseButton", _("Button to check"))
|
.AddParameter("mouseButton", _("Button to check"))
|
||||||
.MarkAsSimple();
|
.MarkAsSimple();
|
||||||
|
@@ -15,8 +15,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
|
|||||||
.SetExtensionInformation(
|
.SetExtensionInformation(
|
||||||
"BuiltinNetwork",
|
"BuiltinNetwork",
|
||||||
_("Network"),
|
_("Network"),
|
||||||
_("Features to send web requests, communicate with external \"APIs\" "
|
_("Actions to send web requests, communicate with external \"APIs\" "
|
||||||
"and other network related tasks."),
|
"and other network related tasks. Also contains an action to open "
|
||||||
|
"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")
|
||||||
|
@@ -4,8 +4,8 @@
|
|||||||
* reserved. This project is released under the MIT License.
|
* reserved. This project is released under the MIT License.
|
||||||
*/
|
*/
|
||||||
#include "AllBuiltinExtensions.h"
|
#include "AllBuiltinExtensions.h"
|
||||||
#include "GDCore/Tools/Localization.h"
|
|
||||||
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
|
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
|
||||||
|
#include "GDCore/Tools/Localization.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
namespace gd {
|
namespace gd {
|
||||||
@@ -16,7 +16,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
|
|||||||
.SetExtensionInformation(
|
.SetExtensionInformation(
|
||||||
"BuiltinScene",
|
"BuiltinScene",
|
||||||
_("Scene"),
|
_("Scene"),
|
||||||
_("Actions and conditions to manipulate the scenes during the game."),
|
_("Actions/conditions to change the current scene (or pause it and "
|
||||||
|
"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 */);
|
||||||
@@ -166,25 +170,28 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
|
|||||||
.AddCodeOnlyParameter("currentScene", "");
|
.AddCodeOnlyParameter("currentScene", "");
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddAction("PrioritizeLoadingOfScene",
|
.AddAction(
|
||||||
_("Preload scene"),
|
"PrioritizeLoadingOfScene",
|
||||||
_("Preload a scene resources as soon as possible in background."),
|
_("Preload scene"),
|
||||||
_("Preload scene _PARAM1_ in background"),
|
_("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")
|
"res/actions/hourglass_black.svg",
|
||||||
|
"res/actions/hourglass_black.svg")
|
||||||
.SetHelpPath("/all-features/resources-loading")
|
.SetHelpPath("/all-features/resources-loading")
|
||||||
.AddCodeOnlyParameter("currentScene", "")
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
.AddParameter("sceneName", _("Name of the new scene"))
|
.AddParameter("sceneName", _("Name of the new scene"))
|
||||||
.MarkAsAdvanced();
|
.MarkAsAdvanced();
|
||||||
|
|
||||||
extension.AddExpressionAndCondition("number",
|
extension
|
||||||
"SceneLoadingProgress",
|
.AddExpressionAndCondition("number",
|
||||||
_("Scene loading progress"),
|
"SceneLoadingProgress",
|
||||||
_("The progress of resources loading in background for a scene (between 0 and 1)."),
|
_("Scene loading progress"),
|
||||||
_("_PARAM1_ loading progress"),
|
_("The progress of resources loading in "
|
||||||
_(""),
|
"background for a scene (between 0 and 1)."),
|
||||||
"res/actions/hourglass_black.svg")
|
_("_PARAM1_ loading progress"),
|
||||||
|
_(""),
|
||||||
|
"res/actions/hourglass_black.svg")
|
||||||
.SetHelpPath("/all-features/resources-loading")
|
.SetHelpPath("/all-features/resources-loading")
|
||||||
.AddCodeOnlyParameter("currentScene", "")
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
.AddParameter("sceneName", _("Scene name"))
|
.AddParameter("sceneName", _("Scene name"))
|
||||||
@@ -192,13 +199,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
|
|||||||
.MarkAsAdvanced();
|
.MarkAsAdvanced();
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddCondition("AreSceneAssetsLoaded",
|
.AddCondition(
|
||||||
_("Scene preloaded"),
|
"AreSceneAssetsLoaded",
|
||||||
_("Check if scene resources have finished to load in background."),
|
_("Scene preloaded"),
|
||||||
_("Scene _PARAM1_ was preloaded in background"),
|
_("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")
|
"res/actions/hourglass_black.svg",
|
||||||
|
"res/actions/hourglass_black.svg")
|
||||||
.SetHelpPath("/all-features/resources-loading")
|
.SetHelpPath("/all-features/resources-loading")
|
||||||
.AddCodeOnlyParameter("currentScene", "")
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
.AddParameter("sceneName", _("Scene name"))
|
.AddParameter("sceneName", _("Scene name"))
|
||||||
|
@@ -15,12 +15,13 @@ namespace gd {
|
|||||||
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||||
gd::PlatformExtension& extension) {
|
gd::PlatformExtension& extension) {
|
||||||
extension
|
extension
|
||||||
.SetExtensionInformation("Sprite",
|
.SetExtensionInformation(
|
||||||
_("Sprite"),
|
"Sprite",
|
||||||
_("Sprite are animated object which can be used "
|
_("Sprite"),
|
||||||
"for most elements of a game."),
|
_("Sprite are animated objects which can be used "
|
||||||
"Florian Rival",
|
"for most elements of a 2D game."),
|
||||||
"Open source (MIT License)")
|
"Florian Rival",
|
||||||
|
"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");
|
||||||
@@ -30,7 +31,7 @@ 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 game."),
|
"most elements of a 2D game."),
|
||||||
"CppPlatform/Extensions/spriteicon.png")
|
"CppPlatform/Extensions/spriteicon.png")
|
||||||
.SetCategoryFullName(_("General"))
|
.SetCategoryFullName(_("General"))
|
||||||
.SetOpenFullEditorLabel(_("Edit animations"))
|
.SetOpenFullEditorLabel(_("Edit animations"))
|
||||||
@@ -645,11 +646,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
|||||||
"res/actions/sprite.png")
|
"res/actions/sprite.png")
|
||||||
.AddParameter("object", _("Object"), "Sprite");
|
.AddParameter("object", _("Object"), "Sprite");
|
||||||
|
|
||||||
obj.AddExpression("AnimationFrameCount",
|
obj.AddExpression(
|
||||||
_("Number of frames"),
|
"AnimationFrameCount",
|
||||||
_("Number of frames in the current animation of the object"),
|
_("Number of frames"),
|
||||||
_("Animations and images"),
|
_("Number of frames in the current animation of the object"),
|
||||||
"res/actions/sprite.png")
|
_("Animations and images"),
|
||||||
|
"res/actions/sprite.png")
|
||||||
.AddParameter("object", _("Object"), "Sprite");
|
.AddParameter("object", _("Object"), "Sprite");
|
||||||
|
|
||||||
// Deprecated
|
// Deprecated
|
||||||
|
@@ -16,7 +16,8 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
|
|||||||
.SetExtensionInformation(
|
.SetExtensionInformation(
|
||||||
"BuiltinStringInstructions",
|
"BuiltinStringInstructions",
|
||||||
_("Text manipulation"),
|
_("Text manipulation"),
|
||||||
"Provides expressions to manipulate strings (also called texts).",
|
"Provides expressions to manipulate strings (also called texts): new "
|
||||||
|
"line, upper/lowercase, substring, find, replace, etc...",
|
||||||
"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 */);
|
||||||
@@ -191,7 +192,8 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
|
|||||||
"res/conditions/toujours24_black.png")
|
"res/conditions/toujours24_black.png")
|
||||||
.AddParameter("string", _("Text in which the replacement must be done"))
|
.AddParameter("string", _("Text in which the replacement must be done"))
|
||||||
.AddParameter("string", _("Text to find inside the first text"))
|
.AddParameter("string", _("Text to find inside the first text"))
|
||||||
.AddParameter("string", _("Replacement to put instead of the text to find"));
|
.AddParameter("string",
|
||||||
|
_("Replacement to put instead of the text to find"));
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddStrExpression("StrReplaceAll",
|
.AddStrExpression("StrReplaceAll",
|
||||||
@@ -199,10 +201,11 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
|
|||||||
_("Replace all occurrences of a text by another."),
|
_("Replace all occurrences of a text by another."),
|
||||||
"",
|
"",
|
||||||
"res/conditions/toujours24_black.png")
|
"res/conditions/toujours24_black.png")
|
||||||
.AddParameter("string", _("Text in which the replacement(s) must be done"))
|
.AddParameter("string",
|
||||||
|
_("Text in which the replacement(s) must be done"))
|
||||||
.AddParameter("string", _("Text to find inside the first text"))
|
.AddParameter("string", _("Text to find inside the first text"))
|
||||||
.AddParameter("string", _("Replacement to put instead of the text to find"));
|
.AddParameter("string",
|
||||||
|
_("Replacement to put instead of the text to find"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
|
@@ -15,9 +15,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
|||||||
.SetExtensionInformation(
|
.SetExtensionInformation(
|
||||||
"BuiltinTime",
|
"BuiltinTime",
|
||||||
_("Timers and time"),
|
_("Timers and time"),
|
||||||
"Actions and conditions to run timers, get the current time or "
|
"Actions and conditions to start, pause or reset scene timers, "
|
||||||
"modify the time scale (speed at which the game is running - useful "
|
"modify the time scale (speed at which the game "
|
||||||
"for slow motion effects).",
|
"is running - useful for slow motion effects). Also contains an "
|
||||||
|
"action that wait for a delay before running the next actions and "
|
||||||
|
"sub-events and expressions to read the time scale, time delta of "
|
||||||
|
"the last frame or timer elapsed time.",
|
||||||
"Florian Rival",
|
"Florian Rival",
|
||||||
"Open source (MIT License)")
|
"Open source (MIT License)")
|
||||||
.SetExtensionHelpPath("/all-features/timers-and-time");
|
.SetExtensionHelpPath("/all-features/timers-and-time");
|
||||||
@@ -192,26 +195,28 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
|||||||
extension
|
extension
|
||||||
.AddExpression("TimerElapsedTime",
|
.AddExpression("TimerElapsedTime",
|
||||||
_("Scene timer value"),
|
_("Scene timer value"),
|
||||||
_("Value of a scene timer"),
|
_("Value of a scene timer (in seconds)"),
|
||||||
"",
|
"",
|
||||||
"res/actions/time.png")
|
"res/actions/time.png")
|
||||||
.AddCodeOnlyParameter("currentScene", "")
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
.AddParameter("identifier", _("Timer's name"), "sceneTimer");
|
.AddParameter("identifier", _("Timer's name"), "sceneTimer");
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("TimeFromStart",
|
.AddExpression(
|
||||||
_("Time elapsed since the beginning of the scene"),
|
"TimeFromStart",
|
||||||
_("Time elapsed since the beginning of the scene"),
|
_("Time elapsed since the beginning of the scene (in seconds)."),
|
||||||
"",
|
_("Time elapsed since the beginning of the scene (in seconds)."),
|
||||||
"res/actions/time.png")
|
"",
|
||||||
|
"res/actions/time.png")
|
||||||
.AddCodeOnlyParameter("currentScene", "");
|
.AddCodeOnlyParameter("currentScene", "");
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("TempsDebut",
|
.AddExpression(
|
||||||
_("Time elapsed since the beginning of the scene"),
|
"TempsDebut",
|
||||||
_("Time elapsed since the beginning of the scene"),
|
_("Time elapsed since the beginning of the scene (in seconds)."),
|
||||||
"",
|
_("Time elapsed since the beginning of the scene (in seconds)."),
|
||||||
"res/actions/time.png")
|
"",
|
||||||
|
"res/actions/time.png")
|
||||||
.SetHidden()
|
.SetHidden()
|
||||||
.AddCodeOnlyParameter("currentScene", "");
|
.AddCodeOnlyParameter("currentScene", "");
|
||||||
|
|
||||||
@@ -226,16 +231,21 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
|||||||
extension
|
extension
|
||||||
.AddExpression("Time",
|
.AddExpression("Time",
|
||||||
_("Current time"),
|
_("Current time"),
|
||||||
_("Current time"),
|
_("Gives the current time"),
|
||||||
"",
|
"",
|
||||||
"res/actions/time.png")
|
"res/actions/time.png")
|
||||||
.AddCodeOnlyParameter("currentScene", "")
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
.AddParameter(
|
.AddParameter(
|
||||||
"stringWithSelector",
|
"stringWithSelector",
|
||||||
_("Hour: hour - Minutes: min - Seconds: sec - Day of month: "
|
_("- Hour of the day: \"hour\"\n"
|
||||||
"mday - Months since January: mon - Year since 1900: year - Days "
|
"- Minutes: \"min\"\n"
|
||||||
"since Sunday: wday - Days since Jan 1st: yday - Timestamp (ms): "
|
"- Seconds: \"sec\"\n"
|
||||||
"timestamp\""),
|
"- Day of month: \"mday\"\n"
|
||||||
|
"- Months since January: \"mon\"\n"
|
||||||
|
"- Year since 1900: \"year\"\n"
|
||||||
|
"- Days since Sunday: \"wday\"\n"
|
||||||
|
"- Days since Jan 1st: \"yday\"\n"
|
||||||
|
"- Timestamp (ms): \"timestamp\""),
|
||||||
"[\"hour\", \"min\", \"sec\", \"mon\", \"year\", \"wday\", \"mday\", "
|
"[\"hour\", \"min\", \"sec\", \"mon\", \"year\", \"wday\", \"mday\", "
|
||||||
"\"yday\", \"timestamp\"]");
|
"\"yday\", \"timestamp\"]");
|
||||||
}
|
}
|
||||||
|
@@ -15,16 +15,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
|
|||||||
.SetExtensionInformation(
|
.SetExtensionInformation(
|
||||||
"BuiltinWindow",
|
"BuiltinWindow",
|
||||||
_("Game window and resolution"),
|
_("Game window and resolution"),
|
||||||
"Provides actions and conditions to manipulate the game window. "
|
"Actions and conditions to manipulate the game window or change how "
|
||||||
|
"the game is resized according to the screen size. "
|
||||||
"Depending on the platform on which the game is running, not all of "
|
"Depending on the platform on which the game is running, not all of "
|
||||||
"these features can be applied.",
|
"these features can be applied.\n"
|
||||||
|
"Also contains expressions to read the screen size.",
|
||||||
"Florian Rival",
|
"Florian Rival",
|
||||||
"Open source (MIT License)")
|
"Open source (MIT License)")
|
||||||
.SetCategory("User interface")
|
.SetCategory("User interface")
|
||||||
.SetExtensionHelpPath("/all-features/window");
|
.SetExtensionHelpPath("/all-features/window");
|
||||||
extension
|
extension
|
||||||
.AddInstructionOrExpressionGroupMetadata(
|
.AddInstructionOrExpressionGroupMetadata(_("Game window and resolution"))
|
||||||
_("Game window and resolution"))
|
|
||||||
.SetIcon("res/actions/window24.png");
|
.SetIcon("res/actions/window24.png");
|
||||||
|
|
||||||
extension
|
extension
|
||||||
|
@@ -298,6 +298,19 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the behavior can be used on objects from event-based objects.
|
||||||
|
*/
|
||||||
|
bool IsRelevantForChildObjects() const { return isRelevantForChildObjects; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set that behavior can't be used on objects from event-based objects.
|
||||||
|
*/
|
||||||
|
BehaviorMetadata &MarkAsIrrelevantForChildObjects() {
|
||||||
|
isRelevantForChildObjects = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
QuickCustomization::Visibility GetQuickCustomizationVisibility() const {
|
QuickCustomization::Visibility GetQuickCustomizationVisibility() const {
|
||||||
return quickCustomizationVisibility;
|
return quickCustomizationVisibility;
|
||||||
}
|
}
|
||||||
@@ -393,6 +406,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
|||||||
mutable std::vector<gd::String> requiredBehaviors;
|
mutable std::vector<gd::String> requiredBehaviors;
|
||||||
bool isPrivate = false;
|
bool isPrivate = false;
|
||||||
bool isHidden = false;
|
bool isHidden = false;
|
||||||
|
bool isRelevantForChildObjects = true;
|
||||||
gd::String openFullEditorLabel;
|
gd::String openFullEditorLabel;
|
||||||
QuickCustomization::Visibility quickCustomizationVisibility = QuickCustomization::Visibility::Default;
|
QuickCustomization::Visibility quickCustomizationVisibility = QuickCustomization::Visibility::Default;
|
||||||
|
|
||||||
|
@@ -277,6 +277,10 @@ class GD_CORE_API MetadataProvider {
|
|||||||
return &metadata == &badObjectInfo;
|
return &metadata == &badObjectInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsBadEffectMetadata(const gd::EffectMetadata& metadata) {
|
||||||
|
return &metadata == &badEffectMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~MetadataProvider();
|
virtual ~MetadataProvider();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -194,7 +194,8 @@ void ParameterMetadataTools::IterateOverParameters(
|
|||||||
[&fn](const gd::ParameterMetadata& parameterMetadata,
|
[&fn](const gd::ParameterMetadata& parameterMetadata,
|
||||||
const gd::Expression& parameterValue,
|
const gd::Expression& parameterValue,
|
||||||
size_t parameterIndex,
|
size_t parameterIndex,
|
||||||
const gd::String& lastObjectName) {
|
const gd::String& lastObjectName,
|
||||||
|
size_t lastObjectIndex) {
|
||||||
fn(parameterMetadata, parameterValue, lastObjectName);
|
fn(parameterMetadata, parameterValue, lastObjectName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -205,8 +206,10 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
|
|||||||
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
||||||
const gd::Expression& parameterValue,
|
const gd::Expression& parameterValue,
|
||||||
size_t parameterIndex,
|
size_t parameterIndex,
|
||||||
const gd::String& lastObjectName)> fn) {
|
const gd::String& lastObjectName,
|
||||||
|
size_t lastObjectIndex)> fn) {
|
||||||
gd::String lastObjectName = "";
|
gd::String lastObjectName = "";
|
||||||
|
size_t lastObjectIndex = 0;
|
||||||
for (std::size_t pNb = 0; pNb < parametersMetadata.GetParametersCount();
|
for (std::size_t pNb = 0; pNb < parametersMetadata.GetParametersCount();
|
||||||
++pNb) {
|
++pNb) {
|
||||||
const gd::ParameterMetadata ¶meterMetadata =
|
const gd::ParameterMetadata ¶meterMetadata =
|
||||||
@@ -218,15 +221,17 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
|
|||||||
? Expression(parameterMetadata.GetDefaultValue())
|
? Expression(parameterMetadata.GetDefaultValue())
|
||||||
: parameterValue;
|
: parameterValue;
|
||||||
|
|
||||||
fn(parameterMetadata, parameterValueOrDefault, pNb, lastObjectName);
|
fn(parameterMetadata, parameterValueOrDefault, pNb, lastObjectName, lastObjectIndex);
|
||||||
|
|
||||||
// Memorize the last object name. By convention, parameters that require
|
// Memorize the last object name. By convention, parameters that require
|
||||||
// an object (mainly, "objectvar" and "behavior") should be placed after
|
// an object (mainly, "objectvar" and "behavior") should be placed after
|
||||||
// the object in the list of parameters (if possible, just after).
|
// the object in the list of parameters (if possible, just after).
|
||||||
// Search "lastObjectName" in the codebase for other place where this
|
// Search "lastObjectName" in the codebase for other place where this
|
||||||
// convention is enforced.
|
// convention is enforced.
|
||||||
if (gd::ParameterMetadata::IsObject(parameterMetadata.GetType()))
|
if (gd::ParameterMetadata::IsObject(parameterMetadata.GetType())) {
|
||||||
lastObjectName = parameterValueOrDefault.GetPlainString();
|
lastObjectName = parameterValueOrDefault.GetPlainString();
|
||||||
|
lastObjectIndex = pNb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -64,7 +64,8 @@ class GD_CORE_API ParameterMetadataTools {
|
|||||||
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
||||||
const gd::Expression& parameterValue,
|
const gd::Expression& parameterValue,
|
||||||
size_t parameterIndex,
|
size_t parameterIndex,
|
||||||
const gd::String& lastObjectName)> fn);
|
const gd::String& lastObjectName,
|
||||||
|
size_t lastObjectIndex)> fn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate over the parameters of a FunctionCallNode.
|
* Iterate over the parameters of a FunctionCallNode.
|
||||||
|
@@ -779,6 +779,26 @@ gd::String PlatformExtension::GetBehaviorFullType(
|
|||||||
return extensionName + separator + behaviorName;
|
return extensionName + separator + behaviorName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gd::String PlatformExtension::GetExtensionFromFullBehaviorType(
|
||||||
|
const gd::String& type) {
|
||||||
|
const auto separatorIndex =
|
||||||
|
type.find(PlatformExtension::GetNamespaceSeparator());
|
||||||
|
if (separatorIndex == std::string::npos) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return type.substr(0, separatorIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
gd::String PlatformExtension::GetBehaviorNameFromFullBehaviorType(
|
||||||
|
const gd::String& type) {
|
||||||
|
const auto separatorIndex =
|
||||||
|
type.find(PlatformExtension::GetNamespaceSeparator());
|
||||||
|
if (separatorIndex == std::string::npos) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return type.substr(separatorIndex + 2);
|
||||||
|
}
|
||||||
|
|
||||||
gd::String PlatformExtension::GetObjectEventsFunctionFullType(
|
gd::String PlatformExtension::GetObjectEventsFunctionFullType(
|
||||||
const gd::String& extensionName,
|
const gd::String& extensionName,
|
||||||
const gd::String& objectName,
|
const gd::String& objectName,
|
||||||
|
@@ -651,6 +651,10 @@ class GD_CORE_API PlatformExtension {
|
|||||||
static gd::String GetBehaviorFullType(const gd::String& extensionName,
|
static gd::String GetBehaviorFullType(const gd::String& extensionName,
|
||||||
const gd::String& behaviorName);
|
const gd::String& behaviorName);
|
||||||
|
|
||||||
|
static gd::String GetExtensionFromFullBehaviorType(const gd::String& type);
|
||||||
|
|
||||||
|
static gd::String GetBehaviorNameFromFullBehaviorType(const gd::String& type);
|
||||||
|
|
||||||
static gd::String GetObjectEventsFunctionFullType(
|
static gd::String GetObjectEventsFunctionFullType(
|
||||||
const gd::String& extensionName,
|
const gd::String& extensionName,
|
||||||
const gd::String& objectName,
|
const gd::String& objectName,
|
||||||
|
@@ -29,7 +29,7 @@ bool BehaviorParametersFiller::DoVisitInstruction(gd::Instruction &instruction,
|
|||||||
instruction.GetParameters(), metadata.GetParameters(),
|
instruction.GetParameters(), metadata.GetParameters(),
|
||||||
[&](const gd::ParameterMetadata ¶meterMetadata,
|
[&](const gd::ParameterMetadata ¶meterMetadata,
|
||||||
const gd::Expression ¶meterValue, size_t parameterIndex,
|
const gd::Expression ¶meterValue, size_t parameterIndex,
|
||||||
const gd::String &lastObjectName) {
|
const gd::String &lastObjectName, size_t lastObjectIndex) {
|
||||||
if (parameterMetadata.GetValueTypeMetadata().IsBehavior() &&
|
if (parameterMetadata.GetValueTypeMetadata().IsBehavior() &&
|
||||||
parameterValue.GetPlainString().length() == 0) {
|
parameterValue.GetPlainString().length() == 0) {
|
||||||
|
|
||||||
|
@@ -108,12 +108,10 @@ bool EventsBehaviorRenamer::DoVisitInstruction(gd::Instruction& instruction,
|
|||||||
platform, instruction.GetType());
|
platform, instruction.GetType());
|
||||||
|
|
||||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||||
instruction.GetParameters(),
|
instruction.GetParameters(), metadata.GetParameters(),
|
||||||
metadata.GetParameters(),
|
[&](const gd::ParameterMetadata ¶meterMetadata,
|
||||||
[&](const gd::ParameterMetadata& parameterMetadata,
|
const gd::Expression ¶meterValue, size_t parameterIndex,
|
||||||
const gd::Expression& parameterValue,
|
const gd::String &lastObjectName, size_t lastObjectIndex) {
|
||||||
size_t parameterIndex,
|
|
||||||
const gd::String& lastObjectName) {
|
|
||||||
const gd::String& type = parameterMetadata.GetType();
|
const gd::String& type = parameterMetadata.GetType();
|
||||||
|
|
||||||
if (gd::ParameterMetadata::IsBehavior(type)) {
|
if (gd::ParameterMetadata::IsBehavior(type)) {
|
||||||
|
@@ -183,12 +183,10 @@ bool EventsParameterReplacer::DoVisitInstruction(gd::Instruction& instruction,
|
|||||||
platform, instruction.GetType());
|
platform, instruction.GetType());
|
||||||
|
|
||||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||||
instruction.GetParameters(),
|
instruction.GetParameters(), metadata.GetParameters(),
|
||||||
metadata.GetParameters(),
|
[&](const gd::ParameterMetadata ¶meterMetadata,
|
||||||
[&](const gd::ParameterMetadata& parameterMetadata,
|
const gd::Expression ¶meterValue, size_t parameterIndex,
|
||||||
const gd::Expression& parameterValue,
|
const gd::String &lastObjectName, size_t lastObjectIndex) {
|
||||||
size_t parameterIndex,
|
|
||||||
const gd::String& lastObjectName) {
|
|
||||||
if (!gd::EventsParameterReplacer::CanContainParameter(
|
if (!gd::EventsParameterReplacer::CanContainParameter(
|
||||||
parameterMetadata.GetValueTypeMetadata())) {
|
parameterMetadata.GetValueTypeMetadata())) {
|
||||||
return;
|
return;
|
||||||
|
@@ -217,12 +217,10 @@ bool EventsPropertyReplacer::DoVisitInstruction(gd::Instruction& instruction,
|
|||||||
bool shouldDeleteInstruction = false;
|
bool shouldDeleteInstruction = false;
|
||||||
|
|
||||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||||
instruction.GetParameters(),
|
instruction.GetParameters(), metadata.GetParameters(),
|
||||||
metadata.GetParameters(),
|
[&](const gd::ParameterMetadata ¶meterMetadata,
|
||||||
[&](const gd::ParameterMetadata& parameterMetadata,
|
const gd::Expression ¶meterValue, size_t parameterIndex,
|
||||||
const gd::Expression& parameterValue,
|
const gd::String &lastObjectName, size_t lastObjectIndex) {
|
||||||
size_t parameterIndex,
|
|
||||||
const gd::String& lastObjectName) {
|
|
||||||
if (!gd::EventsPropertyReplacer::CanContainProperty(
|
if (!gd::EventsPropertyReplacer::CanContainProperty(
|
||||||
parameterMetadata.GetValueTypeMetadata())) {
|
parameterMetadata.GetValueTypeMetadata())) {
|
||||||
return;
|
return;
|
||||||
|
@@ -334,7 +334,7 @@ private:
|
|||||||
instruction.GetParameters(), metadata.GetParameters(),
|
instruction.GetParameters(), metadata.GetParameters(),
|
||||||
[&](const gd::ParameterMetadata ¶meterMetadata,
|
[&](const gd::ParameterMetadata ¶meterMetadata,
|
||||||
const gd::Expression ¶meterValue, size_t parameterIndex,
|
const gd::Expression ¶meterValue, size_t parameterIndex,
|
||||||
const gd::String &lastObjectName) {
|
const gd::String &lastObjectName, size_t lastObjectIndex) {
|
||||||
if (!gd::EventsObjectReplacer::CanContainObject(
|
if (!gd::EventsObjectReplacer::CanContainObject(
|
||||||
parameterMetadata.GetValueTypeMetadata())) {
|
parameterMetadata.GetValueTypeMetadata())) {
|
||||||
return;
|
return;
|
||||||
|
@@ -42,18 +42,16 @@ bool EventsVariableInstructionTypeSwitcher::DoVisitInstruction(gd::Instruction&
|
|||||||
platform, instruction.GetType());
|
platform, instruction.GetType());
|
||||||
|
|
||||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||||
instruction.GetParameters(),
|
instruction.GetParameters(), metadata.GetParameters(),
|
||||||
metadata.GetParameters(),
|
[&](const gd::ParameterMetadata ¶meterMetadata,
|
||||||
[&](const gd::ParameterMetadata& parameterMetadata,
|
const gd::Expression ¶meterValue, size_t parameterIndex,
|
||||||
const gd::Expression& parameterValue,
|
const gd::String &lastObjectName, size_t lastObjectIndex) {
|
||||||
size_t parameterIndex,
|
|
||||||
const gd::String& lastObjectName) {
|
|
||||||
const gd::String& type = parameterMetadata.GetType();
|
const gd::String& type = parameterMetadata.GetType();
|
||||||
|
|
||||||
if (!gd::ParameterMetadata::IsExpression("variable", type) ||
|
if (!gd::ParameterMetadata::IsExpression("variable", type) ||
|
||||||
!gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction(
|
!gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction(
|
||||||
instruction.GetType())) {
|
instruction.GetType())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto variableName =
|
const auto variableName =
|
||||||
gd::ExpressionVariableNameFinder::GetVariableName(
|
gd::ExpressionVariableNameFinder::GetVariableName(
|
||||||
@@ -72,10 +70,11 @@ bool EventsVariableInstructionTypeSwitcher::DoVisitInstruction(gd::Instruction&
|
|||||||
.GetObjectOrGroupVariablesContainer(lastObjectName);
|
.GetObjectOrGroupVariablesContainer(lastObjectName);
|
||||||
}
|
}
|
||||||
} else if (type == "variableOrProperty") {
|
} else if (type == "variableOrProperty") {
|
||||||
variablesContainer =
|
variablesContainer =
|
||||||
&GetProjectScopedContainers()
|
&GetProjectScopedContainers()
|
||||||
.GetVariablesContainersList()
|
.GetVariablesContainersList()
|
||||||
.GetVariablesContainerFromVariableOrPropertyName(variableName);
|
.GetVariablesContainerFromVariableOrPropertyName(
|
||||||
|
variableName);
|
||||||
} else {
|
} else {
|
||||||
if (GetProjectScopedContainers().GetVariablesContainersList().Has(
|
if (GetProjectScopedContainers().GetVariablesContainersList().Has(
|
||||||
variableName)) {
|
variableName)) {
|
||||||
|
@@ -448,12 +448,10 @@ bool EventsVariableReplacer::DoVisitInstruction(gd::Instruction& instruction,
|
|||||||
bool shouldDeleteInstruction = false;
|
bool shouldDeleteInstruction = false;
|
||||||
|
|
||||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||||
instruction.GetParameters(),
|
instruction.GetParameters(), metadata.GetParameters(),
|
||||||
metadata.GetParameters(),
|
[&](const gd::ParameterMetadata ¶meterMetadata,
|
||||||
[&](const gd::ParameterMetadata& parameterMetadata,
|
const gd::Expression ¶meterValue, size_t parameterIndex,
|
||||||
const gd::Expression& parameterValue,
|
const gd::String &lastObjectName, size_t lastObjectIndex) {
|
||||||
size_t parameterIndex,
|
|
||||||
const gd::String& lastObjectName) {
|
|
||||||
const gd::String& type = parameterMetadata.GetType();
|
const gd::String& type = parameterMetadata.GetType();
|
||||||
|
|
||||||
if (!gd::ParameterMetadata::IsExpression("variable", type) &&
|
if (!gd::ParameterMetadata::IsExpression("variable", type) &&
|
||||||
|
@@ -150,7 +150,7 @@ bool ProjectElementRenamer::DoVisitInstruction(gd::Instruction &instruction,
|
|||||||
instruction.GetParameters(), metadata.GetParameters(),
|
instruction.GetParameters(), metadata.GetParameters(),
|
||||||
[&](const gd::ParameterMetadata ¶meterMetadata,
|
[&](const gd::ParameterMetadata ¶meterMetadata,
|
||||||
const gd::Expression ¶meterValue, size_t parameterIndex,
|
const gd::Expression ¶meterValue, size_t parameterIndex,
|
||||||
const gd::String &lastObjectName) {
|
const gd::String &lastObjectName, size_t lastObjectIndex) {
|
||||||
if (parameterMetadata.GetType() == "layer") {
|
if (parameterMetadata.GetType() == "layer") {
|
||||||
if (parameterValue.GetPlainString().length() < 2) {
|
if (parameterValue.GetPlainString().length() < 2) {
|
||||||
// This is either the base layer or an invalid layer name.
|
// This is either the base layer or an invalid layer name.
|
||||||
|
@@ -63,7 +63,6 @@ void EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy missing behaviors
|
// Copy missing behaviors
|
||||||
auto &behaviors = object.GetAllBehaviorContents();
|
|
||||||
for (const auto &pair : defaultBehaviors) {
|
for (const auto &pair : defaultBehaviors) {
|
||||||
const auto &behaviorName = pair.first;
|
const auto &behaviorName = pair.first;
|
||||||
const auto &defaultBehavior = pair.second;
|
const auto &defaultBehavior = pair.second;
|
||||||
@@ -82,11 +81,9 @@ void EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete extra behaviors
|
// Delete extra behaviors
|
||||||
for (auto it = behaviors.begin(); it != behaviors.end(); ++it) {
|
for (auto &behaviorName : object.GetAllBehaviorNames()) {
|
||||||
const auto &behaviorName = it->first;
|
|
||||||
if (!defaultObject->HasBehaviorNamed(behaviorName)) {
|
if (!defaultObject->HasBehaviorNamed(behaviorName)) {
|
||||||
object.RemoveBehavior(behaviorName);
|
object.RemoveBehavior(behaviorName);
|
||||||
--it;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include "GDCore/Project/Behavior.h"
|
#include "GDCore/Project/Behavior.h"
|
||||||
#include "GDCore/Project/CustomBehavior.h"
|
#include "GDCore/Project/CustomBehavior.h"
|
||||||
#include "GDCore/Project/CustomObjectConfiguration.h"
|
#include "GDCore/Project/CustomObjectConfiguration.h"
|
||||||
|
#include "GDCore/Project/EventsBasedObjectVariant.h"
|
||||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||||
#include "GDCore/Project/Layout.h"
|
#include "GDCore/Project/Layout.h"
|
||||||
#include "GDCore/Project/Object.h"
|
#include "GDCore/Project/Object.h"
|
||||||
@@ -61,9 +62,6 @@ void ObjectAssetSerializer::SerializeTo(
|
|||||||
element.SetAttribute("version", "");
|
element.SetAttribute("version", "");
|
||||||
element.SetIntAttribute("animationsCount", 1);
|
element.SetIntAttribute("animationsCount", 1);
|
||||||
element.SetIntAttribute("maxFramesCount", 1);
|
element.SetIntAttribute("maxFramesCount", 1);
|
||||||
// TODO Find the right object dimensions.
|
|
||||||
element.SetIntAttribute("width", 0);
|
|
||||||
element.SetIntAttribute("height", 0);
|
|
||||||
SerializerElement &authorsElement = element.AddChild("authors");
|
SerializerElement &authorsElement = element.AddChild("authors");
|
||||||
authorsElement.ConsiderAsArrayOf("author");
|
authorsElement.ConsiderAsArrayOf("author");
|
||||||
SerializerElement &tagsElement = element.AddChild("tags");
|
SerializerElement &tagsElement = element.AddChild("tags");
|
||||||
@@ -76,16 +74,28 @@ void ObjectAssetSerializer::SerializeTo(
|
|||||||
|
|
||||||
cleanObject->SerializeTo(objectAssetElement.AddChild("object"));
|
cleanObject->SerializeTo(objectAssetElement.AddChild("object"));
|
||||||
|
|
||||||
|
double width = 0;
|
||||||
|
double height = 0;
|
||||||
|
std::unordered_set<gd::String> alreadyUsedVariantIdentifiers;
|
||||||
if (project.HasEventsBasedObject(object.GetType())) {
|
if (project.HasEventsBasedObject(object.GetType())) {
|
||||||
SerializerElement &variantsElement =
|
SerializerElement &variantsElement =
|
||||||
objectAssetElement.AddChild("variants");
|
objectAssetElement.AddChild("variants");
|
||||||
variantsElement.ConsiderAsArrayOf("variant");
|
variantsElement.ConsiderAsArrayOf("variant");
|
||||||
|
|
||||||
std::unordered_set<gd::String> alreadyUsedVariantIdentifiers;
|
const auto *variant = ObjectAssetSerializer::GetVariant(project, object);
|
||||||
|
if (variant) {
|
||||||
|
width = variant->GetAreaMaxX() - variant->GetAreaMinX();
|
||||||
|
height = variant->GetAreaMaxY() - variant->GetAreaMinY();
|
||||||
|
}
|
||||||
|
|
||||||
gd::ObjectAssetSerializer::SerializeUsedVariantsTo(
|
gd::ObjectAssetSerializer::SerializeUsedVariantsTo(
|
||||||
project, object, variantsElement, alreadyUsedVariantIdentifiers);
|
project, object, variantsElement, alreadyUsedVariantIdentifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Find the right object dimensions when their is no variant.
|
||||||
|
element.SetIntAttribute("width", width);
|
||||||
|
element.SetIntAttribute("height", height);
|
||||||
|
|
||||||
SerializerElement &resourcesElement =
|
SerializerElement &resourcesElement =
|
||||||
objectAssetElement.AddChild("resources");
|
objectAssetElement.AddChild("resources");
|
||||||
resourcesElement.ConsiderAsArrayOf("resource");
|
resourcesElement.ConsiderAsArrayOf("resource");
|
||||||
@@ -104,14 +114,24 @@ void ObjectAssetSerializer::SerializeTo(
|
|||||||
resourceElement.SetAttribute("name", resource.GetName());
|
resourceElement.SetAttribute("name", resource.GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_set<gd::String> usedExtensionNames;
|
||||||
|
usedExtensionNames.insert(extensionName);
|
||||||
|
for (auto &usedVariantIdentifier : alreadyUsedVariantIdentifiers) {
|
||||||
|
usedExtensionNames.insert(PlatformExtension::GetExtensionFromFullObjectType(
|
||||||
|
usedVariantIdentifier));
|
||||||
|
}
|
||||||
SerializerElement &requiredExtensionsElement =
|
SerializerElement &requiredExtensionsElement =
|
||||||
objectAssetElement.AddChild("requiredExtensions");
|
objectAssetElement.AddChild("requiredExtensions");
|
||||||
requiredExtensionsElement.ConsiderAsArrayOf("requiredExtension");
|
requiredExtensionsElement.ConsiderAsArrayOf("requiredExtension");
|
||||||
if (project.HasEventsFunctionsExtensionNamed(extensionName)) {
|
for (auto &usedExtensionName : usedExtensionNames) {
|
||||||
SerializerElement &requiredExtensionElement =
|
if (project.HasEventsFunctionsExtensionNamed(usedExtensionName)) {
|
||||||
requiredExtensionsElement.AddChild("requiredExtension");
|
auto &extension = project.GetEventsFunctionsExtension(usedExtensionName);
|
||||||
requiredExtensionElement.SetAttribute("extensionName", extensionName);
|
SerializerElement &requiredExtensionElement =
|
||||||
requiredExtensionElement.SetAttribute("extensionVersion", "1.0.0");
|
requiredExtensionsElement.AddChild("requiredExtension");
|
||||||
|
requiredExtensionElement.SetAttribute("extensionName", usedExtensionName);
|
||||||
|
requiredExtensionElement.SetAttribute("extensionVersion",
|
||||||
|
extension.GetVersion());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO This can be removed when the asset script no longer require it.
|
// TODO This can be removed when the asset script no longer require it.
|
||||||
@@ -124,10 +144,34 @@ void ObjectAssetSerializer::SerializeUsedVariantsTo(
|
|||||||
gd::Project &project, const gd::Object &object,
|
gd::Project &project, const gd::Object &object,
|
||||||
SerializerElement &variantsElement,
|
SerializerElement &variantsElement,
|
||||||
std::unordered_set<gd::String> &alreadyUsedVariantIdentifiers) {
|
std::unordered_set<gd::String> &alreadyUsedVariantIdentifiers) {
|
||||||
|
const auto *variant = ObjectAssetSerializer::GetVariant(project, object);
|
||||||
if (!project.HasEventsBasedObject(object.GetType())) {
|
if (!variant) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const auto &variantIdentifier =
|
||||||
|
object.GetType() + gd::PlatformExtension::GetNamespaceSeparator() +
|
||||||
|
variant->GetName();
|
||||||
|
auto insertResult = alreadyUsedVariantIdentifiers.insert(variantIdentifier);
|
||||||
|
if (!insertResult.second) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SerializerElement &pairElement = variantsElement.AddChild("variant");
|
||||||
|
pairElement.SetAttribute("objectType", object.GetType());
|
||||||
|
SerializerElement &variantElement = pairElement.AddChild("variant");
|
||||||
|
variant->SerializeTo(variantElement);
|
||||||
|
|
||||||
|
for (auto &object : variant->GetObjects().GetObjects()) {
|
||||||
|
gd::ObjectAssetSerializer::SerializeUsedVariantsTo(
|
||||||
|
project, *object, variantsElement, alreadyUsedVariantIdentifiers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const gd::EventsBasedObjectVariant *
|
||||||
|
ObjectAssetSerializer::GetVariant(gd::Project &project,
|
||||||
|
const gd::Object &object) {
|
||||||
|
if (!project.HasEventsBasedObject(object.GetType())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
const auto &eventsBasedObject =
|
const auto &eventsBasedObject =
|
||||||
project.GetEventsBasedObject(object.GetType());
|
project.GetEventsBasedObject(object.GetType());
|
||||||
const auto &variants = eventsBasedObject.GetVariants();
|
const auto &variants = eventsBasedObject.GetVariants();
|
||||||
@@ -140,26 +184,14 @@ void ObjectAssetSerializer::SerializeUsedVariantsTo(
|
|||||||
->IsMarkedAsOverridingEventsBasedObjectChildrenConfiguration() ||
|
->IsMarkedAsOverridingEventsBasedObjectChildrenConfiguration() ||
|
||||||
customObjectConfiguration
|
customObjectConfiguration
|
||||||
->IsForcedToOverrideEventsBasedObjectChildrenConfiguration())) {
|
->IsForcedToOverrideEventsBasedObjectChildrenConfiguration())) {
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const auto &variantIdentifier =
|
const auto &variantIdentifier =
|
||||||
object.GetType() + gd::PlatformExtension::GetNamespaceSeparator() +
|
object.GetType() + gd::PlatformExtension::GetNamespaceSeparator() +
|
||||||
variantName;
|
variantName;
|
||||||
auto insertResult = alreadyUsedVariantIdentifiers.insert(variantIdentifier);
|
const auto &variant = variants.HasVariantNamed(variantName)
|
||||||
if (insertResult.second) {
|
? variants.GetVariant(variantName)
|
||||||
const auto &variant = variants.HasVariantNamed(variantName)
|
: eventsBasedObject.GetDefaultVariant();
|
||||||
? variants.GetVariant(variantName)
|
return &variant;
|
||||||
: eventsBasedObject.GetDefaultVariant();
|
|
||||||
|
|
||||||
SerializerElement &pairElement = variantsElement.AddChild("variant");
|
|
||||||
pairElement.SetAttribute("objectType", object.GetType());
|
|
||||||
SerializerElement &variantElement = pairElement.AddChild("variant");
|
|
||||||
variant.SerializeTo(variantElement);
|
|
||||||
|
|
||||||
for (auto &object : variant.GetObjects().GetObjects()) {
|
|
||||||
gd::ObjectAssetSerializer::SerializeUsedVariantsTo(
|
|
||||||
project, *object, variantsElement, alreadyUsedVariantIdentifiers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
|
@@ -21,6 +21,7 @@ class InitialInstance;
|
|||||||
class SerializerElement;
|
class SerializerElement;
|
||||||
class EffectsContainer;
|
class EffectsContainer;
|
||||||
class AbstractFileSystem;
|
class AbstractFileSystem;
|
||||||
|
class EventsBasedObjectVariant;
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
|
|
||||||
namespace gd {
|
namespace gd {
|
||||||
@@ -58,6 +59,8 @@ private:
|
|||||||
gd::Project &project, const gd::Object &object,
|
gd::Project &project, const gd::Object &object,
|
||||||
SerializerElement &variantsElement,
|
SerializerElement &variantsElement,
|
||||||
std::unordered_set<gd::String> &alreadyUsedVariantIdentifiers);
|
std::unordered_set<gd::String> &alreadyUsedVariantIdentifiers);
|
||||||
|
|
||||||
|
static const gd::EventsBasedObjectVariant* GetVariant(gd::Project &project, const gd::Object &object);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
|
@@ -227,12 +227,11 @@ bool ResourceWorkerInEventsWorker::DoVisitInstruction(gd::Instruction& instructi
|
|||||||
platform, instruction.GetType());
|
platform, instruction.GetType());
|
||||||
|
|
||||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||||
instruction.GetParameters(),
|
instruction.GetParameters(), metadata.GetParameters(),
|
||||||
metadata.GetParameters(),
|
[this, &instruction](
|
||||||
[this, &instruction](const gd::ParameterMetadata& parameterMetadata,
|
const gd::ParameterMetadata ¶meterMetadata,
|
||||||
const gd::Expression& parameterExpression,
|
const gd::Expression ¶meterExpression, size_t parameterIndex,
|
||||||
size_t parameterIndex,
|
const gd::String &lastObjectName, size_t lastObjectIndex) {
|
||||||
const gd::String& lastObjectName) {
|
|
||||||
const String& parameterValue = parameterExpression.GetPlainString();
|
const String& parameterValue = parameterExpression.GetPlainString();
|
||||||
if (parameterMetadata.GetType() == "fontResource") {
|
if (parameterMetadata.GetType() == "fontResource") {
|
||||||
gd::String updatedParameterValue = parameterValue;
|
gd::String updatedParameterValue = parameterValue;
|
||||||
|
@@ -248,12 +248,13 @@ gd::String PropertyFunctionGenerator::GetStringifiedExtraInfo(
|
|||||||
gd::String arrayString;
|
gd::String arrayString;
|
||||||
arrayString += "[";
|
arrayString += "[";
|
||||||
bool isFirst = true;
|
bool isFirst = true;
|
||||||
for (const gd::String &choice : property.GetExtraInfo()) {
|
for (const auto &choice : property.GetChoices()) {
|
||||||
if (!isFirst) {
|
if (!isFirst) {
|
||||||
arrayString += ",";
|
arrayString += ",";
|
||||||
}
|
}
|
||||||
isFirst = false;
|
isFirst = false;
|
||||||
arrayString += "\"" + choice + "\"";
|
// TODO Handle labels (and search "choice label")
|
||||||
|
arrayString += "\"" + choice.GetValue() + "\"";
|
||||||
}
|
}
|
||||||
arrayString += "]";
|
arrayString += "]";
|
||||||
return arrayString;
|
return arrayString;
|
||||||
|
@@ -75,6 +75,17 @@ void ResourceExposer::ExposeProjectResources(
|
|||||||
// Expose global objects configuration resources
|
// Expose global objects configuration resources
|
||||||
auto objectWorker = gd::GetResourceWorkerOnObjects(project, worker);
|
auto objectWorker = gd::GetResourceWorkerOnObjects(project, worker);
|
||||||
objectWorker.Launch(project.GetObjects());
|
objectWorker.Launch(project.GetObjects());
|
||||||
|
|
||||||
|
// Exposed extension event resources
|
||||||
|
// Note that using resources in extensions is very unlikely and probably not
|
||||||
|
// worth the effort of something smart.
|
||||||
|
auto eventWorker = gd::GetResourceWorkerOnEvents(project, worker);
|
||||||
|
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
||||||
|
e++) {
|
||||||
|
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
||||||
|
gd::ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
|
||||||
|
project, eventsFunctionsExtension, eventWorker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceExposer::ExposeLayoutResources(
|
void ResourceExposer::ExposeLayoutResources(
|
||||||
@@ -103,16 +114,6 @@ void ResourceExposer::ExposeLayoutResources(
|
|||||||
auto eventWorker = gd::GetResourceWorkerOnEvents(project, worker);
|
auto eventWorker = gd::GetResourceWorkerOnEvents(project, worker);
|
||||||
gd::ProjectBrowserHelper::ExposeLayoutEventsAndDependencies(
|
gd::ProjectBrowserHelper::ExposeLayoutEventsAndDependencies(
|
||||||
project, layout, eventWorker);
|
project, layout, eventWorker);
|
||||||
|
|
||||||
// Exposed extension event resources
|
|
||||||
// Note that using resources in extensions is very unlikely and probably not
|
|
||||||
// worth the effort of something smart.
|
|
||||||
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
|
||||||
e++) {
|
|
||||||
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
|
||||||
gd::ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
|
|
||||||
project, eventsFunctionsExtension, eventWorker);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceExposer::ExposeEffectResources(
|
void ResourceExposer::ExposeEffectResources(
|
||||||
|
@@ -1781,6 +1781,14 @@ void WholeProjectRefactorer::DoRenameBehavior(
|
|||||||
projectBrowser.ExposeFunctions(project, behaviorParameterRenamer);
|
projectBrowser.ExposeFunctions(project, behaviorParameterRenamer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WholeProjectRefactorer::UpdateBehaviorsSharedData(gd::Project &project) {
|
||||||
|
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||||
|
gd::Layout &layout = project.GetLayout(i);
|
||||||
|
|
||||||
|
layout.UpdateBehaviorsSharedData(project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void WholeProjectRefactorer::DoRenameObject(
|
void WholeProjectRefactorer::DoRenameObject(
|
||||||
gd::Project &project, const gd::String &oldObjectType,
|
gd::Project &project, const gd::String &oldObjectType,
|
||||||
const gd::String &newObjectType, const gd::ProjectBrowser &projectBrowser) {
|
const gd::String &newObjectType, const gd::ProjectBrowser &projectBrowser) {
|
||||||
|
@@ -704,6 +704,16 @@ class GD_CORE_API WholeProjectRefactorer {
|
|||||||
static size_t GetLayoutAndExternalLayoutLayerInstancesCount(
|
static size_t GetLayoutAndExternalLayoutLayerInstancesCount(
|
||||||
gd::Project &project, gd::Layout &layout, const gd::String &layerName);
|
gd::Project &project, gd::Layout &layout, const gd::String &layerName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This ensures that the scenes had an instance of shared data for
|
||||||
|
* every behavior of every object that can be used on the scene
|
||||||
|
* (i.e. the objects of the scene and the global objects)
|
||||||
|
*
|
||||||
|
* Must be called when a behavior have been added/deleted
|
||||||
|
* from a global object or an object has been made global.
|
||||||
|
*/
|
||||||
|
static void UpdateBehaviorsSharedData(gd::Project &project);
|
||||||
|
|
||||||
virtual ~WholeProjectRefactorer(){};
|
virtual ~WholeProjectRefactorer(){};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -250,25 +250,28 @@ void CustomObjectConfiguration::ExposeResources(gd::ArbitraryResourceWorker& wor
|
|||||||
}
|
}
|
||||||
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
|
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
|
||||||
|
|
||||||
if (isMarkedAsOverridingEventsBasedObjectChildrenConfiguration) {
|
if (IsForcedToOverrideEventsBasedObjectChildrenConfiguration()) {
|
||||||
|
for (auto &childObject : eventsBasedObject.GetObjects().GetObjects()) {
|
||||||
|
auto &configuration = GetChildObjectConfiguration(childObject->GetName());
|
||||||
|
configuration.ExposeResources(worker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (eventsBasedObject.GetVariants().HasVariantNamed(variantName)) {
|
||||||
|
for (auto &childObject : eventsBasedObject.GetVariants()
|
||||||
|
.GetVariant(variantName)
|
||||||
|
.GetObjects()
|
||||||
|
.GetObjects()) {
|
||||||
|
childObject->GetConfiguration().ExposeResources(worker);
|
||||||
|
}
|
||||||
|
} else if (isMarkedAsOverridingEventsBasedObjectChildrenConfiguration) {
|
||||||
for (auto &childObject : eventsBasedObject.GetObjects().GetObjects()) {
|
for (auto &childObject : eventsBasedObject.GetObjects().GetObjects()) {
|
||||||
auto &configuration = GetChildObjectConfiguration(childObject->GetName());
|
auto &configuration = GetChildObjectConfiguration(childObject->GetName());
|
||||||
configuration.ExposeResources(worker);
|
configuration.ExposeResources(worker);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (variantName.empty() ||
|
for (auto &childObject :
|
||||||
!eventsBasedObject.GetVariants().HasVariantNamed(variantName)) {
|
eventsBasedObject.GetDefaultVariant().GetObjects().GetObjects()) {
|
||||||
for (auto &childObject :
|
childObject->GetConfiguration().ExposeResources(worker);
|
||||||
eventsBasedObject.GetDefaultVariant().GetObjects().GetObjects()) {
|
|
||||||
childObject->GetConfiguration().ExposeResources(worker);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (auto &childObject : eventsBasedObject.GetVariants()
|
|
||||||
.GetVariant(variantName)
|
|
||||||
.GetObjects()
|
|
||||||
.GetObjects()) {
|
|
||||||
childObject->GetConfiguration().ExposeResources(worker);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -78,6 +78,15 @@ public:
|
|||||||
variantName = variantName_;
|
variantName = variantName_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Legacy events-based objects don't have any instance in their default
|
||||||
|
* variant since there wasn't a graphical editor at the time. In this case,
|
||||||
|
* the editor doesn't allow to choose a variant, but a variant may have stayed
|
||||||
|
* after a user rolled back the extension. This variant must be ignored.
|
||||||
|
*
|
||||||
|
* @return true when its events-based object doesn't have any initial
|
||||||
|
* instance.
|
||||||
|
*/
|
||||||
bool IsForcedToOverrideEventsBasedObjectChildrenConfiguration() const;
|
bool IsForcedToOverrideEventsBasedObjectChildrenConfiguration() const;
|
||||||
|
|
||||||
bool IsMarkedAsOverridingEventsBasedObjectChildrenConfiguration() const {
|
bool IsMarkedAsOverridingEventsBasedObjectChildrenConfiguration() const {
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
#include "GDCore/Serialization/SerializerElement.h"
|
#include "GDCore/Serialization/SerializerElement.h"
|
||||||
|
|
||||||
namespace gd {
|
namespace gd {
|
||||||
|
|
||||||
|
gd::String Effect::badStringParameterValue;
|
||||||
|
|
||||||
void Effect::SerializeTo(SerializerElement& element) const {
|
void Effect::SerializeTo(SerializerElement& element) const {
|
||||||
element.SetAttribute("name", GetName());
|
element.SetAttribute("name", GetName());
|
||||||
|
@@ -3,8 +3,7 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
#ifndef GDCORE_EFFECT_H
|
#pragma once
|
||||||
#define GDCORE_EFFECT_H
|
|
||||||
#include <map>
|
#include <map>
|
||||||
namespace gd {
|
namespace gd {
|
||||||
class SerializerElement;
|
class SerializerElement;
|
||||||
@@ -35,28 +34,43 @@ class GD_CORE_API Effect {
|
|||||||
void SetFolded(bool fold = true) { folded = fold; }
|
void SetFolded(bool fold = true) { folded = fold; }
|
||||||
bool IsFolded() const { return folded; }
|
bool IsFolded() const { return folded; }
|
||||||
|
|
||||||
void SetDoubleParameter(const gd::String& name, double value) {
|
void SetDoubleParameter(const gd::String &name, double value) {
|
||||||
doubleParameters[name] = value;
|
doubleParameters[name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetDoubleParameter(const gd::String& name) {
|
double GetDoubleParameter(const gd::String &name) const {
|
||||||
return doubleParameters[name];
|
auto itr = doubleParameters.find(name);
|
||||||
|
return itr == doubleParameters.end() ? 0 : itr->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetStringParameter(const gd::String& name, const gd::String& value) {
|
bool HasDoubleParameter(const gd::String &name) const {
|
||||||
|
return doubleParameters.find(name) != doubleParameters.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetStringParameter(const gd::String &name, const gd::String &value) {
|
||||||
stringParameters[name] = value;
|
stringParameters[name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gd::String& GetStringParameter(const gd::String& name) {
|
const gd::String &GetStringParameter(const gd::String &name) const {
|
||||||
return stringParameters[name];
|
auto itr = stringParameters.find(name);
|
||||||
|
return itr == stringParameters.end() ? badStringParameterValue : itr->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetBooleanParameter(const gd::String& name, bool value) {
|
bool HasStringParameter(const gd::String &name) const {
|
||||||
|
return stringParameters.find(name) != stringParameters.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetBooleanParameter(const gd::String &name, bool value) {
|
||||||
booleanParameters[name] = value;
|
booleanParameters[name] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetBooleanParameter(const gd::String& name) {
|
bool GetBooleanParameter(const gd::String &name) const {
|
||||||
return booleanParameters[name];
|
auto itr = booleanParameters.find(name);
|
||||||
|
return itr == booleanParameters.end() ? false : itr->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasBooleanParameter(const gd::String &name) const {
|
||||||
|
return booleanParameters.find(name) != booleanParameters.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<gd::String, double>& GetAllDoubleParameters() const {
|
const std::map<gd::String, double>& GetAllDoubleParameters() const {
|
||||||
@@ -94,7 +108,9 @@ class GD_CORE_API Effect {
|
|||||||
std::map<gd::String, double> doubleParameters; ///< Values of parameters being doubles, keyed by names.
|
std::map<gd::String, double> doubleParameters; ///< Values of parameters being doubles, keyed by names.
|
||||||
std::map<gd::String, gd::String> stringParameters; ///< Values of parameters being strings, keyed by names.
|
std::map<gd::String, gd::String> stringParameters; ///< Values of parameters being strings, keyed by names.
|
||||||
std::map<gd::String, bool> booleanParameters; ///< Values of parameters being booleans, keyed by names.
|
std::map<gd::String, bool> booleanParameters; ///< Values of parameters being booleans, keyed by names.
|
||||||
|
|
||||||
|
static gd::String badStringParameterValue; ///< Empty string returned by
|
||||||
|
///< GeStringParameter
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
#endif
|
|
||||||
|
@@ -37,6 +37,7 @@ void EventsBasedObjectVariant::SerializeTo(SerializerElement &element) const {
|
|||||||
|
|
||||||
layers.SerializeLayersTo(element.AddChild("layers"));
|
layers.SerializeLayersTo(element.AddChild("layers"));
|
||||||
initialInstances.SerializeTo(element.AddChild("instances"));
|
initialInstances.SerializeTo(element.AddChild("instances"));
|
||||||
|
editorSettings.SerializeTo(element.AddChild("editionSettings"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventsBasedObjectVariant::UnserializeFrom(
|
void EventsBasedObjectVariant::UnserializeFrom(
|
||||||
@@ -66,6 +67,7 @@ void EventsBasedObjectVariant::UnserializeFrom(
|
|||||||
layers.Reset();
|
layers.Reset();
|
||||||
}
|
}
|
||||||
initialInstances.UnserializeFrom(element.GetChild("instances"));
|
initialInstances.UnserializeFrom(element.GetChild("instances"));
|
||||||
|
editorSettings.UnserializeFrom(element.GetChild("editionSettings"));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
|
||||||
#include "GDCore/Project/InitialInstancesContainer.h"
|
#include "GDCore/Project/InitialInstancesContainer.h"
|
||||||
#include "GDCore/Project/LayersContainer.h"
|
#include "GDCore/Project/LayersContainer.h"
|
||||||
#include "GDCore/Project/ObjectsContainer.h"
|
#include "GDCore/Project/ObjectsContainer.h"
|
||||||
@@ -199,6 +200,19 @@ public:
|
|||||||
const gd::String &GetAssetStoreOriginalName() const {
|
const gd::String &GetAssetStoreOriginalName() const {
|
||||||
return assetStoreOriginalName;
|
return assetStoreOriginalName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \brief Get the user settings for the IDE.
|
||||||
|
*/
|
||||||
|
const gd::EditorSettings& GetAssociatedEditorSettings() const {
|
||||||
|
return editorSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the user settings for the IDE.
|
||||||
|
*/
|
||||||
|
gd::EditorSettings& GetAssociatedEditorSettings() { return editorSettings; }
|
||||||
|
|
||||||
void SerializeTo(SerializerElement &element) const;
|
void SerializeTo(SerializerElement &element) const;
|
||||||
|
|
||||||
@@ -224,6 +238,7 @@ private:
|
|||||||
* store.
|
* store.
|
||||||
*/
|
*/
|
||||||
gd::String assetStoreOriginalName;
|
gd::String assetStoreOriginalName;
|
||||||
|
gd::EditorSettings editorSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
|
@@ -83,6 +83,9 @@ void EventsFunctionsExtension::SerializeTo(SerializerElement& element, bool isEx
|
|||||||
element.SetAttribute("iconUrl", iconUrl);
|
element.SetAttribute("iconUrl", iconUrl);
|
||||||
element.SetAttribute("helpPath", helpPath);
|
element.SetAttribute("helpPath", helpPath);
|
||||||
element.SetAttribute("gdevelopVersion", gdevelopVersion);
|
element.SetAttribute("gdevelopVersion", gdevelopVersion);
|
||||||
|
if (changelog.GetChangesCount() > 0) {
|
||||||
|
changelog.SerializeTo(element.AddChild("changelog"));
|
||||||
|
}
|
||||||
auto& dependenciesElement = element.AddChild("dependencies");
|
auto& dependenciesElement = element.AddChild("dependencies");
|
||||||
dependenciesElement.ConsiderAsArray();
|
dependenciesElement.ConsiderAsArray();
|
||||||
for (auto& dependency : dependencies)
|
for (auto& dependency : dependencies)
|
||||||
@@ -139,6 +142,9 @@ void EventsFunctionsExtension::UnserializeExtensionDeclarationFrom(
|
|||||||
iconUrl = element.GetStringAttribute("iconUrl");
|
iconUrl = element.GetStringAttribute("iconUrl");
|
||||||
helpPath = element.GetStringAttribute("helpPath");
|
helpPath = element.GetStringAttribute("helpPath");
|
||||||
gdevelopVersion = element.GetStringAttribute("gdevelopVersion");
|
gdevelopVersion = element.GetStringAttribute("gdevelopVersion");
|
||||||
|
if (element.HasChild("changelog")) {
|
||||||
|
changelog.UnserializeFrom(element.GetChild("changelog"));
|
||||||
|
}
|
||||||
|
|
||||||
if (element.HasChild("origin")) {
|
if (element.HasChild("origin")) {
|
||||||
gd::String originName =
|
gd::String originName =
|
||||||
|
@@ -12,9 +12,11 @@
|
|||||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||||
#include "GDCore/Project/EventsBasedObject.h"
|
#include "GDCore/Project/EventsBasedObject.h"
|
||||||
#include "GDCore/Project/EventsFunctionsContainer.h"
|
#include "GDCore/Project/EventsFunctionsContainer.h"
|
||||||
|
#include "GDCore/Project/EventsFunctionsExtensionChangelog.h"
|
||||||
#include "GDCore/Project/VariablesContainer.h"
|
#include "GDCore/Project/VariablesContainer.h"
|
||||||
#include "GDCore/String.h"
|
#include "GDCore/String.h"
|
||||||
#include "GDCore/Tools/SerializableWithNameList.h"
|
#include "GDCore/Tools/SerializableWithNameList.h"
|
||||||
|
|
||||||
namespace gd {
|
namespace gd {
|
||||||
class SerializerElement;
|
class SerializerElement;
|
||||||
class Project;
|
class Project;
|
||||||
@@ -406,6 +408,7 @@ class GD_CORE_API EventsFunctionsExtension {
|
|||||||
gd::String helpPath; ///< The relative path to the help for this extension in
|
gd::String helpPath; ///< The relative path to the help for this extension in
|
||||||
///< the documentation (or an absolute URL).
|
///< the documentation (or an absolute URL).
|
||||||
gd::String gdevelopVersion;
|
gd::String gdevelopVersion;
|
||||||
|
gd::EventsFunctionsExtensionChangelog changelog;
|
||||||
gd::SerializableWithNameList<EventsBasedBehavior> eventsBasedBehaviors;
|
gd::SerializableWithNameList<EventsBasedBehavior> eventsBasedBehaviors;
|
||||||
gd::SerializableWithNameList<EventsBasedObject> eventsBasedObjects;
|
gd::SerializableWithNameList<EventsBasedObject> eventsBasedObjects;
|
||||||
std::vector<gd::DependencyMetadata> dependencies;
|
std::vector<gd::DependencyMetadata> dependencies;
|
||||||
|
105
Core/GDCore/Project/EventsFunctionsExtensionChangelog.h
Normal file
105
Core/GDCore/Project/EventsFunctionsExtensionChangelog.h
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* 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 <vector>
|
||||||
|
|
||||||
|
#include "GDCore/Serialization/SerializerElement.h"
|
||||||
|
#include "GDCore/String.h"
|
||||||
|
|
||||||
|
namespace gd {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The change of a specific extension version (only the breaking
|
||||||
|
* changes).
|
||||||
|
*/
|
||||||
|
class GD_CORE_API EventsFunctionsExtensionVersionChange {
|
||||||
|
public:
|
||||||
|
EventsFunctionsExtensionVersionChange(){};
|
||||||
|
virtual ~EventsFunctionsExtensionVersionChange(){};
|
||||||
|
|
||||||
|
const gd::String &GetVersion() const { return version; };
|
||||||
|
gd::EventsFunctionsExtensionVersionChange &
|
||||||
|
SetVersion(const gd::String &version_) {
|
||||||
|
version = version_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gd::String &GetBreakingChangesDescription() const { return version; };
|
||||||
|
gd::EventsFunctionsExtensionVersionChange &
|
||||||
|
GetBreakingChangesDescription(const gd::String &breakingChangesDescription_) {
|
||||||
|
breakingChangesDescription = breakingChangesDescription_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Serialize the EventsFunctionsExtensionVersionChange to the specified
|
||||||
|
* element
|
||||||
|
*/
|
||||||
|
void SerializeTo(gd::SerializerElement &element) const {
|
||||||
|
element.SetAttribute("version", version);
|
||||||
|
element.AddChild("breaking")
|
||||||
|
.SetMultilineStringValue(breakingChangesDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Load the EventsFunctionsExtensionVersionChange from the specified
|
||||||
|
* element.
|
||||||
|
*/
|
||||||
|
void UnserializeFrom(const gd::SerializerElement &element) {
|
||||||
|
version = element.GetStringAttribute("version");
|
||||||
|
breakingChangesDescription =
|
||||||
|
element.GetChild("breaking").GetMultilineStringValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
gd::String version;
|
||||||
|
gd::String breakingChangesDescription;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The changelog of an extension (only the breaking changes).
|
||||||
|
*/
|
||||||
|
class GD_CORE_API EventsFunctionsExtensionChangelog {
|
||||||
|
public:
|
||||||
|
EventsFunctionsExtensionChangelog(){};
|
||||||
|
virtual ~EventsFunctionsExtensionChangelog(){};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Return the number of variants.
|
||||||
|
*/
|
||||||
|
std::size_t GetChangesCount() const { return versionChanges.size(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Serialize the EventsFunctionsExtensionChangelog to the specified
|
||||||
|
* element
|
||||||
|
*/
|
||||||
|
void SerializeTo(gd::SerializerElement &element) const {
|
||||||
|
element.ConsiderAsArray();
|
||||||
|
for (const auto &versionChange : versionChanges) {
|
||||||
|
versionChange.SerializeTo(element.AddChild(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Load the EventsFunctionsExtensionChangelog from the specified
|
||||||
|
* element.
|
||||||
|
*/
|
||||||
|
void UnserializeFrom(const gd::SerializerElement &element) {
|
||||||
|
versionChanges.clear();
|
||||||
|
element.ConsiderAsArray();
|
||||||
|
for (std::size_t i = 0; i < element.GetChildrenCount(); ++i) {
|
||||||
|
gd::EventsFunctionsExtensionVersionChange versionChange;
|
||||||
|
versionChange.UnserializeFrom(element.GetChild(i));
|
||||||
|
versionChanges.push_back(versionChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<gd::EventsFunctionsExtensionVersionChange> versionChanges;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gd
|
@@ -365,6 +365,8 @@ class GD_CORE_API InitialInstance {
|
|||||||
* the same initial instance between serialization.
|
* the same initial instance between serialization.
|
||||||
*/
|
*/
|
||||||
InitialInstance& ResetPersistentUuid();
|
InitialInstance& ResetPersistentUuid();
|
||||||
|
|
||||||
|
const gd::String& GetPersistentUuid() const { return persistentUuid; }
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -36,7 +36,7 @@ namespace gd {
|
|||||||
|
|
||||||
gd::BehaviorsSharedData Layout::badBehaviorSharedData("", "");
|
gd::BehaviorsSharedData Layout::badBehaviorSharedData("", "");
|
||||||
|
|
||||||
Layout::Layout(const Layout &other)
|
Layout::Layout(const Layout& other)
|
||||||
: objectsContainer(gd::ObjectsContainer::SourceType::Scene) {
|
: objectsContainer(gd::ObjectsContainer::SourceType::Scene) {
|
||||||
Init(other);
|
Init(other);
|
||||||
}
|
}
|
||||||
@@ -54,6 +54,8 @@ Layout::Layout()
|
|||||||
backgroundColorG(209),
|
backgroundColorG(209),
|
||||||
backgroundColorB(209),
|
backgroundColorB(209),
|
||||||
stopSoundsOnStartup(true),
|
stopSoundsOnStartup(true),
|
||||||
|
resourcesPreloading("inherit"),
|
||||||
|
resourcesUnloading("inherit"),
|
||||||
standardSortMethod(true),
|
standardSortMethod(true),
|
||||||
disableInputWhenNotFocused(true),
|
disableInputWhenNotFocused(true),
|
||||||
variables(gd::VariablesContainer::SourceType::Scene),
|
variables(gd::VariablesContainer::SourceType::Scene),
|
||||||
@@ -244,6 +246,10 @@ void Layout::SerializeTo(SerializerElement& element) const {
|
|||||||
element.SetAttribute("title", GetWindowDefaultTitle());
|
element.SetAttribute("title", GetWindowDefaultTitle());
|
||||||
element.SetAttribute("standardSortMethod", standardSortMethod);
|
element.SetAttribute("standardSortMethod", standardSortMethod);
|
||||||
element.SetAttribute("stopSoundsOnStartup", stopSoundsOnStartup);
|
element.SetAttribute("stopSoundsOnStartup", stopSoundsOnStartup);
|
||||||
|
if (resourcesPreloading != "inherit")
|
||||||
|
element.SetAttribute("resourcesPreloading", resourcesPreloading);
|
||||||
|
if (resourcesUnloading != "inherit")
|
||||||
|
element.SetAttribute("resourcesUnloading", resourcesUnloading);
|
||||||
element.SetAttribute("disableInputWhenNotFocused",
|
element.SetAttribute("disableInputWhenNotFocused",
|
||||||
disableInputWhenNotFocused);
|
disableInputWhenNotFocused);
|
||||||
|
|
||||||
@@ -304,6 +310,10 @@ void Layout::UnserializeFrom(gd::Project& project,
|
|||||||
element.GetStringAttribute("title", "(No title)", "titre"));
|
element.GetStringAttribute("title", "(No title)", "titre"));
|
||||||
standardSortMethod = element.GetBoolAttribute("standardSortMethod");
|
standardSortMethod = element.GetBoolAttribute("standardSortMethod");
|
||||||
stopSoundsOnStartup = element.GetBoolAttribute("stopSoundsOnStartup");
|
stopSoundsOnStartup = element.GetBoolAttribute("stopSoundsOnStartup");
|
||||||
|
resourcesPreloading =
|
||||||
|
element.GetStringAttribute("resourcesPreloading", "inherit");
|
||||||
|
resourcesUnloading =
|
||||||
|
element.GetStringAttribute("resourcesUnloading", "inherit");
|
||||||
disableInputWhenNotFocused =
|
disableInputWhenNotFocused =
|
||||||
element.GetBoolAttribute("disableInputWhenNotFocused");
|
element.GetBoolAttribute("disableInputWhenNotFocused");
|
||||||
|
|
||||||
@@ -391,6 +401,8 @@ void Layout::Init(const Layout& other) {
|
|||||||
standardSortMethod = other.standardSortMethod;
|
standardSortMethod = other.standardSortMethod;
|
||||||
title = other.title;
|
title = other.title;
|
||||||
stopSoundsOnStartup = other.stopSoundsOnStartup;
|
stopSoundsOnStartup = other.stopSoundsOnStartup;
|
||||||
|
resourcesPreloading = other.resourcesPreloading;
|
||||||
|
resourcesUnloading = other.resourcesUnloading;
|
||||||
disableInputWhenNotFocused = other.disableInputWhenNotFocused;
|
disableInputWhenNotFocused = other.disableInputWhenNotFocused;
|
||||||
initialInstances = other.initialInstances;
|
initialInstances = other.initialInstances;
|
||||||
layers = other.layers;
|
layers = other.layers;
|
||||||
|
@@ -349,6 +349,36 @@ class GD_CORE_API Layout {
|
|||||||
* launched
|
* launched
|
||||||
*/
|
*/
|
||||||
bool StopSoundsOnStartup() const { return stopSoundsOnStartup; }
|
bool StopSoundsOnStartup() const { return stopSoundsOnStartup; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set when the scene must preload its resources: `at-startup`, `never` or
|
||||||
|
* `inherit` (default).
|
||||||
|
*/
|
||||||
|
void SetResourcesPreloading(gd::String resourcesPreloading_) {
|
||||||
|
resourcesPreloading = resourcesPreloading_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get when the scene must preload its resources: `at-startup`, `never` or
|
||||||
|
* `inherit` (default).
|
||||||
|
*/
|
||||||
|
const gd::String& GetResourcesPreloading() const {
|
||||||
|
return resourcesPreloading;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set when the scene must unload its resources: `at-scene-exit`, `never` or
|
||||||
|
* `inherit` (default).
|
||||||
|
*/
|
||||||
|
void SetResourcesUnloading(gd::String resourcesUnloading_) {
|
||||||
|
resourcesUnloading = resourcesUnloading_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get when the scene must unload its resources: `at-scene-exit`, `never` or
|
||||||
|
* `inherit` (default).
|
||||||
|
*/
|
||||||
|
const gd::String& GetResourcesUnloading() const { return resourcesUnloading; }
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/** \name Saving and loading
|
/** \name Saving and loading
|
||||||
@@ -381,6 +411,10 @@ class GD_CORE_API Layout {
|
|||||||
behaviorsSharedData; ///< Initial shared datas of behaviors
|
behaviorsSharedData; ///< Initial shared datas of behaviors
|
||||||
bool stopSoundsOnStartup = true; ///< True to make the scene stop all sounds at
|
bool stopSoundsOnStartup = true; ///< True to make the scene stop all sounds at
|
||||||
///< startup.
|
///< startup.
|
||||||
|
gd::String
|
||||||
|
resourcesPreloading; ///< `at-startup`, `never` or `inherit` (default).
|
||||||
|
gd::String
|
||||||
|
resourcesUnloading; ///< `at-scene-exit`, `never` or `inherit` (default).
|
||||||
bool standardSortMethod = true; ///< True to sort objects using standard sort.
|
bool standardSortMethod = true; ///< True to sort objects using standard sort.
|
||||||
bool disableInputWhenNotFocused = true; /// If set to true, the input must be
|
bool disableInputWhenNotFocused = true; /// If set to true, the input must be
|
||||||
/// disabled when the window do not have the
|
/// disabled when the window do not have the
|
||||||
|
@@ -81,6 +81,11 @@ class GD_CORE_API ObjectsContainersList {
|
|||||||
/**
|
/**
|
||||||
* \brief Return the container of the variables for the specified object or
|
* \brief Return the container of the variables for the specified object or
|
||||||
* group of objects.
|
* group of objects.
|
||||||
|
*
|
||||||
|
* \warning In most cases, prefer to use other methods to access variables or use
|
||||||
|
* ObjectVariableHelper::MergeVariableContainers if you know you're dealing with a group.
|
||||||
|
* This is because the variables container of an object group does not exist and the one from
|
||||||
|
* first object of the group will be returned.
|
||||||
*/
|
*/
|
||||||
const gd::VariablesContainer* GetObjectOrGroupVariablesContainer(
|
const gd::VariablesContainer* GetObjectOrGroupVariablesContainer(
|
||||||
const gd::String& objectOrGroupName) const;
|
const gd::String& objectOrGroupName) const;
|
||||||
|
@@ -74,7 +74,9 @@ Project::Project()
|
|||||||
gdMinorVersion(gd::VersionWrapper::Minor()),
|
gdMinorVersion(gd::VersionWrapper::Minor()),
|
||||||
gdBuildVersion(gd::VersionWrapper::Build()),
|
gdBuildVersion(gd::VersionWrapper::Build()),
|
||||||
variables(gd::VariablesContainer::SourceType::Global),
|
variables(gd::VariablesContainer::SourceType::Global),
|
||||||
objectsContainer(gd::ObjectsContainer::SourceType::Global) {}
|
objectsContainer(gd::ObjectsContainer::SourceType::Global),
|
||||||
|
sceneResourcesPreloading("at-startup"),
|
||||||
|
sceneResourcesUnloading("never") {}
|
||||||
|
|
||||||
Project::~Project() {}
|
Project::~Project() {}
|
||||||
|
|
||||||
@@ -1166,6 +1168,13 @@ void Project::SerializeTo(SerializerElement& element) const {
|
|||||||
else
|
else
|
||||||
std::cout << "ERROR: The project current platform is NULL.";
|
std::cout << "ERROR: The project current platform is NULL.";
|
||||||
|
|
||||||
|
if (sceneResourcesPreloading != "at-startup") {
|
||||||
|
propElement.SetAttribute("sceneResourcesPreloading", sceneResourcesPreloading);
|
||||||
|
}
|
||||||
|
if (sceneResourcesUnloading != "never") {
|
||||||
|
propElement.SetAttribute("sceneResourcesUnloading", sceneResourcesUnloading);
|
||||||
|
}
|
||||||
|
|
||||||
resourcesManager.SerializeTo(element.AddChild("resources"));
|
resourcesManager.SerializeTo(element.AddChild("resources"));
|
||||||
objectsContainer.SerializeObjectsTo(element.AddChild("objects"));
|
objectsContainer.SerializeObjectsTo(element.AddChild("objects"));
|
||||||
objectsContainer.SerializeFoldersTo(element.AddChild("objectsFolderStructure"));
|
objectsContainer.SerializeFoldersTo(element.AddChild("objectsFolderStructure"));
|
||||||
@@ -1307,6 +1316,9 @@ void Project::Init(const gd::Project& game) {
|
|||||||
variables = game.GetVariables();
|
variables = game.GetVariables();
|
||||||
|
|
||||||
projectFile = game.GetProjectFile();
|
projectFile = game.GetProjectFile();
|
||||||
|
|
||||||
|
sceneResourcesPreloading = game.sceneResourcesPreloading;
|
||||||
|
sceneResourcesUnloading = game.sceneResourcesUnloading;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gd
|
} // namespace gd
|
||||||
|
@@ -964,6 +964,37 @@ class GD_CORE_API Project {
|
|||||||
*/
|
*/
|
||||||
ResourcesManager& GetResourcesManager() { return resourcesManager; }
|
ResourcesManager& GetResourcesManager() { return resourcesManager; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set when the scenes must preload their resources: `at-startup`, `never`
|
||||||
|
* (default).
|
||||||
|
*/
|
||||||
|
void SetSceneResourcesPreloading(gd::String sceneResourcesPreloading_) {
|
||||||
|
sceneResourcesPreloading = sceneResourcesPreloading_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get when the scenes must preload their resources: `at-startup`, `never`
|
||||||
|
* (default).
|
||||||
|
*/
|
||||||
|
const gd::String& GetSceneResourcesPreloading() const {
|
||||||
|
return sceneResourcesPreloading;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set when the scenes must unload their resources: `at-scene-exit`, `never`
|
||||||
|
* (default).
|
||||||
|
*/
|
||||||
|
void SetSceneResourcesUnloading(gd::String sceneResourcesUnloading_) {
|
||||||
|
sceneResourcesUnloading = sceneResourcesUnloading_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get when the scenes must unload their resources: `at-scene-exit`, `never`
|
||||||
|
* (default).
|
||||||
|
*/
|
||||||
|
const gd::String& GetSceneResourcesUnloading() const {
|
||||||
|
return sceneResourcesUnloading;
|
||||||
|
}
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/** \name Variable management
|
/** \name Variable management
|
||||||
@@ -1121,6 +1152,10 @@ class GD_CORE_API Project {
|
|||||||
ExtensionProperties
|
ExtensionProperties
|
||||||
extensionProperties; ///< The properties of the extensions.
|
extensionProperties; ///< The properties of the extensions.
|
||||||
gd::WholeProjectDiagnosticReport wholeProjectDiagnosticReport;
|
gd::WholeProjectDiagnosticReport wholeProjectDiagnosticReport;
|
||||||
|
gd::String sceneResourcesPreloading; ///< `at-startup` or `never`
|
||||||
|
///< (default: `at-startup`).
|
||||||
|
gd::String sceneResourcesUnloading; ///< `at-scene-exit` or `never`
|
||||||
|
///< (default: `never`).
|
||||||
mutable unsigned int gdMajorVersion =
|
mutable unsigned int gdMajorVersion =
|
||||||
0; ///< The GD major version used the last
|
0; ///< The GD major version used the last
|
||||||
///< time the project was saved.
|
///< time the project was saved.
|
||||||
|
@@ -21,14 +21,33 @@ void PropertyDescriptor::SerializeTo(SerializerElement& element) const {
|
|||||||
element.AddChild("unit").SetStringValue(measurementUnit.GetName());
|
element.AddChild("unit").SetStringValue(measurementUnit.GetName());
|
||||||
}
|
}
|
||||||
element.AddChild("label").SetStringValue(label);
|
element.AddChild("label").SetStringValue(label);
|
||||||
element.AddChild("description").SetStringValue(description);
|
if (!description.empty())
|
||||||
element.AddChild("group").SetStringValue(group);
|
element.AddChild("description").SetStringValue(description);
|
||||||
SerializerElement& extraInformationElement =
|
if (!group.empty()) element.AddChild("group").SetStringValue(group);
|
||||||
element.AddChild("extraInformation");
|
|
||||||
extraInformationElement.ConsiderAsArray();
|
if (!extraInformation.empty()) {
|
||||||
for (const gd::String& information : extraInformation) {
|
SerializerElement& extraInformationElement =
|
||||||
extraInformationElement.AddChild("").SetStringValue(information);
|
element.AddChild("extraInformation");
|
||||||
|
extraInformationElement.ConsiderAsArray();
|
||||||
|
for (const gd::String& information : extraInformation) {
|
||||||
|
extraInformationElement.AddChild("").SetStringValue(information);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!choices.empty()
|
||||||
|
// Compatibility with GD <= 5.5.239
|
||||||
|
|| !extraInformation.empty()
|
||||||
|
// end of compatibility code
|
||||||
|
) {
|
||||||
|
SerializerElement &choicesElement = element.AddChild("choices");
|
||||||
|
choicesElement.ConsiderAsArrayOf("choice");
|
||||||
|
for (const auto &choice : choices) {
|
||||||
|
auto &choiceElement = choicesElement.AddChild("Choice");
|
||||||
|
choiceElement.SetStringAttribute("value", choice.GetValue());
|
||||||
|
choiceElement.SetStringAttribute("label", choice.GetLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (hidden) {
|
if (hidden) {
|
||||||
element.AddChild("hidden").SetBoolValue(hidden);
|
element.AddChild("hidden").SetBoolValue(hidden);
|
||||||
}
|
}
|
||||||
@@ -59,16 +78,41 @@ void PropertyDescriptor::UnserializeFrom(const SerializerElement& element) {
|
|||||||
: gd::MeasurementUnit::GetUndefined();
|
: gd::MeasurementUnit::GetUndefined();
|
||||||
}
|
}
|
||||||
label = element.GetChild("label").GetStringValue();
|
label = element.GetChild("label").GetStringValue();
|
||||||
description = element.GetChild("description").GetStringValue();
|
description = element.HasChild("description")
|
||||||
group = element.GetChild("group").GetStringValue();
|
? element.GetChild("description").GetStringValue()
|
||||||
|
: "";
|
||||||
|
group = element.HasChild("group") ? element.GetChild("group").GetStringValue()
|
||||||
|
: "";
|
||||||
|
|
||||||
extraInformation.clear();
|
extraInformation.clear();
|
||||||
const SerializerElement& extraInformationElement =
|
if (element.HasChild("extraInformation")) {
|
||||||
element.GetChild("extraInformation");
|
const SerializerElement& extraInformationElement =
|
||||||
extraInformationElement.ConsiderAsArray();
|
element.GetChild("extraInformation");
|
||||||
for (std::size_t i = 0; i < extraInformationElement.GetChildrenCount(); ++i)
|
extraInformationElement.ConsiderAsArray();
|
||||||
extraInformation.push_back(
|
for (std::size_t i = 0; i < extraInformationElement.GetChildrenCount(); ++i)
|
||||||
extraInformationElement.GetChild(i).GetStringValue());
|
extraInformation.push_back(
|
||||||
|
extraInformationElement.GetChild(i).GetStringValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.HasChild("choices")) {
|
||||||
|
choices.clear();
|
||||||
|
const SerializerElement &choicesElement = element.GetChild("choices");
|
||||||
|
choicesElement.ConsiderAsArrayOf("choice");
|
||||||
|
for (std::size_t i = 0; i < choicesElement.GetChildrenCount(); ++i) {
|
||||||
|
auto &choiceElement = choicesElement.GetChild(i);
|
||||||
|
AddChoice(choiceElement.GetStringAttribute("value"),
|
||||||
|
choiceElement.GetStringAttribute("label"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Compatibility with GD <= 5.5.239
|
||||||
|
else if (type == "Choice") {
|
||||||
|
choices.clear();
|
||||||
|
for (auto &choiceValue : extraInformation) {
|
||||||
|
AddChoice(choiceValue, choiceValue);
|
||||||
|
}
|
||||||
|
extraInformation.clear();
|
||||||
|
}
|
||||||
|
// end of compatibility code
|
||||||
|
|
||||||
hidden = element.HasChild("hidden")
|
hidden = element.HasChild("hidden")
|
||||||
? element.GetChild("hidden").GetBoolValue()
|
? element.GetChild("hidden").GetBoolValue()
|
||||||
|
@@ -7,9 +7,9 @@
|
|||||||
#define GDCORE_PROPERTYDESCRIPTOR
|
#define GDCORE_PROPERTYDESCRIPTOR
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "GDCore/String.h"
|
|
||||||
#include "GDCore/Project/MeasurementUnit.h"
|
#include "GDCore/Project/MeasurementUnit.h"
|
||||||
#include "GDCore/Project/QuickCustomization.h"
|
#include "GDCore/Project/QuickCustomization.h"
|
||||||
|
#include "GDCore/String.h"
|
||||||
|
|
||||||
namespace gd {
|
namespace gd {
|
||||||
class SerializerElement;
|
class SerializerElement;
|
||||||
@@ -17,6 +17,19 @@ class SerializerElement;
|
|||||||
|
|
||||||
namespace gd {
|
namespace gd {
|
||||||
|
|
||||||
|
class GD_CORE_API PropertyDescriptorChoice {
|
||||||
|
public:
|
||||||
|
PropertyDescriptorChoice(const gd::String& value, const gd::String& label)
|
||||||
|
: value(value), label(label) {}
|
||||||
|
|
||||||
|
const gd::String& GetValue() const { return value; }
|
||||||
|
const gd::String& GetLabel() const { return label; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
gd::String value;
|
||||||
|
gd::String label;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Used to describe a property shown in a property grid.
|
* \brief Used to describe a property shown in a property grid.
|
||||||
* \see gd::Object
|
* \see gd::Object
|
||||||
@@ -31,8 +44,12 @@ class GD_CORE_API PropertyDescriptor {
|
|||||||
* \param propertyValue The value of the property.
|
* \param propertyValue The value of the property.
|
||||||
*/
|
*/
|
||||||
PropertyDescriptor(gd::String propertyValue)
|
PropertyDescriptor(gd::String propertyValue)
|
||||||
: currentValue(propertyValue), type("string"), label(""), hidden(false),
|
: currentValue(propertyValue),
|
||||||
deprecated(false), advanced(false),
|
type("string"),
|
||||||
|
label(""),
|
||||||
|
hidden(false),
|
||||||
|
deprecated(false),
|
||||||
|
advanced(false),
|
||||||
hasImpactOnOtherProperties(false),
|
hasImpactOnOtherProperties(false),
|
||||||
measurementUnit(gd::MeasurementUnit::GetUndefined()),
|
measurementUnit(gd::MeasurementUnit::GetUndefined()),
|
||||||
quickCustomizationVisibility(QuickCustomization::Visibility::Default) {}
|
quickCustomizationVisibility(QuickCustomization::Visibility::Default) {}
|
||||||
@@ -41,10 +58,13 @@ class GD_CORE_API PropertyDescriptor {
|
|||||||
* \brief Empty constructor creating an empty property to be displayed.
|
* \brief Empty constructor creating an empty property to be displayed.
|
||||||
*/
|
*/
|
||||||
PropertyDescriptor()
|
PropertyDescriptor()
|
||||||
: hidden(false), deprecated(false), advanced(false),
|
: hidden(false),
|
||||||
|
deprecated(false),
|
||||||
|
advanced(false),
|
||||||
hasImpactOnOtherProperties(false),
|
hasImpactOnOtherProperties(false),
|
||||||
measurementUnit(gd::MeasurementUnit::GetUndefined()),
|
measurementUnit(gd::MeasurementUnit::GetUndefined()),
|
||||||
quickCustomizationVisibility(QuickCustomization::Visibility::Default){};
|
quickCustomizationVisibility(QuickCustomization::Visibility::Default) {
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Destructor
|
* \brief Destructor
|
||||||
@@ -88,13 +108,25 @@ class GD_CORE_API PropertyDescriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Change the group where this property is displayed to the user, if any.
|
* \brief Change the group where this property is displayed to the user, if
|
||||||
|
* any.
|
||||||
*/
|
*/
|
||||||
PropertyDescriptor& SetGroup(gd::String group_) {
|
PropertyDescriptor& SetGroup(gd::String group_) {
|
||||||
group = group_;
|
group = group_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PropertyDescriptor& ClearChoices() {
|
||||||
|
choices.clear();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyDescriptor& AddChoice(const gd::String& value,
|
||||||
|
const gd::String& label) {
|
||||||
|
choices.push_back(PropertyDescriptorChoice(value, label));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set and replace the additional information for the property.
|
* \brief Set and replace the additional information for the property.
|
||||||
*/
|
*/
|
||||||
@@ -118,7 +150,8 @@ class GD_CORE_API PropertyDescriptor {
|
|||||||
/**
|
/**
|
||||||
* \brief Change the unit of measurement of the property value.
|
* \brief Change the unit of measurement of the property value.
|
||||||
*/
|
*/
|
||||||
PropertyDescriptor& SetMeasurementUnit(const gd::MeasurementUnit &measurementUnit_) {
|
PropertyDescriptor& SetMeasurementUnit(
|
||||||
|
const gd::MeasurementUnit& measurementUnit_) {
|
||||||
measurementUnit = measurementUnit_;
|
measurementUnit = measurementUnit_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -128,14 +161,18 @@ class GD_CORE_API PropertyDescriptor {
|
|||||||
const gd::String& GetLabel() const { return label; }
|
const gd::String& GetLabel() const { return label; }
|
||||||
const gd::String& GetDescription() const { return description; }
|
const gd::String& GetDescription() const { return description; }
|
||||||
const gd::String& GetGroup() const { return group; }
|
const gd::String& GetGroup() const { return group; }
|
||||||
const gd::MeasurementUnit& GetMeasurementUnit() const { return measurementUnit; }
|
const gd::MeasurementUnit& GetMeasurementUnit() const {
|
||||||
|
return measurementUnit;
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<gd::String>& GetExtraInfo() const {
|
const std::vector<gd::String>& GetExtraInfo() const {
|
||||||
return extraInformation;
|
return extraInformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<gd::String>& GetExtraInfo() {
|
std::vector<gd::String>& GetExtraInfo() { return extraInformation; }
|
||||||
return extraInformation;
|
|
||||||
|
const std::vector<PropertyDescriptorChoice>& GetChoices() const {
|
||||||
|
return choices;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,23 +215,26 @@ class GD_CORE_API PropertyDescriptor {
|
|||||||
bool IsAdvanced() const { return advanced; }
|
bool IsAdvanced() const { return advanced; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Check if the property has impact on other properties - which means a change
|
* \brief Check if the property has impact on other properties - which means a
|
||||||
* must re-render other properties.
|
* change must re-render other properties.
|
||||||
*/
|
*/
|
||||||
bool HasImpactOnOtherProperties() const { return hasImpactOnOtherProperties; }
|
bool HasImpactOnOtherProperties() const { return hasImpactOnOtherProperties; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set if the property has impact on other properties - which means a change
|
* \brief Set if the property has impact on other properties - which means a
|
||||||
* must re-render other properties.
|
* change must re-render other properties.
|
||||||
*/
|
*/
|
||||||
PropertyDescriptor& SetHasImpactOnOtherProperties(bool enable) {
|
PropertyDescriptor& SetHasImpactOnOtherProperties(bool enable) {
|
||||||
hasImpactOnOtherProperties = enable;
|
hasImpactOnOtherProperties = enable;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
QuickCustomization::Visibility GetQuickCustomizationVisibility() const { return quickCustomizationVisibility; }
|
QuickCustomization::Visibility GetQuickCustomizationVisibility() const {
|
||||||
|
return quickCustomizationVisibility;
|
||||||
|
}
|
||||||
|
|
||||||
PropertyDescriptor& SetQuickCustomizationVisibility(QuickCustomization::Visibility visibility) {
|
PropertyDescriptor& SetQuickCustomizationVisibility(
|
||||||
|
QuickCustomization::Visibility visibility) {
|
||||||
quickCustomizationVisibility = visibility;
|
quickCustomizationVisibility = visibility;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -231,15 +271,17 @@ class GD_CORE_API PropertyDescriptor {
|
|||||||
gd::String label; //< The user-friendly property name
|
gd::String label; //< The user-friendly property name
|
||||||
gd::String description; //< The user-friendly property description
|
gd::String description; //< The user-friendly property description
|
||||||
gd::String group; //< The user-friendly property group
|
gd::String group; //< The user-friendly property group
|
||||||
|
std::vector<PropertyDescriptorChoice>
|
||||||
|
choices; //< The optional choices for the property.
|
||||||
std::vector<gd::String>
|
std::vector<gd::String>
|
||||||
extraInformation; ///< Can be used to store for example the available
|
extraInformation; ///< Can be used to store an additional information
|
||||||
///< choices, if a property is a displayed as a combo
|
///< like an object type.
|
||||||
///< box.
|
|
||||||
bool hidden;
|
bool hidden;
|
||||||
bool deprecated;
|
bool deprecated;
|
||||||
bool advanced;
|
bool advanced;
|
||||||
bool hasImpactOnOtherProperties;
|
bool hasImpactOnOtherProperties;
|
||||||
gd::MeasurementUnit measurementUnit; //< The unit of measurement of the property vale.
|
gd::MeasurementUnit
|
||||||
|
measurementUnit; //< The unit of measurement of the property vale.
|
||||||
QuickCustomization::Visibility quickCustomizationVisibility;
|
QuickCustomization::Visibility quickCustomizationVisibility;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@ The rest of this page is an introduction to the main concepts of GDevelop archit
|
|||||||
|
|
||||||
Extensions do have the same distinction between the "**IDE**" part and the "**Runtime**" part. For example, most extensions have:
|
Extensions do have the same distinction between the "**IDE**" part and the "**Runtime**" part. For example, most extensions have:
|
||||||
|
|
||||||
- A file called [`JsExtension.js`(https://github.com/4ian/GDevelop/blob/master/Extensions/ExampleJsExtension/JsExtension.js)], which contains the _declaration_ of the extension for the **IDE**
|
- A file called [`JsExtension.js`](https://github.com/4ian/GDevelop/blob/master/Extensions/ExampleJsExtension/JsExtension.js), which contains the _declaration_ of the extension for the **IDE**
|
||||||
- One or more files implementing the feature for the game, in other words for **Runtime**. This can be a [Runtime Object](https://github.com/4ian/GDevelop/blob/master/Extensions/ExampleJsExtension/dummyruntimeobject.ts) or a [Runtime Behavior](https://github.com/4ian/GDevelop/blob/master/Extensions/ExampleJsExtension/dummyruntimebehavior.ts), [functions called by actions or conditions](https://github.com/4ian/GDevelop/blob/master/Extensions/ExampleJsExtension/examplejsextensiontools.ts) or by the game engine.
|
- One or more files implementing the feature for the game, in other words for **Runtime**. This can be a [Runtime Object](https://github.com/4ian/GDevelop/blob/master/Extensions/ExampleJsExtension/dummyruntimeobject.ts) or a [Runtime Behavior](https://github.com/4ian/GDevelop/blob/master/Extensions/ExampleJsExtension/dummyruntimebehavior.ts), [functions called by actions or conditions](https://github.com/4ian/GDevelop/blob/master/Extensions/ExampleJsExtension/examplejsextensiontools.ts) or by the game engine.
|
||||||
|
|
||||||
### "Runtime" and "IDE" difference using an example: the `gd::Variable` class
|
### "Runtime" and "IDE" difference using an example: the `gd::Variable` class
|
||||||
|
@@ -764,129 +764,6 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
|||||||
REQUIRE(worker.audios[0] == "res4");
|
REQUIRE(worker.audios[0] == "res4");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Can find resource usages in event-based functions") {
|
|
||||||
gd::Project project;
|
|
||||||
gd::Platform platform;
|
|
||||||
SetupProjectWithDummyPlatform(project, platform);
|
|
||||||
|
|
||||||
project.GetResourcesManager().AddResource(
|
|
||||||
"res1", "path/to/file1.png", "image");
|
|
||||||
project.GetResourcesManager().AddResource(
|
|
||||||
"res2", "path/to/file2.png", "image");
|
|
||||||
project.GetResourcesManager().AddResource(
|
|
||||||
"res3", "path/to/file3.png", "image");
|
|
||||||
ArbitraryResourceWorkerTest worker(project.GetResourcesManager());
|
|
||||||
|
|
||||||
auto& extension = project.InsertNewEventsFunctionsExtension("MyEventExtension", 0);
|
|
||||||
auto &function = extension.GetEventsFunctions().InsertNewEventsFunction(
|
|
||||||
"MyFreeFunction", 0);
|
|
||||||
|
|
||||||
gd::StandardEvent standardEvent;
|
|
||||||
gd::Instruction instruction;
|
|
||||||
instruction.SetType("MyExtension::DoSomethingWithResources");
|
|
||||||
instruction.SetParametersCount(3);
|
|
||||||
instruction.SetParameter(0, "res3");
|
|
||||||
instruction.SetParameter(1, "res1");
|
|
||||||
instruction.SetParameter(2, "res4");
|
|
||||||
standardEvent.GetActions().Insert(instruction);
|
|
||||||
function.GetEvents().InsertEvent(standardEvent);
|
|
||||||
|
|
||||||
auto& layout = project.InsertNewLayout("MyScene", 0);
|
|
||||||
|
|
||||||
// MyEventExtension::MyFreeFunction doesn't need to be actually used in
|
|
||||||
// events because the implementation is naive.
|
|
||||||
|
|
||||||
gd::ResourceExposer::ExposeLayoutResources(project, layout, worker);
|
|
||||||
REQUIRE(worker.bitmapFonts.size() == 1);
|
|
||||||
REQUIRE(worker.bitmapFonts[0] == "res3");
|
|
||||||
REQUIRE(worker.images.size() == 1);
|
|
||||||
REQUIRE(worker.images[0] == "res1");
|
|
||||||
REQUIRE(worker.audios.size() == 1);
|
|
||||||
REQUIRE(worker.audios[0] == "res4");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Can find resource usages in event-based behavior functions") {
|
|
||||||
gd::Project project;
|
|
||||||
gd::Platform platform;
|
|
||||||
SetupProjectWithDummyPlatform(project, platform);
|
|
||||||
|
|
||||||
project.GetResourcesManager().AddResource(
|
|
||||||
"res1", "path/to/file1.png", "image");
|
|
||||||
project.GetResourcesManager().AddResource(
|
|
||||||
"res2", "path/to/file2.png", "image");
|
|
||||||
project.GetResourcesManager().AddResource(
|
|
||||||
"res3", "path/to/file3.png", "image");
|
|
||||||
ArbitraryResourceWorkerTest worker(project.GetResourcesManager());
|
|
||||||
|
|
||||||
auto& extension = project.InsertNewEventsFunctionsExtension("MyEventExtension", 0);
|
|
||||||
auto& behavior = extension.GetEventsBasedBehaviors().InsertNew("MyBehavior", 0);
|
|
||||||
auto& function = behavior.GetEventsFunctions().InsertNewEventsFunction("MyFunction", 0);
|
|
||||||
|
|
||||||
gd::StandardEvent standardEvent;
|
|
||||||
gd::Instruction instruction;
|
|
||||||
instruction.SetType("MyExtension::DoSomethingWithResources");
|
|
||||||
instruction.SetParametersCount(3);
|
|
||||||
instruction.SetParameter(0, "res3");
|
|
||||||
instruction.SetParameter(1, "res1");
|
|
||||||
instruction.SetParameter(2, "res4");
|
|
||||||
standardEvent.GetActions().Insert(instruction);
|
|
||||||
function.GetEvents().InsertEvent(standardEvent);
|
|
||||||
|
|
||||||
auto& layout = project.InsertNewLayout("MyScene", 0);
|
|
||||||
|
|
||||||
// MyEventExtension::MyBehavior::MyFunction doesn't need to be actually used in
|
|
||||||
// events because the implementation is naive.
|
|
||||||
|
|
||||||
gd::ResourceExposer::ExposeLayoutResources(project, layout, worker);
|
|
||||||
REQUIRE(worker.bitmapFonts.size() == 1);
|
|
||||||
REQUIRE(worker.bitmapFonts[0] == "res3");
|
|
||||||
REQUIRE(worker.images.size() == 1);
|
|
||||||
REQUIRE(worker.images[0] == "res1");
|
|
||||||
REQUIRE(worker.audios.size() == 1);
|
|
||||||
REQUIRE(worker.audios[0] == "res4");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Can find resource usages in event-based object functions") {
|
|
||||||
gd::Project project;
|
|
||||||
gd::Platform platform;
|
|
||||||
SetupProjectWithDummyPlatform(project, platform);
|
|
||||||
|
|
||||||
project.GetResourcesManager().AddResource(
|
|
||||||
"res1", "path/to/file1.png", "image");
|
|
||||||
project.GetResourcesManager().AddResource(
|
|
||||||
"res2", "path/to/file2.png", "image");
|
|
||||||
project.GetResourcesManager().AddResource(
|
|
||||||
"res3", "path/to/file3.png", "image");
|
|
||||||
ArbitraryResourceWorkerTest worker(project.GetResourcesManager());
|
|
||||||
|
|
||||||
auto& extension = project.InsertNewEventsFunctionsExtension("MyEventExtension", 0);
|
|
||||||
auto& object = extension.GetEventsBasedObjects().InsertNew("MyObject", 0);
|
|
||||||
auto& function = object.GetEventsFunctions().InsertNewEventsFunction("MyFunction", 0);
|
|
||||||
|
|
||||||
gd::StandardEvent standardEvent;
|
|
||||||
gd::Instruction instruction;
|
|
||||||
instruction.SetType("MyExtension::DoSomethingWithResources");
|
|
||||||
instruction.SetParametersCount(3);
|
|
||||||
instruction.SetParameter(0, "res3");
|
|
||||||
instruction.SetParameter(1, "res1");
|
|
||||||
instruction.SetParameter(2, "res4");
|
|
||||||
standardEvent.GetActions().Insert(instruction);
|
|
||||||
function.GetEvents().InsertEvent(standardEvent);
|
|
||||||
|
|
||||||
auto& layout = project.InsertNewLayout("MyScene", 0);
|
|
||||||
|
|
||||||
// MyEventExtension::MyObject::MyFunction doesn't need to be actually used in
|
|
||||||
// events because the implementation is naive.
|
|
||||||
|
|
||||||
gd::ResourceExposer::ExposeLayoutResources(project, layout, worker);
|
|
||||||
REQUIRE(worker.bitmapFonts.size() == 1);
|
|
||||||
REQUIRE(worker.bitmapFonts[0] == "res3");
|
|
||||||
REQUIRE(worker.images.size() == 1);
|
|
||||||
REQUIRE(worker.images[0] == "res1");
|
|
||||||
REQUIRE(worker.audios.size() == 1);
|
|
||||||
REQUIRE(worker.audios[0] == "res4");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Can find resource usages in layer effects") {
|
SECTION("Can find resource usages in layer effects") {
|
||||||
gd::Project project;
|
gd::Project project;
|
||||||
gd::Platform platform;
|
gd::Platform platform;
|
||||||
|
@@ -139,8 +139,8 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
|||||||
.SetLabel("Dot shape")
|
.SetLabel("Dot shape")
|
||||||
.SetDescription("The shape is used for collision.")
|
.SetDescription("The shape is used for collision.")
|
||||||
.SetGroup("Movement");
|
.SetGroup("Movement");
|
||||||
property.GetExtraInfo().push_back("Dot shape");
|
property.AddChoice("DotShape", "Dot shape");
|
||||||
property.GetExtraInfo().push_back("Bounding disk");
|
property.AddChoice("BoundingDisk", "Bounding disk");
|
||||||
|
|
||||||
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
|
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
|
||||||
project, extension, behavior, property, false);
|
project, extension, behavior, property, false);
|
||||||
@@ -157,7 +157,7 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
|||||||
gd::EventsFunction::ExpressionAndCondition);
|
gd::EventsFunction::ExpressionAndCondition);
|
||||||
REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector");
|
REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector");
|
||||||
REQUIRE(getter.GetExpressionType().GetExtraInfo() ==
|
REQUIRE(getter.GetExpressionType().GetExtraInfo() ==
|
||||||
"[\"Dot shape\",\"Bounding disk\"]");
|
"[\"DotShape\",\"BoundingDisk\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Can generate functions for a boolean property in a behavior") {
|
SECTION("Can generate functions for a boolean property in a behavior") {
|
||||||
@@ -386,8 +386,8 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
|||||||
.SetLabel("Dot shape")
|
.SetLabel("Dot shape")
|
||||||
.SetDescription("The shape is used for collision.")
|
.SetDescription("The shape is used for collision.")
|
||||||
.SetGroup("Movement");
|
.SetGroup("Movement");
|
||||||
property.GetExtraInfo().push_back("Dot shape");
|
property.AddChoice("DotShape", "Dot shape");
|
||||||
property.GetExtraInfo().push_back("Bounding disk");
|
property.AddChoice("BoundingDisk", "Bounding disk");
|
||||||
|
|
||||||
gd::PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
|
gd::PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
|
||||||
project, extension, object, property);
|
project, extension, object, property);
|
||||||
@@ -404,7 +404,7 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
|||||||
gd::EventsFunction::ExpressionAndCondition);
|
gd::EventsFunction::ExpressionAndCondition);
|
||||||
REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector");
|
REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector");
|
||||||
REQUIRE(getter.GetExpressionType().GetExtraInfo() ==
|
REQUIRE(getter.GetExpressionType().GetExtraInfo() ==
|
||||||
"[\"Dot shape\",\"Bounding disk\"]");
|
"[\"DotShape\",\"BoundingDisk\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Can generate functions for a boolean property in an object") {
|
SECTION("Can generate functions for a boolean property in an object") {
|
||||||
|
@@ -5,8 +5,6 @@ namespace gdjs {
|
|||||||
type Object3DNetworkSyncDataType = {
|
type Object3DNetworkSyncDataType = {
|
||||||
// z is position on the Z axis, different from zo, which is Z order
|
// z is position on the Z axis, different from zo, which is Z order
|
||||||
z: number;
|
z: number;
|
||||||
w: number;
|
|
||||||
h: number;
|
|
||||||
d: number;
|
d: number;
|
||||||
rx: number;
|
rx: number;
|
||||||
ry: number;
|
ry: number;
|
||||||
@@ -99,6 +97,14 @@ namespace gdjs {
|
|||||||
oldObjectData: Object3DData,
|
oldObjectData: Object3DData,
|
||||||
newObjectData: Object3DData
|
newObjectData: Object3DData
|
||||||
): boolean {
|
): boolean {
|
||||||
|
this.updateOriginalDimensionsFromObjectData(oldObjectData, newObjectData);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOriginalDimensionsFromObjectData(
|
||||||
|
oldObjectData: Object3DData,
|
||||||
|
newObjectData: Object3DData
|
||||||
|
): void {
|
||||||
// There is no need to check if they changed because events can't modify them.
|
// There is no need to check if they changed because events can't modify them.
|
||||||
this._setOriginalWidth(
|
this._setOriginalWidth(
|
||||||
getValidDimensionValue(newObjectData.content.width)
|
getValidDimensionValue(newObjectData.content.width)
|
||||||
@@ -109,15 +115,14 @@ namespace gdjs {
|
|||||||
this._setOriginalDepth(
|
this._setOriginalDepth(
|
||||||
getValidDimensionValue(newObjectData.content.depth)
|
getValidDimensionValue(newObjectData.content.depth)
|
||||||
);
|
);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getNetworkSyncData(): Object3DNetworkSyncData {
|
getNetworkSyncData(
|
||||||
|
syncOptions: GetNetworkSyncDataOptions
|
||||||
|
): Object3DNetworkSyncData {
|
||||||
return {
|
return {
|
||||||
...super.getNetworkSyncData(),
|
...super.getNetworkSyncData(syncOptions),
|
||||||
z: this.getZ(),
|
z: this.getZ(),
|
||||||
w: this.getWidth(),
|
|
||||||
h: this.getHeight(),
|
|
||||||
d: this.getDepth(),
|
d: this.getDepth(),
|
||||||
rx: this.getRotationX(),
|
rx: this.getRotationX(),
|
||||||
ry: this.getRotationY(),
|
ry: this.getRotationY(),
|
||||||
@@ -127,11 +132,12 @@ namespace gdjs {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFromNetworkSyncData(networkSyncData: Object3DNetworkSyncData) {
|
updateFromNetworkSyncData(
|
||||||
super.updateFromNetworkSyncData(networkSyncData);
|
networkSyncData: Object3DNetworkSyncData,
|
||||||
|
options: UpdateFromNetworkSyncDataOptions
|
||||||
|
) {
|
||||||
|
super.updateFromNetworkSyncData(networkSyncData, options);
|
||||||
if (networkSyncData.z !== undefined) this.setZ(networkSyncData.z);
|
if (networkSyncData.z !== undefined) this.setZ(networkSyncData.z);
|
||||||
if (networkSyncData.w !== undefined) this.setWidth(networkSyncData.w);
|
|
||||||
if (networkSyncData.h !== undefined) this.setHeight(networkSyncData.h);
|
|
||||||
if (networkSyncData.d !== undefined) this.setDepth(networkSyncData.d);
|
if (networkSyncData.d !== undefined) this.setDepth(networkSyncData.d);
|
||||||
if (networkSyncData.rx !== undefined)
|
if (networkSyncData.rx !== undefined)
|
||||||
this.setRotationX(networkSyncData.rx);
|
this.setRotationX(networkSyncData.rx);
|
||||||
|
@@ -25,6 +25,8 @@ namespace gdjs {
|
|||||||
topFaceVisible: boolean;
|
topFaceVisible: boolean;
|
||||||
bottomFaceVisible: boolean;
|
bottomFaceVisible: boolean;
|
||||||
tint: string | undefined;
|
tint: string | undefined;
|
||||||
|
isCastingShadow: boolean;
|
||||||
|
isReceivingShadow: boolean;
|
||||||
materialType: 'Basic' | 'StandardWithoutMetalness';
|
materialType: 'Basic' | 'StandardWithoutMetalness';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -71,8 +73,10 @@ namespace gdjs {
|
|||||||
string,
|
string,
|
||||||
];
|
];
|
||||||
_materialType: gdjs.Cube3DRuntimeObject.MaterialType =
|
_materialType: gdjs.Cube3DRuntimeObject.MaterialType =
|
||||||
gdjs.Cube3DRuntimeObject.MaterialType.Basic;
|
gdjs.Cube3DRuntimeObject.MaterialType.StandardWithoutMetalness;
|
||||||
_tint: string;
|
_tint: string;
|
||||||
|
_isCastingShadow: boolean = true;
|
||||||
|
_isReceivingShadow: boolean = true;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||||
@@ -121,6 +125,8 @@ namespace gdjs {
|
|||||||
];
|
];
|
||||||
|
|
||||||
this._tint = objectData.content.tint || '255;255;255';
|
this._tint = objectData.content.tint || '255;255;255';
|
||||||
|
this._isCastingShadow = objectData.content.isCastingShadow || false;
|
||||||
|
this._isReceivingShadow = objectData.content.isReceivingShadow || false;
|
||||||
|
|
||||||
this._materialType = this._convertMaterialType(
|
this._materialType = this._convertMaterialType(
|
||||||
objectData.content.materialType
|
objectData.content.materialType
|
||||||
@@ -430,13 +436,27 @@ namespace gdjs {
|
|||||||
) {
|
) {
|
||||||
this.setMaterialType(newObjectData.content.materialType);
|
this.setMaterialType(newObjectData.content.materialType);
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
oldObjectData.content.isCastingShadow !==
|
||||||
|
newObjectData.content.isCastingShadow
|
||||||
|
) {
|
||||||
|
this.updateShadowCasting(newObjectData.content.isCastingShadow);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
oldObjectData.content.isReceivingShadow !==
|
||||||
|
newObjectData.content.isReceivingShadow
|
||||||
|
) {
|
||||||
|
this.updateShadowReceiving(newObjectData.content.isReceivingShadow);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getNetworkSyncData(): Cube3DObjectNetworkSyncData {
|
getNetworkSyncData(
|
||||||
|
syncOptions: GetNetworkSyncDataOptions
|
||||||
|
): Cube3DObjectNetworkSyncData {
|
||||||
return {
|
return {
|
||||||
...super.getNetworkSyncData(),
|
...super.getNetworkSyncData(syncOptions),
|
||||||
mt: this._materialType,
|
mt: this._materialType,
|
||||||
fo: this._facesOrientation,
|
fo: this._facesOrientation,
|
||||||
bfu: this._backFaceUpThroughWhichAxisRotation,
|
bfu: this._backFaceUpThroughWhichAxisRotation,
|
||||||
@@ -448,9 +468,10 @@ namespace gdjs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateFromNetworkSyncData(
|
updateFromNetworkSyncData(
|
||||||
networkSyncData: Cube3DObjectNetworkSyncData
|
networkSyncData: Cube3DObjectNetworkSyncData,
|
||||||
|
options: UpdateFromNetworkSyncDataOptions
|
||||||
): void {
|
): void {
|
||||||
super.updateFromNetworkSyncData(networkSyncData);
|
super.updateFromNetworkSyncData(networkSyncData, options);
|
||||||
|
|
||||||
if (networkSyncData.mt !== undefined) {
|
if (networkSyncData.mt !== undefined) {
|
||||||
this._materialType = networkSyncData.mt;
|
this._materialType = networkSyncData.mt;
|
||||||
@@ -531,6 +552,14 @@ namespace gdjs {
|
|||||||
this._materialType = newMaterialType;
|
this._materialType = newMaterialType;
|
||||||
this._renderer._updateMaterials();
|
this._renderer._updateMaterials();
|
||||||
}
|
}
|
||||||
|
updateShadowCasting(value: boolean) {
|
||||||
|
this._isCastingShadow = value;
|
||||||
|
this._renderer.updateShadowCasting();
|
||||||
|
}
|
||||||
|
updateShadowReceiving(value: boolean) {
|
||||||
|
this._isReceivingShadow = value;
|
||||||
|
this._renderer.updateShadowReceiving();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace Cube3DRuntimeObject {
|
export namespace Cube3DRuntimeObject {
|
||||||
|
@@ -81,13 +81,14 @@ namespace gdjs {
|
|||||||
.map((_, index) =>
|
.map((_, index) =>
|
||||||
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[index])
|
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[index])
|
||||||
);
|
);
|
||||||
|
|
||||||
const boxMesh = new THREE.Mesh(geometry, materials);
|
const boxMesh = new THREE.Mesh(geometry, materials);
|
||||||
|
|
||||||
super(runtimeObject, instanceContainer, boxMesh);
|
super(runtimeObject, instanceContainer, boxMesh);
|
||||||
this._boxMesh = boxMesh;
|
this._boxMesh = boxMesh;
|
||||||
this._cube3DRuntimeObject = runtimeObject;
|
this._cube3DRuntimeObject = runtimeObject;
|
||||||
|
|
||||||
|
boxMesh.receiveShadow = this._cube3DRuntimeObject._isReceivingShadow;
|
||||||
|
boxMesh.castShadow = this._cube3DRuntimeObject._isCastingShadow;
|
||||||
this.updateSize();
|
this.updateSize();
|
||||||
this.updatePosition();
|
this.updatePosition();
|
||||||
this.updateRotation();
|
this.updateRotation();
|
||||||
@@ -114,6 +115,13 @@ namespace gdjs {
|
|||||||
new THREE.BufferAttribute(new Float32Array(tints), 3)
|
new THREE.BufferAttribute(new Float32Array(tints), 3)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
updateShadowCasting() {
|
||||||
|
this._boxMesh.castShadow = this._cube3DRuntimeObject._isCastingShadow;
|
||||||
|
}
|
||||||
|
updateShadowReceiving() {
|
||||||
|
this._boxMesh.receiveShadow =
|
||||||
|
this._cube3DRuntimeObject._isReceivingShadow;
|
||||||
|
}
|
||||||
|
|
||||||
updateFace(faceIndex: integer) {
|
updateFace(faceIndex: integer) {
|
||||||
const materialIndex = faceIndexToMaterialIndex[faceIndex];
|
const materialIndex = faceIndexToMaterialIndex[faceIndex];
|
||||||
|
@@ -1,4 +1,16 @@
|
|||||||
namespace gdjs {
|
namespace gdjs {
|
||||||
|
type CustomObject3DNetworkSyncDataType = {
|
||||||
|
z: float;
|
||||||
|
d: float;
|
||||||
|
rx: float;
|
||||||
|
ry: float;
|
||||||
|
ifz: boolean;
|
||||||
|
ccz: float;
|
||||||
|
};
|
||||||
|
|
||||||
|
type CustomObject3DNetworkSyncData = CustomObjectNetworkSyncData &
|
||||||
|
CustomObject3DNetworkSyncDataType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for 3D custom objects.
|
* Base class for 3D custom objects.
|
||||||
*/
|
*/
|
||||||
@@ -34,7 +46,6 @@ namespace gdjs {
|
|||||||
objectData: gdjs.Object3DData & gdjs.CustomObjectConfiguration
|
objectData: gdjs.Object3DData & gdjs.CustomObjectConfiguration
|
||||||
) {
|
) {
|
||||||
super(parent, objectData);
|
super(parent, objectData);
|
||||||
this._renderer.reinitialize(this, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override _createRender() {
|
protected override _createRender() {
|
||||||
@@ -78,6 +89,36 @@ namespace gdjs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNetworkSyncData(
|
||||||
|
syncOptions: GetNetworkSyncDataOptions
|
||||||
|
): CustomObject3DNetworkSyncData {
|
||||||
|
return {
|
||||||
|
...super.getNetworkSyncData(syncOptions),
|
||||||
|
z: this.getZ(),
|
||||||
|
d: this.getDepth(),
|
||||||
|
rx: this.getRotationX(),
|
||||||
|
ry: this.getRotationY(),
|
||||||
|
ifz: this.isFlippedZ(),
|
||||||
|
ccz: this._customCenterZ,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFromNetworkSyncData(
|
||||||
|
networkSyncData: CustomObject3DNetworkSyncData,
|
||||||
|
options: UpdateFromNetworkSyncDataOptions
|
||||||
|
): void {
|
||||||
|
super.updateFromNetworkSyncData(networkSyncData, options);
|
||||||
|
if (networkSyncData.z !== undefined) this.setZ(networkSyncData.z);
|
||||||
|
if (networkSyncData.d !== undefined) this.setDepth(networkSyncData.d);
|
||||||
|
if (networkSyncData.rx !== undefined)
|
||||||
|
this.setRotationX(networkSyncData.rx);
|
||||||
|
if (networkSyncData.ry !== undefined)
|
||||||
|
this.setRotationY(networkSyncData.ry);
|
||||||
|
if (networkSyncData.ifz !== undefined) this.flipZ(networkSyncData.ifz);
|
||||||
|
if (networkSyncData.ccz !== undefined)
|
||||||
|
this._customCenterZ = networkSyncData.ccz;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the object position on the Z axis.
|
* Set the object position on the Z axis.
|
||||||
*/
|
*/
|
||||||
|
@@ -44,10 +44,7 @@ namespace gdjs {
|
|||||||
) {
|
) {
|
||||||
this._object = object;
|
this._object = object;
|
||||||
this._isContainerDirty = true;
|
this._isContainerDirty = true;
|
||||||
const layer = parent.getLayer('');
|
this._threeGroup.clear();
|
||||||
if (layer) {
|
|
||||||
layer.getRenderer().add3DRendererObject(this._threeGroup);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateThreeGroup() {
|
_updateThreeGroup() {
|
||||||
|
@@ -6,6 +6,7 @@ namespace gdjs {
|
|||||||
r: number;
|
r: number;
|
||||||
t: string;
|
t: string;
|
||||||
}
|
}
|
||||||
|
const shadowHelper = false;
|
||||||
gdjs.PixiFiltersTools.registerFilterCreator(
|
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||||
'Scene3D::DirectionalLight',
|
'Scene3D::DirectionalLight',
|
||||||
new (class implements gdjs.PixiFiltersTools.FilterCreator {
|
new (class implements gdjs.PixiFiltersTools.FilterCreator {
|
||||||
@@ -17,19 +18,63 @@ namespace gdjs {
|
|||||||
return new gdjs.PixiFiltersTools.EmptyFilter();
|
return new gdjs.PixiFiltersTools.EmptyFilter();
|
||||||
}
|
}
|
||||||
return new (class implements gdjs.PixiFiltersTools.Filter {
|
return new (class implements gdjs.PixiFiltersTools.Filter {
|
||||||
light: THREE.DirectionalLight;
|
private _top: string = 'Z+';
|
||||||
rotationObject: THREE.Group;
|
private _elevation: float = 45;
|
||||||
_isEnabled: boolean = false;
|
private _rotation: float = 0;
|
||||||
top: string = 'Y-';
|
private _shadowMapSize: float = 1024;
|
||||||
elevation: float = 45;
|
private _minimumShadowBias: float = 0;
|
||||||
rotation: float = 0;
|
private _distanceFromCamera: float = 1500;
|
||||||
|
private _frustumSize: float = 4000;
|
||||||
|
|
||||||
|
private _isEnabled: boolean = false;
|
||||||
|
private _light: THREE.DirectionalLight;
|
||||||
|
private _shadowMapDirty = true;
|
||||||
|
private _shadowCameraDirty = true;
|
||||||
|
private _shadowCameraHelper: THREE.CameraHelper | null;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.light = new THREE.DirectionalLight();
|
this._light = new THREE.DirectionalLight();
|
||||||
this.light.position.set(1, 0, 0);
|
|
||||||
this.rotationObject = new THREE.Group();
|
if (shadowHelper) {
|
||||||
this.rotationObject.add(this.light);
|
this._shadowCameraHelper = new THREE.CameraHelper(
|
||||||
this.updateRotation();
|
this._light.shadow.camera
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this._shadowCameraHelper = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._light.shadow.camera.updateProjectionMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _updateShadowCamera(): void {
|
||||||
|
if (!this._shadowCameraDirty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._shadowCameraDirty = false;
|
||||||
|
|
||||||
|
this._light.shadow.camera.near = 1;
|
||||||
|
this._light.shadow.camera.far = this._distanceFromCamera + 10000;
|
||||||
|
this._light.shadow.camera.right = this._frustumSize / 2;
|
||||||
|
this._light.shadow.camera.left = -this._frustumSize / 2;
|
||||||
|
this._light.shadow.camera.top = this._frustumSize / 2;
|
||||||
|
this._light.shadow.camera.bottom = -this._frustumSize / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _updateShadowMapSize(): void {
|
||||||
|
if (!this._shadowMapDirty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._shadowMapDirty = false;
|
||||||
|
|
||||||
|
this._light.shadow.mapSize.set(
|
||||||
|
this._shadowMapSize,
|
||||||
|
this._shadowMapSize
|
||||||
|
);
|
||||||
|
|
||||||
|
// Force the recreation of the shadow map texture:
|
||||||
|
this._light.shadow.map?.dispose();
|
||||||
|
this._light.shadow.map = null;
|
||||||
|
this._light.shadow.needsUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
isEnabled(target: EffectsTarget): boolean {
|
isEnabled(target: EffectsTarget): boolean {
|
||||||
@@ -53,7 +98,12 @@ namespace gdjs {
|
|||||||
if (!scene) {
|
if (!scene) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
scene.add(this.rotationObject);
|
scene.add(this._light);
|
||||||
|
scene.add(this._light.target);
|
||||||
|
if (this._shadowCameraHelper) {
|
||||||
|
scene.add(this._shadowCameraHelper);
|
||||||
|
}
|
||||||
|
|
||||||
this._isEnabled = true;
|
this._isEnabled = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -65,82 +115,164 @@ namespace gdjs {
|
|||||||
if (!scene) {
|
if (!scene) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
scene.remove(this.rotationObject);
|
scene.remove(this._light);
|
||||||
|
scene.remove(this._light.target);
|
||||||
|
if (this._shadowCameraHelper) {
|
||||||
|
scene.remove(this._shadowCameraHelper);
|
||||||
|
}
|
||||||
this._isEnabled = false;
|
this._isEnabled = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
updatePreRender(target: gdjs.EffectsTarget): any {}
|
updatePreRender(target: gdjs.EffectsTarget): any {
|
||||||
|
// Apply any update to the camera or shadow map size.
|
||||||
|
this._updateShadowCamera();
|
||||||
|
this._updateShadowMapSize();
|
||||||
|
|
||||||
|
// Avoid shadow acne due to depth buffer precision.
|
||||||
|
const biasMultiplier =
|
||||||
|
this._shadowMapSize < 1024
|
||||||
|
? 2
|
||||||
|
: this._shadowMapSize < 2048
|
||||||
|
? 1.25
|
||||||
|
: 1;
|
||||||
|
this._light.shadow.bias = -this._minimumShadowBias * biasMultiplier;
|
||||||
|
|
||||||
|
// Apply update to the light position and its target.
|
||||||
|
// By doing this, the shadows are "following" the GDevelop camera.
|
||||||
|
if (!target.getRuntimeLayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const layer = target.getRuntimeLayer();
|
||||||
|
const x = layer.getCameraX();
|
||||||
|
const y = layer.getCameraY();
|
||||||
|
const z = layer.getCameraZ(layer.getInitialCamera3DFieldOfView());
|
||||||
|
|
||||||
|
const roundedX = Math.floor(x / 100) * 100;
|
||||||
|
const roundedY = Math.floor(y / 100) * 100;
|
||||||
|
const roundedZ = Math.floor(z / 100) * 100;
|
||||||
|
if (this._top === 'Y-') {
|
||||||
|
const posLightX =
|
||||||
|
roundedX +
|
||||||
|
this._distanceFromCamera *
|
||||||
|
Math.cos(gdjs.toRad(-this._rotation + 90)) *
|
||||||
|
Math.cos(gdjs.toRad(this._elevation));
|
||||||
|
const posLightY =
|
||||||
|
roundedY -
|
||||||
|
this._distanceFromCamera *
|
||||||
|
Math.sin(gdjs.toRad(this._elevation));
|
||||||
|
const posLightZ =
|
||||||
|
roundedZ +
|
||||||
|
this._distanceFromCamera *
|
||||||
|
Math.sin(gdjs.toRad(-this._rotation + 90)) *
|
||||||
|
Math.cos(gdjs.toRad(this._elevation));
|
||||||
|
this._light.position.set(posLightX, posLightY, posLightZ);
|
||||||
|
this._light.target.position.set(roundedX, roundedY, roundedZ);
|
||||||
|
} else {
|
||||||
|
const posLightX =
|
||||||
|
roundedX +
|
||||||
|
this._distanceFromCamera *
|
||||||
|
Math.cos(gdjs.toRad(this._rotation)) *
|
||||||
|
Math.cos(gdjs.toRad(this._elevation));
|
||||||
|
const posLightY =
|
||||||
|
roundedY +
|
||||||
|
this._distanceFromCamera *
|
||||||
|
Math.sin(gdjs.toRad(this._rotation)) *
|
||||||
|
Math.cos(gdjs.toRad(this._elevation));
|
||||||
|
const posLightZ =
|
||||||
|
roundedZ +
|
||||||
|
this._distanceFromCamera *
|
||||||
|
Math.sin(gdjs.toRad(this._elevation));
|
||||||
|
|
||||||
|
this._light.position.set(posLightX, posLightY, posLightZ);
|
||||||
|
this._light.target.position.set(roundedX, roundedY, roundedZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
updateDoubleParameter(parameterName: string, value: number): void {
|
updateDoubleParameter(parameterName: string, value: number): void {
|
||||||
if (parameterName === 'intensity') {
|
if (parameterName === 'intensity') {
|
||||||
this.light.intensity = value;
|
this._light.intensity = value;
|
||||||
} else if (parameterName === 'elevation') {
|
} else if (parameterName === 'elevation') {
|
||||||
this.elevation = value;
|
this._elevation = value;
|
||||||
this.updateRotation();
|
|
||||||
} else if (parameterName === 'rotation') {
|
} else if (parameterName === 'rotation') {
|
||||||
this.rotation = value;
|
this._rotation = value;
|
||||||
this.updateRotation();
|
} else if (parameterName === 'distanceFromCamera') {
|
||||||
|
this._distanceFromCamera = value;
|
||||||
|
} else if (parameterName === 'frustumSize') {
|
||||||
|
this._frustumSize = value;
|
||||||
|
} else if (parameterName === 'minimumShadowBias') {
|
||||||
|
this._minimumShadowBias = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getDoubleParameter(parameterName: string): number {
|
getDoubleParameter(parameterName: string): number {
|
||||||
if (parameterName === 'intensity') {
|
if (parameterName === 'intensity') {
|
||||||
return this.light.intensity;
|
return this._light.intensity;
|
||||||
} else if (parameterName === 'elevation') {
|
} else if (parameterName === 'elevation') {
|
||||||
return this.elevation;
|
return this._elevation;
|
||||||
} else if (parameterName === 'rotation') {
|
} else if (parameterName === 'rotation') {
|
||||||
return this.rotation;
|
return this._rotation;
|
||||||
|
} else if (parameterName === 'distanceFromCamera') {
|
||||||
|
return this._distanceFromCamera;
|
||||||
|
} else if (parameterName === 'frustumSize') {
|
||||||
|
return this._frustumSize;
|
||||||
|
} else if (parameterName === 'minimumShadowBias') {
|
||||||
|
return this._minimumShadowBias;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
updateStringParameter(parameterName: string, value: string): void {
|
updateStringParameter(parameterName: string, value: string): void {
|
||||||
if (parameterName === 'color') {
|
if (parameterName === 'color') {
|
||||||
this.light.color = new THREE.Color(
|
this._light.color = new THREE.Color(
|
||||||
gdjs.rgbOrHexStringToNumber(value)
|
gdjs.rgbOrHexStringToNumber(value)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (parameterName === 'top') {
|
if (parameterName === 'top') {
|
||||||
this.top = value;
|
this._top = value;
|
||||||
this.updateRotation();
|
}
|
||||||
|
if (parameterName === 'shadowQuality') {
|
||||||
|
if (value === 'low' && this._shadowMapSize !== 512) {
|
||||||
|
this._shadowMapSize = 512;
|
||||||
|
this._shadowMapDirty = true;
|
||||||
|
}
|
||||||
|
if (value === 'medium' && this._shadowMapSize !== 1024) {
|
||||||
|
this._shadowMapSize = 1024;
|
||||||
|
this._shadowMapDirty = true;
|
||||||
|
}
|
||||||
|
if (value === 'high' && this._shadowMapSize !== 2048) {
|
||||||
|
this._shadowMapSize = 2048;
|
||||||
|
this._shadowMapDirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateColorParameter(parameterName: string, value: number): void {
|
updateColorParameter(parameterName: string, value: number): void {
|
||||||
if (parameterName === 'color') {
|
if (parameterName === 'color') {
|
||||||
this.light.color.setHex(value);
|
this._light.color.setHex(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getColorParameter(parameterName: string): number {
|
getColorParameter(parameterName: string): number {
|
||||||
if (parameterName === 'color') {
|
if (parameterName === 'color') {
|
||||||
return this.light.color.getHex();
|
return this._light.color.getHex();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
updateBooleanParameter(parameterName: string, value: boolean): void {}
|
updateBooleanParameter(parameterName: string, value: boolean): void {
|
||||||
updateRotation() {
|
if (parameterName === 'isCastingShadow') {
|
||||||
if (this.top === 'Z+') {
|
this._light.castShadow = value;
|
||||||
// 0° is a light from the right of the screen.
|
|
||||||
this.rotationObject.rotation.z = gdjs.toRad(this.rotation);
|
|
||||||
this.rotationObject.rotation.y = -gdjs.toRad(this.elevation);
|
|
||||||
} else {
|
|
||||||
// 0° becomes a light from Z+.
|
|
||||||
this.rotationObject.rotation.y = gdjs.toRad(this.rotation - 90);
|
|
||||||
this.rotationObject.rotation.z = -gdjs.toRad(this.elevation);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getNetworkSyncData(): DirectionalLightFilterNetworkSyncData {
|
getNetworkSyncData(): DirectionalLightFilterNetworkSyncData {
|
||||||
return {
|
return {
|
||||||
i: this.light.intensity,
|
i: this._light.intensity,
|
||||||
c: this.light.color.getHex(),
|
c: this._light.color.getHex(),
|
||||||
e: this.elevation,
|
e: this._elevation,
|
||||||
r: this.rotation,
|
r: this._rotation,
|
||||||
t: this.top,
|
t: this._top,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
updateFromNetworkSyncData(syncData: any): void {
|
updateFromNetworkSyncData(syncData: any): void {
|
||||||
this.light.intensity = syncData.i;
|
this._light.intensity = syncData.i;
|
||||||
this.light.color.setHex(syncData.c);
|
this._light.color.setHex(syncData.c);
|
||||||
this.elevation = syncData.e;
|
this._elevation = syncData.e;
|
||||||
this.rotation = syncData.r;
|
this._rotation = syncData.r;
|
||||||
this.top = syncData.t;
|
this._top = syncData.t;
|
||||||
this.updateRotation();
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
@@ -18,18 +18,15 @@ namespace gdjs {
|
|||||||
return new gdjs.PixiFiltersTools.EmptyFilter();
|
return new gdjs.PixiFiltersTools.EmptyFilter();
|
||||||
}
|
}
|
||||||
return new (class implements gdjs.PixiFiltersTools.Filter {
|
return new (class implements gdjs.PixiFiltersTools.Filter {
|
||||||
light: THREE.HemisphereLight;
|
_top: string = 'Z+';
|
||||||
rotationObject: THREE.Group;
|
_elevation: float = 90;
|
||||||
|
_rotation: float = 0;
|
||||||
|
|
||||||
_isEnabled: boolean = false;
|
_isEnabled: boolean = false;
|
||||||
top: string = 'Y-';
|
_light: THREE.HemisphereLight;
|
||||||
elevation: float = 45;
|
|
||||||
rotation: float = 0;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.light = new THREE.HemisphereLight();
|
this._light = new THREE.HemisphereLight();
|
||||||
this.light.position.set(1, 0, 0);
|
|
||||||
this.rotationObject = new THREE.Group();
|
|
||||||
this.rotationObject.add(this.light);
|
|
||||||
this.updateRotation();
|
this.updateRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +51,7 @@ namespace gdjs {
|
|||||||
if (!scene) {
|
if (!scene) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
scene.add(this.rotationObject);
|
scene.add(this._light);
|
||||||
this._isEnabled = true;
|
this._isEnabled = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -66,96 +63,106 @@ namespace gdjs {
|
|||||||
if (!scene) {
|
if (!scene) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
scene.remove(this.rotationObject);
|
scene.remove(this._light);
|
||||||
this._isEnabled = false;
|
this._isEnabled = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
updatePreRender(target: gdjs.EffectsTarget): any {}
|
updatePreRender(target: gdjs.EffectsTarget): any {}
|
||||||
updateDoubleParameter(parameterName: string, value: number): void {
|
updateDoubleParameter(parameterName: string, value: number): void {
|
||||||
if (parameterName === 'intensity') {
|
if (parameterName === 'intensity') {
|
||||||
this.light.intensity = value;
|
this._light.intensity = value;
|
||||||
} else if (parameterName === 'elevation') {
|
} else if (parameterName === 'elevation') {
|
||||||
this.elevation = value;
|
this._elevation = value;
|
||||||
this.updateRotation();
|
this.updateRotation();
|
||||||
} else if (parameterName === 'rotation') {
|
} else if (parameterName === 'rotation') {
|
||||||
this.rotation = value;
|
this._rotation = value;
|
||||||
this.updateRotation();
|
this.updateRotation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getDoubleParameter(parameterName: string): number {
|
getDoubleParameter(parameterName: string): number {
|
||||||
if (parameterName === 'intensity') {
|
if (parameterName === 'intensity') {
|
||||||
return this.light.intensity;
|
return this._light.intensity;
|
||||||
} else if (parameterName === 'elevation') {
|
} else if (parameterName === 'elevation') {
|
||||||
return this.elevation;
|
return this._elevation;
|
||||||
} else if (parameterName === 'rotation') {
|
} else if (parameterName === 'rotation') {
|
||||||
return this.rotation;
|
return this._rotation;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
updateStringParameter(parameterName: string, value: string): void {
|
updateStringParameter(parameterName: string, value: string): void {
|
||||||
if (parameterName === 'skyColor') {
|
if (parameterName === 'skyColor') {
|
||||||
this.light.color = new THREE.Color(
|
this._light.color = new THREE.Color(
|
||||||
gdjs.rgbOrHexStringToNumber(value)
|
gdjs.rgbOrHexStringToNumber(value)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (parameterName === 'groundColor') {
|
if (parameterName === 'groundColor') {
|
||||||
this.light.groundColor = new THREE.Color(
|
this._light.groundColor = new THREE.Color(
|
||||||
gdjs.rgbOrHexStringToNumber(value)
|
gdjs.rgbOrHexStringToNumber(value)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (parameterName === 'top') {
|
if (parameterName === 'top') {
|
||||||
this.top = value;
|
this._top = value;
|
||||||
this.updateRotation();
|
this.updateRotation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateColorParameter(parameterName: string, value: number): void {
|
updateColorParameter(parameterName: string, value: number): void {
|
||||||
if (parameterName === 'skyColor') {
|
if (parameterName === 'skyColor') {
|
||||||
this.light.color.setHex(value);
|
this._light.color.setHex(value);
|
||||||
}
|
}
|
||||||
if (parameterName === 'groundColor') {
|
if (parameterName === 'groundColor') {
|
||||||
this.light.groundColor.setHex(value);
|
this._light.groundColor.setHex(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getColorParameter(parameterName: string): number {
|
getColorParameter(parameterName: string): number {
|
||||||
if (parameterName === 'skyColor') {
|
if (parameterName === 'skyColor') {
|
||||||
return this.light.color.getHex();
|
return this._light.color.getHex();
|
||||||
}
|
}
|
||||||
if (parameterName === 'groundColor') {
|
if (parameterName === 'groundColor') {
|
||||||
return this.light.groundColor.getHex();
|
return this._light.groundColor.getHex();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
updateBooleanParameter(parameterName: string, value: boolean): void {}
|
updateBooleanParameter(parameterName: string, value: boolean): void {}
|
||||||
updateRotation() {
|
updateRotation() {
|
||||||
if (this.top === 'Z+') {
|
if (this._top === 'Y-') {
|
||||||
// 0° is a light from the right of the screen.
|
// `rotation` at 0° becomes a light from Z+.
|
||||||
this.rotationObject.rotation.z = gdjs.toRad(this.rotation);
|
this._light.position.set(
|
||||||
this.rotationObject.rotation.y = -gdjs.toRad(this.elevation);
|
Math.cos(gdjs.toRad(-this._rotation + 90)) *
|
||||||
|
Math.cos(gdjs.toRad(this._elevation)),
|
||||||
|
-Math.sin(gdjs.toRad(this._elevation)),
|
||||||
|
Math.sin(gdjs.toRad(-this._rotation + 90)) *
|
||||||
|
Math.cos(gdjs.toRad(this._elevation))
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// 0° becomes a light from Z+.
|
// `rotation` at 0° is a light from the right of the screen.
|
||||||
this.rotationObject.rotation.y = gdjs.toRad(this.rotation - 90);
|
this._light.position.set(
|
||||||
this.rotationObject.rotation.z = -gdjs.toRad(this.elevation);
|
Math.cos(gdjs.toRad(this._rotation)) *
|
||||||
|
Math.cos(gdjs.toRad(this._elevation)),
|
||||||
|
Math.sin(gdjs.toRad(this._rotation)) *
|
||||||
|
Math.cos(gdjs.toRad(this._elevation)),
|
||||||
|
Math.sin(gdjs.toRad(this._elevation))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getNetworkSyncData(): HemisphereLightFilterNetworkSyncData {
|
getNetworkSyncData(): HemisphereLightFilterNetworkSyncData {
|
||||||
return {
|
return {
|
||||||
i: this.light.intensity,
|
i: this._light.intensity,
|
||||||
sc: this.light.color.getHex(),
|
sc: this._light.color.getHex(),
|
||||||
gc: this.light.groundColor.getHex(),
|
gc: this._light.groundColor.getHex(),
|
||||||
e: this.elevation,
|
e: this._elevation,
|
||||||
r: this.rotation,
|
r: this._rotation,
|
||||||
t: this.top,
|
t: this._top,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
updateFromNetworkSyncData(
|
updateFromNetworkSyncData(
|
||||||
syncData: HemisphereLightFilterNetworkSyncData
|
syncData: HemisphereLightFilterNetworkSyncData
|
||||||
): void {
|
): void {
|
||||||
this.light.intensity = syncData.i;
|
this._light.intensity = syncData.i;
|
||||||
this.light.color.setHex(syncData.sc);
|
this._light.color.setHex(syncData.sc);
|
||||||
this.light.groundColor.setHex(syncData.gc);
|
this._light.groundColor.setHex(syncData.gc);
|
||||||
this.elevation = syncData.e;
|
this._elevation = syncData.e;
|
||||||
this.rotation = syncData.r;
|
this._rotation = syncData.r;
|
||||||
this.top = syncData.t;
|
this._top = syncData.t;
|
||||||
this.updateRotation();
|
this.updateRotation();
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@@ -21,7 +21,9 @@ module.exports = {
|
|||||||
.setExtensionInformation(
|
.setExtensionInformation(
|
||||||
'Scene3D',
|
'Scene3D',
|
||||||
_('3D'),
|
_('3D'),
|
||||||
_('Support for 3D in GDevelop.'),
|
_(
|
||||||
|
'Support for 3D in GDevelop: this provides 3D objects and the common features for all 3D objects.'
|
||||||
|
),
|
||||||
'Florian Rival',
|
'Florian Rival',
|
||||||
'MIT'
|
'MIT'
|
||||||
)
|
)
|
||||||
@@ -36,7 +38,9 @@ module.exports = {
|
|||||||
'Base3DBehavior',
|
'Base3DBehavior',
|
||||||
_('3D capability'),
|
_('3D capability'),
|
||||||
'Object3D',
|
'Object3D',
|
||||||
_('Move the object in 3D space.'),
|
_(
|
||||||
|
'Common features for all 3D objects: position in 3D space (including the Z axis, in addition to X and Y), size (including depth, in addition to width and height), rotation (on X and Y axis, in addition to the Z axis), scale (including Z axis, in addition to X and Y), flipping (on Z axis, in addition to horizontal (Y)/vertical (X) flipping).'
|
||||||
|
),
|
||||||
'',
|
'',
|
||||||
'res/conditions/3d_box.svg',
|
'res/conditions/3d_box.svg',
|
||||||
'Base3DBehavior',
|
'Base3DBehavior',
|
||||||
@@ -158,7 +162,12 @@ module.exports = {
|
|||||||
)
|
)
|
||||||
.addParameter('object', _('3D object'), '', false)
|
.addParameter('object', _('3D object'), '', false)
|
||||||
.addParameter('behavior', _('Behavior'), 'Base3DBehavior')
|
.addParameter('behavior', _('Behavior'), 'Base3DBehavior')
|
||||||
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
|
.useStandardParameters(
|
||||||
|
'number',
|
||||||
|
gd.ParameterOptions.makeNewOptions().setDescription(
|
||||||
|
_('Angle (in degrees)')
|
||||||
|
)
|
||||||
|
)
|
||||||
.setFunctionName('setRotationX')
|
.setFunctionName('setRotationX')
|
||||||
.setGetter('getRotationX');
|
.setGetter('getRotationX');
|
||||||
|
|
||||||
@@ -174,7 +183,12 @@ module.exports = {
|
|||||||
)
|
)
|
||||||
.addParameter('object', _('3D object'), '', false)
|
.addParameter('object', _('3D object'), '', false)
|
||||||
.addParameter('behavior', _('Behavior'), 'Base3DBehavior')
|
.addParameter('behavior', _('Behavior'), 'Base3DBehavior')
|
||||||
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
|
.useStandardParameters(
|
||||||
|
'number',
|
||||||
|
gd.ParameterOptions.makeNewOptions().setDescription(
|
||||||
|
_('Angle (in degrees)')
|
||||||
|
)
|
||||||
|
)
|
||||||
.setFunctionName('setRotationY')
|
.setFunctionName('setRotationY')
|
||||||
.setGetter('getRotationY');
|
.setGetter('getRotationY');
|
||||||
|
|
||||||
@@ -192,7 +206,7 @@ module.exports = {
|
|||||||
)
|
)
|
||||||
.addParameter('object', _('3D object'), '', false)
|
.addParameter('object', _('3D object'), '', false)
|
||||||
.addParameter('behavior', _('Behavior'), 'Base3DBehavior')
|
.addParameter('behavior', _('Behavior'), 'Base3DBehavior')
|
||||||
.addParameter('number', _('Rotation angle'), '', false)
|
.addParameter('number', _('Angle to add (in degrees)'), '', false)
|
||||||
.markAsAdvanced()
|
.markAsAdvanced()
|
||||||
.setFunctionName('turnAroundX');
|
.setFunctionName('turnAroundX');
|
||||||
|
|
||||||
@@ -210,7 +224,7 @@ module.exports = {
|
|||||||
)
|
)
|
||||||
.addParameter('object', _('3D object'), '', false)
|
.addParameter('object', _('3D object'), '', false)
|
||||||
.addParameter('behavior', _('Behavior'), 'Base3DBehavior')
|
.addParameter('behavior', _('Behavior'), 'Base3DBehavior')
|
||||||
.addParameter('number', _('Rotation angle'), '', false)
|
.addParameter('number', _('Angle to add (in degrees)'), '', false)
|
||||||
.markAsAdvanced()
|
.markAsAdvanced()
|
||||||
.setFunctionName('turnAroundY');
|
.setFunctionName('turnAroundY');
|
||||||
|
|
||||||
@@ -228,7 +242,7 @@ module.exports = {
|
|||||||
)
|
)
|
||||||
.addParameter('object', _('3D object'), '', false)
|
.addParameter('object', _('3D object'), '', false)
|
||||||
.addParameter('behavior', _('Behavior'), 'Base3DBehavior')
|
.addParameter('behavior', _('Behavior'), 'Base3DBehavior')
|
||||||
.addParameter('number', _('Rotation angle'), '', false)
|
.addParameter('number', _('Angle to add (in degrees)'), '', false)
|
||||||
.markAsAdvanced()
|
.markAsAdvanced()
|
||||||
.setFunctionName('turnAroundZ');
|
.setFunctionName('turnAroundZ');
|
||||||
}
|
}
|
||||||
@@ -238,7 +252,7 @@ module.exports = {
|
|||||||
.addObject(
|
.addObject(
|
||||||
'Model3DObject',
|
'Model3DObject',
|
||||||
_('3D Model'),
|
_('3D Model'),
|
||||||
_('An animated 3D model.'),
|
_('An animated 3D model, useful for most elements of a 3D game.'),
|
||||||
'JsPlatform/Extensions/3d_model.svg',
|
'JsPlatform/Extensions/3d_model.svg',
|
||||||
new gd.Model3DObjectConfiguration()
|
new gd.Model3DObjectConfiguration()
|
||||||
)
|
)
|
||||||
@@ -590,7 +604,12 @@ module.exports = {
|
|||||||
'res/conditions/3d_box.svg'
|
'res/conditions/3d_box.svg'
|
||||||
)
|
)
|
||||||
.addParameter('object', _('3D model'), 'Model3DObject', false)
|
.addParameter('object', _('3D model'), 'Model3DObject', false)
|
||||||
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
|
.useStandardParameters(
|
||||||
|
'number',
|
||||||
|
gd.ParameterOptions.makeNewOptions().setDescription(
|
||||||
|
_('Angle (in degrees)')
|
||||||
|
)
|
||||||
|
)
|
||||||
.setHidden()
|
.setHidden()
|
||||||
.setFunctionName('setRotationX')
|
.setFunctionName('setRotationX')
|
||||||
.setGetter('getRotationX');
|
.setGetter('getRotationX');
|
||||||
@@ -607,7 +626,12 @@ module.exports = {
|
|||||||
'res/conditions/3d_box.svg'
|
'res/conditions/3d_box.svg'
|
||||||
)
|
)
|
||||||
.addParameter('object', _('3D model'), 'Model3DObject', false)
|
.addParameter('object', _('3D model'), 'Model3DObject', false)
|
||||||
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
|
.useStandardParameters(
|
||||||
|
'number',
|
||||||
|
gd.ParameterOptions.makeNewOptions().setDescription(
|
||||||
|
_('Angle (in degrees)')
|
||||||
|
)
|
||||||
|
)
|
||||||
.setHidden()
|
.setHidden()
|
||||||
.setFunctionName('setRotationY')
|
.setFunctionName('setRotationY')
|
||||||
.setGetter('getRotationY');
|
.setGetter('getRotationY');
|
||||||
@@ -626,7 +650,7 @@ module.exports = {
|
|||||||
'res/conditions/3d_box.svg'
|
'res/conditions/3d_box.svg'
|
||||||
)
|
)
|
||||||
.addParameter('object', _('3D model'), 'Model3DObject', false)
|
.addParameter('object', _('3D model'), 'Model3DObject', false)
|
||||||
.addParameter('number', _('Rotation angle'), '', false)
|
.addParameter('number', _('Angle to add (in degrees)'), '', false)
|
||||||
.markAsAdvanced()
|
.markAsAdvanced()
|
||||||
.setHidden()
|
.setHidden()
|
||||||
.setFunctionName('turnAroundX');
|
.setFunctionName('turnAroundX');
|
||||||
@@ -645,7 +669,7 @@ module.exports = {
|
|||||||
'res/conditions/3d_box.svg'
|
'res/conditions/3d_box.svg'
|
||||||
)
|
)
|
||||||
.addParameter('object', _('3D model'), 'Model3DObject', false)
|
.addParameter('object', _('3D model'), 'Model3DObject', false)
|
||||||
.addParameter('number', _('Rotation angle'), '', false)
|
.addParameter('number', _('Angle to add (in degrees)'), '', false)
|
||||||
.markAsAdvanced()
|
.markAsAdvanced()
|
||||||
.setHidden()
|
.setHidden()
|
||||||
.setFunctionName('turnAroundY');
|
.setFunctionName('turnAroundY');
|
||||||
@@ -664,7 +688,7 @@ module.exports = {
|
|||||||
'res/conditions/3d_box.svg'
|
'res/conditions/3d_box.svg'
|
||||||
)
|
)
|
||||||
.addParameter('object', _('3D model'), 'Model3DObject', false)
|
.addParameter('object', _('3D model'), 'Model3DObject', false)
|
||||||
.addParameter('number', _('Rotation angle'), '', false)
|
.addParameter('number', _('Angle to add (in degrees)'), '', false)
|
||||||
.markAsAdvanced()
|
.markAsAdvanced()
|
||||||
.setHidden()
|
.setHidden()
|
||||||
.setFunctionName('turnAroundZ');
|
.setFunctionName('turnAroundZ');
|
||||||
@@ -855,7 +879,9 @@ module.exports = {
|
|||||||
propertyName === 'rightFaceResourceRepeat' ||
|
propertyName === 'rightFaceResourceRepeat' ||
|
||||||
propertyName === 'topFaceResourceRepeat' ||
|
propertyName === 'topFaceResourceRepeat' ||
|
||||||
propertyName === 'bottomFaceResourceRepeat' ||
|
propertyName === 'bottomFaceResourceRepeat' ||
|
||||||
propertyName === 'enableTextureTransparency'
|
propertyName === 'enableTextureTransparency' ||
|
||||||
|
propertyName === 'isCastingShadow' ||
|
||||||
|
propertyName === 'isReceivingShadow'
|
||||||
) {
|
) {
|
||||||
objectContent[propertyName] = newValue === '1';
|
objectContent[propertyName] = newValue === '1';
|
||||||
return true;
|
return true;
|
||||||
@@ -883,8 +909,8 @@ module.exports = {
|
|||||||
.getOrCreate('facesOrientation')
|
.getOrCreate('facesOrientation')
|
||||||
.setValue(objectContent.facesOrientation || 'Y')
|
.setValue(objectContent.facesOrientation || 'Y')
|
||||||
.setType('choice')
|
.setType('choice')
|
||||||
.addExtraInfo('Y')
|
.addChoice('Y', 'Y')
|
||||||
.addExtraInfo('Z')
|
.addChoice('Z', 'Z')
|
||||||
.setLabel(_('Faces orientation'))
|
.setLabel(_('Faces orientation'))
|
||||||
.setDescription(
|
.setDescription(
|
||||||
_(
|
_(
|
||||||
@@ -944,8 +970,8 @@ module.exports = {
|
|||||||
.getOrCreate('backFaceUpThroughWhichAxisRotation')
|
.getOrCreate('backFaceUpThroughWhichAxisRotation')
|
||||||
.setValue(objectContent.backFaceUpThroughWhichAxisRotation || 'X')
|
.setValue(objectContent.backFaceUpThroughWhichAxisRotation || 'X')
|
||||||
.setType('choice')
|
.setType('choice')
|
||||||
.addExtraInfo('X')
|
.addChoice('X', 'X')
|
||||||
.addExtraInfo('Y')
|
.addChoice('Y', 'Y')
|
||||||
.setLabel(_('Back face orientation'))
|
.setLabel(_('Back face orientation'))
|
||||||
.setDescription(
|
.setDescription(
|
||||||
_(
|
_(
|
||||||
@@ -1079,11 +1105,29 @@ module.exports = {
|
|||||||
|
|
||||||
objectProperties
|
objectProperties
|
||||||
.getOrCreate('materialType')
|
.getOrCreate('materialType')
|
||||||
.setValue(objectContent.materialType || 'Basic')
|
.setValue(objectContent.materialType || 'StandardWithoutMetalness')
|
||||||
.setType('choice')
|
.setType('choice')
|
||||||
.addExtraInfo('Basic')
|
.addChoice('Basic', _('Basic (no lighting, no shadows)'))
|
||||||
.addExtraInfo('StandardWithoutMetalness')
|
.addChoice(
|
||||||
.setLabel(_('Material type'));
|
'StandardWithoutMetalness',
|
||||||
|
_('Standard (without metalness)')
|
||||||
|
)
|
||||||
|
.setLabel(_('Material type'))
|
||||||
|
.setGroup(_('Lighting'));
|
||||||
|
|
||||||
|
objectProperties
|
||||||
|
.getOrCreate('isCastingShadow')
|
||||||
|
.setValue(objectContent.isCastingShadow ? 'true' : 'false')
|
||||||
|
.setType('boolean')
|
||||||
|
.setLabel(_('Shadow casting'))
|
||||||
|
.setGroup(_('Lighting'));
|
||||||
|
|
||||||
|
objectProperties
|
||||||
|
.getOrCreate('isReceivingShadow')
|
||||||
|
.setValue(objectContent.isReceivingShadow ? 'true' : 'false')
|
||||||
|
.setType('boolean')
|
||||||
|
.setLabel(_('Shadow receiving'))
|
||||||
|
.setGroup(_('Lighting'));
|
||||||
|
|
||||||
return objectProperties;
|
return objectProperties;
|
||||||
};
|
};
|
||||||
@@ -1101,7 +1145,7 @@ module.exports = {
|
|||||||
topFaceResourceName: '',
|
topFaceResourceName: '',
|
||||||
bottomFaceResourceName: '',
|
bottomFaceResourceName: '',
|
||||||
frontFaceVisible: true,
|
frontFaceVisible: true,
|
||||||
backFaceVisible: false,
|
backFaceVisible: true,
|
||||||
leftFaceVisible: true,
|
leftFaceVisible: true,
|
||||||
rightFaceVisible: true,
|
rightFaceVisible: true,
|
||||||
topFaceVisible: true,
|
topFaceVisible: true,
|
||||||
@@ -1112,8 +1156,10 @@ module.exports = {
|
|||||||
rightFaceResourceRepeat: false,
|
rightFaceResourceRepeat: false,
|
||||||
topFaceResourceRepeat: false,
|
topFaceResourceRepeat: false,
|
||||||
bottomFaceResourceRepeat: false,
|
bottomFaceResourceRepeat: false,
|
||||||
materialType: 'Basic',
|
materialType: 'StandardWithoutMetalness',
|
||||||
tint: '255;255;255',
|
tint: '255;255;255',
|
||||||
|
isCastingShadow: true,
|
||||||
|
isReceivingShadow: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
Cube3DObject.updateInitialInstanceProperty = function (
|
Cube3DObject.updateInitialInstanceProperty = function (
|
||||||
@@ -1467,7 +1513,12 @@ module.exports = {
|
|||||||
'res/conditions/3d_box.svg'
|
'res/conditions/3d_box.svg'
|
||||||
)
|
)
|
||||||
.addParameter('object', _('3D cube'), 'Cube3DObject', false)
|
.addParameter('object', _('3D cube'), 'Cube3DObject', false)
|
||||||
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
|
.useStandardParameters(
|
||||||
|
'number',
|
||||||
|
gd.ParameterOptions.makeNewOptions().setDescription(
|
||||||
|
_('Angle (in degrees)')
|
||||||
|
)
|
||||||
|
)
|
||||||
.setFunctionName('setRotationX')
|
.setFunctionName('setRotationX')
|
||||||
.setHidden()
|
.setHidden()
|
||||||
.setGetter('getRotationX');
|
.setGetter('getRotationX');
|
||||||
@@ -1484,7 +1535,12 @@ module.exports = {
|
|||||||
'res/conditions/3d_box.svg'
|
'res/conditions/3d_box.svg'
|
||||||
)
|
)
|
||||||
.addParameter('object', _('3D cube'), 'Cube3DObject', false)
|
.addParameter('object', _('3D cube'), 'Cube3DObject', false)
|
||||||
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
|
.useStandardParameters(
|
||||||
|
'number',
|
||||||
|
gd.ParameterOptions.makeNewOptions().setDescription(
|
||||||
|
_('Angle (in degrees)')
|
||||||
|
)
|
||||||
|
)
|
||||||
.setFunctionName('setRotationY')
|
.setFunctionName('setRotationY')
|
||||||
.setHidden()
|
.setHidden()
|
||||||
.setGetter('getRotationY');
|
.setGetter('getRotationY');
|
||||||
@@ -1845,6 +1901,11 @@ module.exports = {
|
|||||||
.getOrCreate('density')
|
.getOrCreate('density')
|
||||||
.setValue('0.0012')
|
.setValue('0.0012')
|
||||||
.setLabel(_('Density'))
|
.setLabel(_('Density'))
|
||||||
|
.setDescription(
|
||||||
|
_(
|
||||||
|
'Density of the fog. Usual values are between 0.0005 (far away) and 0.005 (very thick fog).'
|
||||||
|
)
|
||||||
|
)
|
||||||
.setType('number');
|
.setType('number');
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@@ -1852,7 +1913,9 @@ module.exports = {
|
|||||||
.addEffect('AmbientLight')
|
.addEffect('AmbientLight')
|
||||||
.setFullName(_('Ambient light'))
|
.setFullName(_('Ambient light'))
|
||||||
.setDescription(
|
.setDescription(
|
||||||
_('A light that illuminates all objects from every direction.')
|
_(
|
||||||
|
'A light that illuminates all objects from every direction. Often used along with a Directional light (though a Hemisphere light can be used instead of an Ambient light).'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.markAsNotWorkingForObjects()
|
.markAsNotWorkingForObjects()
|
||||||
.markAsOnlyWorkingFor3D()
|
.markAsOnlyWorkingFor3D()
|
||||||
@@ -1873,7 +1936,11 @@ module.exports = {
|
|||||||
const effect = extension
|
const effect = extension
|
||||||
.addEffect('DirectionalLight')
|
.addEffect('DirectionalLight')
|
||||||
.setFullName(_('Directional light'))
|
.setFullName(_('Directional light'))
|
||||||
.setDescription(_('A very far light source like the sun.'))
|
.setDescription(
|
||||||
|
_(
|
||||||
|
"A very far light source like the sun. This is the light to use for casting shadows for 3D objects (other lights won't emit shadows). Often used along with a Hemisphere light."
|
||||||
|
)
|
||||||
|
)
|
||||||
.markAsNotWorkingForObjects()
|
.markAsNotWorkingForObjects()
|
||||||
.markAsOnlyWorkingFor3D()
|
.markAsOnlyWorkingFor3D()
|
||||||
.addIncludeFile('Extensions/3D/DirectionalLight.js');
|
.addIncludeFile('Extensions/3D/DirectionalLight.js');
|
||||||
@@ -1890,11 +1957,11 @@ module.exports = {
|
|||||||
.setType('number');
|
.setType('number');
|
||||||
properties
|
properties
|
||||||
.getOrCreate('top')
|
.getOrCreate('top')
|
||||||
.setValue('Y-')
|
.setValue('Z+')
|
||||||
.setLabel(_('3D world top'))
|
.setLabel(_('3D world top'))
|
||||||
.setType('choice')
|
.setType('choice')
|
||||||
.addExtraInfo('Y-')
|
|
||||||
.addExtraInfo('Z+')
|
.addExtraInfo('Z+')
|
||||||
|
.addExtraInfo('Y-')
|
||||||
.setGroup(_('Orientation'));
|
.setGroup(_('Orientation'));
|
||||||
properties
|
properties
|
||||||
.getOrCreate('elevation')
|
.getOrCreate('elevation')
|
||||||
@@ -1909,6 +1976,47 @@ module.exports = {
|
|||||||
.setLabel(_('Rotation (in degrees)'))
|
.setLabel(_('Rotation (in degrees)'))
|
||||||
.setType('number')
|
.setType('number')
|
||||||
.setGroup(_('Orientation'));
|
.setGroup(_('Orientation'));
|
||||||
|
properties
|
||||||
|
.getOrCreate('isCastingShadow')
|
||||||
|
.setValue('false')
|
||||||
|
.setLabel(_('Shadow casting'))
|
||||||
|
.setType('boolean')
|
||||||
|
.setGroup(_('Shadows'));
|
||||||
|
properties
|
||||||
|
.getOrCreate('shadowQuality')
|
||||||
|
.setValue('medium')
|
||||||
|
.addChoice('low', _('Low quality'))
|
||||||
|
.addChoice('medium', _('Medium quality'))
|
||||||
|
.addChoice('high', _('High quality'))
|
||||||
|
.setLabel(_('Shadow quality'))
|
||||||
|
.setType('choice')
|
||||||
|
.setGroup(_('Shadows'));
|
||||||
|
properties
|
||||||
|
.getOrCreate('minimumShadowBias')
|
||||||
|
.setValue('0')
|
||||||
|
.setLabel(_('Shadow bias'))
|
||||||
|
.setDescription(
|
||||||
|
_(
|
||||||
|
'Use this to avoid "shadow acne" due to depth buffer precision. Choose a value small enough like 0.001 to avoid creating distance between shadows and objects but not too small to avoid shadow glitches on low/medium quality. This value is used for high quality, and multiplied by 1.25 for medium quality and 2 for low quality.'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.setType('number')
|
||||||
|
.setGroup(_('Shadows'))
|
||||||
|
.setAdvanced(true);
|
||||||
|
properties
|
||||||
|
.getOrCreate('frustumSize')
|
||||||
|
.setValue('4000')
|
||||||
|
.setLabel(_('Shadow frustum size'))
|
||||||
|
.setType('number')
|
||||||
|
.setGroup(_('Shadows'))
|
||||||
|
.setAdvanced(true);
|
||||||
|
properties
|
||||||
|
.getOrCreate('distanceFromCamera')
|
||||||
|
.setValue('1500')
|
||||||
|
.setLabel(_("Distance from layer's camera"))
|
||||||
|
.setType('number')
|
||||||
|
.setGroup(_('Shadows'))
|
||||||
|
.setAdvanced(true);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const effect = extension
|
const effect = extension
|
||||||
@@ -1916,7 +2024,7 @@ module.exports = {
|
|||||||
.setFullName(_('Hemisphere light'))
|
.setFullName(_('Hemisphere light'))
|
||||||
.setDescription(
|
.setDescription(
|
||||||
_(
|
_(
|
||||||
'A light that illuminates objects from every direction with a gradient.'
|
'A light that illuminates objects from every direction with a gradient. Often used along with a Directional light.'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.markAsNotWorkingForObjects()
|
.markAsNotWorkingForObjects()
|
||||||
@@ -1940,11 +2048,11 @@ module.exports = {
|
|||||||
.setType('number');
|
.setType('number');
|
||||||
properties
|
properties
|
||||||
.getOrCreate('top')
|
.getOrCreate('top')
|
||||||
.setValue('Y-')
|
.setValue('Z+')
|
||||||
.setLabel(_('3D world top'))
|
.setLabel(_('3D world top'))
|
||||||
.setType('choice')
|
.setType('choice')
|
||||||
.addExtraInfo('Y-')
|
|
||||||
.addExtraInfo('Z+')
|
.addExtraInfo('Z+')
|
||||||
|
.addExtraInfo('Y-')
|
||||||
.setGroup(_('Orientation'));
|
.setGroup(_('Orientation'));
|
||||||
properties
|
properties
|
||||||
.getOrCreate('elevation')
|
.getOrCreate('elevation')
|
||||||
@@ -1960,6 +2068,48 @@ module.exports = {
|
|||||||
.setType('number')
|
.setType('number')
|
||||||
.setGroup(_('Orientation'));
|
.setGroup(_('Orientation'));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const effect = extension
|
||||||
|
.addEffect('Skybox')
|
||||||
|
.setFullName(_('Skybox'))
|
||||||
|
.setDescription(
|
||||||
|
_('Display a background on a cube surrounding the scene.')
|
||||||
|
)
|
||||||
|
.markAsNotWorkingForObjects()
|
||||||
|
.markAsOnlyWorkingFor3D()
|
||||||
|
.addIncludeFile('Extensions/3D/Skybox.js');
|
||||||
|
const properties = effect.getProperties();
|
||||||
|
properties
|
||||||
|
.getOrCreate('rightFaceResourceName')
|
||||||
|
.setType('resource')
|
||||||
|
.addExtraInfo('image')
|
||||||
|
.setLabel(_('Right face (X+)'));
|
||||||
|
properties
|
||||||
|
.getOrCreate('leftFaceResourceName')
|
||||||
|
.setType('resource')
|
||||||
|
.addExtraInfo('image')
|
||||||
|
.setLabel(_('Left face (X-)'));
|
||||||
|
properties
|
||||||
|
.getOrCreate('bottomFaceResourceName')
|
||||||
|
.setType('resource')
|
||||||
|
.addExtraInfo('image')
|
||||||
|
.setLabel(_('Bottom face (Y+)'));
|
||||||
|
properties
|
||||||
|
.getOrCreate('topFaceResourceName')
|
||||||
|
.setType('resource')
|
||||||
|
.addExtraInfo('image')
|
||||||
|
.setLabel(_('Top face (Y-)'));
|
||||||
|
properties
|
||||||
|
.getOrCreate('frontFaceResourceName')
|
||||||
|
.setType('resource')
|
||||||
|
.addExtraInfo('image')
|
||||||
|
.setLabel(_('Front face (Z+)'));
|
||||||
|
properties
|
||||||
|
.getOrCreate('backFaceResourceName')
|
||||||
|
.setType('resource')
|
||||||
|
.addExtraInfo('image')
|
||||||
|
.setLabel(_('Back face (Z-)'));
|
||||||
|
}
|
||||||
{
|
{
|
||||||
const effect = extension
|
const effect = extension
|
||||||
.addEffect('HueAndSaturation')
|
.addEffect('HueAndSaturation')
|
||||||
@@ -3206,6 +3356,8 @@ module.exports = {
|
|||||||
|
|
||||||
this._threeObject = new THREE.Group();
|
this._threeObject = new THREE.Group();
|
||||||
this._threeObject.rotation.order = 'ZYX';
|
this._threeObject.rotation.order = 'ZYX';
|
||||||
|
this._threeObject.castShadow = true;
|
||||||
|
this._threeObject.receiveShadow = true;
|
||||||
this._threeGroup.add(this._threeObject);
|
this._threeGroup.add(this._threeObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@ Model3DObjectConfiguration::Model3DObjectConfiguration()
|
|||||||
: width(100), height(100), depth(100), rotationX(0), rotationY(0),
|
: width(100), height(100), depth(100), rotationX(0), rotationY(0),
|
||||||
rotationZ(0), modelResourceName(""), materialType("StandardWithoutMetalness"),
|
rotationZ(0), modelResourceName(""), materialType("StandardWithoutMetalness"),
|
||||||
originLocation("ModelOrigin"), centerLocation("ModelOrigin"),
|
originLocation("ModelOrigin"), centerLocation("ModelOrigin"),
|
||||||
keepAspectRatio(true), crossfadeDuration(0.1f) {}
|
keepAspectRatio(true), crossfadeDuration(0.1f), isCastingShadow(true), isReceivingShadow(true) {}
|
||||||
|
|
||||||
bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
|
bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
|
||||||
const gd::String &newValue) {
|
const gd::String &newValue) {
|
||||||
@@ -75,6 +75,16 @@ bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
|
|||||||
crossfadeDuration = newValue.To<double>();
|
crossfadeDuration = newValue.To<double>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if(propertyName == "isCastingShadow")
|
||||||
|
{
|
||||||
|
isCastingShadow = newValue == "1";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(propertyName == "isReceivingShadow")
|
||||||
|
{
|
||||||
|
isReceivingShadow = newValue == "1";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -143,19 +153,20 @@ Model3DObjectConfiguration::GetProperties() const {
|
|||||||
objectProperties["materialType"]
|
objectProperties["materialType"]
|
||||||
.SetValue(materialType.empty() ? "Basic" : materialType)
|
.SetValue(materialType.empty() ? "Basic" : materialType)
|
||||||
.SetType("choice")
|
.SetType("choice")
|
||||||
.AddExtraInfo("Basic")
|
.AddChoice("Basic", _("Basic (no lighting, no shadows)"))
|
||||||
.AddExtraInfo("StandardWithoutMetalness")
|
.AddChoice("StandardWithoutMetalness", _("Standard (without metalness)"))
|
||||||
.AddExtraInfo("KeepOriginal")
|
.AddChoice("KeepOriginal", _("Keep original"))
|
||||||
.SetLabel(_("Material"));
|
.SetLabel(_("Material"))
|
||||||
|
.SetGroup(_("Lighting"));
|
||||||
|
|
||||||
objectProperties["originLocation"]
|
objectProperties["originLocation"]
|
||||||
.SetValue(originLocation.empty() ? "TopLeft" : originLocation)
|
.SetValue(originLocation.empty() ? "TopLeft" : originLocation)
|
||||||
.SetType("choice")
|
.SetType("choice")
|
||||||
.AddExtraInfo("ModelOrigin")
|
.AddChoice("ModelOrigin", _("Model origin"))
|
||||||
.AddExtraInfo("TopLeft")
|
.AddChoice("TopLeft", _("Top left"))
|
||||||
.AddExtraInfo("ObjectCenter")
|
.AddChoice("ObjectCenter", _("Object center"))
|
||||||
.AddExtraInfo("BottomCenterZ")
|
.AddChoice("BottomCenterZ", _("Bottom center (Z)"))
|
||||||
.AddExtraInfo("BottomCenterY")
|
.AddChoice("BottomCenterY", _("Bottom center (Y)"))
|
||||||
.SetLabel(_("Origin point"))
|
.SetLabel(_("Origin point"))
|
||||||
.SetGroup(_("Points"))
|
.SetGroup(_("Points"))
|
||||||
.SetAdvanced(true);
|
.SetAdvanced(true);
|
||||||
@@ -163,10 +174,10 @@ Model3DObjectConfiguration::GetProperties() const {
|
|||||||
objectProperties["centerLocation"]
|
objectProperties["centerLocation"]
|
||||||
.SetValue(centerLocation.empty() ? "ObjectCenter" : centerLocation)
|
.SetValue(centerLocation.empty() ? "ObjectCenter" : centerLocation)
|
||||||
.SetType("choice")
|
.SetType("choice")
|
||||||
.AddExtraInfo("ModelOrigin")
|
.AddChoice("ModelOrigin", _("Model origin"))
|
||||||
.AddExtraInfo("ObjectCenter")
|
.AddChoice("ObjectCenter", _("Object center"))
|
||||||
.AddExtraInfo("BottomCenterZ")
|
.AddChoice("BottomCenterZ", _("Bottom center (Z)"))
|
||||||
.AddExtraInfo("BottomCenterY")
|
.AddChoice("BottomCenterY", _("Bottom center (Y)"))
|
||||||
.SetLabel(_("Center point"))
|
.SetLabel(_("Center point"))
|
||||||
.SetGroup(_("Points"))
|
.SetGroup(_("Points"))
|
||||||
.SetAdvanced(true);
|
.SetAdvanced(true);
|
||||||
@@ -178,6 +189,20 @@ Model3DObjectConfiguration::GetProperties() const {
|
|||||||
.SetGroup(_("Animations"))
|
.SetGroup(_("Animations"))
|
||||||
.SetMeasurementUnit(gd::MeasurementUnit::GetSecond());
|
.SetMeasurementUnit(gd::MeasurementUnit::GetSecond());
|
||||||
|
|
||||||
|
objectProperties["isCastingShadow"]
|
||||||
|
.SetValue(isCastingShadow ? "true" : "false")
|
||||||
|
.SetType("boolean")
|
||||||
|
.SetLabel(_("Shadow casting"))
|
||||||
|
.SetGroup(_("Lighting"));
|
||||||
|
|
||||||
|
objectProperties["isReceivingShadow"]
|
||||||
|
.SetValue(isReceivingShadow ? "true" : "false")
|
||||||
|
.SetType("boolean")
|
||||||
|
.SetLabel(_("Shadow receiving"))
|
||||||
|
.SetGroup(_("Lighting"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return objectProperties;
|
return objectProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,6 +235,8 @@ void Model3DObjectConfiguration::DoUnserializeFrom(
|
|||||||
centerLocation = content.GetStringAttribute("centerLocation");
|
centerLocation = content.GetStringAttribute("centerLocation");
|
||||||
keepAspectRatio = content.GetBoolAttribute("keepAspectRatio");
|
keepAspectRatio = content.GetBoolAttribute("keepAspectRatio");
|
||||||
crossfadeDuration = content.GetDoubleAttribute("crossfadeDuration");
|
crossfadeDuration = content.GetDoubleAttribute("crossfadeDuration");
|
||||||
|
isCastingShadow = content.GetBoolAttribute("isCastingShadow");
|
||||||
|
isReceivingShadow = content.GetBoolAttribute("isReceivingShadow");
|
||||||
|
|
||||||
RemoveAllAnimations();
|
RemoveAllAnimations();
|
||||||
auto &animationsElement = content.GetChild("animations");
|
auto &animationsElement = content.GetChild("animations");
|
||||||
@@ -239,6 +266,8 @@ void Model3DObjectConfiguration::DoSerializeTo(
|
|||||||
content.SetAttribute("centerLocation", centerLocation);
|
content.SetAttribute("centerLocation", centerLocation);
|
||||||
content.SetAttribute("keepAspectRatio", keepAspectRatio);
|
content.SetAttribute("keepAspectRatio", keepAspectRatio);
|
||||||
content.SetAttribute("crossfadeDuration", crossfadeDuration);
|
content.SetAttribute("crossfadeDuration", crossfadeDuration);
|
||||||
|
content.SetAttribute("isCastingShadow", isCastingShadow);
|
||||||
|
content.SetAttribute("isReceivingShadow", isReceivingShadow);
|
||||||
|
|
||||||
auto &animationsElement = content.AddChild("animations");
|
auto &animationsElement = content.AddChild("animations");
|
||||||
animationsElement.ConsiderAsArrayOf("animation");
|
animationsElement.ConsiderAsArrayOf("animation");
|
||||||
|
@@ -160,6 +160,8 @@ public:
|
|||||||
const gd::String& GetCenterLocation() const { return centerLocation; };
|
const gd::String& GetCenterLocation() const { return centerLocation; };
|
||||||
|
|
||||||
bool shouldKeepAspectRatio() const { return keepAspectRatio; };
|
bool shouldKeepAspectRatio() const { return keepAspectRatio; };
|
||||||
|
bool shouldCastShadow() const { return isCastingShadow; };
|
||||||
|
bool shouldReceiveShadow() const { return isReceivingShadow; };
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -182,6 +184,8 @@ private:
|
|||||||
gd::String centerLocation;
|
gd::String centerLocation;
|
||||||
|
|
||||||
bool keepAspectRatio;
|
bool keepAspectRatio;
|
||||||
|
bool isCastingShadow;
|
||||||
|
bool isReceivingShadow;
|
||||||
|
|
||||||
std::vector<Model3DAnimation> animations;
|
std::vector<Model3DAnimation> animations;
|
||||||
static Model3DAnimation badAnimation; //< Bad animation when an out of bound
|
static Model3DAnimation badAnimation; //< Bad animation when an out of bound
|
||||||
|
@@ -8,6 +8,7 @@ namespace gdjs {
|
|||||||
anis: Model3DAnimation[];
|
anis: Model3DAnimation[];
|
||||||
ai: integer;
|
ai: integer;
|
||||||
ass: float;
|
ass: float;
|
||||||
|
aet: float;
|
||||||
ap: boolean;
|
ap: boolean;
|
||||||
cfd: float;
|
cfd: float;
|
||||||
};
|
};
|
||||||
@@ -38,6 +39,8 @@ namespace gdjs {
|
|||||||
| 'BottomCenterY';
|
| 'BottomCenterY';
|
||||||
animations: Model3DAnimation[];
|
animations: Model3DAnimation[];
|
||||||
crossfadeDuration: float;
|
crossfadeDuration: float;
|
||||||
|
isCastingShadow: boolean;
|
||||||
|
isReceivingShadow: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +104,8 @@ namespace gdjs {
|
|||||||
_animationSpeedScale: float = 1;
|
_animationSpeedScale: float = 1;
|
||||||
_animationPaused: boolean = false;
|
_animationPaused: boolean = false;
|
||||||
_crossfadeDuration: float = 0;
|
_crossfadeDuration: float = 0;
|
||||||
|
_isCastingShadow: boolean = true;
|
||||||
|
_isReceivingShadow: boolean = true;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||||
@@ -123,6 +128,8 @@ namespace gdjs {
|
|||||||
objectData.content.materialType
|
objectData.content.materialType
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.setIsCastingShadow(objectData.content.isCastingShadow);
|
||||||
|
this.setIsReceivingShadow(objectData.content.isReceivingShadow);
|
||||||
this.onModelChanged(objectData);
|
this.onModelChanged(objectData);
|
||||||
|
|
||||||
this._crossfadeDuration = objectData.content.crossfadeDuration || 0;
|
this._crossfadeDuration = objectData.content.crossfadeDuration || 0;
|
||||||
@@ -146,6 +153,14 @@ namespace gdjs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override updateOriginalDimensionsFromObjectData(
|
||||||
|
oldObjectData: Object3DData,
|
||||||
|
newObjectData: Object3DData
|
||||||
|
): void {
|
||||||
|
// Original dimensions must not be reset by `super.updateFromObjectData`.
|
||||||
|
// `_updateModel` has a different logic to evaluate them using `keepAspectRatio`.
|
||||||
|
}
|
||||||
|
|
||||||
updateFromObjectData(
|
updateFromObjectData(
|
||||||
oldObjectData: Model3DObjectData,
|
oldObjectData: Model3DObjectData,
|
||||||
newObjectData: Model3DObjectData
|
newObjectData: Model3DObjectData
|
||||||
@@ -175,8 +190,14 @@ namespace gdjs {
|
|||||||
oldObjectData.content.keepAspectRatio !==
|
oldObjectData.content.keepAspectRatio !==
|
||||||
newObjectData.content.keepAspectRatio ||
|
newObjectData.content.keepAspectRatio ||
|
||||||
oldObjectData.content.materialType !==
|
oldObjectData.content.materialType !==
|
||||||
newObjectData.content.materialType
|
newObjectData.content.materialType ||
|
||||||
|
oldObjectData.content.centerLocation !==
|
||||||
|
newObjectData.content.centerLocation
|
||||||
) {
|
) {
|
||||||
|
// The center is applied to the model by `_updateModel`.
|
||||||
|
this._centerPoint = getPointForLocation(
|
||||||
|
newObjectData.content.centerLocation
|
||||||
|
);
|
||||||
this._updateModel(newObjectData);
|
this._updateModel(newObjectData);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@@ -186,36 +207,45 @@ namespace gdjs {
|
|||||||
this._originPoint = getPointForLocation(
|
this._originPoint = getPointForLocation(
|
||||||
newObjectData.content.originLocation
|
newObjectData.content.originLocation
|
||||||
);
|
);
|
||||||
|
this._renderer.updatePosition();
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
oldObjectData.content.centerLocation !==
|
oldObjectData.content.isCastingShadow !==
|
||||||
newObjectData.content.centerLocation
|
newObjectData.content.isCastingShadow
|
||||||
) {
|
) {
|
||||||
this._centerPoint = getPointForLocation(
|
this.setIsCastingShadow(newObjectData.content.isCastingShadow);
|
||||||
newObjectData.content.centerLocation
|
}
|
||||||
);
|
if (
|
||||||
|
oldObjectData.content.isReceivingShadow !==
|
||||||
|
newObjectData.content.isReceivingShadow
|
||||||
|
) {
|
||||||
|
this.setIsReceivingShadow(newObjectData.content.isReceivingShadow);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getNetworkSyncData(): Model3DObjectNetworkSyncData {
|
getNetworkSyncData(
|
||||||
|
syncOptions: GetNetworkSyncDataOptions
|
||||||
|
): Model3DObjectNetworkSyncData {
|
||||||
return {
|
return {
|
||||||
...super.getNetworkSyncData(),
|
...super.getNetworkSyncData(syncOptions),
|
||||||
mt: this._materialType,
|
mt: this._materialType,
|
||||||
op: this._originPoint,
|
op: this._originPoint,
|
||||||
cp: this._centerPoint,
|
cp: this._centerPoint,
|
||||||
anis: this._animations,
|
anis: this._animations,
|
||||||
ai: this._currentAnimationIndex,
|
ai: this._currentAnimationIndex,
|
||||||
ass: this._animationSpeedScale,
|
ass: this._animationSpeedScale,
|
||||||
|
aet: this.getAnimationElapsedTime(),
|
||||||
ap: this._animationPaused,
|
ap: this._animationPaused,
|
||||||
cfd: this._crossfadeDuration,
|
cfd: this._crossfadeDuration,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFromNetworkSyncData(
|
updateFromNetworkSyncData(
|
||||||
networkSyncData: Model3DObjectNetworkSyncData
|
networkSyncData: Model3DObjectNetworkSyncData,
|
||||||
|
options: UpdateFromNetworkSyncDataOptions
|
||||||
): void {
|
): void {
|
||||||
super.updateFromNetworkSyncData(networkSyncData);
|
super.updateFromNetworkSyncData(networkSyncData, options);
|
||||||
|
|
||||||
if (networkSyncData.mt !== undefined) {
|
if (networkSyncData.mt !== undefined) {
|
||||||
this._materialType = networkSyncData.mt;
|
this._materialType = networkSyncData.mt;
|
||||||
@@ -229,11 +259,14 @@ namespace gdjs {
|
|||||||
if (networkSyncData.anis !== undefined) {
|
if (networkSyncData.anis !== undefined) {
|
||||||
this._animations = networkSyncData.anis;
|
this._animations = networkSyncData.anis;
|
||||||
}
|
}
|
||||||
|
if (networkSyncData.ass !== undefined) {
|
||||||
|
this.setAnimationSpeedScale(networkSyncData.ass);
|
||||||
|
}
|
||||||
if (networkSyncData.ai !== undefined) {
|
if (networkSyncData.ai !== undefined) {
|
||||||
this.setAnimationIndex(networkSyncData.ai);
|
this.setAnimationIndex(networkSyncData.ai);
|
||||||
}
|
}
|
||||||
if (networkSyncData.ass !== undefined) {
|
if (networkSyncData.aet !== undefined) {
|
||||||
this.setAnimationSpeedScale(networkSyncData.ass);
|
this.setAnimationElapsedTime(networkSyncData.aet);
|
||||||
}
|
}
|
||||||
if (networkSyncData.ap !== undefined) {
|
if (networkSyncData.ap !== undefined) {
|
||||||
if (networkSyncData.ap !== this.isAnimationPaused()) {
|
if (networkSyncData.ap !== this.isAnimationPaused()) {
|
||||||
@@ -255,14 +288,17 @@ namespace gdjs {
|
|||||||
const rotationX = objectData.content.rotationX || 0;
|
const rotationX = objectData.content.rotationX || 0;
|
||||||
const rotationY = objectData.content.rotationY || 0;
|
const rotationY = objectData.content.rotationY || 0;
|
||||||
const rotationZ = objectData.content.rotationZ || 0;
|
const rotationZ = objectData.content.rotationZ || 0;
|
||||||
|
const width = objectData.content.width || 100;
|
||||||
|
const height = objectData.content.height || 100;
|
||||||
|
const depth = objectData.content.depth || 100;
|
||||||
const keepAspectRatio = objectData.content.keepAspectRatio;
|
const keepAspectRatio = objectData.content.keepAspectRatio;
|
||||||
this._renderer._updateModel(
|
this._renderer._updateModel(
|
||||||
rotationX,
|
rotationX,
|
||||||
rotationY,
|
rotationY,
|
||||||
rotationZ,
|
rotationZ,
|
||||||
this._getOriginalWidth(),
|
width,
|
||||||
this._getOriginalHeight(),
|
height,
|
||||||
this._getOriginalDepth(),
|
depth,
|
||||||
keepAspectRatio
|
keepAspectRatio
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -358,6 +394,16 @@ namespace gdjs {
|
|||||||
return this._renderer.hasAnimationEnded();
|
return this._renderer.hasAnimationEnded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsCastingShadow(value: boolean): void {
|
||||||
|
this._isCastingShadow = value;
|
||||||
|
this._renderer._updateShadow();
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsReceivingShadow(value: boolean): void {
|
||||||
|
this._isReceivingShadow = value;
|
||||||
|
this._renderer._updateShadow();
|
||||||
|
}
|
||||||
|
|
||||||
setCrossfadeDuration(duration: number): void {
|
setCrossfadeDuration(duration: number): void {
|
||||||
if (this._crossfadeDuration === duration) return;
|
if (this._crossfadeDuration === duration) return;
|
||||||
this._crossfadeDuration = duration;
|
this._crossfadeDuration = duration;
|
||||||
|
@@ -233,6 +233,10 @@ namespace gdjs {
|
|||||||
this._object._setOriginalWidth(scaleRatio * modelWidth);
|
this._object._setOriginalWidth(scaleRatio * modelWidth);
|
||||||
this._object._setOriginalHeight(scaleRatio * modelHeight);
|
this._object._setOriginalHeight(scaleRatio * modelHeight);
|
||||||
this._object._setOriginalDepth(scaleRatio * modelDepth);
|
this._object._setOriginalDepth(scaleRatio * modelDepth);
|
||||||
|
} else {
|
||||||
|
this._object._setOriginalWidth(originalWidth);
|
||||||
|
this._object._setOriginalHeight(originalHeight);
|
||||||
|
this._object._setOriginalDepth(originalDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,6 +290,8 @@ namespace gdjs {
|
|||||||
this.get3DRendererObject().remove(this._threeObject);
|
this.get3DRendererObject().remove(this._threeObject);
|
||||||
this.get3DRendererObject().add(threeObject);
|
this.get3DRendererObject().add(threeObject);
|
||||||
this._threeObject = threeObject;
|
this._threeObject = threeObject;
|
||||||
|
this.updatePosition();
|
||||||
|
this._updateShadow();
|
||||||
|
|
||||||
// Start the current animation on the new 3D object.
|
// Start the current animation on the new 3D object.
|
||||||
this._animationMixer = new THREE.AnimationMixer(root);
|
this._animationMixer = new THREE.AnimationMixer(root);
|
||||||
@@ -323,6 +329,13 @@ namespace gdjs {
|
|||||||
return this._originalModel.animations[animationIndex].name;
|
return this._originalModel.animations[animationIndex].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_updateShadow() {
|
||||||
|
this._threeObject.traverse((child) => {
|
||||||
|
child.castShadow = this._model3DRuntimeObject._isCastingShadow;
|
||||||
|
child.receiveShadow = this._model3DRuntimeObject._isReceivingShadow;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if animation has ended.
|
* Return true if animation has ended.
|
||||||
* The animation had ended if:
|
* The animation had ended if:
|
||||||
|
102
Extensions/3D/Skybox.ts
Normal file
102
Extensions/3D/Skybox.ts
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
namespace gdjs {
|
||||||
|
interface SkyboxFilterNetworkSyncData {}
|
||||||
|
gdjs.PixiFiltersTools.registerFilterCreator(
|
||||||
|
'Scene3D::Skybox',
|
||||||
|
new (class implements gdjs.PixiFiltersTools.FilterCreator {
|
||||||
|
makeFilter(
|
||||||
|
target: EffectsTarget,
|
||||||
|
effectData: EffectData
|
||||||
|
): gdjs.PixiFiltersTools.Filter {
|
||||||
|
if (typeof THREE === 'undefined') {
|
||||||
|
return new gdjs.PixiFiltersTools.EmptyFilter();
|
||||||
|
}
|
||||||
|
return new (class implements gdjs.PixiFiltersTools.Filter {
|
||||||
|
_cubeTexture: THREE.CubeTexture;
|
||||||
|
_oldBackground:
|
||||||
|
| THREE.CubeTexture
|
||||||
|
| THREE.Texture
|
||||||
|
| THREE.Color
|
||||||
|
| null = null;
|
||||||
|
_isEnabled: boolean = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._cubeTexture = target
|
||||||
|
.getRuntimeScene()
|
||||||
|
.getGame()
|
||||||
|
.getImageManager()
|
||||||
|
.getThreeCubeTexture(
|
||||||
|
effectData.stringParameters.rightFaceResourceName,
|
||||||
|
effectData.stringParameters.leftFaceResourceName,
|
||||||
|
effectData.stringParameters.topFaceResourceName,
|
||||||
|
effectData.stringParameters.bottomFaceResourceName,
|
||||||
|
effectData.stringParameters.frontFaceResourceName,
|
||||||
|
effectData.stringParameters.backFaceResourceName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
isEnabled(target: EffectsTarget): boolean {
|
||||||
|
return this._isEnabled;
|
||||||
|
}
|
||||||
|
setEnabled(target: EffectsTarget, enabled: boolean): boolean {
|
||||||
|
if (this._isEnabled === enabled) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (enabled) {
|
||||||
|
return this.applyEffect(target);
|
||||||
|
} else {
|
||||||
|
return this.removeEffect(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
applyEffect(target: EffectsTarget): boolean {
|
||||||
|
const scene = target.get3DRendererObject() as
|
||||||
|
| THREE.Scene
|
||||||
|
| null
|
||||||
|
| undefined;
|
||||||
|
if (!scene) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TODO Add a background stack in LayerPixiRenderer to allow
|
||||||
|
// filters to stack them.
|
||||||
|
this._oldBackground = scene.background;
|
||||||
|
scene.background = this._cubeTexture;
|
||||||
|
if (!scene.environment) {
|
||||||
|
scene.environment = this._cubeTexture;
|
||||||
|
}
|
||||||
|
this._isEnabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
removeEffect(target: EffectsTarget): boolean {
|
||||||
|
const scene = target.get3DRendererObject() as
|
||||||
|
| THREE.Scene
|
||||||
|
| null
|
||||||
|
| undefined;
|
||||||
|
if (!scene) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
scene.background = this._oldBackground;
|
||||||
|
scene.environment = null;
|
||||||
|
this._isEnabled = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
updatePreRender(target: gdjs.EffectsTarget): any {}
|
||||||
|
updateDoubleParameter(parameterName: string, value: number): void {}
|
||||||
|
getDoubleParameter(parameterName: string): number {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
updateStringParameter(parameterName: string, value: string): void {}
|
||||||
|
updateColorParameter(parameterName: string, value: number): void {}
|
||||||
|
getColorParameter(parameterName: string): number {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
updateBooleanParameter(parameterName: string, value: boolean): void {}
|
||||||
|
getNetworkSyncData(): SkyboxFilterNetworkSyncData {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
updateFromNetworkSyncData(
|
||||||
|
syncData: SkyboxFilterNetworkSyncData
|
||||||
|
): void {}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
);
|
||||||
|
}
|
@@ -473,7 +473,14 @@ namespace gdjs {
|
|||||||
this._parentOldMaxY = instanceContainer.getUnrotatedViewportMaxY();
|
this._parentOldMaxY = instanceContainer.getUnrotatedViewportMaxY();
|
||||||
}
|
}
|
||||||
|
|
||||||
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {}
|
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
|
||||||
|
// Custom objects can be resized during the events step.
|
||||||
|
// The anchor constraints must be applied on child-objects after the parent events.
|
||||||
|
const isChildObject = instanceContainer !== instanceContainer.getScene();
|
||||||
|
if (isChildObject) {
|
||||||
|
this.doStepPreEvents(instanceContainer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _convertCoords(
|
private _convertCoords(
|
||||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||||
|
@@ -14,6 +14,7 @@ describe('gdjs.AnchorRuntimeBehavior', () => {
|
|||||||
effects: [],
|
effects: [],
|
||||||
content: {},
|
content: {},
|
||||||
childrenContent: {},
|
childrenContent: {},
|
||||||
|
isInnerAreaFollowingParentSize: false,
|
||||||
});
|
});
|
||||||
runtimeScene.addObject(customObject);
|
runtimeScene.addObject(customObject);
|
||||||
customObject.setPosition(500, 250);
|
customObject.setPosition(500, 250);
|
||||||
|
@@ -75,9 +75,9 @@ module.exports = {
|
|||||||
.getOrCreate('align')
|
.getOrCreate('align')
|
||||||
.setValue(objectContent.align)
|
.setValue(objectContent.align)
|
||||||
.setType('choice')
|
.setType('choice')
|
||||||
.addExtraInfo('left')
|
.addChoice('left', _('Left'))
|
||||||
.addExtraInfo('center')
|
.addChoice('center', _('Center'))
|
||||||
.addExtraInfo('right')
|
.addChoice('right', _('Right'))
|
||||||
.setLabel(_('Base alignment'))
|
.setLabel(_('Base alignment'))
|
||||||
.setGroup(_('Appearance'));
|
.setGroup(_('Appearance'));
|
||||||
|
|
||||||
@@ -88,9 +88,9 @@ module.exports = {
|
|||||||
.getOrCreate('verticalTextAlignment')
|
.getOrCreate('verticalTextAlignment')
|
||||||
.setValue(objectContent.verticalTextAlignment)
|
.setValue(objectContent.verticalTextAlignment)
|
||||||
.setType('choice')
|
.setType('choice')
|
||||||
.addExtraInfo('top')
|
.addChoice('top', _('Top'))
|
||||||
.addExtraInfo('center')
|
.addChoice('center', _('Center'))
|
||||||
.addExtraInfo('bottom')
|
.addChoice('bottom', _('Bottom'))
|
||||||
.setLabel(_('Vertical alignment'))
|
.setLabel(_('Vertical alignment'))
|
||||||
.setGroup(_('Appearance'));
|
.setGroup(_('Appearance'));
|
||||||
|
|
||||||
@@ -508,7 +508,7 @@ module.exports = {
|
|||||||
associatedObjectConfiguration,
|
associatedObjectConfiguration,
|
||||||
pixiContainer,
|
pixiContainer,
|
||||||
pixiResourcesLoader,
|
pixiResourcesLoader,
|
||||||
propertyOverridings
|
getPropertyOverridings
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
project,
|
project,
|
||||||
@@ -516,7 +516,7 @@ module.exports = {
|
|||||||
associatedObjectConfiguration,
|
associatedObjectConfiguration,
|
||||||
pixiContainer,
|
pixiContainer,
|
||||||
pixiResourcesLoader,
|
pixiResourcesLoader,
|
||||||
propertyOverridings
|
getPropertyOverridings
|
||||||
);
|
);
|
||||||
|
|
||||||
const bbTextStyles = {
|
const bbTextStyles = {
|
||||||
@@ -555,9 +555,11 @@ module.exports = {
|
|||||||
gd.ObjectJsImplementation
|
gd.ObjectJsImplementation
|
||||||
);
|
);
|
||||||
|
|
||||||
const rawText = this._propertyOverridings.has('Text')
|
const propertyOverridings = this.getPropertyOverridings();
|
||||||
? this._propertyOverridings.get('Text')
|
const rawText =
|
||||||
: object.content.text;
|
propertyOverridings && propertyOverridings.has('Text')
|
||||||
|
? propertyOverridings.get('Text')
|
||||||
|
: object.content.text;
|
||||||
if (rawText !== this._pixiObject.text) {
|
if (rawText !== this._pixiObject.text) {
|
||||||
this._pixiObject.text = rawText;
|
this._pixiObject.text = rawText;
|
||||||
}
|
}
|
||||||
|
@@ -145,9 +145,11 @@ namespace gdjs {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
override getNetworkSyncData(): BBTextObjectNetworkSyncData {
|
override getNetworkSyncData(
|
||||||
|
syncOptions: GetNetworkSyncDataOptions
|
||||||
|
): BBTextObjectNetworkSyncData {
|
||||||
return {
|
return {
|
||||||
...super.getNetworkSyncData(),
|
...super.getNetworkSyncData(syncOptions),
|
||||||
text: this._text,
|
text: this._text,
|
||||||
o: this._opacity,
|
o: this._opacity,
|
||||||
c: this._color,
|
c: this._color,
|
||||||
@@ -162,9 +164,10 @@ namespace gdjs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override updateFromNetworkSyncData(
|
override updateFromNetworkSyncData(
|
||||||
networkSyncData: BBTextObjectNetworkSyncData
|
networkSyncData: BBTextObjectNetworkSyncData,
|
||||||
|
options: UpdateFromNetworkSyncDataOptions
|
||||||
): void {
|
): void {
|
||||||
super.updateFromNetworkSyncData(networkSyncData);
|
super.updateFromNetworkSyncData(networkSyncData, options);
|
||||||
if (this._text !== undefined) {
|
if (this._text !== undefined) {
|
||||||
this.setBBText(networkSyncData.text);
|
this.setBBText(networkSyncData.text);
|
||||||
}
|
}
|
||||||
@@ -383,6 +386,10 @@ namespace gdjs {
|
|||||||
return this._renderer.getHeight();
|
return this._renderer.getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override setWidth(width: float): void {
|
||||||
|
this.setWrappingWidth(width);
|
||||||
|
}
|
||||||
|
|
||||||
override getDrawableY(): float {
|
override getDrawableY(): float {
|
||||||
return (
|
return (
|
||||||
this.getY() -
|
this.getY() -
|
||||||
|
@@ -61,9 +61,9 @@ module.exports = {
|
|||||||
.getOrCreate('align')
|
.getOrCreate('align')
|
||||||
.setValue(objectContent.align)
|
.setValue(objectContent.align)
|
||||||
.setType('choice')
|
.setType('choice')
|
||||||
.addExtraInfo('left')
|
.addChoice('left', _('Left'))
|
||||||
.addExtraInfo('center')
|
.addChoice('center', _('Center'))
|
||||||
.addExtraInfo('right')
|
.addChoice('right', _('Right'))
|
||||||
.setLabel(_('Alignment'))
|
.setLabel(_('Alignment'))
|
||||||
.setGroup(_('Appearance'));
|
.setGroup(_('Appearance'));
|
||||||
|
|
||||||
@@ -74,9 +74,9 @@ module.exports = {
|
|||||||
.getOrCreate('verticalTextAlignment')
|
.getOrCreate('verticalTextAlignment')
|
||||||
.setValue(objectContent.verticalTextAlignment)
|
.setValue(objectContent.verticalTextAlignment)
|
||||||
.setType('choice')
|
.setType('choice')
|
||||||
.addExtraInfo('top')
|
.addChoice('top', _('Top'))
|
||||||
.addExtraInfo('center')
|
.addChoice('center', _('Center'))
|
||||||
.addExtraInfo('bottom')
|
.addChoice('bottom', _('Bottom'))
|
||||||
.setLabel(_('Vertical alignment'))
|
.setLabel(_('Vertical alignment'))
|
||||||
.setGroup(_('Appearance'));
|
.setGroup(_('Appearance'));
|
||||||
|
|
||||||
@@ -631,7 +631,7 @@ module.exports = {
|
|||||||
associatedObjectConfiguration,
|
associatedObjectConfiguration,
|
||||||
pixiContainer,
|
pixiContainer,
|
||||||
pixiResourcesLoader,
|
pixiResourcesLoader,
|
||||||
propertyOverridings
|
getPropertyOverridings
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
project,
|
project,
|
||||||
@@ -639,7 +639,7 @@ module.exports = {
|
|||||||
associatedObjectConfiguration,
|
associatedObjectConfiguration,
|
||||||
pixiContainer,
|
pixiContainer,
|
||||||
pixiResourcesLoader,
|
pixiResourcesLoader,
|
||||||
propertyOverridings
|
getPropertyOverridings
|
||||||
);
|
);
|
||||||
|
|
||||||
// We'll track changes of the font to trigger the loading of the new font.
|
// We'll track changes of the font to trigger the loading of the new font.
|
||||||
@@ -665,9 +665,11 @@ module.exports = {
|
|||||||
|
|
||||||
// Update the rendered text properties (note: Pixi is only
|
// Update the rendered text properties (note: Pixi is only
|
||||||
// applying changes if there were changed).
|
// applying changes if there were changed).
|
||||||
this._pixiObject.text = this._propertyOverridings.has('Text')
|
const propertyOverridings = this.getPropertyOverridings();
|
||||||
? this._propertyOverridings.get('Text')
|
this._pixiObject.text =
|
||||||
: object.content.text;
|
propertyOverridings && propertyOverridings.has('Text')
|
||||||
|
? propertyOverridings.get('Text')
|
||||||
|
: object.content.text;
|
||||||
|
|
||||||
const align = object.content.align;
|
const align = object.content.align;
|
||||||
this._pixiObject.align = align;
|
this._pixiObject.align = align;
|
||||||
|
@@ -155,9 +155,11 @@ namespace gdjs {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
override getNetworkSyncData(): BitmapTextObjectNetworkSyncData {
|
override getNetworkSyncData(
|
||||||
|
syncOptions: GetNetworkSyncDataOptions
|
||||||
|
): BitmapTextObjectNetworkSyncData {
|
||||||
return {
|
return {
|
||||||
...super.getNetworkSyncData(),
|
...super.getNetworkSyncData(syncOptions),
|
||||||
text: this._text,
|
text: this._text,
|
||||||
opa: this._opacity,
|
opa: this._opacity,
|
||||||
tint: this._tint,
|
tint: this._tint,
|
||||||
@@ -172,9 +174,10 @@ namespace gdjs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override updateFromNetworkSyncData(
|
override updateFromNetworkSyncData(
|
||||||
networkSyncData: BitmapTextObjectNetworkSyncData
|
networkSyncData: BitmapTextObjectNetworkSyncData,
|
||||||
|
options: UpdateFromNetworkSyncDataOptions
|
||||||
): void {
|
): void {
|
||||||
super.updateFromNetworkSyncData(networkSyncData);
|
super.updateFromNetworkSyncData(networkSyncData, options);
|
||||||
if (this._text !== undefined) {
|
if (this._text !== undefined) {
|
||||||
this.setText(networkSyncData.text);
|
this.setText(networkSyncData.text);
|
||||||
}
|
}
|
||||||
@@ -426,6 +429,10 @@ namespace gdjs {
|
|||||||
return this._renderer.getHeight();
|
return this._renderer.getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override setWidth(width: float): void {
|
||||||
|
this.setWrappingWidth(width);
|
||||||
|
}
|
||||||
|
|
||||||
override getDrawableY(): float {
|
override getDrawableY(): float {
|
||||||
return (
|
return (
|
||||||
this.getY() -
|
this.getY() -
|
||||||
|
@@ -21,7 +21,9 @@ module.exports = {
|
|||||||
.setExtensionInformation(
|
.setExtensionInformation(
|
||||||
'DebuggerTools',
|
'DebuggerTools',
|
||||||
_('Debugger Tools'),
|
_('Debugger Tools'),
|
||||||
_('Allow to interact with the editor debugger from the game.'),
|
_(
|
||||||
|
'Allow to interact with the editor debugger from the game (notably: enable 2D debug draw, log a message in the debugger console).'
|
||||||
|
),
|
||||||
'Arthur Pacaud (arthuro555), Aurélien Vivet (Bouh)',
|
'Arthur Pacaud (arthuro555), Aurélien Vivet (Bouh)',
|
||||||
'MIT'
|
'MIT'
|
||||||
)
|
)
|
||||||
|
@@ -12,7 +12,8 @@ This project is released under the MIT License.
|
|||||||
#include "GDCore/Tools/Localization.h"
|
#include "GDCore/Tools/Localization.h"
|
||||||
|
|
||||||
void DestroyOutsideBehavior::InitializeContent(gd::SerializerElement& content) {
|
void DestroyOutsideBehavior::InitializeContent(gd::SerializerElement& content) {
|
||||||
content.SetAttribute("extraBorder", 0);
|
content.SetAttribute("extraBorder", 200);
|
||||||
|
content.SetAttribute("unseenGraceDistance", 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GD_IDE_ONLY)
|
#if defined(GD_IDE_ONLY)
|
||||||
@@ -27,7 +28,15 @@ DestroyOutsideBehavior::GetProperties(
|
|||||||
.SetType("Number")
|
.SetType("Number")
|
||||||
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
|
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
|
||||||
.SetLabel(_("Deletion margin"))
|
.SetLabel(_("Deletion margin"))
|
||||||
.SetDescription(_("Margin before deleting the object, in pixels"));
|
.SetDescription(_("Margin before deleting the object, in pixels."));
|
||||||
|
|
||||||
|
properties["unseenGraceDistance"]
|
||||||
|
.SetValue(gd::String::From(
|
||||||
|
behaviorContent.GetDoubleAttribute("unseenGraceDistance", 0)))
|
||||||
|
.SetType("Number")
|
||||||
|
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
|
||||||
|
.SetLabel(_("Unseen object grace distance"))
|
||||||
|
.SetDescription(_("If the object hasn't been visible yet, don't delete it until it travels this far beyond the screen (in pixels). Useful to avoid objects being deleted before they are visible when they spawn."));
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
@@ -38,6 +47,8 @@ bool DestroyOutsideBehavior::UpdateProperty(
|
|||||||
const gd::String& value) {
|
const gd::String& value) {
|
||||||
if (name == "extraBorder")
|
if (name == "extraBorder")
|
||||||
behaviorContent.SetAttribute("extraBorder", value.To<double>());
|
behaviorContent.SetAttribute("extraBorder", value.To<double>());
|
||||||
|
else if (name == "unseenGraceDistance")
|
||||||
|
behaviorContent.SetAttribute("unseenGraceDistance", value.To<double>());
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@@ -6,65 +6,77 @@ This project is released under the MIT License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DestroyOutsideBehavior.h"
|
#include "DestroyOutsideBehavior.h"
|
||||||
|
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
|
||||||
#include "GDCore/Extensions/PlatformExtension.h"
|
#include "GDCore/Extensions/PlatformExtension.h"
|
||||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||||
#include "GDCore/Tools/Localization.h"
|
#include "GDCore/Tools/Localization.h"
|
||||||
|
|
||||||
void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension) {
|
void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension) {
|
||||||
extension
|
extension
|
||||||
.SetExtensionInformation("DestroyOutsideBehavior",
|
.SetExtensionInformation(
|
||||||
_("Destroy Outside Screen Behavior"),
|
"DestroyOutsideBehavior",
|
||||||
_("This behavior can be used to destroy "
|
_("Destroy Outside Screen Behavior"),
|
||||||
"objects when they go outside of "
|
_("This behavior can be used to destroy objects when they go "
|
||||||
"the bounds of the camera. Useful for bullets "
|
"outside of the bounds of the 2D camera. Useful for 2D bullets or "
|
||||||
"or other short-lived objects."),
|
"other short-lived objects. Don't use it for 3D objects in a "
|
||||||
"Florian Rival",
|
"FPS/TPS game or any game with a camera not being a top view "
|
||||||
"Open source (MIT License)")
|
"(for 3D objects, prefer comparing the position, for example Z "
|
||||||
|
"position to see if an object goes outside of the bound of the "
|
||||||
|
"map). If the object appears outside of the screen, it's not "
|
||||||
|
"removed unless it goes beyond the unseen object grace distance."),
|
||||||
|
"Florian Rival",
|
||||||
|
"Open source (MIT License)")
|
||||||
.SetCategory("Game mechanic")
|
.SetCategory("Game mechanic")
|
||||||
.SetTags("screen")
|
.SetTags("screen")
|
||||||
.SetExtensionHelpPath("/behaviors/destroyoutside");
|
.SetExtensionHelpPath("/behaviors/destroyoutside");
|
||||||
|
|
||||||
gd::BehaviorMetadata& aut =
|
gd::BehaviorMetadata& aut =
|
||||||
extension.AddBehavior("DestroyOutside",
|
extension
|
||||||
_("Destroy when outside of the screen"),
|
.AddBehavior("DestroyOutside",
|
||||||
_("DestroyOutside"),
|
_("Destroy when outside of the screen"),
|
||||||
_("Destroy objects automatically when they go "
|
_("DestroyOutside"),
|
||||||
"outside of the screen's borders."),
|
_("Destroy objects automatically when they go "
|
||||||
"",
|
"outside of the 2D camera borders."),
|
||||||
"CppPlatform/Extensions/destroyoutsideicon.png",
|
"",
|
||||||
"DestroyOutsideBehavior",
|
"CppPlatform/Extensions/destroyoutsideicon.png",
|
||||||
std::make_shared<DestroyOutsideBehavior>(),
|
"DestroyOutsideBehavior",
|
||||||
std::shared_ptr<gd::BehaviorsSharedData>())
|
std::make_shared<DestroyOutsideBehavior>(),
|
||||||
.SetQuickCustomizationVisibility(gd::QuickCustomization::Hidden);
|
std::shared_ptr<gd::BehaviorsSharedData>())
|
||||||
|
.SetQuickCustomizationVisibility(gd::QuickCustomization::Hidden);
|
||||||
|
|
||||||
aut.AddCondition("ExtraBorder",
|
aut.AddExpressionAndConditionAndAction(
|
||||||
_("Additional border"),
|
"number",
|
||||||
_("Compare the additional border that the object must cross "
|
"ExtraBorder",
|
||||||
"before being deleted."),
|
_("Additional border (extra distance before deletion)"),
|
||||||
_("the additional border"),
|
_("the extra distance (in pixels) the object must "
|
||||||
_("Destroy outside configuration"),
|
"travel beyond the screen before it gets deleted"),
|
||||||
"CppPlatform/Extensions/destroyoutsideicon24.png",
|
_("the additional border"),
|
||||||
"CppPlatform/Extensions/destroyoutsideicon16.png")
|
_("Destroy outside configuration"),
|
||||||
|
"CppPlatform/Extensions/destroyoutsideicon24.png")
|
||||||
.AddParameter("object", _("Object"))
|
.AddParameter("object", _("Object"))
|
||||||
.AddParameter("behavior", _("Behavior"), "DestroyOutside")
|
.AddParameter("behavior", _("Behavior"), "DestroyOutside")
|
||||||
.UseStandardRelationalOperatorParameters(
|
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions())
|
||||||
"number", gd::ParameterOptions::MakeNewOptions())
|
.MarkAsAdvanced();
|
||||||
.MarkAsAdvanced()
|
|
||||||
.SetFunctionName("GetExtraBorder");
|
|
||||||
|
|
||||||
aut.AddAction("ExtraBorder",
|
// Deprecated:
|
||||||
_("Additional border"),
|
aut.AddDuplicatedAction("ExtraBorder", "DestroyOutside::SetExtraBorder")
|
||||||
_("Change the additional border that the object must cross "
|
.SetHidden();
|
||||||
"before being deleted."),
|
aut.AddDuplicatedCondition("ExtraBorder", "DestroyOutside::ExtraBorder")
|
||||||
_("the additional border"),
|
.SetHidden();
|
||||||
_("Destroy outside configuration"),
|
|
||||||
"CppPlatform/Extensions/destroyoutsideicon24.png",
|
aut.AddExpressionAndConditionAndAction(
|
||||||
"CppPlatform/Extensions/destroyoutsideicon16.png")
|
"number",
|
||||||
|
"UnseenGraceDistance",
|
||||||
|
_("Unseen object grace distance"),
|
||||||
|
_("the grace distance (in pixels) before deleting the object if it "
|
||||||
|
"has "
|
||||||
|
"never been visible on the screen. Useful to avoid objects being "
|
||||||
|
"deleted before they are visible when they spawn"),
|
||||||
|
_("the unseen grace distance"),
|
||||||
|
_("Destroy outside configuration"),
|
||||||
|
"CppPlatform/Extensions/destroyoutsideicon24.png")
|
||||||
.AddParameter("object", _("Object"))
|
.AddParameter("object", _("Object"))
|
||||||
.AddParameter("behavior", _("Behavior"), "DestroyOutside")
|
.AddParameter("behavior", _("Behavior"), "DestroyOutside")
|
||||||
.UseStandardOperatorParameters("number",
|
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions())
|
||||||
gd::ParameterOptions::MakeNewOptions())
|
.MarkAsAdvanced();
|
||||||
.MarkAsAdvanced()
|
|
||||||
.SetFunctionName("SetExtraBorder")
|
|
||||||
.SetGetter("GetExtraBorder");
|
|
||||||
}
|
}
|
||||||
|
@@ -5,11 +5,11 @@ Copyright (c) 2014-2016 Florian Rival (Florian.Rival@gmail.com)
|
|||||||
This project is released under the MIT License.
|
This project is released under the MIT License.
|
||||||
*/
|
*/
|
||||||
#if defined(GD_IDE_ONLY)
|
#if defined(GD_IDE_ONLY)
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "GDCore/Extensions/PlatformExtension.h"
|
#include "GDCore/Extensions/PlatformExtension.h"
|
||||||
#include "GDCore/Tools/Localization.h"
|
#include "GDCore/Tools/Localization.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension);
|
void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,19 +29,36 @@ class DestroyOutsideBehaviorJsExtension : public gd::PlatformExtension {
|
|||||||
"Extensions/DestroyOutsideBehavior/"
|
"Extensions/DestroyOutsideBehavior/"
|
||||||
"destroyoutsideruntimebehavior.js");
|
"destroyoutsideruntimebehavior.js");
|
||||||
|
|
||||||
|
GetAllExpressionsForBehavior(
|
||||||
|
"DestroyOutsideBehavior::DestroyOutside")["ExtraBorder"]
|
||||||
|
.SetFunctionName("getExtraBorder");
|
||||||
|
GetAllConditionsForBehavior("DestroyOutsideBehavior::DestroyOutside")
|
||||||
|
["DestroyOutsideBehavior::DestroyOutside::ExtraBorder"]
|
||||||
|
.SetFunctionName("getExtraBorder");
|
||||||
|
GetAllActionsForBehavior("DestroyOutsideBehavior::DestroyOutside")
|
||||||
|
["DestroyOutsideBehavior::DestroyOutside::SetExtraBorder"]
|
||||||
|
.SetFunctionName("setExtraBorder")
|
||||||
|
.SetGetter("getExtraBorder");
|
||||||
|
|
||||||
|
// Deprecated:
|
||||||
GetAllConditionsForBehavior("DestroyOutsideBehavior::DestroyOutside")
|
GetAllConditionsForBehavior("DestroyOutsideBehavior::DestroyOutside")
|
||||||
["DestroyOutsideBehavior::ExtraBorder"]
|
["DestroyOutsideBehavior::ExtraBorder"]
|
||||||
.SetFunctionName("getExtraBorder")
|
.SetFunctionName("getExtraBorder");
|
||||||
.SetIncludeFile(
|
|
||||||
"Extensions/DestroyOutsideBehavior/"
|
|
||||||
"destroyoutsideruntimebehavior.js");
|
|
||||||
GetAllActionsForBehavior("DestroyOutsideBehavior::DestroyOutside")
|
GetAllActionsForBehavior("DestroyOutsideBehavior::DestroyOutside")
|
||||||
["DestroyOutsideBehavior::ExtraBorder"]
|
["DestroyOutsideBehavior::ExtraBorder"]
|
||||||
.SetFunctionName("setExtraBorder")
|
.SetFunctionName("setExtraBorder")
|
||||||
.SetGetter("getExtraBorder")
|
.SetGetter("getExtraBorder");
|
||||||
.SetIncludeFile(
|
|
||||||
"Extensions/DestroyOutsideBehavior/"
|
GetAllExpressionsForBehavior(
|
||||||
"destroyoutsideruntimebehavior.js");
|
"DestroyOutsideBehavior::DestroyOutside")["UnseenGraceDistance"]
|
||||||
|
.SetFunctionName("getUnseenGraceDistance");
|
||||||
|
GetAllConditionsForBehavior("DestroyOutsideBehavior::DestroyOutside")
|
||||||
|
["DestroyOutsideBehavior::DestroyOutside::UnseenGraceDistance"]
|
||||||
|
.SetFunctionName("getUnseenGraceDistance");
|
||||||
|
GetAllActionsForBehavior("DestroyOutsideBehavior::DestroyOutside")
|
||||||
|
["DestroyOutsideBehavior::DestroyOutside::SetUnseenGraceDistance"]
|
||||||
|
.SetFunctionName("setUnseenGraceDistance")
|
||||||
|
.SetGetter("getUnseenGraceDistance");
|
||||||
|
|
||||||
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
|
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
|
||||||
};
|
};
|
||||||
|
@@ -8,7 +8,9 @@ namespace gdjs {
|
|||||||
* The DestroyOutsideRuntimeBehavior represents a behavior that destroys the object when it leaves the screen.
|
* The DestroyOutsideRuntimeBehavior represents a behavior that destroys the object when it leaves the screen.
|
||||||
*/
|
*/
|
||||||
export class DestroyOutsideRuntimeBehavior extends gdjs.RuntimeBehavior {
|
export class DestroyOutsideRuntimeBehavior extends gdjs.RuntimeBehavior {
|
||||||
_extraBorder: any;
|
_extraBorder: float;
|
||||||
|
_unseenGraceDistance: float;
|
||||||
|
_hasBeenOnScreen: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||||
@@ -17,12 +19,20 @@ namespace gdjs {
|
|||||||
) {
|
) {
|
||||||
super(instanceContainer, behaviorData, owner);
|
super(instanceContainer, behaviorData, owner);
|
||||||
this._extraBorder = behaviorData.extraBorder || 0;
|
this._extraBorder = behaviorData.extraBorder || 0;
|
||||||
|
this._unseenGraceDistance = behaviorData.unseenGraceDistance || 0;
|
||||||
|
this._hasBeenOnScreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFromBehaviorData(oldBehaviorData, newBehaviorData): boolean {
|
updateFromBehaviorData(oldBehaviorData, newBehaviorData): boolean {
|
||||||
if (oldBehaviorData.extraBorder !== newBehaviorData.extraBorder) {
|
if (oldBehaviorData.extraBorder !== newBehaviorData.extraBorder) {
|
||||||
this._extraBorder = newBehaviorData.extraBorder;
|
this._extraBorder = newBehaviorData.extraBorder;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
oldBehaviorData.unseenGraceDistance !==
|
||||||
|
newBehaviorData.unseenGraceDistance
|
||||||
|
) {
|
||||||
|
this._unseenGraceDistance = newBehaviorData.unseenGraceDistance;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,23 +45,47 @@ namespace gdjs {
|
|||||||
const ocy = this.owner.getDrawableY() + this.owner.getCenterY();
|
const ocy = this.owner.getDrawableY() + this.owner.getCenterY();
|
||||||
const layer = instanceContainer.getLayer(this.owner.getLayer());
|
const layer = instanceContainer.getLayer(this.owner.getLayer());
|
||||||
const boundingCircleRadius = Math.sqrt(ow * ow + oh * oh) / 2.0;
|
const boundingCircleRadius = Math.sqrt(ow * ow + oh * oh) / 2.0;
|
||||||
|
|
||||||
|
const cameraLeft = layer.getCameraX() - layer.getCameraWidth() / 2;
|
||||||
|
const cameraRight = layer.getCameraX() + layer.getCameraWidth() / 2;
|
||||||
|
const cameraTop = layer.getCameraY() - layer.getCameraHeight() / 2;
|
||||||
|
const cameraBottom = layer.getCameraY() + layer.getCameraHeight() / 2;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
ocx + boundingCircleRadius + this._extraBorder <
|
ocx + boundingCircleRadius + this._extraBorder < cameraLeft ||
|
||||||
layer.getCameraX() - layer.getCameraWidth() / 2 ||
|
ocx - boundingCircleRadius - this._extraBorder > cameraRight ||
|
||||||
ocx - boundingCircleRadius - this._extraBorder >
|
ocy + boundingCircleRadius + this._extraBorder < cameraTop ||
|
||||||
layer.getCameraX() + layer.getCameraWidth() / 2 ||
|
ocy - boundingCircleRadius - this._extraBorder > cameraBottom
|
||||||
ocy + boundingCircleRadius + this._extraBorder <
|
|
||||||
layer.getCameraY() - layer.getCameraHeight() / 2 ||
|
|
||||||
ocy - boundingCircleRadius - this._extraBorder >
|
|
||||||
layer.getCameraY() + layer.getCameraHeight() / 2
|
|
||||||
) {
|
) {
|
||||||
//We are outside the camera area.
|
if (this._hasBeenOnScreen) {
|
||||||
this.owner.deleteFromScene(instanceContainer);
|
// Object is outside the camera area and object was previously seen inside it:
|
||||||
|
// delete it now.
|
||||||
|
this.owner.deleteFromScene();
|
||||||
|
} else if (
|
||||||
|
ocx + boundingCircleRadius + this._unseenGraceDistance < cameraLeft ||
|
||||||
|
ocx - boundingCircleRadius - this._unseenGraceDistance >
|
||||||
|
cameraRight ||
|
||||||
|
ocy + boundingCircleRadius + this._unseenGraceDistance < cameraTop ||
|
||||||
|
ocy - boundingCircleRadius - this._unseenGraceDistance > cameraBottom
|
||||||
|
) {
|
||||||
|
// Object is outside the camera area and also outside the grace distance:
|
||||||
|
// force deletion.
|
||||||
|
this.owner.deleteFromScene();
|
||||||
|
} else {
|
||||||
|
// Object is outside the camera area but inside the grace distance
|
||||||
|
// and was never seen inside the camera area: don't delete it yet.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._hasBeenOnScreen = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an additional border to the camera viewport as a buffer before the object gets destroyed.
|
* Set the additional border outside the camera area.
|
||||||
|
*
|
||||||
|
* If the object goes beyond the camera area and this border, it will be deleted (unless it was
|
||||||
|
* never seen inside the camera area and this border before, in which case it will be deleted
|
||||||
|
* according to the grace distance).
|
||||||
* @param val Border in pixels.
|
* @param val Border in pixels.
|
||||||
*/
|
*/
|
||||||
setExtraBorder(val: number): void {
|
setExtraBorder(val: number): void {
|
||||||
@@ -59,12 +93,36 @@ namespace gdjs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the additional border of the camera viewport buffer which triggers the destruction of an object.
|
* Get the additional border outside the camera area.
|
||||||
* @return The additional border around the camera viewport in pixels
|
* @return The additional border around the camera viewport in pixels
|
||||||
*/
|
*/
|
||||||
getExtraBorder(): number {
|
getExtraBorder(): number {
|
||||||
return this._extraBorder;
|
return this._extraBorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the grace distance before an object is deleted if it's outside the camera area
|
||||||
|
* and was never seen inside the camera area. Typically useful to avoid objects being deleted
|
||||||
|
* before they are visible when they spawn.
|
||||||
|
*/
|
||||||
|
setUnseenGraceDistance(val: number): void {
|
||||||
|
this._unseenGraceDistance = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the grace distance before an object is deleted if it's outside the camera area
|
||||||
|
* and was never seen inside the camera area.
|
||||||
|
*/
|
||||||
|
getUnseenGraceDistance(): number {
|
||||||
|
return this._unseenGraceDistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this object has been visible on screen (precisely: inside the camera area *including* the extra border).
|
||||||
|
*/
|
||||||
|
hasBeenOnScreen(): boolean {
|
||||||
|
return this._hasBeenOnScreen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
gdjs.registerBehavior(
|
gdjs.registerBehavior(
|
||||||
'DestroyOutsideBehavior::DestroyOutside',
|
'DestroyOutsideBehavior::DestroyOutside',
|
||||||
|
@@ -35,25 +35,32 @@ void DeclareDraggableBehaviorExtension(gd::PlatformExtension& extension) {
|
|||||||
std::make_shared<DraggableBehavior>(),
|
std::make_shared<DraggableBehavior>(),
|
||||||
std::shared_ptr<gd::BehaviorsSharedData>());
|
std::shared_ptr<gd::BehaviorsSharedData>());
|
||||||
|
|
||||||
aut.AddCondition("Dragged",
|
aut.AddCondition(
|
||||||
_("Being dragged"),
|
"Dragged",
|
||||||
_("Check if the object is being dragged."),
|
_("Being dragged"),
|
||||||
_("_PARAM0_ is being dragged"),
|
_("Check if the object is being dragged. This means the mouse button "
|
||||||
_("Draggable"),
|
"or touch is pressed on it. When the mouse button or touch is "
|
||||||
"CppPlatform/Extensions/draggableicon24.png",
|
"released, the object is no longer being considered dragged (use "
|
||||||
"CppPlatform/Extensions/draggableicon16.png")
|
"the condition \"Was just dropped\" to check when the dragging is "
|
||||||
|
"ending)."),
|
||||||
|
_("_PARAM0_ is being dragged"),
|
||||||
|
_("Draggable"),
|
||||||
|
"CppPlatform/Extensions/draggableicon24.png",
|
||||||
|
"CppPlatform/Extensions/draggableicon16.png")
|
||||||
|
|
||||||
.AddParameter("object", _("Object"))
|
.AddParameter("object", _("Object"))
|
||||||
.AddParameter("behavior", _("Behavior"), "Draggable")
|
.AddParameter("behavior", _("Behavior"), "Draggable")
|
||||||
.SetFunctionName("IsDragged");
|
.SetFunctionName("IsDragged");
|
||||||
|
|
||||||
aut.AddCondition("Dropped",
|
aut.AddCondition(
|
||||||
_("Was just dropped"),
|
"Dropped",
|
||||||
_("Check if the object was just dropped after being dragged."),
|
_("Was just dropped"),
|
||||||
_("_PARAM0_ was just dropped"),
|
_("Check if the object was just dropped after being dragged (the "
|
||||||
_("Draggable"),
|
"mouse button or touch was just released this frame)."),
|
||||||
"CppPlatform/Extensions/draggableicon24.png",
|
_("_PARAM0_ was just dropped"),
|
||||||
"CppPlatform/Extensions/draggableicon16.png")
|
_("Draggable"),
|
||||||
|
"CppPlatform/Extensions/draggableicon24.png",
|
||||||
|
"CppPlatform/Extensions/draggableicon16.png")
|
||||||
|
|
||||||
.AddParameter("object", _("Object"))
|
.AddParameter("object", _("Object"))
|
||||||
.AddParameter("behavior", _("Behavior"), "Draggable")
|
.AddParameter("behavior", _("Behavior"), "Draggable")
|
||||||
|
@@ -21,7 +21,9 @@ module.exports = {
|
|||||||
.setExtensionInformation(
|
.setExtensionInformation(
|
||||||
'FileSystem',
|
'FileSystem',
|
||||||
_('File system'),
|
_('File system'),
|
||||||
_('Access the filesystem of the operating system.'),
|
_(
|
||||||
|
'Access the filesystem of the operating system - only works on native, desktop games exported to Windows, Linux or macOS.'
|
||||||
|
),
|
||||||
'Matthias Meike',
|
'Matthias Meike',
|
||||||
'Open source (MIT License)'
|
'Open source (MIT License)'
|
||||||
)
|
)
|
||||||
|
@@ -5,23 +5,25 @@ Copyright (c) 2008-2016 Florian Rival (Florian.Rival@gmail.com)
|
|||||||
This project is released under the MIT License.
|
This project is released under the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "GDCore/Extensions/PlatformExtension.h"
|
#include "GDCore/Extensions/PlatformExtension.h"
|
||||||
#include "GDCore/Tools/Localization.h"
|
#include "GDCore/Tools/Localization.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
void DeclareInventoryExtension(gd::PlatformExtension& extension) {
|
void DeclareInventoryExtension(gd::PlatformExtension& extension) {
|
||||||
extension.SetExtensionInformation(
|
extension
|
||||||
"Inventory",
|
.SetExtensionInformation(
|
||||||
_("Inventories"),
|
"Inventory",
|
||||||
_("Provides actions and conditions to add an inventory to your game, "
|
_("Inventories"),
|
||||||
"with items in memory."),
|
_("Actions and conditions to store named inventories in memory, "
|
||||||
"Florian Rival",
|
"with items (indexed by their name), a count for each of them, "
|
||||||
"Open source (MIT License)")
|
"a maximum count and an equipped state. Can be loaded/saved "
|
||||||
|
"from/to a GDevelop variable."),
|
||||||
|
"Florian Rival",
|
||||||
|
"Open source (MIT License)")
|
||||||
.SetExtensionHelpPath("/all-features/inventory")
|
.SetExtensionHelpPath("/all-features/inventory")
|
||||||
.SetCategory("Game mechanic");
|
.SetCategory("Game mechanic");
|
||||||
extension
|
extension.AddInstructionOrExpressionGroupMetadata(_("Inventories"))
|
||||||
.AddInstructionOrExpressionGroupMetadata(_("Inventories"))
|
|
||||||
.SetIcon("CppPlatform/Extensions/Inventoryicon.png");
|
.SetIcon("CppPlatform/Extensions/Inventoryicon.png");
|
||||||
|
|
||||||
extension
|
extension
|
||||||
@@ -164,14 +166,15 @@ void DeclareInventoryExtension(gd::PlatformExtension& extension) {
|
|||||||
.SetFunctionName("InventoryTools::IsEquipped");
|
.SetFunctionName("InventoryTools::IsEquipped");
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddAction("SerializeToVariable",
|
.AddAction(
|
||||||
_("Save an inventory in a scene variable"),
|
"SerializeToVariable",
|
||||||
_("Save all the items of the inventory in a scene variable, so that "
|
_("Save an inventory in a scene variable"),
|
||||||
"it can be restored later."),
|
_("Save all the items of the inventory in a scene variable, so that "
|
||||||
_("Save inventory _PARAM1_ in variable _PARAM2_"),
|
"it can be restored later."),
|
||||||
_("Variables"),
|
_("Save inventory _PARAM1_ in variable _PARAM2_"),
|
||||||
"CppPlatform/Extensions/Inventoryicon.png",
|
_("Variables"),
|
||||||
"CppPlatform/Extensions/Inventoryicon.png")
|
"CppPlatform/Extensions/Inventoryicon.png",
|
||||||
|
"CppPlatform/Extensions/Inventoryicon.png")
|
||||||
|
|
||||||
.AddCodeOnlyParameter("currentScene", "")
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
.AddParameter("string", _("Inventory name"))
|
.AddParameter("string", _("Inventory name"))
|
||||||
@@ -204,13 +207,14 @@ void DeclareInventoryExtension(gd::PlatformExtension& extension) {
|
|||||||
.SetFunctionName("InventoryTools::Count");
|
.SetFunctionName("InventoryTools::Count");
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.AddExpression("Maximum",
|
.AddExpression("Maximum",
|
||||||
_("Item maximum"),
|
_("Item maximum"),
|
||||||
_("Get the maximum of an item in the inventory, or 0 if it is unlimited"),
|
_("Get the maximum of an item in the inventory, or 0 if "
|
||||||
"",
|
"it is unlimited"),
|
||||||
"CppPlatform/Extensions/Inventoryicon.png")
|
"",
|
||||||
.AddCodeOnlyParameter("currentScene", "")
|
"CppPlatform/Extensions/Inventoryicon.png")
|
||||||
.AddParameter("string", _("Inventory name"))
|
.AddCodeOnlyParameter("currentScene", "")
|
||||||
.AddParameter("string", _("Item name"))
|
.AddParameter("string", _("Inventory name"))
|
||||||
.SetFunctionName("InventoryTools::Maximum");
|
.AddParameter("string", _("Item name"))
|
||||||
|
.SetFunctionName("InventoryTools::Maximum");
|
||||||
}
|
}
|
||||||
|
9
Extensions/JsExtensionTypes.d.ts
vendored
9
Extensions/JsExtensionTypes.d.ts
vendored
@@ -27,7 +27,7 @@ class RenderedInstance {
|
|||||||
associatedObjectConfiguration: gdObjectConfiguration,
|
associatedObjectConfiguration: gdObjectConfiguration,
|
||||||
pixiContainer: PIXI.Container,
|
pixiContainer: PIXI.Container,
|
||||||
pixiResourcesLoader: Class<PixiResourcesLoader>,
|
pixiResourcesLoader: Class<PixiResourcesLoader>,
|
||||||
propertyOverridings: Map<string, string> = new Map<string, string>()
|
getPropertyOverridings: (() => Map<string, string>) | null = null
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,6 +80,8 @@ class RenderedInstance {
|
|||||||
getDefaultHeight(): number;
|
getDefaultHeight(): number;
|
||||||
|
|
||||||
getDefaultDepth(): number;
|
getDefaultDepth(): number;
|
||||||
|
|
||||||
|
getPropertyOverridings(): Map<string, string> | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,7 +109,8 @@ class Rendered3DInstance {
|
|||||||
associatedObjectConfiguration: gdObjectConfiguration,
|
associatedObjectConfiguration: gdObjectConfiguration,
|
||||||
pixiContainer: PIXI.Container,
|
pixiContainer: PIXI.Container,
|
||||||
threeGroup: THREE.Group,
|
threeGroup: THREE.Group,
|
||||||
pixiResourcesLoader: Class<PixiResourcesLoader>
|
pixiResourcesLoader: Class<PixiResourcesLoader>,
|
||||||
|
getPropertyOverridings: (() => Map<string, string>) | null = null
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,6 +177,8 @@ class Rendered3DInstance {
|
|||||||
* Return the depth of the instance when the instance doesn't have a custom size.
|
* Return the depth of the instance when the instance doesn't have a custom size.
|
||||||
*/
|
*/
|
||||||
getDefaultDepth(): number;
|
getDefaultDepth(): number;
|
||||||
|
|
||||||
|
getPropertyOverridings(): Map<string, string> | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare type ObjectsRenderingService = {
|
declare type ObjectsRenderingService = {
|
||||||
|
@@ -21,7 +21,9 @@ module.exports = {
|
|||||||
.setExtensionInformation(
|
.setExtensionInformation(
|
||||||
'Leaderboards',
|
'Leaderboards',
|
||||||
_('Leaderboards'),
|
_('Leaderboards'),
|
||||||
_('Allow your game to send scores to your leaderboards.'),
|
_(
|
||||||
|
'Allow your game to send scores to your leaderboards (anonymously or from the logged-in player) or display existing leaderboards to the player.'
|
||||||
|
),
|
||||||
'Florian Rival',
|
'Florian Rival',
|
||||||
'Open source (MIT License)'
|
'Open source (MIT License)'
|
||||||
)
|
)
|
||||||
@@ -30,6 +32,12 @@ module.exports = {
|
|||||||
.addInstructionOrExpressionGroupMetadata(_('Leaderboards'))
|
.addInstructionOrExpressionGroupMetadata(_('Leaderboards'))
|
||||||
.setIcon('JsPlatform/Extensions/leaderboard.svg');
|
.setIcon('JsPlatform/Extensions/leaderboard.svg');
|
||||||
|
|
||||||
|
extension
|
||||||
|
.addDependency()
|
||||||
|
.setName('Safari View Controller Cordova plugin')
|
||||||
|
.setDependencyType('cordova')
|
||||||
|
.setExportName('@gdevelop/cordova-plugin-safariviewcontroller');
|
||||||
|
|
||||||
extension
|
extension
|
||||||
.addAction(
|
.addAction(
|
||||||
'SavePlayerScore',
|
'SavePlayerScore',
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user