Compare commits

..

3 Commits

Author SHA1 Message Date
Florian Rival
9bfde5425f Update lint-with-clang-tidy.js 2025-01-22 19:35:46 +01:00
Florian Rival
542d799cc7 Temporarily run clang-tidy on this branch 2025-01-22 19:25:21 +01:00
Florian Rival
8782b5d5b4 Enable clang-tidy on extension C++ files 2025-01-22 19:24:17 +01:00
984 changed files with 18113 additions and 49527 deletions

View File

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

View File

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

View File

@@ -61,12 +61,10 @@ void GroupEvent::UnserializeFrom(gd::Project& project,
project, events, element.GetChild("events"));
parameters.clear();
if (element.HasChild("parameters")) {
gd::SerializerElement& parametersElement = element.GetChild("parameters");
parametersElement.ConsiderAsArrayOf("parameters");
for (std::size_t i = 0; i < parametersElement.GetChildrenCount(); ++i)
parameters.push_back(parametersElement.GetChild(i).GetValue().GetString());
}
gd::SerializerElement& parametersElement = element.GetChild("parameters");
parametersElement.ConsiderAsArrayOf("parameters");
for (std::size_t i = 0; i < parametersElement.GetChildrenCount(); ++i)
parameters.push_back(parametersElement.GetChild(i).GetValue().GetString());
}
void GroupEvent::SetBackgroundColor(unsigned int colorR_,

View File

@@ -163,21 +163,6 @@ void LinkEvent::UnserializeFrom(gd::Project& project,
// end of compatibility code
}
vector<gd::String> LinkEvent::GetAllSearchableStrings() const {
vector<gd::String> allSearchableStrings;
allSearchableStrings.push_back(target);
return allSearchableStrings;
}
bool LinkEvent::ReplaceAllSearchableStrings(
std::vector<gd::String> newSearchableString) {
if (newSearchableString[0] == target) return false;
SetTarget(newSearchableString[0]);
return true;
}
bool LinkEvent::AcceptVisitor(gd::EventVisitor &eventVisitor) {
return BaseEvent::AcceptVisitor(eventVisitor) ||
eventVisitor.VisitLinkEvent(*this);

View File

@@ -109,10 +109,6 @@ class GD_CORE_API LinkEvent : public gd::BaseEvent {
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 UnserializeFrom(gd::Project& project,
const SerializerElement& element) override;

View File

@@ -286,20 +286,6 @@ class GD_CORE_API BaseEvent {
* \brief True if the event should be folded in the events editor.
*/
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>
@@ -318,7 +304,6 @@ class GD_CORE_API BaseEvent {
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.
///< Used for saving the event for instance.
gd::String aiGeneratedEventId; ///< When generated by an AI/external tool.
static gd::EventsList badSubEvents;
static gd::VariablesContainer badLocalVariables;

View File

@@ -221,8 +221,6 @@ void EventsListSerialization::UnserializeEventsFrom(
event->SetDisabled(eventElem.GetBoolAttribute("disabled", false));
event->SetFolded(eventElem.GetBoolAttribute("folded", false));
event->SetAiGeneratedEventId(
eventElem.GetStringAttribute("aiGeneratedEventId", ""));
list.InsertEvent(event, list.GetEventsCount());
}
@@ -238,8 +236,6 @@ void EventsListSerialization::SerializeEventsTo(const EventsList& list,
if (event.IsDisabled())
eventElem.SetAttribute("disabled", event.IsDisabled());
if (event.IsFolded()) eventElem.SetAttribute("folded", event.IsFolded());
if (!event.GetAiGeneratedEventId().empty())
eventElem.SetAttribute("aiGeneratedEventId", event.GetAiGeneratedEventId());
eventElem.AddChild("type").SetValue(event.GetType());
event.SerializeTo(eventElem);

View File

@@ -141,8 +141,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
extension
.AddExpression(
@@ -178,8 +177,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddCondition(
@@ -193,8 +191,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.UseStandardRelationalOperatorParameters(
"string", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
}
} // namespace gd

View File

@@ -37,8 +37,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.SetIcon("res/actions/position24_black.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Angle"))
.SetIcon("res/actions/direction24_black.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon(
"res/actions/scale24_black.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Size"))
.SetIcon("res/actions/scale24_black.png");
gd::ObjectMetadata& obj = extension.AddObject<gd::ObjectConfiguration>(
"", _("Base object"), _("Base object"), "res/objeticon24.png");
@@ -117,7 +117,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Change the position of the center of _PARAM0_: _PARAM1_ "
"_PARAM2_ (x "
"axis), _PARAM3_ _PARAM4_ (y axis)"),
_("Position Center"),
_("Position/Center"),
"res/actions/position24_black.png",
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
@@ -133,7 +133,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Center X position"),
_("the X position of the center of rotation"),
_("the X position of the center"),
_("Position Center"),
_("Position/Center"),
"res/actions/position24_black.png")
.AddParameter("object", _("Object"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
@@ -144,7 +144,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Center Y position"),
_("the Y position of the center of rotation"),
_("the Y position of the center"),
_("Position Center"),
_("Position/Center"),
"res/actions/position24_black.png")
.AddParameter("object", _("Object"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
@@ -155,7 +155,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the bounding box (the area encapsulating "
"the object) left position"),
_("the bounding box left position"),
_("Position Bounding Box"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-left_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
@@ -166,7 +166,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Bounding box top position"),
_("the bounding box (the area encapsulating the object) top position"),
_("the bounding box top position"),
_("Position Bounding Box"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-top_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
@@ -177,7 +177,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the bounding box (the area encapsulating "
"the object) right position"),
_("the bounding box right position"),
_("Position Bounding Box"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-right_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
@@ -188,7 +188,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the bounding box (the area encapsulating "
"the object) bottom position"),
_("the bounding box bottom position"),
_("Position Bounding Box"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-bottom_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
@@ -199,7 +199,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the bounding box (the area encapsulating "
"the object) center X position"),
_("the bounding box center X position"),
_("Position Bounding Box"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-center_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
@@ -210,7 +210,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the bounding box (the area encapsulating "
"the object) center Y position"),
_("the bounding box center Y position"),
_("Position Bounding Box"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-center_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
@@ -235,8 +235,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddAction("SetAngle",
_("Angle"),
_("Change the angle of rotation of an object (in degrees). For "
"3D objects, this is the rotation around the Z axis."),
_("Change the angle of rotation of an object (in degrees)."),
_("the angle"),
_("Angle"),
"res/actions/direction24_black.png",
@@ -251,12 +250,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddAction("Rotate",
_("Rotate"),
_("Rotate an object, clockwise if the speed is positive, "
"counterclockwise otherwise. For 3D objects, this is the "
"rotation around the Z axis."),
"counterclockwise otherwise."),
_("Rotate _PARAM0_ at speed _PARAM1_ deg/second"),
_("Angle"),
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angular speed (in degrees per second)"))
.AddCodeOnlyParameter("currentScene", "")
@@ -270,6 +269,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Angle"),
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle to rotate towards (in degrees)"))
.AddParameter("expression", _("Angular speed (in degrees per second)"))
@@ -285,6 +285,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Angle"),
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
@@ -303,12 +304,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/force24.png",
"res/actions/force.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Speed on X axis (in pixels per second)"))
.AddParameter("expression", _("Speed on Y axis (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.SetHelpPath("/tutorials/how-to-move-objects/");
.SetDefaultValue("0");
obj.AddAction("AddForceAL",
_("Add a force (angle)"),
@@ -320,12 +321,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/force24.png",
"res/actions/force.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle"))
.AddParameter("expression", _("Speed (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddAction(
@@ -338,13 +339,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/force24.png",
"res/actions/force.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
.AddParameter("expression", _("Speed (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddAction(
@@ -359,13 +360,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/forceTourne24.png",
"res/actions/forceTourne.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", "X position of the center")
.AddParameter("expression", "Y position of the center")
.AddParameter("expression", "Speed (in Degrees per seconds)")
.AddParameter("expression", "Distance (in pixels)")
.AddParameter("forceMultiplier", "Force multiplier")
.SetHelpPath("/tutorials/how-to-move-objects/")
.SetHidden();
obj.AddAction("Arreter",
@@ -375,8 +376,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/arreter24.png",
"res/actions/arreter.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddAction("Delete",
@@ -417,7 +418,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.MarkAsAdvanced();
obj.AddAction("SetNumberObjectVariable",
_("Change object variable value"),
_("Change variable value"),
_("Modify the number value of an object variable."),
_("the variable _PARAM1_"),
_("Variables"),
@@ -428,11 +429,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddAction("SetStringObjectVariable",
_("Change object variable value"),
_("Change text variable"),
_("Modify the text of an object variable."),
_("the variable _PARAM1_"),
_("Variables"),
@@ -443,11 +443,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddAction("SetBooleanObjectVariable",
_("Change object variable value"),
_("Change boolean variable"),
_("Modify the boolean value of an object variable."),
_("Change the variable _PARAM1_ of _PARAM0_: _PARAM2_"),
_("Variables"),
@@ -459,11 +458,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
// This parameter allows to keep the operand expression
// when the editor switch between variable instructions.
.AddCodeOnlyParameter("yesorno", _("Value"))
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddCondition("NumberObjectVariable",
_("Object variable value"),
_("Variable value"),
_("Compare the number value of an object variable."),
_("the variable _PARAM1_"),
_("Variables"),
@@ -474,11 +472,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddCondition("StringObjectVariable",
_("Object variable value"),
_("Text variable"),
_("Compare the text of an object variable."),
_("the variable _PARAM1_"),
_("Variables"),
@@ -489,11 +486,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddCondition("BooleanObjectVariable",
_("Object variable value"),
_("Boolean variable"),
_("Compare the boolean value of an object variable."),
_("The variable _PARAM1_ of _PARAM0_ is _PARAM2_"),
_("Variables"),
@@ -506,7 +502,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
// This parameter allows to keep the operand expression
// when the editor switch between variable instructions.
.AddCodeOnlyParameter("yesorno", _("Value"))
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddAction("ModVarObjet",
@@ -519,7 +514,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.SetHelpPath("/all-features/variables/object-variables/")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly();
@@ -534,7 +528,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.SetHelpPath("/all-features/variables/object-variables/")
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly();
@@ -551,7 +544,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.AddParameter("trueorfalse", _("New Value:"))
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddAction(
@@ -568,7 +560,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddCondition("ObjectVariableChildExists",
@@ -576,26 +567,24 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Check if the specified child of the object "
"structure variable exists."),
_("Child _PARAM2_ of variable _PARAM1_ of _PARAM0_ exists"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Structure variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddAction("ObjectVariableRemoveChild",
_("Remove a child"),
_("Remove a child from an object structure variable."),
_("Remove child _PARAM2_ from variable _PARAM1_ of _PARAM0_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddAction("ObjectVariableClearChildren",
@@ -603,12 +592,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Remove all the children from the object array or structure "
"variable."),
_("Clear children from variable _PARAM1_ of _PARAM0_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array or structure variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddAction("Cache",
@@ -636,8 +624,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddCondition("Angle",
_("Angle"),
_("Compare the angle, in degrees, of the specified object. "
"For 3D objects, this is the angle around the Z axis."),
_("Compare the angle of the specified object."),
_("the angle (in degrees)"),
_("Angle"),
"res/conditions/direction24_black.png",
@@ -704,8 +691,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/conditions/arret24.png",
"res/conditions/arret.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddCondition("Vitesse",
@@ -715,10 +702,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/conditions/vitesse24.png",
"res/conditions/vitesse.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
// Deprecated
@@ -735,7 +722,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Tolerance, in degrees"))
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddCondition("IsTotalForceAngleAround",
@@ -749,7 +735,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Tolerance, in degrees"))
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddCondition("VarObjet",
@@ -764,7 +749,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddCondition("VarObjetTxt",
@@ -779,7 +763,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddCondition("ObjectVariableAsBoolean",
@@ -794,7 +777,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.AddParameter("trueorfalse", _("Check if the value is"))
.SetDefaultValue("true")
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddCondition("VarObjetDef",
@@ -811,44 +793,42 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddAction(
"PushStringToObjectVariable",
_("Add value to object array variable"),
_("Add text variable"),
_("Adds a text (string) to the end of an object array variable."),
_("Add value _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForLayoutEventsOnly();
obj.AddAction("PushNumberToObjectVariable",
_("Add value to object array variable"),
_("Add variable array value"),
_("Adds a number to the end of an object array variable."),
_("Add value _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForLayoutEventsOnly();
obj.AddAction("PushBooleanToObjectVariable",
_("Add value to object array variable"),
_("Adds a boolean to the end of an object array variable."),
_("Add value _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
obj.AddAction(
"PushBooleanToObjectVariable",
_("Add boolean variable"),
_("Adds a boolean to the end of an object array variable."),
_("Add value _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForLayoutEventsOnly();
@@ -858,7 +838,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Add existing variable"),
_("Adds an existing variable to the end of an object array variable."),
_("Add variable _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
@@ -867,7 +847,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.SetParameterLongDescription(_("The content of the object variable will "
"*be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetHidden();
@@ -876,7 +855,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Add existing variable"),
_("Adds an existing variable to the end of an object array variable."),
_("Add variable _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
@@ -885,7 +864,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.SetParameterLongDescription(_("The content of the object variable will "
"*be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddAction(
@@ -893,13 +871,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Add text variable"),
_("Adds a text (string) to the end of an object array variable."),
_("Add text _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly();
@@ -907,13 +884,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Add number variable"),
_("Adds a number to the end of an object array variable."),
_("Add number _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly();
@@ -922,13 +898,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Add boolean variable"),
_("Adds a boolean to the end of an object array variable."),
_("Add boolean _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly();
@@ -939,13 +914,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"variable."),
_("Remove variable at index _PARAM2_ from array variable _PARAM1_ of "
"_PARAM0_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddCondition(
@@ -953,14 +927,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Number of children"),
_("Compare the number of children in an object array variable."),
_("The number of children in the array variable _PARAM1_"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddStrExpression(
@@ -968,44 +941,40 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("First text child"),
_("Get the value of the first element of an object array variable, if "
"it is a text (string) variable."),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("objectvar", _("Array variable"));
obj.AddExpression(
"ArrayVariableFirstNumber",
_("First number child"),
_("Get the value of the first element of an object array variable, if "
"it is a number variable."),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("objectvar", _("Array variable"));
obj.AddStrExpression(
"ArrayVariableLastString",
_("Last text child"),
_("Get the value of the last element of an object array variable, if "
"it is a text (string) variable."),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("objectvar", _("Array variable"));
obj.AddExpression(
"ArrayVariableLastNumber",
_("Last number child"),
_("Get the value of the last element of an object array variable, if "
"it is a number variable."),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("objectvar", _("Array variable"));
obj.AddCondition("BehaviorActivated",
_("Behavior activated"),
@@ -1040,12 +1009,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/forceVers24.png",
"res/actions/forceVers.png")
.AddParameter("object", _("Object"))
.AddParameter("objectPtr", _("Target Object"))
.AddParameter("expression", _("Speed (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddAction(
@@ -1060,13 +1029,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/forceTourne24.png",
"res/actions/forceTourne.png")
.AddParameter("object", _("Object"))
.AddParameter("objectPtr", _("Rotate around this object"))
.AddParameter("expression", _("Speed (in degrees per second)"))
.AddParameter("expression", _("Distance (in pixels)"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddAction("MettreAutour",
@@ -1094,10 +1063,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/ecarter24.png",
"res/actions/ecarter.png")
.SetHidden()
.AddParameter("object", _("Object"))
.AddParameter("objectList", "Object 2 (won't move)")
.SetHelpPath("/tutorials/how-to-move-objects/");
.AddParameter("objectList", "Object 2 (won't move)");
// Deprecated action
obj.AddAction("Ecarter",
@@ -1121,6 +1090,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Position"),
"res/actions/ecarter24.png",
"res/actions/ecarter.png")
.AddParameter("object", _("Object"))
.AddParameter("objectList", _("Objects (won't move)"))
.AddParameter("yesorno",
@@ -1129,7 +1099,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"",
true)
.SetDefaultValue("no")
.SetHelpPath("/all-features/collisions/")
.MarkAsSimple();
obj.AddCondition("CollisionPoint",
@@ -1142,7 +1111,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("expression", _("X position of the point"))
.AddParameter("expression", _("Y position of the point"))
.SetHelpPath("/all-features/collisions/")
.MarkAsSimple();
extension
@@ -1174,7 +1142,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.AddParameter("expression", _("Time in seconds"))
.SetHelpPath("/all-features/timers-and-time/")
.SetHidden();
obj.AddCondition(
@@ -1190,7 +1157,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.AddParameter("relationalOperator", _("Sign of the test"), "time")
.AddParameter("expression", _("Time in seconds"))
.SetHelpPath("/all-features/timers-and-time/")
.SetManipulatedType("number");
obj.AddCondition("ObjectTimerPaused",
@@ -1202,7 +1168,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/timerPaused.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/")
.MarkAsAdvanced();
obj.AddAction(
@@ -1215,8 +1180,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/timer24.png",
"res/actions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/");
.AddParameter("identifier", _("Timer's name"), "objectTimer");
obj.AddAction("PauseObjectTimer",
_("Pause an object timer"),
@@ -1227,7 +1191,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/pauseTimer.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/")
.MarkAsAdvanced();
obj.AddAction("UnPauseObjectTimer",
@@ -1239,7 +1202,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/unPauseTimer.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/")
.MarkAsAdvanced();
obj.AddAction("RemoveObjectTimer",
@@ -1251,7 +1213,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/")
.MarkAsAdvanced();
obj.AddExpression("X",
@@ -1270,8 +1231,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddExpression("Angle",
_("Angle"),
_("Current angle, in degrees, of the object. For 3D "
"objects, this is the angle around the Z axis."),
_("Current angle, in degrees, of the object"),
_("Angle"),
"res/actions/direction_black.png")
.AddParameter("object", _("Object"));
@@ -1281,32 +1241,28 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("X coordinate of the sum of forces"),
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/");
.AddParameter("object", _("Object"));
obj.AddExpression("ForceY",
_("Y coordinate of the sum of forces"),
_("Y coordinate of the sum of forces"),
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/");
.AddParameter("object", _("Object"));
obj.AddExpression("ForceAngle",
_("Angle of the sum of forces"),
_("Angle of the sum of forces (in degrees)"),
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/");
.AddParameter("object", _("Object"));
obj.AddExpression("ForceLength",
_("Length of the sum of forces"),
_("Length of the sum of forces"),
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/");
.AddParameter("object", _("Object"));
obj.AddExpression("Longueur",
_("Length of the sum of forces"),
@@ -1314,7 +1270,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/")
.SetHidden();
obj.AddExpression("Width",
@@ -1411,11 +1366,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"VariableChildCount",
_("Number of children"),
_("Number of children in an object array or structure variable"),
_("Variables Arrays and structures"),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array or structure variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("objectvar", _("Array or structure variable"));
obj.AddStrExpression("VariableString",
_("Text variable"),
@@ -1424,7 +1378,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddExpression("ObjectTimerElapsedTime",
@@ -1433,8 +1386,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Timers"),
"res/actions/time.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/");
.AddParameter("identifier", _("Timer's name"), "objectTimer");
obj.AddExpression("AngleToObject",
_("Angle between two objects"),
@@ -1574,9 +1526,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
extension
.AddAction("Create",
_("Create an object"),
_("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 an object at specified position"),
_("Create object _PARAM1_ at position _PARAM2_;_PARAM3_ "
"(layer: _PARAM4_)"),
"",
@@ -1656,7 +1606,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/doMove24.png",
"res/actions/doMove.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
extension
@@ -1672,7 +1621,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectList", _("Object 2"))
.AddParameter("expression", _("Tolerance, in degrees"))
.AddCodeOnlyParameter("conditionInverted", "")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
extension
@@ -1805,7 +1753,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"",
true)
.SetDefaultValue("no")
.SetHelpPath("/all-features/collisions/")
.MarkAsSimple();
extension
@@ -1868,7 +1815,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Scene variable where to store the Y position of the intersection. "
"If no intersection is found, the variable won't be changed."))
.AddCodeOnlyParameter("conditionInverted", "")
.SetHelpPath("/all-features/collisions/")
.MarkAsAdvanced();
extension
@@ -1900,7 +1846,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Scene variable where to store the Y position of the intersection. "
"If no intersection is found, the variable won't be changed."))
.AddCodeOnlyParameter("conditionInverted", "")
.SetHelpPath("/all-features/collisions/")
.MarkAsAdvanced();
extension

View File

@@ -19,7 +19,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTextContainerExtension(
extension
.SetExtensionInformation("TextContainerCapability",
_("Text capability"),
_("Allows an object to contain a text, usually shown on screen, that can be modified."),
_("Animate objects."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
@@ -30,7 +30,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTextContainerExtension(
"TextContainerBehavior",
_("Text capability"),
"Text",
_("Allows an object to contain a text, usually shown on screen, that can be modified."),
_("Access objects text."),
"",
"res/conditions/text24_black.png",
"TextContainerBehavior",

View File

@@ -59,57 +59,47 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
// end of compatibility code
extension
.AddCondition(
"Or",
_("Or"),
_("Checks if at least one sub-condition is true. If no "
"sub-condition is specified, it will always be false. "
"This is rarely used — multiple events and sub-events are "
"usually a better approach."),
_("If one of these conditions is true:"),
"",
"res/conditions/or24_black.png",
"res/conditions/or_black.png")
.AddCondition("Or",
_("Or"),
_("Check if one of the sub conditions is true"),
_("If one of these conditions is true:"),
"",
"res/conditions/or24_black.png",
"res/conditions/or_black.png")
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
extension
.AddCondition("And",
_("And"),
_("Check if all sub conditions are true"),
_("If all of these conditions are true:"),
"",
"res/conditions/and24_black.png",
"res/conditions/and_black.png")
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
extension
.AddCondition(
"And",
_("And"),
_("Checks if all sub-conditions are true. If no sub-condition is "
"specified, it will always be false. This is rarely needed, as "
"events already check all conditions before running actions."),
_("If all of these conditions are true:"),
"Not",
_("Not"),
_("Return the contrary of the result of the sub conditions"),
_("Invert the logical result of these conditions:"),
"",
"res/conditions/and24_black.png",
"res/conditions/and_black.png")
"res/conditions/not24_black.png",
"res/conditions/not_black.png")
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
extension
.AddCondition("Not",
_("Not"),
_("Returns the opposite of the sub-condition(s) result. "
"This is rarely needed, as most conditions can be "
"inverted or expressed more simply."),
_("Invert the logical result of these conditions:"),
"",
"res/conditions/not24_black.png",
"res/conditions/not_black.png")
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
extension
.AddCondition("Once",
_("Trigger once while true"),
_("Run actions only once, for each time the conditions "
"have been met."),
_("Trigger once"),
"",
"res/conditions/once24.png",
"res/conditions/once.png")
.SetHelpPath("/all-features/advanced-conditions/trigger-once");
extension.AddCondition(
"Once",
_("Trigger once while true"),
_("Run actions only once, for each time the conditions have been met."),
_("Trigger once"),
"",
"res/conditions/once24.png",
"res/conditions/once.png");
extension
.AddCondition("CompareNumbers",

View File

@@ -28,7 +28,7 @@ BuiltinExtensionsImplementer::ImplementsExternalLayoutsExtension(
.AddAction("CreateObjectsFromExternalLayout",
_("Create objects from an external layout"),
_("Create objects from an external layout."),
_("Create objects from the external layout named _PARAM1_ at position _PARAM2_;_PARAM3_;_PARAM4_"),
_("Create objects from the external layout named _PARAM1_"),
"",
"res/ribbon_default/externallayout32.png",
"res/ribbon_default/externallayout32.png")

View File

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

View File

@@ -182,7 +182,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
"SceneLoadingProgress",
_("Scene loading progress"),
_("The progress of resources loading in background for a scene (between 0 and 1)."),
_("_PARAM1_ loading progress"),
_("_PARAM0_ loading progress"),
_(""),
"res/actions/hourglass_black.svg")
.SetHelpPath("/all-features/resources-loading")

View File

@@ -43,9 +43,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
.AddCondition("CompareTimer",
_("Value of a scene timer"),
_("Compare the elapsed time of a scene timer. This "
"condition doesn't start the timer and will always be "
"false if the timer was not started previously (whatever "
"the comparison being made)."),
"condition doesn't start the timer."),
_("The timer _PARAM1_ _PARAM2_ _PARAM3_ seconds"),
"",

View File

@@ -79,7 +79,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddAction("SetStringVariable",
_("Change variable value"),
_("Change text variable"),
_("Modify the text (string) of a variable."),
_("the variable _PARAM0_"),
"",
@@ -92,7 +92,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddAction(
"SetBooleanVariable",
_("Change variable value"),
_("Change boolean variable"),
_("Modify the boolean value of a variable."),
_("Change the variable _PARAM0_: _PARAM1_"),
"",
@@ -116,7 +116,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.AddParameter("variable", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -130,7 +129,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/conditions/var.png")
.AddParameter("variable", _("Variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -144,7 +142,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("variable", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -157,7 +154,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Structure or array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -174,13 +170,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddAction(
"PushString",
_("Add value to array variable"),
_("Add text variable"),
_("Adds a text (string) at the end of a array variable."),
_("Add the value _PARAM1_ to array variable _PARAM0_"),
_("Arrays and structures"),
@@ -188,12 +183,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddAction("PushNumber",
_("Add value to array variable"),
_("Add variable array value"),
_("Adds a number at the end of an array variable."),
_("Add the value _PARAM1_ to array variable _PARAM0_"),
_("Arrays and structures"),
@@ -201,12 +195,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddAction("PushBoolean",
_("Add value to array variable"),
_("Add boolean variable"),
_("Adds a boolean at the end of an array variable."),
_("Add the value _PARAM1_ to array variable _PARAM0_"),
_("Arrays and structures"),
@@ -214,7 +207,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -229,7 +221,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -240,8 +231,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"it is a text (string)."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("variable", _("Array variable"));
extension
.AddExpression(
@@ -251,8 +241,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"it is a number."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("variable", _("Array variable"));
extension
.AddStrExpression(
@@ -262,8 +251,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"it is a text (string)."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("variable", _("Array variable"));
extension
.AddExpression(
@@ -273,8 +261,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"it is a number."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("variable", _("Array variable"));
// Legacy instructions
@@ -283,28 +270,26 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Number variable"),
_("Compare the number value of a scene variable."),
_("The number of scene variable _PARAM0_"),
_("External variables Scene variables"),
_("External variables/Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddCondition("VarSceneTxt",
_("Text variable"),
_("Compare the text (string) of a scene variable."),
_("The text of scene variable _PARAM0_"),
_("External variables Scene variables"),
_("External variables/Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddCondition(
@@ -312,14 +297,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Boolean variable"),
_("Compare the boolean value of a scene variable."),
_("The boolean value of scene variable _PARAM0_ is _PARAM1_"),
_("External variables Scene variables"),
_("External variables/Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddParameter("trueorfalse", _("Check if the value is"))
.SetDefaultValue("true")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddCondition("VariableChildExists",
@@ -327,14 +311,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Check if the specified child of the scene structure "
"variable exists."),
_("Child _PARAM1_ of scene variable _PARAM0_ exists"),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -343,14 +325,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Check if the specified child of the global structure "
"variable exists."),
_("Child _PARAM1_ of global variable _PARAM0_ exists"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -358,7 +338,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"Variable defined",
"Test if the scene variable exists.",
"Scene variable _PARAM0_ is defined",
_("External variables Scene variables"),
_("External variables/Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddCodeOnlyParameter("currentScene", "")
@@ -370,14 +350,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Number variable"),
_("Compare the number value of a global variable."),
_("the global variable _PARAM0_"),
_("External variables Global variables"),
_("External variables/Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -385,14 +364,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Text variable"),
_("Compare the text (string) of a global variable."),
_("the text of the global variable _PARAM0_"),
_("External variables Global variables"),
_("External variables/Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -401,21 +379,20 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Boolean variable"),
_("Compare the boolean value of a global variable."),
_("The boolean value of global variable _PARAM0_ is _PARAM1_"),
_("External variables Global variables"),
_("External variables/Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.AddParameter("trueorfalse", _("Check if the value is"))
.SetDefaultValue("true")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddCondition("VarGlobalDef",
"Variable defined",
"Test if a global variable exists.",
"Global variable _PARAM0_ is defined",
_("External variables Global variables"),
_("External variables/Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddCodeOnlyParameter("currentScene", "")
@@ -428,28 +405,26 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Change number variable"),
_("Modify the number value of a scene variable."),
_("the scene variable _PARAM0_"),
_("External variables Scene variables"),
_("External variables/Scene variables"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddAction("ModVarSceneTxt",
_("Change text variable"),
_("Modify the text (string) of a scene variable."),
_("the text of scene variable _PARAM0_"),
_("External variables Scene variables"),
_("External variables/Scene variables"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddAction(
@@ -457,13 +432,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Change boolean variable"),
_("Modify the boolean value of a scene variable."),
_("Set the boolean value of scene variable _PARAM0_ to _PARAM1_"),
_("External variables Scene variables"),
_("External variables/Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddParameter("trueorfalse", _("New Value:"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddAction("ToggleSceneVariableAsBoolean",
@@ -472,26 +446,24 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("If it was true, it will become false, and if it was "
"false it will become true."),
_("Toggle the boolean value of scene variable _PARAM0_"),
_("External variables Scene variables"),
_("External variables/Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddAction("ModVarGlobal",
_("Change number variable"),
_("Modify the number value of a global variable."),
_("the global variable _PARAM0_"),
_("External variables Global variables"),
_("External variables/Global variables"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -499,14 +471,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Change text variable"),
_("Modify the text (string) of a global variable."),
_("the text of global variable _PARAM0_"),
_("External variables Global variables"),
_("External variables/Global variables"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -515,13 +486,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Change boolean variable"),
_("Modify the boolean value of a global variable."),
_("Set the boolean value of global variable _PARAM0_ to _PARAM1_"),
_("External variables Global variables"),
_("External variables/Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.AddParameter("trueorfalse", _("New Value:"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddAction("ToggleGlobalVariableAsBoolean",
@@ -530,12 +500,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("If it was true, it will become false, and if it was "
"false it will become true."),
_("Toggle the boolean value of global variable _PARAM0_"),
_("External variables Global variables"),
_("External variables/Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddAction(
@@ -543,15 +512,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Remove a child"),
_("Remove a child from a scene structure variable."),
_("Remove child _PARAM1_ from scene structure variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddAction(
@@ -559,15 +526,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Remove a child"),
_("Remove a child from a global structure variable."),
_("Remove child _PARAM1_ from global structure variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddAction("VariableClearChildren",
@@ -575,13 +540,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Remove all the children from the scene structure or array "
"variable."),
_("Clear children from scene variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Structure or array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -590,13 +553,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Remove all the children from the global structure or array "
"variable."),
_("Clear children from global variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Structure or array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -605,7 +566,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Adds an existing variable at the end of a scene array "
"variable."),
_("Add variable _PARAM1_ to array variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
@@ -613,9 +574,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -624,14 +583,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add text variable"),
_("Adds a text (string) at the end of a scene array variable."),
_("Add text _PARAM1_ to array variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -639,14 +596,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add number variable"),
_("Adds a number at the end of a scene array variable."),
_("Add number _PARAM1_ to array variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -654,14 +609,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add boolean variable"),
_("Adds a boolean at the end of a scene array variable."),
_("Add boolean _PARAM1_ to array variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -671,14 +624,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"variable."),
_("Remove variable at index _PARAM1_ from scene array "
"variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -687,15 +638,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Number of children"),
_("Compare the number of children in a scene array variable."),
_("The number of children in the array variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -704,12 +653,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("First text child"),
_("Get the value of the first element of a scene array variable, if "
"it is a text (string)."),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddExpression(
@@ -717,12 +664,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("First number child"),
_("Get the value of the first element of a scene array variable, if "
"it is a number."),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddStrExpression(
@@ -730,12 +675,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Last text child"),
_("Get the value of the last element of a scene array variable, if "
"it is a text (string)."),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddExpression(
@@ -743,12 +686,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Last number child"),
_("Get the value of the last element of a scene array variable, if "
"it is a number."),
_("External variables Scene variables Arrays and structures"),
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddAction(
@@ -756,7 +697,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add existing variable"),
_("Adds an existing variable at the end of a global array variable."),
_("Add variable _PARAM1_ to array variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
@@ -764,9 +705,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -776,14 +715,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"array variable."),
_("Remove variable at index _PARAM1_ from global array "
"variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -792,14 +729,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add text variable"),
_("Adds a text (string) at the end of a global array variable."),
_("Add text _PARAM1_ to array variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -807,14 +742,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add number variable"),
_("Adds a number at the end of a global array variable."),
_("Add number _PARAM1_ to array variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -822,14 +755,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add boolean variable"),
_("Adds a boolean at the end of a global array variable."),
_("Add boolean _PARAM1_ to array variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -838,15 +769,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Number of children"),
_("Compare the number of children in a global array variable."),
_("The number of children of the array variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -854,24 +783,20 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("First text child"),
_("Value of the first element of a global array "
"variable, if it is a text (string) variable."),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddExpression("GlobalVariableFirstNumber",
_("First number child"),
_("Value of the first element of a global array "
"variable, if it is a number variable"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddStrExpression(
@@ -879,12 +804,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Last text child"),
_("Value of the last element of a global array variable, if "
"it is a text (string) variable."),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddExpression(
@@ -892,23 +815,20 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Last number child"),
_("Value of the last element of a global array variable, if "
"it is a number variable"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddExpression("GlobalVariableChildCount",
_("Number of children"),
_("Number of children in a global array or "
"structure variable"),
_("External variables Global variables Arrays and structures"),
_("External variables/Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array or structure variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddExpression("VariableChildCount",
@@ -917,48 +837,43 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"structure variable"),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array or structure variable"), "AllowUndeclaredVariable")
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("variable", _("Array or structure variable"), "AllowUndeclaredVariable");
extension
.AddExpression("Variable",
_("Number variable"),
_("Number value of a scene variable"),
_("External variables Scene variables"),
_("External variables/Scene variables"),
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddStrExpression("VariableString",
_("Text variable"),
_("Text of a scene variable"),
_("External variables Scene variables"),
_("External variables/Scene variables"),
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddExpression("GlobalVariable",
_("Number variable"),
_("Number value of a global variable"),
_("External variables Global variables"),
_("External variables/Global variables"),
"res/actions/var.png")
.AddParameter("globalvar", _("Name of the global variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddStrExpression("GlobalVariableString",
_("Text variable"),
_("Text of a global variable"),
_("External variables Global variables"),
_("External variables/Global variables"),
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
}
} // namespace gd

View File

@@ -101,7 +101,7 @@ const gd::String &ValueTypeMetadata::ConvertPropertyTypeToValueType(
} else if (propertyType == "KeyboardKey") {
return keyboardKeyValueType;
}
// For "String", "Resource", "MultilineString" or default
// For "String", "Resource" or default
return stringValueType;
};

View File

@@ -18,8 +18,8 @@
#include "GDCore/Extensions/Platform.h"
#include "GDCore/IDE/PlatformManager.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/ObjectConfiguration.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Tools/Localization.h"
namespace gd {
@@ -200,11 +200,11 @@ PlatformExtension::AddExpressionAndConditionAndAction(
group,
icon)
: AddStrExpression(name,
fullname,
expressionDescriptionTemplate.FindAndReplace(
"<subject>", descriptionSubject),
group,
icon);
fullname,
expressionDescriptionTemplate.FindAndReplace(
"<subject>", descriptionSubject),
group,
icon);
return MultipleInstructionMetadata::WithExpressionAndConditionAndAction(
expression, condition, action);
@@ -244,10 +244,12 @@ gd::ObjectMetadata& PlatformExtension::AddEventsBasedObject(
const gd::String& description,
const gd::String& icon24x24) {
gd::String nameWithNamespace = GetNameSpace() + name;
objectsInfos[nameWithNamespace] =
ObjectMetadata(
GetNameSpace(), nameWithNamespace, fullname, description, icon24x24)
.SetHelpPath(GetHelpPath());
objectsInfos[nameWithNamespace] = ObjectMetadata(GetNameSpace(),
nameWithNamespace,
fullname,
description,
icon24x24)
.SetHelpPath(GetHelpPath());
return objectsInfos[nameWithNamespace];
}
@@ -351,7 +353,8 @@ gd::BehaviorMetadata& PlatformExtension::GetBehaviorMetadata(
return badBehaviorMetadata;
}
bool PlatformExtension::HasBehavior(const gd::String& behaviorType) const {
bool PlatformExtension::HasBehavior(
const gd::String& behaviorType) const {
return behaviorsInfo.find(behaviorType) != behaviorsInfo.end();
}
@@ -383,7 +386,7 @@ gd::InstructionMetadata& PlatformExtension::AddDuplicatedAction(
auto copiedAction = actionsInfos.find(copiedNameWithNamespace);
if (copiedAction == actionsInfos.end()) {
gd::LogError("Could not find an action with name " +
copiedNameWithNamespace + " to copy.");
copiedNameWithNamespace + " to copy.");
} else {
actionsInfos[newNameWithNamespace] = copiedAction->second;
}
@@ -403,7 +406,7 @@ gd::InstructionMetadata& PlatformExtension::AddDuplicatedCondition(
auto copiedCondition = conditionsInfos.find(copiedNameWithNamespace);
if (copiedCondition == conditionsInfos.end()) {
gd::LogError("Could not find a condition with name " +
copiedNameWithNamespace + " to copy.");
copiedNameWithNamespace + " to copy.");
} else {
conditionsInfos[newNameWithNamespace] = copiedCondition->second;
}
@@ -420,7 +423,7 @@ gd::ExpressionMetadata& PlatformExtension::AddDuplicatedExpression(
auto copiedExpression = expressionsInfos.find(copiedNameWithNamespace);
if (copiedExpression == expressionsInfos.end()) {
gd::LogError("Could not find an expression with name " +
copiedNameWithNamespace + " to copy.");
copiedNameWithNamespace + " to copy.");
} else {
expressionsInfos[newNameWithNamespace] = copiedExpression->second;
}
@@ -437,7 +440,7 @@ gd::ExpressionMetadata& PlatformExtension::AddDuplicatedStrExpression(
auto copiedExpression = strExpressionsInfos.find(copiedNameWithNamespace);
if (copiedExpression == strExpressionsInfos.end()) {
gd::LogError("Could not find a string expression with name " +
copiedNameWithNamespace + " to copy.");
copiedNameWithNamespace + " to copy.");
} else {
strExpressionsInfos[newNameWithNamespace] = copiedExpression->second;
}
@@ -465,8 +468,7 @@ PlatformExtension::GetAllStrExpressions() {
return strExpressionsInfos;
}
const std::vector<gd::DependencyMetadata>&
PlatformExtension::GetAllDependencies() const {
const std::vector<gd::DependencyMetadata>& PlatformExtension::GetAllDependencies() const {
return extensionDependenciesMetadata;
}
@@ -474,8 +476,7 @@ std::vector<gd::DependencyMetadata>& PlatformExtension::GetAllDependencies() {
return extensionDependenciesMetadata;
}
const std::vector<gd::SourceFileMetadata>&
PlatformExtension::GetAllSourceFiles() const {
const std::vector<gd::SourceFileMetadata>& PlatformExtension::GetAllSourceFiles() const {
return extensionSourceFilesMetadata;
}
@@ -614,6 +615,37 @@ void PlatformExtension::SetNameSpace(gd::String nameSpace_) {
nameSpace = nameSpace_ + GetNamespaceSeparator();
}
std::vector<gd::String> PlatformExtension::GetBuiltinExtensionsNames() {
std::vector<gd::String> builtinExtensions;
builtinExtensions.push_back("Sprite");
builtinExtensions.push_back("BuiltinObject");
builtinExtensions.push_back("BuiltinAudio");
builtinExtensions.push_back("BuiltinMouse");
builtinExtensions.push_back("BuiltinKeyboard");
builtinExtensions.push_back("BuiltinJoystick");
builtinExtensions.push_back("BuiltinTime");
builtinExtensions.push_back("BuiltinFile");
builtinExtensions.push_back("BuiltinVariables");
builtinExtensions.push_back("BuiltinCamera");
builtinExtensions.push_back("BuiltinWindow");
builtinExtensions.push_back("BuiltinNetwork");
builtinExtensions.push_back("BuiltinScene");
builtinExtensions.push_back("BuiltinAdvanced");
builtinExtensions.push_back("BuiltinCommonConversions");
builtinExtensions.push_back("BuiltinStringInstructions");
builtinExtensions.push_back("BuiltinMathematicalTools");
builtinExtensions.push_back("BuiltinExternalLayouts");
builtinExtensions.push_back("BuiltinCommonInstructions");
return builtinExtensions;
}
bool PlatformExtension::IsBuiltin() const {
std::vector<gd::String> builtinExtensions = GetBuiltinExtensionsNames();
return std::find(builtinExtensions.begin(), builtinExtensions.end(), name) !=
builtinExtensions.end();
}
void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
for (std::map<gd::String, gd::InstructionMetadata>::iterator it =
GetAllActions().begin();
@@ -759,62 +791,41 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
}
}
gd::String PlatformExtension::GetEventsFunctionFullType(
const gd::String& extensionName, const gd::String& functionName) {
const auto& separator = GetNamespaceSeparator();
gd::String
PlatformExtension::GetEventsFunctionFullType(const gd::String &extensionName,
const gd::String &functionName) {
const auto &separator = GetNamespaceSeparator();
return extensionName + separator + functionName;
}
gd::String PlatformExtension::GetBehaviorEventsFunctionFullType(
const gd::String& extensionName,
const gd::String& behaviorName,
const gd::String& functionName) {
const auto& separator = GetNamespaceSeparator();
const gd::String &extensionName, const gd::String &behaviorName,
const gd::String &functionName) {
const auto &separator = GetNamespaceSeparator();
return extensionName + separator + behaviorName + separator + functionName;
}
gd::String PlatformExtension::GetBehaviorFullType(
const gd::String& extensionName, const gd::String& behaviorName) {
const auto& separator = GetNamespaceSeparator();
gd::String
PlatformExtension::GetBehaviorFullType(const gd::String &extensionName,
const gd::String &behaviorName) {
const auto &separator = GetNamespaceSeparator();
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(
const gd::String& extensionName,
const gd::String& objectName,
const gd::String& functionName) {
const auto& separator = GetNamespaceSeparator();
const gd::String &extensionName, const gd::String &objectName,
const gd::String &functionName) {
const auto &separator = GetNamespaceSeparator();
return extensionName + separator + objectName + separator + functionName;
}
gd::String PlatformExtension::GetObjectFullType(const gd::String& extensionName,
const gd::String& objectName) {
const auto& separator = GetNamespaceSeparator();
gd::String PlatformExtension::GetObjectFullType(const gd::String &extensionName,
const gd::String &objectName) {
const auto &separator = GetNamespaceSeparator();
return extensionName + separator + objectName;
}
gd::String PlatformExtension::GetExtensionFromFullObjectType(
const gd::String& type) {
gd::String PlatformExtension::GetExtensionFromFullObjectType(const gd::String& type) {
const auto separatorIndex =
type.find(PlatformExtension::GetNamespaceSeparator());
if (separatorIndex == std::string::npos) {
@@ -823,8 +834,7 @@ gd::String PlatformExtension::GetExtensionFromFullObjectType(
return type.substr(0, separatorIndex);
}
gd::String PlatformExtension::GetObjectNameFromFullObjectType(
const gd::String& type) {
gd::String PlatformExtension::GetObjectNameFromFullObjectType(const gd::String& type) {
const auto separatorIndex =
type.find(PlatformExtension::GetNamespaceSeparator());
if (separatorIndex == std::string::npos) {

View File

@@ -13,11 +13,11 @@
#include "GDCore/CommonTools.h"
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
#include "GDCore/Extensions/Metadata/DependencyMetadata.h"
#include "GDCore/Extensions/Metadata/SourceFileMetadata.h"
#include "GDCore/Extensions/Metadata/EffectMetadata.h"
#include "GDCore/Extensions/Metadata/EventMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionOrExpressionGroupMetadata.h"
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
#include "GDCore/Extensions/Metadata/SourceFileMetadata.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/String.h"
#include "GDCore/Tools/VersionPriv.h"
@@ -440,6 +440,12 @@ class GD_CORE_API PlatformExtension {
*/
bool IsDeprecated() const { return deprecated; }
/**
* \brief Return true if the extension is a standard extension that cannot be
* deactivated
*/
bool IsBuiltin() const;
/**
* \brief Get the namespace of the extension.
* \note The namespace is simply the name of the extension concatenated with
@@ -634,6 +640,12 @@ class GD_CORE_API PlatformExtension {
}
///@}
/**
* \brief Return the name of all the extensions which are considered provided
* by platforms.
*/
static std::vector<gd::String> GetBuiltinExtensionsNames();
/**
* \brief Get the string used to separate the name of the
* instruction/expression and the extension.
@@ -651,10 +663,6 @@ class GD_CORE_API PlatformExtension {
static gd::String GetBehaviorFullType(const gd::String& extensionName,
const gd::String& behaviorName);
static gd::String GetExtensionFromFullBehaviorType(const gd::String& type);
static gd::String GetBehaviorNameFromFullBehaviorType(const gd::String& type);
static gd::String GetObjectEventsFunctionFullType(
const gd::String& extensionName,
const gd::String& objectName,

View File

@@ -73,7 +73,6 @@ class GD_CORE_API EventsVariableReplacer
*/
const gd::String targetGroupName;
const VariablesRenamingChangesetNode &variablesRenamingChangesetRoot;
// TODO There is no reason de delete events. This dead code should be removed.
const std::unordered_set<gd::String> &removedVariableNames;
static VariablesContainer nullVariablesContainer;

View File

@@ -1,235 +0,0 @@
#include "ExampleExtensionUsagesFinder.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
#include "GDCore/IDE/ProjectBrowserHelper.h"
#include "GDCore/IDE/WholeProjectRefactorer.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
namespace gd {
std::set<gd::String>
ExampleExtensionUsagesFinder::GetUsedExtensions(gd::Project &project) {
ExampleExtensionUsagesFinder worker(project);
gd::ProjectBrowserHelper::ExposeProjectObjects(project, worker);
gd::ProjectBrowserHelper::ExposeProjectEventsWithoutExtensions(project,
worker);
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
worker.isStoreExtension =
eventsFunctionsExtension.GetOriginName() == "gdevelop-extension-store";
ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
project, eventsFunctionsExtension, worker);
}
if (!worker.has3DObjects) {
worker.usedExtensions.erase("Scene3D");
}
return worker.usedExtensions;
};
void ExampleExtensionUsagesFinder::AddUsedExtension(
const gd::PlatformExtension &extension) {
usedExtensions.insert(extension.GetName());
}
void ExampleExtensionUsagesFinder::AddUsedBuiltinExtension(
const gd::String &extensionName) {
usedExtensions.insert(extensionName);
}
// Objects scanner
void ExampleExtensionUsagesFinder::DoVisitObject(gd::Object &object) {
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
project.GetCurrentPlatform(), object.GetType());
if (metadata.GetMetadata().IsRenderedIn3D()) {
has3DObjects = true;
}
AddUsedExtension(metadata.GetExtension());
};
// Behaviors scanner
void ExampleExtensionUsagesFinder::DoVisitBehavior(gd::Behavior &behavior) {
auto metadata = gd::MetadataProvider::GetExtensionAndBehaviorMetadata(
project.GetCurrentPlatform(), behavior.GetTypeName());
AddUsedExtension(metadata.GetExtension());
};
// Instructions scanner
bool ExampleExtensionUsagesFinder::DoVisitInstruction(
gd::Instruction &instruction, bool isCondition) {
auto metadata =
isCondition ? gd::MetadataProvider::GetExtensionAndConditionMetadata(
project.GetCurrentPlatform(), instruction.GetType())
: gd::MetadataProvider::GetExtensionAndActionMetadata(
project.GetCurrentPlatform(), instruction.GetType());
// Unused event-based objects or events-based behaviors may use object and
// behavior instructions that should not be detected as extension usage.
// The extension of actually used objects and behaviors will be detected on
// scene objects. This is why object or behavior instructions usually don't
// have any import.
// Built-in extensions that are included by default don't declare any include
// files on their instructions either. To still detect their usage, we
// consider that main events and dedicated extensions can't have dead code.
if (!isStoreExtension || !metadata.GetMetadata().GetIncludeFiles().empty()) {
AddUsedExtension(metadata.GetExtension());
}
gd::ParameterMetadataTools::IterateOverParameters(
instruction.GetParameters(), metadata.GetMetadata().GetParameters(),
[this](const gd::ParameterMetadata &parameterMetadata,
const gd::Expression &parameterValue,
const gd::String &lastObjectName) {
const gd::String &parameterType = parameterMetadata.GetType();
if (gd::ParameterMetadata::IsExpression("string", parameterType)) {
rootType = "string";
parameterValue.GetRootNode()->Visit(*this);
} else if (gd::ParameterMetadata::IsExpression("number",
parameterType)) {
rootType = "number";
parameterValue.GetRootNode()->Visit(*this);
} else if (gd::ParameterMetadata::IsExpression("variable",
parameterType))
AddUsedBuiltinExtension("BuiltinVariables");
});
return false;
}
// Expressions scanner
// Ignore literals nodes
void ExampleExtensionUsagesFinder::OnVisitNumberNode(NumberNode &node){};
void ExampleExtensionUsagesFinder::OnVisitTextNode(TextNode &node){};
// Ignore nodes without valid extensions
void ExampleExtensionUsagesFinder::OnVisitEmptyNode(EmptyNode &node){};
void ExampleExtensionUsagesFinder::OnVisitObjectFunctionNameNode(
ObjectFunctionNameNode &node){};
// Visit sub-expressions
void ExampleExtensionUsagesFinder::OnVisitSubExpressionNode(
SubExpressionNode &node) {
node.expression->Visit(*this);
};
void ExampleExtensionUsagesFinder::OnVisitOperatorNode(OperatorNode &node) {
node.leftHandSide->Visit(*this);
node.rightHandSide->Visit(*this);
};
void ExampleExtensionUsagesFinder::OnVisitUnaryOperatorNode(
UnaryOperatorNode &node) {
node.factor->Visit(*this);
};
// Add variable extension and visit sub-expressions on variable nodes
void ExampleExtensionUsagesFinder::OnVisitVariableNode(VariableNode &node) {
AddUsedBuiltinExtension("BuiltinVariables");
auto type = gd::ExpressionTypeFinder::GetType(project.GetCurrentPlatform(),
GetProjectScopedContainers(),
rootType, node);
if (gd::ParameterMetadata::IsExpression("variable", type)) {
// Nothing to do (this can't reference an object)
} else {
GetProjectScopedContainers().MatchIdentifierWithName<void>(
node.name,
[&]() {
// This represents an object.
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
project.GetCurrentPlatform(), node.name);
AddUsedExtension(metadata.GetExtension());
},
[&]() {
// This is a variable.
},
[&]() {
// This is a property.
},
[&]() {
// This is a parameter.
},
[&]() {
// This is something else.
});
}
if (node.child)
node.child->Visit(*this);
};
void ExampleExtensionUsagesFinder::OnVisitVariableAccessorNode(
VariableAccessorNode &node) {
AddUsedBuiltinExtension("BuiltinVariables");
if (node.child)
node.child->Visit(*this);
};
void ExampleExtensionUsagesFinder::OnVisitVariableBracketAccessorNode(
VariableBracketAccessorNode &node) {
AddUsedBuiltinExtension("BuiltinVariables");
node.expression->Visit(*this);
if (node.child)
node.child->Visit(*this);
};
// Add extensions bound to Objects/Behaviors/Functions
void ExampleExtensionUsagesFinder::OnVisitIdentifierNode(IdentifierNode &node) {
auto type = gd::ExpressionTypeFinder::GetType(project.GetCurrentPlatform(),
GetProjectScopedContainers(),
rootType, node);
if (gd::ParameterMetadata::IsObject(type) ||
GetObjectsContainersList().HasObjectOrGroupNamed(node.identifierName)) {
// An object or object variable is used.
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
project.GetCurrentPlatform(), node.identifierName);
AddUsedExtension(metadata.GetExtension());
}
};
void ExampleExtensionUsagesFinder::OnVisitFunctionCallNode(
FunctionCallNode &node) {
// Extensions of non-free functions are already found when scanning objects.
if (!(node.objectName.empty() && node.behaviorName.empty()))
return;
gd::ExtensionAndMetadata<gd::ExpressionMetadata> metadata;
// Try to find a free number expression
metadata = gd::MetadataProvider::GetExtensionAndExpressionMetadata(
project.GetCurrentPlatform(), node.functionName);
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata.GetMetadata())) {
// Try to find a free str expression
metadata = gd::MetadataProvider::GetExtensionAndStrExpressionMetadata(
project.GetCurrentPlatform(), node.functionName);
// No valid expression found, return.
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata.GetMetadata()))
return;
}
// Unused event-based objects or events-based behaviors may use object and
// behavior expressions that should not be detected as extension usage.
// The extension of actually used objects and behaviors will be detected on
// scene objects. This is why object or behavior expressions usually don't
// have any import.
// Built-in extensions that are included by default don't declare any include
// files on their instructions either. To still detect their usage, we
// consider that main events and dedicated extensions can't have dead code.
if (!isStoreExtension || !metadata.GetMetadata().GetIncludeFiles().empty()) {
AddUsedExtension(metadata.GetExtension());
}
};
} // namespace gd

View File

@@ -1,77 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <set>
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/Extensions/Metadata/SourceFileMetadata.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
#include "GDCore/String.h"
namespace gd {
class Project;
class Object;
class Behavior;
} // namespace gd
namespace gd {
/**
* @brief List extension usages for generated example web-pages.
*
* Dependency transitivity is not ensured (see UsedExtensionsFinder).
*/
class GD_CORE_API ExampleExtensionUsagesFinder
: public ArbitraryObjectsWorker,
public ArbitraryEventsWorkerWithContext,
public ExpressionParser2NodeWorker {
public:
static std::set<gd::String> GetUsedExtensions(gd::Project &project);
private:
ExampleExtensionUsagesFinder(gd::Project &project_) : project(project_){};
gd::Project &project;
gd::String rootType;
bool isStoreExtension = false;
// Result
std::set<gd::String> usedExtensions;
bool has3DObjects = false;
void AddUsedExtension(const gd::PlatformExtension &extension);
void AddUsedBuiltinExtension(const gd::String &extensionName);
// Object Visitor
void DoVisitObject(gd::Object &object) override;
// Behavior Visitor
void DoVisitBehavior(gd::Behavior &behavior) override;
// Instructions Visitor
bool DoVisitInstruction(gd::Instruction &instruction,
bool isCondition) override;
// Expression Visitor
void OnVisitSubExpressionNode(SubExpressionNode &node) override;
void OnVisitOperatorNode(OperatorNode &node) override;
void OnVisitUnaryOperatorNode(UnaryOperatorNode &node) override;
void OnVisitNumberNode(NumberNode &node) override;
void OnVisitTextNode(TextNode &node) override;
void OnVisitVariableNode(VariableNode &node) override;
void OnVisitVariableAccessorNode(VariableAccessorNode &node) override;
void OnVisitVariableBracketAccessorNode(
VariableBracketAccessorNode &node) override;
void OnVisitIdentifierNode(IdentifierNode &node) override;
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode &node) override;
void OnVisitFunctionCallNode(FunctionCallNode &node) override;
void OnVisitEmptyNode(EmptyNode &node) override;
};
}; // namespace gd

View File

@@ -69,9 +69,16 @@ bool UsedExtensionsFinder::DoVisitInstruction(gd::Instruction& instruction,
project.GetCurrentPlatform(), instruction.GetType())
: gd::MetadataProvider::GetExtensionAndActionMetadata(
project.GetCurrentPlatform(), instruction.GetType());
result.AddUsedExtension(metadata.GetExtension());
for (auto&& includeFile : metadata.GetMetadata().GetIncludeFiles()) {
result.AddUsedIncludeFiles(includeFile);
// Unused event-based objects or events-based behaviors may use object and
// behavior instructions that should not be detected as extension usage.
// The extension of actually used objects and behaviors will be detected on
// scene objects. This is why object or behavior instructions usually don't
// have any import.
if (!metadata.GetMetadata().GetIncludeFiles().empty()) {
result.AddUsedExtension(metadata.GetExtension());
for (auto &&includeFile : metadata.GetMetadata().GetIncludeFiles()) {
result.AddUsedIncludeFiles(includeFile);
}
}
gd::ParameterMetadataTools::IterateOverParameters(
@@ -199,9 +206,16 @@ void UsedExtensionsFinder::OnVisitFunctionCallNode(FunctionCallNode& node) {
return;
}
result.AddUsedExtension(metadata.GetExtension());
for (auto&& includeFile : metadata.GetMetadata().GetIncludeFiles()) {
result.AddUsedIncludeFiles(includeFile);
// Unused event-based objects or events-based behaviors may use object and
// behavior expressions that should not be detected as extension usage.
// The extension of actually used objects and behaviors will be detected on
// scene objects. This is why object or behavior expressions usually don't
// have any import.
if (!metadata.GetMetadata().GetIncludeFiles().empty()) {
result.AddUsedExtension(metadata.GetExtension());
for (auto &&includeFile : metadata.GetMetadata().GetIncludeFiles()) {
result.AddUsedIncludeFiles(includeFile);
}
}
};

View File

@@ -1,157 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "EventsBasedObjectVariantHelper.h"
#include "GDCore/Project/EventsBasedObject.h"
#include "GDCore/Project/InitialInstancesContainer.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/ObjectGroup.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/ObjectsContainersList.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/Variable.h"
#include "GDCore/Project/VariablesContainer.h"
#include "GDCore/String.h"
namespace gd {
void EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
const gd::Project &project, gd::EventsBasedObject &eventsBasedObject) {
auto &defaultObjects = eventsBasedObject.GetDefaultVariant().GetObjects();
for (const auto &variant :
eventsBasedObject.GetVariants().GetInternalVector()) {
auto &objects = variant->GetObjects();
// Delete extra objects
for (auto it = objects.GetObjects().begin();
it != objects.GetObjects().end(); ++it) {
const auto &objectName = it->get()->GetName();
if (!defaultObjects.HasObjectNamed(objectName)) {
variant->GetInitialInstances().RemoveInitialInstancesOfObject(
objectName);
// Do it in last because it unalloc objectName.
objects.RemoveObject(objectName);
--it;
}
}
for (const auto &defaultObject : defaultObjects.GetObjects()) {
const auto &objectName = defaultObject->GetName();
const auto &defaultVariables = defaultObject->GetVariables();
const auto &defaultBehaviors = defaultObject->GetAllBehaviorContents();
// Copy missing objects
if (!objects.HasObjectNamed(objectName)) {
objects.InsertObject(*defaultObject,
defaultObjects.GetObjectPosition(objectName));
objects.AddMissingObjectsInRootFolder();
continue;
}
// Change object types
auto &object = objects.GetObject(objectName);
if (object.GetType() != defaultObject->GetType()) {
// Keep a copy of the old object.
auto oldObject = objects.GetObject(objectName);
objects.RemoveObject(objectName);
objects.InsertObject(*defaultObject,
defaultObjects.GetObjectPosition(objectName));
object.CopyWithoutConfiguration(oldObject);
objects.AddMissingObjectsInRootFolder();
}
// Copy missing behaviors
auto &behaviors = object.GetAllBehaviorContents();
for (const auto &pair : defaultBehaviors) {
const auto &behaviorName = pair.first;
const auto &defaultBehavior = pair.second;
if (object.HasBehaviorNamed(behaviorName) &&
object.GetBehavior(behaviorName).GetTypeName() !=
defaultBehavior->GetTypeName()) {
object.RemoveBehavior(behaviorName);
}
if (!object.HasBehaviorNamed(behaviorName)) {
auto *behavior = object.AddNewBehavior(
project, defaultBehavior->GetTypeName(), behaviorName);
gd::SerializerElement element;
defaultBehavior->SerializeTo(element);
behavior->UnserializeFrom(element);
}
}
// Delete extra behaviors
for (auto it = behaviors.begin(); it != behaviors.end(); ++it) {
const auto &behaviorName = it->first;
if (!defaultObject->HasBehaviorNamed(behaviorName)) {
object.RemoveBehavior(behaviorName);
--it;
}
}
// Sort and copy missing variables
auto &variables = object.GetVariables();
for (size_t defaultVariableIndex = 0;
defaultVariableIndex < defaultVariables.Count();
defaultVariableIndex++) {
const auto &variableName =
defaultVariables.GetNameAt(defaultVariableIndex);
const auto &defaultVariable =
defaultVariables.Get(defaultVariableIndex);
auto variableIndex = variables.GetPosition(variableName);
if (variableIndex == gd::String::npos) {
variables.Insert(variableName, defaultVariable, defaultVariableIndex);
} else {
variables.Move(variableIndex, defaultVariableIndex);
}
if (variables.Get(variableName).GetType() != defaultVariable.GetType()) {
variables.Remove(variableName);
variables.Insert(variableName, defaultVariable, defaultVariableIndex);
}
}
// Remove extra variables
auto variableToRemoveCount = variables.Count() - defaultVariables.Count();
for (size_t iteration = 0; iteration < variableToRemoveCount;
iteration++) {
variables.Remove(variables.GetNameAt(variables.Count() - 1));
}
// Remove extra instance variables
variant->GetInitialInstances().IterateOverInstances(
[&objectName,
&defaultVariables](gd::InitialInstance &initialInstance) {
if (initialInstance.GetObjectName() != objectName) {
return false;
}
auto &instanceVariables = initialInstance.GetVariables();
for (size_t instanceVariableIndex = 0;
instanceVariableIndex < instanceVariables.Count();
instanceVariableIndex++) {
const auto &variableName =
defaultVariables.GetNameAt(instanceVariableIndex);
if (!defaultVariables.Has(variableName)) {
instanceVariables.Remove(variableName);
}
}
return false;
});
}
auto &defaultObjectGroups =
eventsBasedObject.GetDefaultVariant().GetObjects().GetObjectGroups();
auto &objectGroups = variant->GetObjects().GetObjectGroups();
auto objectGroupsCount = objectGroups.Count();
// Clear groups
for (size_t index = 0; index < objectGroupsCount; index++) {
objectGroups.Remove(objectGroups.Get(0).GetName());
}
// Copy groups
for (size_t index = 0; index < defaultObjectGroups.Count(); index++) {
objectGroups.Insert(defaultObjectGroups.Get(index), index);
}
}
}
} // namespace gd

View File

@@ -1,26 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
namespace gd {
class EventsBasedObject;
class Project;
} // namespace gd
namespace gd {
class GD_CORE_API EventsBasedObjectVariantHelper {
public:
/**
* @brief Apply the changes done on events-based object children to all its
* variants.
*/
static void
ComplyVariantsToEventsBasedObject(const gd::Project &project,
gd::EventsBasedObject &eventsBasedObject);
};
} // namespace gd

View File

@@ -3,11 +3,9 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ObjectVariableHelper.h"
#include "GroupVariableHelper.h"
#include "GDCore/IDE/WholeProjectRefactorer.h"
#include "GDCore/Project/EventsBasedObject.h"
#include "GDCore/Project/InitialInstancesContainer.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/ObjectGroup.h"
#include "GDCore/Project/ObjectsContainer.h"
@@ -18,7 +16,7 @@
namespace gd {
void ObjectVariableHelper::FillAnyVariableBetweenObjects(
void GroupVariableHelper::FillAnyVariableBetweenObjects(
gd::ObjectsContainer &globalObjectsContainer,
gd::ObjectsContainer &objectsContainer,
const gd::ObjectGroup &objectGroup) {
@@ -67,7 +65,7 @@ void ObjectVariableHelper::FillAnyVariableBetweenObjects(
}
}
gd::VariablesContainer ObjectVariableHelper::MergeVariableContainers(
gd::VariablesContainer GroupVariableHelper::MergeVariableContainers(
const gd::ObjectsContainersList &objectsContainersList,
const gd::ObjectGroup &objectGroup) {
gd::VariablesContainer mergedVariablesContainer;
@@ -115,7 +113,7 @@ gd::VariablesContainer ObjectVariableHelper::MergeVariableContainers(
return mergedVariablesContainer;
}
void ObjectVariableHelper::FillMissingGroupVariablesToObjects(
void GroupVariableHelper::FillMissingGroupVariablesToObjects(
gd::ObjectsContainer &globalObjectsContainer,
gd::ObjectsContainer &objectsContainer, const gd::ObjectGroup &objectGroup,
const gd::SerializerElement &originalSerializedVariables) {
@@ -147,7 +145,7 @@ void ObjectVariableHelper::FillMissingGroupVariablesToObjects(
// TODO Handle position changes for group variables.
// We could try to change the order of object variables in a way that the next
// call to MergeVariableContainers rebuild them in the same order.
void ObjectVariableHelper::ApplyChangesToObjects(
void GroupVariableHelper::ApplyChangesToObjects(
gd::ObjectsContainer &globalObjectsContainer,
gd::ObjectsContainer &objectsContainer,
const gd::VariablesContainer &groupVariablesContainer,
@@ -174,7 +172,6 @@ void ObjectVariableHelper::ApplyChangesToObjects(
groupVariablesContainer.Get(variableName),
variablesContainer.Count());
}
// TODO Check what happens if 2 variables exchange their names.
for (const auto &pair : changeset.oldToNewVariableNames) {
const gd::String &oldVariableName = pair.first;
const gd::String &newVariableName = pair.second;
@@ -196,109 +193,4 @@ void ObjectVariableHelper::ApplyChangesToObjects(
}
}
void ObjectVariableHelper::ApplyChangesToObjectInstances(
gd::VariablesContainer &objectVariablesContainer,
gd::InitialInstancesContainer &initialInstancesContainer,
const gd::String &objectName, const gd::VariablesChangeset &changeset) {
initialInstancesContainer.IterateOverInstances(
[&objectVariablesContainer, &objectName,
&changeset](gd::InitialInstance &instance) {
if (instance.GetObjectName() == objectName) {
auto &destinationVariablesContainer = instance.GetVariables();
for (const gd::String &variableName :
changeset.removedVariableNames) {
destinationVariablesContainer.Remove(variableName);
}
for (const gd::String &variableName : changeset.addedVariableNames) {
// Instance variables may already exist with another type.
if (destinationVariablesContainer.Has(variableName) &&
destinationVariablesContainer.Get(variableName).GetType() !=
objectVariablesContainer.Get(variableName).GetType()) {
destinationVariablesContainer.Remove(variableName);
}
}
// TODO Check what happens if 2 variables exchange their names.
for (const auto &pair : changeset.oldToNewVariableNames) {
const gd::String &oldVariableName = pair.first;
const gd::String &newVariableName = pair.second;
if (destinationVariablesContainer.Has(newVariableName)) {
// It can happens if an instance already had the variable.
destinationVariablesContainer.Remove(oldVariableName);
} else {
destinationVariablesContainer.Rename(oldVariableName,
newVariableName);
}
}
// Apply type changes
for (const gd::String &variableName :
changeset.valueChangedVariableNames) {
if (destinationVariablesContainer.Has(variableName) &&
destinationVariablesContainer.Get(variableName).GetType() !=
objectVariablesContainer.Get(variableName).GetType()) {
destinationVariablesContainer.Remove(variableName);
}
}
}
return false;
});
}
void ObjectVariableHelper::ApplyChangesToVariants(
gd::EventsBasedObject &eventsBasedObject, const gd::String &objectName,
const gd::VariablesChangeset &changeset) {
auto &defaultVariablesContainer = eventsBasedObject.GetDefaultVariant()
.GetObjects()
.GetObject(objectName)
.GetVariables();
for (auto &variant : eventsBasedObject.GetVariants().GetInternalVector()) {
if (!variant->GetObjects().HasObjectNamed(objectName)) {
continue;
}
auto &object = variant->GetObjects().GetObject(objectName);
auto &variablesContainer = object.GetVariables();
for (const gd::String &variableName : changeset.removedVariableNames) {
variablesContainer.Remove(variableName);
}
for (const gd::String &variableName : changeset.addedVariableNames) {
if (variablesContainer.Has(variableName)) {
// It can happens if a child-object already had the variable but it was
// missing in other variant child-object.
continue;
}
variablesContainer.Insert(variableName,
defaultVariablesContainer.Get(variableName),
variablesContainer.Count());
}
// TODO Check what happens if 2 variables exchange their names.
for (const auto &pair : changeset.oldToNewVariableNames) {
const gd::String &oldVariableName = pair.first;
const gd::String &newVariableName = pair.second;
if (variablesContainer.Has(newVariableName)) {
// It can happens if a child-object already had the variable but it was
// missing in other variant child-object.
variablesContainer.Remove(oldVariableName);
} else {
variablesContainer.Rename(oldVariableName, newVariableName);
}
}
// Apply type changes
for (const gd::String &variableName : changeset.valueChangedVariableNames) {
size_t index = variablesContainer.GetPosition(variableName);
if (variablesContainer.Has(variableName) &&
variablesContainer.Get(variableName).GetType() !=
defaultVariablesContainer.Get(variableName).GetType()) {
variablesContainer.Remove(variableName);
variablesContainer.Insert(
variableName, defaultVariablesContainer.Get(variableName), index);
}
}
gd::ObjectVariableHelper::ApplyChangesToObjectInstances(
variablesContainer, variant->GetInitialInstances(), objectName,
changeset);
}
}
} // namespace gd

View File

@@ -8,8 +8,6 @@
#include "GDCore/Project/VariablesContainer.h"
namespace gd {
class EventsBasedObject;
class InitialInstancesContainer;
class ObjectsContainersList;
class ObjectsContainer;
class ObjectGroup;
@@ -24,7 +22,7 @@ namespace gd {
*
* This is used by the object group variable editor.
*/
class GD_CORE_API ObjectVariableHelper {
class GD_CORE_API GroupVariableHelper {
public:
/**
* Copy every variable from every object of the group to the other objects
@@ -54,7 +52,7 @@ public:
* Objects can be added during the group edition and may not necessarily have
* all the variables initially shared by the group.
*
* \see gd::ObjectVariableHelper::MergeVariableContainers
* \see gd::GroupVariableHelper::MergeVariableContainers
*/
static void FillMissingGroupVariablesToObjects(
gd::ObjectsContainer &globalObjectsContainer,
@@ -72,22 +70,6 @@ public:
const gd::VariablesContainer &groupVariablesContainer,
const gd::ObjectGroup &objectGroup,
const gd::VariablesChangeset &changeset);
/**
* @brief Apply the changes done on an object to all its instances.
*/
static void ApplyChangesToObjectInstances(
gd::VariablesContainer &objectVariablesContainer,
gd::InitialInstancesContainer &initialInstancesContainer,
const gd::String &objectName, const gd::VariablesChangeset &changeset);
/**
* @brief Apply the changes done on events-based object child to all its
* variants.
*/
static void ApplyChangesToVariants(gd::EventsBasedObject &eventsBasedObject,
const gd::String &objectName,
const gd::VariablesChangeset &changeset);
};
} // namespace gd
} // namespace gd

View File

@@ -17,8 +17,6 @@
#include "GDCore/IDE/Project/ResourcesRenamer.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/CustomBehavior.h"
#include "GDCore/Project/CustomObjectConfiguration.h"
#include "GDCore/Project/EventsBasedObjectVariant.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
@@ -62,6 +60,9 @@ void ObjectAssetSerializer::SerializeTo(
element.SetAttribute("version", "");
element.SetIntAttribute("animationsCount", 1);
element.SetIntAttribute("maxFramesCount", 1);
// TODO Find the right object dimensions.
element.SetIntAttribute("width", 0);
element.SetIntAttribute("height", 0);
SerializerElement &authorsElement = element.AddChild("authors");
authorsElement.ConsiderAsArrayOf("author");
SerializerElement &tagsElement = element.AddChild("tags");
@@ -74,28 +75,6 @@ void ObjectAssetSerializer::SerializeTo(
cleanObject->SerializeTo(objectAssetElement.AddChild("object"));
double width = 0;
double height = 0;
if (project.HasEventsBasedObject(object.GetType())) {
SerializerElement &variantsElement =
objectAssetElement.AddChild("variants");
variantsElement.ConsiderAsArrayOf("variant");
const auto *variant = ObjectAssetSerializer::GetVariant(project, object);
if (variant) {
width = variant->GetAreaMaxX() - variant->GetAreaMinX();
height = variant->GetAreaMaxY() - variant->GetAreaMinY();
}
std::unordered_set<gd::String> alreadyUsedVariantIdentifiers;
gd::ObjectAssetSerializer::SerializeUsedVariantsTo(
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 =
objectAssetElement.AddChild("resources");
resourcesElement.ConsiderAsArrayOf("resource");
@@ -129,59 +108,4 @@ void ObjectAssetSerializer::SerializeTo(
objectAssetElement.AddChild("customization");
customizationElement.ConsiderAsArrayOf("empty");
}
void ObjectAssetSerializer::SerializeUsedVariantsTo(
gd::Project &project, const gd::Object &object,
SerializerElement &variantsElement,
std::unordered_set<gd::String> &alreadyUsedVariantIdentifiers) {
const auto *variant = ObjectAssetSerializer::GetVariant(project, object);
if (!variant) {
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 =
project.GetEventsBasedObject(object.GetType());
const auto &variants = eventsBasedObject.GetVariants();
const auto *customObjectConfiguration =
dynamic_cast<const gd::CustomObjectConfiguration *>(
&object.GetConfiguration());
const auto &variantName = customObjectConfiguration->GetVariantName();
if (!variants.HasVariantNamed(variantName) &&
(customObjectConfiguration
->IsMarkedAsOverridingEventsBasedObjectChildrenConfiguration() ||
customObjectConfiguration
->IsForcedToOverrideEventsBasedObjectChildrenConfiguration())) {
return nullptr;
}
const auto &variantIdentifier =
object.GetType() + gd::PlatformExtension::GetNamespaceSeparator() +
variantName;
const auto &variant = variants.HasVariantNamed(variantName)
? variants.GetVariant(variantName)
: eventsBasedObject.GetDefaultVariant();
return &variant;
}
} // namespace gd

View File

@@ -6,7 +6,6 @@
#pragma once
#include <map>
#include <vector>
#include <unordered_set>
#include "GDCore/String.h"
@@ -21,7 +20,6 @@ class InitialInstance;
class SerializerElement;
class EffectsContainer;
class AbstractFileSystem;
class EventsBasedObjectVariant;
} // namespace gd
namespace gd {
@@ -54,13 +52,6 @@ private:
ObjectAssetSerializer(){};
static gd::String GetObjectExtensionName(const gd::Object &object);
static void SerializeUsedVariantsTo(
gd::Project &project, const gd::Object &object,
SerializerElement &variantsElement,
std::unordered_set<gd::String> &alreadyUsedVariantIdentifiers);
static const gd::EventsBasedObjectVariant* GetVariant(gd::Project &project, const gd::Object &object);
};
} // namespace gd

View File

@@ -39,22 +39,6 @@ void ProjectBrowserHelper::ExposeProjectEvents(
}
}
void ProjectBrowserHelper::ExposeProjectEvents(
gd::Project &project, gd::ArbitraryEventsWorkerWithContext &worker) {
// See also gd::ResourceExposer::ExposeWholeProjectResources
// for a method that traverses the whole project (this time for resources)
// and ExposeProjectEffects (this time for effects).
ExposeProjectEventsWithoutExtensions(project, worker);
// Add events based extensions
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(project, eventsFunctionsExtension, worker);
}
}
void ProjectBrowserHelper::ExposeProjectEventsWithoutExtensions(
gd::Project& project, gd::ArbitraryEventsWorker& worker) {
// Add layouts events
@@ -67,28 +51,6 @@ void ProjectBrowserHelper::ExposeProjectEventsWithoutExtensions(
}
}
void ProjectBrowserHelper::ExposeProjectEventsWithoutExtensions(
gd::Project& project, gd::ArbitraryEventsWorkerWithContext& worker) {
// Add layouts events
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
auto &layout = project.GetLayout(s);
auto projectScopedContainers =
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
worker.Launch(layout.GetEvents(), projectScopedContainers);
}
// Add external events events
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
const auto &externalEvents = project.GetExternalEvents(s);
const gd::String &associatedLayout = externalEvents.GetAssociatedLayout();
if (project.HasLayoutNamed(associatedLayout)) {
auto &layout = project.GetLayout(associatedLayout);
auto projectScopedContainers =
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
worker.Launch(project.GetExternalEvents(s).GetEvents(), projectScopedContainers);
}
}
}
void ProjectBrowserHelper::ExposeLayoutEventsAndExternalEvents(
gd::Project &project, gd::Layout &layout,
gd::ArbitraryEventsWorker &worker) {
@@ -149,6 +111,38 @@ void ProjectBrowserHelper::ExposeLayoutEventsAndDependencies(
}
}
void ProjectBrowserHelper::ExposeProjectEvents(
gd::Project &project, gd::ArbitraryEventsWorkerWithContext &worker) {
// See also gd::ResourceExposer::ExposeWholeProjectResources
// for a method that traverses the whole project (this time for resources)
// and ExposeProjectEffects (this time for effects).
// Add layouts events
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
auto &layout = project.GetLayout(s);
auto projectScopedContainers =
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
worker.Launch(layout.GetEvents(), projectScopedContainers);
}
// Add external events events
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
const auto &externalEvents = project.GetExternalEvents(s);
const gd::String &associatedLayout = externalEvents.GetAssociatedLayout();
if (project.HasLayoutNamed(associatedLayout)) {
auto &layout = project.GetLayout(associatedLayout);
auto projectScopedContainers =
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
worker.Launch(project.GetExternalEvents(s).GetEvents(), projectScopedContainers);
}
}
// Add events based extensions
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(project, eventsFunctionsExtension, worker);
}
}
void ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
gd::ArbitraryEventsWorker &worker) {
@@ -314,12 +308,6 @@ void ProjectBrowserHelper::ExposeProjectObjects(
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
auto eventsBasedObject = eventsBasedObjectUniquePtr.get();
worker.Launch(eventsBasedObject->GetObjects());
for (auto &&variantUniquePtr :
eventsBasedObject->GetVariants().GetInternalVector()) {
auto variant = variantUniquePtr.get();
worker.Launch(variant->GetObjects());
}
}
}
};

View File

@@ -57,15 +57,6 @@ public:
ExposeProjectEventsWithoutExtensions(gd::Project &project,
gd::ArbitraryEventsWorker &worker);
/**
* \brief Call the specified worker on all events of the project (layout and
* external events) but not events from extensions.
*
* Only use this for stats.
*/
static void ExposeProjectEventsWithoutExtensions(
gd::Project &project, gd::ArbitraryEventsWorkerWithContext &worker);
/**
* \brief Call the specified worker on all events of a layout and
* its external events.

View File

@@ -42,9 +42,6 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
const gd::NamedPropertyDescriptor &property, const gd::String &objectType,
bool isBehavior, bool isSharedProperties) {
auto &propertyName = property.GetName();
const auto &primitiveType = gd::ValueTypeMetadata::GetPrimitiveValueType(
gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(
property.GetType()));
auto &functionsContainer = eventsBasedEntity.GetEventsFunctions();
gd::String capitalizedName = CapitalizeFirstLetter(property.GetName());
gd::String setterName = "Set" + capitalizedName;
@@ -62,9 +59,9 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
property.GetLabel().empty() ? property.GetName() : property.GetLabel();
gd::String descriptionSubject =
(primitiveType == "boolean" ? "if " : "the ") +
(property.GetType() == "Boolean" ? "if " : "the ") +
UnCapitalizeFirstLetter(propertyLabel) +
(isSharedProperties || primitiveType == "boolean"
(isSharedProperties || property.GetType() == "Boolean"
? "."
: " of the object.") +
(property.GetDescription().empty() ? ""
@@ -74,7 +71,19 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
"objects using the behavior."
: "");
gd::String propertyGetterName =
(isSharedProperties ? "SharedProperty" : "Property") + property.GetName();
gd::String getterType =
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
extension.GetName(), eventsBasedEntity.GetName(), propertyGetterName);
gd::String setterType =
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
extension.GetName(), eventsBasedEntity.GetName(),
"Set" + propertyGetterName);
gd::String getterName = capitalizedName;
gd::String numberOrString =
property.GetType() == "Number" ? "Number" : "String";
if (!functionsContainer.HasEventsFunctionNamed(getterName)) {
auto &getter = functionsContainer.InsertNewEventsFunction(
@@ -90,7 +99,7 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
.SetName(legacyExpressionType)
.SetExtraInfo(GetStringifiedExtraInfo(property));
getter.SetFullName(propertyLabel).SetGroup(functionGroupName);
if (primitiveType == "boolean") {
if (property.GetType() == "Boolean") {
getter.SetFunctionType(gd::EventsFunction::Condition)
.SetDescription("Check " + descriptionSubject)
.SetSentence("_PARAM0_ " + UnCapitalizeFirstLetter(propertyLabel));
@@ -103,12 +112,13 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
auto &event =
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().InsertNewEvent(
project, "BuiltinCommonInstructions::Standard", 0));
if (primitiveType == "boolean") {
if (property.GetType() == "Boolean") {
gd::Instruction condition;
condition.SetType("BooleanVariable");
condition.AddParameter(propertyName);
condition.AddParameter("True");
condition.AddParameter("");
condition.SetType(getterType);
condition.AddParameter("Object");
if (isBehavior) {
condition.AddParameter("Behavior");
}
event.GetConditions().Insert(condition, 0);
gd::Instruction action;
@@ -117,8 +127,6 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
event.GetActions().Insert(action, 0);
} else {
gd::Instruction action;
gd::String numberOrString =
primitiveType == "number" ? "Number" : "String";
action.SetType("SetReturn" + numberOrString);
action.AddParameter(property.GetName());
event.GetActions().Insert(action, 0);
@@ -128,7 +136,7 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
if (!functionsContainer.HasEventsFunctionNamed(setterName)) {
auto &setter = functionsContainer.InsertNewEventsFunction(
setterName, functionsContainer.GetEventsFunctionsCount());
if (primitiveType == "boolean") {
if (property.GetType() == "Boolean") {
setter.SetFunctionType(gd::EventsFunction::Action)
.SetFullName(propertyLabel)
.SetGroup(functionGroupName)
@@ -169,24 +177,26 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
setter.SetGetterName(getterName);
}
if (primitiveType == "boolean") {
if (property.GetType() == "Boolean") {
{
auto &event =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().InsertNewEvent(
project, "BuiltinCommonInstructions::Standard", 0));
gd::Instruction condition;
condition.SetType("BooleanVariable");
condition.AddParameter("Value");
condition.AddParameter("True");
condition.AddParameter("");
condition.SetType("GetArgumentAsBoolean");
condition.AddParameter("\"Value\"");
event.GetConditions().Insert(condition, 0);
gd::Instruction action;
action.SetType("SetBooleanVariable");
action.AddParameter(propertyName);
action.AddParameter("True");
action.AddParameter("");
action.SetType(setterType);
action.AddParameter("Object");
if (isBehavior) {
action.AddParameter("Behavior");
action.AddParameter("yes");
} else {
action.AddParameter("yes");
}
event.GetActions().Insert(action, 0);
}
{
@@ -195,17 +205,20 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
project, "BuiltinCommonInstructions::Standard", 0));
gd::Instruction condition;
condition.SetType("BooleanVariable");
condition.AddParameter("Value");
condition.AddParameter("False");
condition.AddParameter("");
condition.SetType("GetArgumentAsBoolean");
condition.AddParameter("\"Value\"");
condition.SetInverted(true);
event.GetConditions().Insert(condition, 0);
gd::Instruction action;
action.SetType("SetBooleanVariable");
action.AddParameter(propertyName);
action.AddParameter("False");
action.AddParameter("");
action.SetType(setterType);
action.AddParameter("Object");
if (isBehavior) {
action.AddParameter("Behavior");
action.AddParameter("no");
} else {
action.AddParameter("no");
}
event.GetActions().Insert(action, 0);
}
} else {
@@ -214,11 +227,16 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
project, "BuiltinCommonInstructions::Standard", 0));
gd::Instruction action;
action.SetType(primitiveType == "number" ? "SetNumberVariable"
: "SetStringVariable");
action.AddParameter(propertyName);
action.AddParameter("=");
action.AddParameter("Value");
action.SetType(setterType);
action.AddParameter("Object");
if (isBehavior) {
action.AddParameter("Behavior");
action.AddParameter("=");
action.AddParameter("Value");
} else {
action.AddParameter("=");
action.AddParameter("Value");
}
event.GetActions().Insert(action, 0);
}
}

View File

@@ -3,7 +3,8 @@
* Copyright 2008-2022 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#ifndef GDCORE_PROPERTYFUNCTIONGENERATOR_H
#define GDCORE_PROPERTYFUNCTIONGENERATOR_H
namespace gd {
class String;
@@ -72,3 +73,5 @@ class GD_CORE_API PropertyFunctionGenerator {
};
} // namespace gd
#endif // GDCORE_PROPERTYFUNCTIONGENERATOR_H

View File

@@ -11,7 +11,7 @@
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/DependenciesAnalyzer.h"
#include "GDCore/IDE/ObjectVariableHelper.h"
#include "GDCore/IDE/GroupVariableHelper.h"
#include "GDCore/IDE/EventBasedBehaviorBrowser.h"
#include "GDCore/IDE/EventBasedObjectBrowser.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
@@ -314,16 +314,9 @@ void WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
variablesContainer.SerializeTo(editedSerializedVariables);
variablesContainer.UnserializeFrom(originalSerializedVariables);
// Rename variables
// Pass an empty set to avoid deletion of actions/conditions or events using
// them.
// While we support refactoring that would remove all references (actions,
// conditions...) it's both a bit dangerous for the user and we would need to
// show the user what will be removed before doing so. For now, just clear the
// removed variables so they don't trigger any refactoring.
std::unordered_set<gd::String> removedVariableNames;
// Rename and remove variables
gd::EventsVariableReplacer eventsVariableReplacer(
project.GetCurrentPlatform(), changeset, removedVariableNames,
project.GetCurrentPlatform(), changeset, changeset.removedVariableNames,
variablesContainer);
gd::ProjectBrowserHelper::ExposeProjectEvents(project,
eventsVariableReplacer);
@@ -340,25 +333,9 @@ void WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
project, eventsVariableInstructionTypeSwitcher);
}
// TODO Apply the refactor to external layouts.
void WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
gd::Project &project, gd::VariablesContainer &objectVariablesContainer,
gd::InitialInstancesContainer &initialInstancesContainer,
const gd::String &objectName, const gd::VariablesChangeset &changeset,
const gd::SerializerElement &originalSerializedVariables) {
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
project, objectVariablesContainer, changeset,
originalSerializedVariables);
gd::ObjectVariableHelper::ApplyChangesToObjectInstances(
objectVariablesContainer, initialInstancesContainer, objectName,
changeset);
}
void WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
gd::Project &project, gd::ObjectsContainer &globalObjectsContainer,
gd::ObjectsContainer &objectsContainer,
gd::InitialInstancesContainer &initialInstancesContainer,
const gd::VariablesContainer &groupVariablesContainer,
const gd::ObjectGroup &objectGroup,
const gd::VariablesChangeset &changeset,
@@ -378,15 +355,11 @@ void WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
}
auto &object = hasObject ? objectsContainer.GetObject(objectName)
: globalObjectsContainer.GetObject(objectName);
auto &objectVariablesContainer = object.GetVariables();
gd::ObjectVariableHelper::ApplyChangesToObjectInstances(
objectVariablesContainer, initialInstancesContainer, objectName,
changeset);
auto &variablesContainer = object.GetVariables();
gd::EventsVariableReplacer eventsVariableReplacer(
project.GetCurrentPlatform(), changeset,
removedVariableNames, objectVariablesContainer);
removedVariableNames, variablesContainer);
gd::ProjectBrowserHelper::ExposeProjectEvents(project,
eventsVariableReplacer);
}
@@ -399,12 +372,12 @@ void WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
eventsVariableReplacer);
// Apply changes to objects.
gd::ObjectVariableHelper::FillMissingGroupVariablesToObjects(
gd::GroupVariableHelper::FillMissingGroupVariablesToObjects(
globalObjectsContainer,
objectsContainer,
objectGroup,
originalSerializedVariables);
gd::ObjectVariableHelper::ApplyChangesToObjects(
gd::GroupVariableHelper::ApplyChangesToObjects(
globalObjectsContainer, objectsContainer, groupVariablesContainer,
objectGroup, changeset);
@@ -1781,14 +1754,6 @@ void WholeProjectRefactorer::DoRenameBehavior(
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(
gd::Project &project, const gd::String &oldObjectType,
const gd::String &newObjectType, const gd::ProjectBrowser &projectBrowser) {
@@ -2137,26 +2102,6 @@ void WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject(
groups[g].RenameObject(oldName, newName);
}
}
for (auto &variant : eventsBasedObject.GetVariants().GetInternalVector()) {
auto &variantObjects = variant->GetObjects();
auto &variantObjectGroups = variantObjects.GetObjectGroups();
if (isObjectGroup) {
if (variantObjectGroups.Has(oldName)) {
variantObjectGroups.Get(oldName).SetName(newName);
}
// Object groups can't have instances or be in other groups
}
else {
if (variantObjects.HasObjectNamed(oldName)) {
variantObjects.GetObject(oldName).SetName(newName);
}
variant->GetInitialInstances().RenameInstancesOfObject(oldName, newName);
for (std::size_t g = 0; g < variantObjectGroups.size(); ++g) {
variantObjectGroups[g].RenameObject(oldName, newName);
}
}
}
}
void WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(

View File

@@ -32,7 +32,6 @@ class UnfilledRequiredBehaviorPropertyProblem;
class ProjectBrowser;
class SerializerElement;
class ProjectScopedContainers;
class InitialInstancesContainer;
struct VariablesRenamingChangesetNode;
} // namespace gd
@@ -81,23 +80,13 @@ class GD_CORE_API WholeProjectRefactorer {
/**
* \brief Refactor the project according to the changes (renaming or deletion)
* made to global or scene variables.
* made to variables.
*/
static void ApplyRefactoringForVariablesContainer(
gd::Project &project, gd::VariablesContainer &variablesContainer,
const gd::VariablesChangeset &changeset,
const gd::SerializerElement &originalSerializedVariables);
/**
* \brief Refactor the project according to the changes (renaming or deletion)
* made to object variables.
*/
static void ApplyRefactoringForObjectVariablesContainer(
gd::Project &project, gd::VariablesContainer &objectVariablesContainer,
gd::InitialInstancesContainer &initialInstancesContainer,
const gd::String &objectName, const gd::VariablesChangeset &changeset,
const gd::SerializerElement &originalSerializedVariables);
/**
* \brief Refactor the project according to the changes (renaming or deletion)
* made to variables of a group.
@@ -105,7 +94,6 @@ class GD_CORE_API WholeProjectRefactorer {
static void ApplyRefactoringForGroupVariablesContainer(
gd::Project &project, gd::ObjectsContainer &globalObjectsContainer,
gd::ObjectsContainer &objectsContainer,
gd::InitialInstancesContainer &initialInstancesContainer,
const gd::VariablesContainer &groupVariablesContainer,
const gd::ObjectGroup &objectGroup,
const gd::VariablesChangeset &changeset,
@@ -704,16 +692,6 @@ class GD_CORE_API WholeProjectRefactorer {
static size_t GetLayoutAndExternalLayoutLayerInstancesCount(
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(){};
private:

View File

@@ -19,7 +19,6 @@ using namespace gd;
void CustomObjectConfiguration::Init(const gd::CustomObjectConfiguration& objectConfiguration) {
project = objectConfiguration.project;
variantName = objectConfiguration.variantName;
objectContent = objectConfiguration.objectContent;
animations = objectConfiguration.animations;
isMarkedAsOverridingEventsBasedObjectChildrenConfiguration =
@@ -166,7 +165,6 @@ void CustomObjectConfiguration::DoSerializeTo(SerializerElement& element) const
animations.SerializeTo(animatableElement);
}
element.SetAttribute("variant", variantName);
if (IsOverridingEventsBasedObjectChildrenConfiguration()) {
auto &childrenContentElement = element.AddChild("childrenContent");
for (auto &pair : childObjectConfigurations) {
@@ -186,7 +184,6 @@ void CustomObjectConfiguration::DoUnserializeFrom(Project& project,
animations.UnserializeFrom(animatableElement);
}
variantName = element.GetStringAttribute("variant");
isMarkedAsOverridingEventsBasedObjectChildrenConfiguration =
element.HasChild("childrenContent");
if (isMarkedAsOverridingEventsBasedObjectChildrenConfiguration) {
@@ -250,29 +247,9 @@ void CustomObjectConfiguration::ExposeResources(gd::ArbitraryResourceWorker& wor
}
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
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()) {
auto &configuration = GetChildObjectConfiguration(childObject->GetName());
configuration.ExposeResources(worker);
}
} else {
for (auto &childObject :
eventsBasedObject.GetDefaultVariant().GetObjects().GetObjects()) {
childObject->GetConfiguration().ExposeResources(worker);
}
for (auto& childObject : eventsBasedObject.GetObjects().GetObjects()) {
auto &configuration = GetChildObjectConfiguration(childObject->GetName());
configuration.ExposeResources(worker);
}
}

View File

@@ -29,9 +29,9 @@ namespace gd {
* "resource".
*/
class CustomObjectConfiguration : public gd::ObjectConfiguration {
public:
CustomObjectConfiguration(const Project &project_, const String &type_)
: project(&project_) {
public:
CustomObjectConfiguration(const Project& project_, const String& type_)
: project(&project_), isMarkedAsOverridingEventsBasedObjectChildrenConfiguration(false) {
SetType(type_);
}
std::unique_ptr<gd::ObjectConfiguration> Clone() const override;
@@ -66,27 +66,6 @@ public:
void ExposeResources(gd::ArbitraryResourceWorker& worker) override;
/**
* \brief Get the name of the events-based object variant used by this custom object.
*/
const gd::String &GetVariantName() const { return variantName; };
/**
* \brief Set the name of the events-based object variant used by this custom object.
*/
void SetVariantName(const gd::String &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 IsMarkedAsOverridingEventsBasedObjectChildrenConfiguration() const {
@@ -166,7 +145,6 @@ protected:
gd::SerializerElement objectContent;
std::unordered_set<gd::String> unfoldedChildren;
gd::String variantName = "";
bool isMarkedAsOverridingEventsBasedObjectChildrenConfiguration = false;
mutable std::map<gd::String, std::unique_ptr<gd::ObjectConfiguration>> childObjectConfigurations;

View File

@@ -17,13 +17,19 @@ EventsBasedObject::EventsBasedObject()
isAnimatable(false),
isTextContainer(false),
isInnerAreaFollowingParentSize(false),
isUsingLegacyInstancesRenderer(false) {
isUsingLegacyInstancesRenderer(false),
areaMinX(0),
areaMinY(0),
areaMinZ(0),
areaMaxX(64),
areaMaxY(64),
areaMaxZ(64),
objectsContainer(gd::ObjectsContainer::SourceType::Object) {
}
EventsBasedObject::~EventsBasedObject() {}
void EventsBasedObject::SerializeToExternal(SerializerElement& element) const {
void EventsBasedObject::SerializeTo(SerializerElement& element) const {
element.SetAttribute("defaultName", defaultName);
if (isRenderedIn3D) {
element.SetBoolAttribute("is3D", true);
@@ -38,16 +44,20 @@ void EventsBasedObject::SerializeToExternal(SerializerElement& element) const {
element.SetBoolAttribute("isInnerAreaFollowingParentSize", true);
}
element.SetBoolAttribute("isUsingLegacyInstancesRenderer", isUsingLegacyInstancesRenderer);
element.SetIntAttribute("areaMinX", areaMinX);
element.SetIntAttribute("areaMinY", areaMinY);
element.SetIntAttribute("areaMinZ", areaMinZ);
element.SetIntAttribute("areaMaxX", areaMaxX);
element.SetIntAttribute("areaMaxY", areaMaxY);
element.SetIntAttribute("areaMaxZ", areaMaxZ);
// The EventsBasedObjectVariant SerializeTo method override the name.
// AbstractEventsBasedEntity::SerializeTo must be done after.
defaultVariant.SerializeTo(element);
AbstractEventsBasedEntity::SerializeTo(element);
}
objectsContainer.SerializeObjectsTo(element.AddChild("objects"));
objectsContainer.SerializeFoldersTo(element.AddChild("objectsFolderStructure"));
objectsContainer.GetObjectGroups().SerializeTo(element.AddChild("objectsGroups"));
void EventsBasedObject::SerializeTo(SerializerElement& element) const {
SerializeToExternal(element);
variants.SerializeVariantsTo(element.AddChild("variants"));
layers.SerializeLayersTo(element.AddChild("layers"));
initialInstances.SerializeTo(element.AddChild("instances"));
}
void EventsBasedObject::UnserializeFrom(gd::Project& project,
@@ -58,22 +68,36 @@ void EventsBasedObject::UnserializeFrom(gd::Project& project,
isTextContainer = element.GetBoolAttribute("isTextContainer", false);
isInnerAreaFollowingParentSize =
element.GetBoolAttribute("isInnerAreaFollowingParentSize", false);
areaMinX = element.GetIntAttribute("areaMinX", 0);
areaMinY = element.GetIntAttribute("areaMinY", 0);
areaMinZ = element.GetIntAttribute("areaMinZ", 0);
areaMaxX = element.GetIntAttribute("areaMaxX", 64);
areaMaxY = element.GetIntAttribute("areaMaxY", 64);
areaMaxZ = element.GetIntAttribute("areaMaxZ", 64);
defaultVariant.UnserializeFrom(project, element);
defaultVariant.SetName("");
AbstractEventsBasedEntity::UnserializeFrom(project, element);
objectsContainer.UnserializeObjectsFrom(project, element.GetChild("objects"));
if (element.HasChild("objectsFolderStructure")) {
objectsContainer.UnserializeFoldersFrom(project, element.GetChild("objectsFolderStructure", 0));
}
objectsContainer.AddMissingObjectsInRootFolder();
objectsContainer.GetObjectGroups().UnserializeFrom(
element.GetChild("objectsGroups"));
if (element.HasChild("variants")) {
variants.UnserializeVariantsFrom(project, element.GetChild("variants"));
if (element.HasChild("layers")) {
layers.UnserializeLayersFrom(element.GetChild("layers"));
} else {
layers.Reset();
}
initialInstances.UnserializeFrom(element.GetChild("instances"));
if (element.HasChild("isUsingLegacyInstancesRenderer")) {
isUsingLegacyInstancesRenderer =
element.GetBoolAttribute("isUsingLegacyInstancesRenderer", false);
}
else {
// Compatibility with GD <= 5.4.212
isUsingLegacyInstancesRenderer = GetInitialInstances().GetInstancesCount() == 0;
isUsingLegacyInstancesRenderer = initialInstances.GetInstancesCount() == 0;
// end of compatibility code
}
}

View File

@@ -7,8 +7,6 @@
#include <vector>
#include "GDCore/Project/AbstractEventsBasedEntity.h"
#include "GDCore/Project/EventsBasedObjectVariant.h"
#include "GDCore/Project/EventsBasedObjectVariantsContainer.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/InitialInstancesContainer.h"
#include "GDCore/Project/LayersContainer.h"
@@ -164,38 +162,18 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
*/
bool IsTextContainer() const { return isTextContainer; }
/**
* \brief Get the default variant of the custom object.
*/
const gd::EventsBasedObjectVariant& GetDefaultVariant() const { return defaultVariant; }
/**
* \brief Get the default variant of the custom object.
*/
gd::EventsBasedObjectVariant& GetDefaultVariant() { return defaultVariant; }
/**
* \brief Get the variants of the custom object.
*/
const gd::EventsBasedObjectVariantsContainer& GetVariants() const { return variants; }
/**
* \brief Get the variants of the custom object.
*/
gd::EventsBasedObjectVariantsContainer& GetVariants() { return variants; }
/** \name Layers
*/
///@{
/**
* \brief Get the layers of the custom object.
*/
const gd::LayersContainer& GetLayers() const { return defaultVariant.GetLayers(); }
const gd::LayersContainer& GetLayers() const { return layers; }
/**
* \brief Get the layers of the custom object.
*/
gd::LayersContainer& GetLayers() { return defaultVariant.GetLayers(); }
gd::LayersContainer& GetLayers() { return layers; }
///@}
/** \name Child objects
@@ -205,14 +183,14 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
* \brief Get the objects of the custom object.
*/
gd::ObjectsContainer& GetObjects() {
return defaultVariant.GetObjects();
return objectsContainer;
}
/**
* \brief Get the objects of the custom object.
*/
const gd::ObjectsContainer& GetObjects() const {
return defaultVariant.GetObjects();
return objectsContainer;
}
///@}
@@ -223,14 +201,14 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
* \brief Get the instances of the custom object.
*/
gd::InitialInstancesContainer& GetInitialInstances() {
return defaultVariant.GetInitialInstances();
return initialInstances;
}
/**
* \brief Get the instances of the custom object.
*/
const gd::InitialInstancesContainer& GetInitialInstances() const {
return defaultVariant.GetInitialInstances();
return initialInstances;
}
/**
@@ -241,14 +219,14 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMinX() const {
return defaultVariant.GetAreaMinX();
return areaMinX;
}
/**
* \brief Set the left bound of the custom object.
*/
void SetAreaMinX(int areaMinX) {
defaultVariant.SetAreaMinX(areaMinX);
void SetAreaMinX(int areaMinX_) {
areaMinX = areaMinX_;
}
/**
@@ -259,14 +237,14 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMinY() const {
return defaultVariant.GetAreaMinY();
return areaMinY;
}
/**
* \brief Set the top bound of the custom object.
*/
void SetAreaMinY(int areaMinY) {
defaultVariant.SetAreaMinY(areaMinY);
void SetAreaMinY(int areaMinY_) {
areaMinY = areaMinY_;
}
/**
@@ -277,14 +255,14 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMinZ() const {
return defaultVariant.GetAreaMinZ();
return areaMinZ;
}
/**
* \brief Set the min Z bound of the custom object.
*/
void SetAreaMinZ(int areaMinZ) {
defaultVariant.SetAreaMinZ(areaMinZ);
void SetAreaMinZ(int areaMinZ_) {
areaMinZ = areaMinZ_;
}
/**
@@ -295,14 +273,14 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMaxX() const {
return defaultVariant.GetAreaMaxX();
return areaMaxX;
}
/**
* \brief Set the right bound of the custom object.
*/
void SetAreaMaxX(int areaMaxX) {
defaultVariant.SetAreaMaxX(areaMaxX);
void SetAreaMaxX(int areaMaxX_) {
areaMaxX = areaMaxX_;
}
/**
@@ -313,14 +291,14 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMaxY() const {
return defaultVariant.GetAreaMaxY();
return areaMaxY;
}
/**
* \brief Set the bottom bound of the custom object.
*/
void SetAreaMaxY(int areaMaxY) {
defaultVariant.SetAreaMaxY(areaMaxY);
void SetAreaMaxY(int areaMaxY_) {
areaMaxY = areaMaxY_;
}
/**
@@ -331,22 +309,16 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
* \see EventsBasedObject::GetInitialInstances
*/
int GetAreaMaxZ() const {
return defaultVariant.GetAreaMaxZ();
return areaMaxZ;
}
/**
* \brief Set the bottom bound of the custom object.
*/
void SetAreaMaxZ(int areaMaxZ) {
defaultVariant.SetAreaMaxZ(areaMaxZ);
void SetAreaMaxZ(int areaMaxZ_) {
areaMaxZ = areaMaxZ_;
}
///@}
/**
* @brief Serialize the events-based object for an extension in an external file.
* Variants are not serialized.
*/
void SerializeToExternal(SerializerElement& element) const;
void SerializeTo(SerializerElement& element) const override;
@@ -360,8 +332,15 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
bool isTextContainer;
bool isInnerAreaFollowingParentSize;
bool isUsingLegacyInstancesRenderer;
gd::EventsBasedObjectVariant defaultVariant;
gd::EventsBasedObjectVariantsContainer variants;
gd::InitialInstancesContainer initialInstances;
gd::LayersContainer layers;
gd::ObjectsContainer objectsContainer;
double areaMinX;
double areaMinY;
double areaMinZ;
double areaMaxX;
double areaMaxY;
double areaMaxZ;
};
} // namespace gd

View File

@@ -1,71 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "EventsBasedObjectVariant.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Serialization/SerializerElement.h"
namespace gd {
EventsBasedObjectVariant::EventsBasedObjectVariant()
: areaMinX(0), areaMinY(0), areaMinZ(0), areaMaxX(64), areaMaxY(64),
areaMaxZ(64), objectsContainer(gd::ObjectsContainer::SourceType::Object) {
}
EventsBasedObjectVariant::~EventsBasedObjectVariant() {}
void EventsBasedObjectVariant::SerializeTo(SerializerElement &element) const {
element.SetAttribute("name", name);
if (!GetAssetStoreAssetId().empty() && !GetAssetStoreOriginalName().empty()) {
element.SetAttribute("assetStoreAssetId", GetAssetStoreAssetId());
element.SetAttribute("assetStoreOriginalName", GetAssetStoreOriginalName());
}
element.SetIntAttribute("areaMinX", areaMinX);
element.SetIntAttribute("areaMinY", areaMinY);
element.SetIntAttribute("areaMinZ", areaMinZ);
element.SetIntAttribute("areaMaxX", areaMaxX);
element.SetIntAttribute("areaMaxY", areaMaxY);
element.SetIntAttribute("areaMaxZ", areaMaxZ);
objectsContainer.SerializeObjectsTo(element.AddChild("objects"));
objectsContainer.SerializeFoldersTo(
element.AddChild("objectsFolderStructure"));
objectsContainer.GetObjectGroups().SerializeTo(
element.AddChild("objectsGroups"));
layers.SerializeLayersTo(element.AddChild("layers"));
initialInstances.SerializeTo(element.AddChild("instances"));
}
void EventsBasedObjectVariant::UnserializeFrom(
gd::Project &project, const SerializerElement &element) {
name = element.GetStringAttribute("name");
assetStoreAssetId = element.GetStringAttribute("assetStoreAssetId");
assetStoreOriginalName = element.GetStringAttribute("assetStoreOriginalName");
areaMinX = element.GetIntAttribute("areaMinX", 0);
areaMinY = element.GetIntAttribute("areaMinY", 0);
areaMinZ = element.GetIntAttribute("areaMinZ", 0);
areaMaxX = element.GetIntAttribute("areaMaxX", 64);
areaMaxY = element.GetIntAttribute("areaMaxY", 64);
areaMaxZ = element.GetIntAttribute("areaMaxZ", 64);
objectsContainer.UnserializeObjectsFrom(project, element.GetChild("objects"));
if (element.HasChild("objectsFolderStructure")) {
objectsContainer.UnserializeFoldersFrom(
project, element.GetChild("objectsFolderStructure", 0));
}
objectsContainer.AddMissingObjectsInRootFolder();
objectsContainer.GetObjectGroups().UnserializeFrom(
element.GetChild("objectsGroups"));
if (element.HasChild("layers")) {
layers.UnserializeLayersFrom(element.GetChild("layers"));
} else {
layers.Reset();
}
initialInstances.UnserializeFrom(element.GetChild("instances"));
}
} // namespace gd

View File

@@ -1,229 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2025 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/Project/InitialInstancesContainer.h"
#include "GDCore/Project/LayersContainer.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/String.h"
#include <vector>
namespace gd {
class SerializerElement;
class Project;
} // namespace gd
namespace gd {
/**
* \brief Represents a variation of style of an events-based object.
*
* \ingroup PlatformDefinition
*/
class GD_CORE_API EventsBasedObjectVariant {
public:
EventsBasedObjectVariant();
virtual ~EventsBasedObjectVariant();
/**
* \brief Return a pointer to a new EventsBasedObjectVariant constructed from
* this one.
*/
EventsBasedObjectVariant *Clone() const {
return new EventsBasedObjectVariant(*this);
};
/**
* \brief Get the name of the variant.
*/
const gd::String &GetName() const { return name; };
/**
* \brief Set the name of the variant.
*/
EventsBasedObjectVariant &SetName(const gd::String &name_) {
name = name_;
return *this;
}
/** \name Layers
*/
///@{
/**
* \brief Get the layers of the variant.
*/
const gd::LayersContainer &GetLayers() const { return layers; }
/**
* \brief Get the layers of the variant.
*/
gd::LayersContainer &GetLayers() { return layers; }
///@}
/** \name Child objects
*/
///@{
/**
* \brief Get the objects of the variant.
*/
gd::ObjectsContainer &GetObjects() { return objectsContainer; }
/**
* \brief Get the objects of the variant.
*/
const gd::ObjectsContainer &GetObjects() const { return objectsContainer; }
///@}
/** \name Instances
*/
///@{
/**
* \brief Get the instances of the variant.
*/
gd::InitialInstancesContainer &GetInitialInstances() {
return initialInstances;
}
/**
* \brief Get the instances of the variant.
*/
const gd::InitialInstancesContainer &GetInitialInstances() const {
return initialInstances;
}
/**
* \brief Get the left bound of the variant.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObjectVariant::GetInitialInstances
*/
int GetAreaMinX() const { return areaMinX; }
/**
* \brief Set the left bound of the variant.
*/
void SetAreaMinX(int areaMinX_) { areaMinX = areaMinX_; }
/**
* \brief Get the top bound of the variant.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObjectVariant::GetInitialInstances
*/
int GetAreaMinY() const { return areaMinY; }
/**
* \brief Set the top bound of the variant.
*/
void SetAreaMinY(int areaMinY_) { areaMinY = areaMinY_; }
/**
* \brief Get the min Z bound of the variant.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObjectVariant::GetInitialInstances
*/
int GetAreaMinZ() const { return areaMinZ; }
/**
* \brief Set the min Z bound of the variant.
*/
void SetAreaMinZ(int areaMinZ_) { areaMinZ = areaMinZ_; }
/**
* \brief Get the right bound of the variant.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObjectVariant::GetInitialInstances
*/
int GetAreaMaxX() const { return areaMaxX; }
/**
* \brief Set the right bound of the variant.
*/
void SetAreaMaxX(int areaMaxX_) { areaMaxX = areaMaxX_; }
/**
* \brief Get the bottom bound of the variant.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObjectVariant::GetInitialInstances
*/
int GetAreaMaxY() const { return areaMaxY; }
/**
* \brief Set the bottom bound of the variant.
*/
void SetAreaMaxY(int areaMaxY_) { areaMaxY = areaMaxY_; }
/**
* \brief Get the max Z bound of the variant.
*
* This is used only if there is any initial instances.
*
* \see EventsBasedObjectVariant::GetInitialInstances
*/
int GetAreaMaxZ() const { return areaMaxZ; }
/**
* \brief Set the bottom bound of the variant.
*/
void SetAreaMaxZ(int areaMaxZ_) { areaMaxZ = areaMaxZ_; }
///@}
/** \brief Change the object asset store id of this variant.
*/
void SetAssetStoreAssetId(const gd::String &assetStoreId_) {
assetStoreAssetId = assetStoreId_;
};
/** \brief Return the object asset store id of this variant.
*/
const gd::String &GetAssetStoreAssetId() const { return assetStoreAssetId; };
/** \brief Change the original name of the variant in the asset.
*/
void SetAssetStoreOriginalName(const gd::String &assetStoreOriginalName_) {
assetStoreOriginalName = assetStoreOriginalName_;
};
/** \brief Return the original name of the variant in the asset.
*/
const gd::String &GetAssetStoreOriginalName() const {
return assetStoreOriginalName;
};
void SerializeTo(SerializerElement &element) const;
void UnserializeFrom(gd::Project &project, const SerializerElement &element);
private:
gd::String name;
gd::InitialInstancesContainer initialInstances;
gd::LayersContainer layers;
gd::ObjectsContainer objectsContainer;
double areaMinX;
double areaMinY;
double areaMinZ;
double areaMaxX;
double areaMaxY;
double areaMaxZ;
/**
* The ID of the asset if the object comes from the store.
*/
gd::String assetStoreAssetId;
/**
* The original name of the variant in the asset if the object comes from the
* store.
*/
gd::String assetStoreOriginalName;
};
} // namespace gd

View File

@@ -1,160 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <vector>
#include "GDCore/Project/EventsBasedObjectVariant.h"
#include "GDCore/String.h"
#include "GDCore/Tools/SerializableWithNameList.h"
namespace gd {
class SerializerElement;
}
namespace gd {
/**
* \brief Used as a base class for classes that will own events-backed
* variants.
*
* \see gd::EventsBasedObjectVariantContainer
* \ingroup PlatformDefinition
*/
class GD_CORE_API EventsBasedObjectVariantsContainer
: private SerializableWithNameList<gd::EventsBasedObjectVariant> {
public:
EventsBasedObjectVariantsContainer() {}
EventsBasedObjectVariantsContainer(const EventsBasedObjectVariantsContainer &other) {
Init(other);
}
EventsBasedObjectVariantsContainer &operator=(const EventsBasedObjectVariantsContainer &other) {
if (this != &other) {
Init(other);
}
return *this;
}
/** \name Events Functions management
*/
///@{
/**
* \brief Check if the variant with the specified name exists.
*/
bool HasVariantNamed(const gd::String& name) const {
return Has(name);
}
/**
* \brief Get the variant with the specified name.
*
* \warning Trying to access to a not existing variant will result in
* undefined behavior.
*/
gd::EventsBasedObjectVariant& GetVariant(const gd::String& name) {
return Get(name);
}
/**
* \brief Get the variant with the specified name.
*
* \warning Trying to access to a not existing variant will result in
* undefined behavior.
*/
const gd::EventsBasedObjectVariant& GetVariant(const gd::String& name) const {
return Get(name);
}
/**
* \brief Get the variant at the specified index in the list.
*
* \warning Trying to access to a not existing variant will result in
* undefined behavior.
*/
gd::EventsBasedObjectVariant& GetVariant(std::size_t index) {
return Get(index);
}
/**
* \brief Get the variant at the specified index in the list.
*
* \warning Trying to access to a not existing variant will result in
* undefined behavior.
*/
const gd::EventsBasedObjectVariant& GetVariant(std::size_t index) const {
return Get(index);
}
/**
* \brief Return the number of variants.
*/
std::size_t GetVariantsCount() const { return GetCount(); }
gd::EventsBasedObjectVariant& InsertNewVariant(const gd::String& name,
std::size_t position) {
return InsertNew(name, position);
}
gd::EventsBasedObjectVariant& InsertVariant(const gd::EventsBasedObjectVariant& object,
std::size_t position) {
return Insert(object, position);
}
void RemoveVariant(const gd::String& name) { return Remove(name); }
void ClearVariants() { return Clear(); }
void MoveVariant(std::size_t oldIndex, std::size_t newIndex) {
return Move(oldIndex, newIndex);
};
std::size_t GetVariantPosition(const gd::EventsBasedObjectVariant& eventsFunction) {
return GetPosition(eventsFunction);
};
/**
* \brief Provide a raw access to the vector containing the variants.
*/
const std::vector<std::unique_ptr<gd::EventsBasedObjectVariant>>& GetInternalVector()
const {
return elements;
};
/**
* \brief Provide a raw access to the vector containing the variants.
*/
std::vector<std::unique_ptr<gd::EventsBasedObjectVariant>>& GetInternalVector() {
return elements;
};
///@}
/** \name Serialization
*/
///@{
/**
* \brief Serialize events variants.
*/
void SerializeVariantsTo(SerializerElement& element) const {
return SerializeElementsTo("variant", element);
};
/**
* \brief Unserialize the events variants.
*/
void UnserializeVariantsFrom(gd::Project& project,
const SerializerElement& element) {
return UnserializeElementsFrom("variant", project, element);
};
///@}
protected:
/**
* Initialize object using another object. Used by copy-ctor and assign-op.
* Don't forget to update me if members were changed!
*/
void Init(const gd::EventsBasedObjectVariantsContainer& other) {
return SerializableWithNameList<gd::EventsBasedObjectVariant>::Init(other);
};
private:
};
} // namespace gd

View File

@@ -47,7 +47,6 @@ void EventsFunctionsExtension::Init(const gd::EventsFunctionsExtension& other) {
previewIconUrl = other.previewIconUrl;
iconUrl = other.iconUrl;
helpPath = other.helpPath;
gdevelopVersion = other.gdevelopVersion;
eventsFunctionsContainer = other.eventsFunctionsContainer;
eventsBasedBehaviors = other.eventsBasedBehaviors;
eventsBasedObjects = other.eventsBasedObjects;
@@ -55,7 +54,7 @@ void EventsFunctionsExtension::Init(const gd::EventsFunctionsExtension& other) {
sceneVariables = other.GetSceneVariables();
}
void EventsFunctionsExtension::SerializeTo(SerializerElement& element, bool isExternal) const {
void EventsFunctionsExtension::SerializeTo(SerializerElement& element) const {
element.SetAttribute("version", version);
element.SetAttribute("extensionNamespace", extensionNamespace);
element.SetAttribute("shortDescription", shortDescription);
@@ -82,10 +81,6 @@ void EventsFunctionsExtension::SerializeTo(SerializerElement& element, bool isEx
element.SetAttribute("previewIconUrl", previewIconUrl);
element.SetAttribute("iconUrl", iconUrl);
element.SetAttribute("helpPath", helpPath);
element.SetAttribute("gdevelopVersion", gdevelopVersion);
if (changelog.GetChangesCount() > 0) {
changelog.SerializeTo(element.AddChild("changelog"));
}
auto& dependenciesElement = element.AddChild("dependencies");
dependenciesElement.ConsiderAsArray();
for (auto& dependency : dependencies)
@@ -105,18 +100,8 @@ void EventsFunctionsExtension::SerializeTo(SerializerElement& element, bool isEx
element.AddChild("eventsFunctions"));
eventsBasedBehaviors.SerializeElementsTo(
"eventsBasedBehavior", element.AddChild("eventsBasedBehaviors"));
if (isExternal) {
auto &eventsBasedObjectElement = element.AddChild("eventsBasedObjects");
eventsBasedObjectElement.ConsiderAsArrayOf("eventsBasedObject");
for (const auto &eventsBasedObject :
eventsBasedObjects.GetInternalVector()) {
eventsBasedObject->SerializeToExternal(
eventsBasedObjectElement.AddChild("eventsBasedObject"));
}
} else {
eventsBasedObjects.SerializeElementsTo(
"eventsBasedObject", element.AddChild("eventsBasedObjects"));
}
eventsBasedObjects.SerializeElementsTo(
"eventsBasedObject", element.AddChild("eventsBasedObjects"));
}
void EventsFunctionsExtension::UnserializeFrom(
@@ -141,10 +126,6 @@ void EventsFunctionsExtension::UnserializeExtensionDeclarationFrom(
previewIconUrl = element.GetStringAttribute("previewIconUrl");
iconUrl = element.GetStringAttribute("iconUrl");
helpPath = element.GetStringAttribute("helpPath");
gdevelopVersion = element.GetStringAttribute("gdevelopVersion");
if (element.HasChild("changelog")) {
changelog.UnserializeFrom(element.GetChild("changelog"));
}
if (element.HasChild("origin")) {
gd::String originName =

View File

@@ -12,11 +12,9 @@
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/EventsBasedObject.h"
#include "GDCore/Project/EventsFunctionsContainer.h"
#include "GDCore/Project/EventsFunctionsExtensionChangelog.h"
#include "GDCore/Project/VariablesContainer.h"
#include "GDCore/String.h"
#include "GDCore/Tools/SerializableWithNameList.h"
namespace gd {
class SerializerElement;
class Project;
@@ -136,19 +134,6 @@ class GD_CORE_API EventsFunctionsExtension {
return *this;
}
/**
* \brief Get the GDevelop version required by this extension.
*/
const gd::String& GetGDevelopVersion() const { return gdevelopVersion; };
/**
* \brief Set the GDevelop version required by this extension.
*/
EventsFunctionsExtension& SetGDevelopVersion(const gd::String& gdevelopVersion_) {
gdevelopVersion = gdevelopVersion_;
return *this;
}
/**
* \brief Return a reference to the list of the events based behaviors.
*/
@@ -288,14 +273,7 @@ class GD_CORE_API EventsFunctionsExtension {
/**
* \brief Serialize the EventsFunctionsExtension to the specified element
*/
void SerializeTo(gd::SerializerElement& element, bool isExternal = false) const;
/**
* \brief Serialize the EventsFunctionsExtension to the specified element
*/
void SerializeToExternal(gd::SerializerElement& element) const {
SerializeTo(element, true);
}
void SerializeTo(gd::SerializerElement& element) const;
/**
* \brief Load the EventsFunctionsExtension from the specified element.
@@ -407,8 +385,6 @@ class GD_CORE_API EventsFunctionsExtension {
gd::String iconUrl;
gd::String helpPath; ///< The relative path to the help for this extension in
///< the documentation (or an absolute URL).
gd::String gdevelopVersion;
gd::EventsFunctionsExtensionChangelog changelog;
gd::SerializableWithNameList<EventsBasedBehavior> eventsBasedBehaviors;
gd::SerializableWithNameList<EventsBasedObject> eventsBasedObjects;
std::vector<gd::DependencyMetadata> dependencies;

View File

@@ -1,105 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <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

View File

@@ -365,8 +365,6 @@ class GD_CORE_API InitialInstance {
* the same initial instance between serialization.
*/
InitialInstance& ResetPersistentUuid();
const gd::String& GetPersistentUuid() const { return persistentUuid; }
///@}
private:

View File

@@ -41,16 +41,6 @@ void InitialInstancesContainer::IterateOverInstances(
for (auto& instance : initialInstances) func(instance);
}
void InitialInstancesContainer::IterateOverInstances(
const std::function< bool(gd::InitialInstance &) >& func) {
for (auto& instance : initialInstances) {
bool shouldStop = func(instance);
if (shouldStop) {
return;
}
}
}
void InitialInstancesContainer::IterateOverInstancesWithZOrdering(
gd::InitialInstanceFunctor& func, const gd::String& layerName) {
std::vector<std::reference_wrapper<gd::InitialInstance>> sortedInstances;

View File

@@ -87,13 +87,6 @@ class GD_CORE_API InitialInstancesContainer {
*/
void IterateOverInstances(InitialInstanceFunctor &func);
/**
* \brief Apply \a func to each instance of the container.
* \see InitialInstanceFunctor
*/
void IterateOverInstances(
const std::function< bool(gd::InitialInstance &) >& func);
/**
* Get the instances on the specified layer,
* sort them regarding their Z order and then apply \a func on them.

View File

@@ -41,11 +41,6 @@ Object::Object(const gd::String& name_,
}
void Object::Init(const gd::Object& object) {
CopyWithoutConfiguration(object);
configuration = object.configuration->Clone();
}
void Object::CopyWithoutConfiguration(const gd::Object& object) {
persistentUuid = object.persistentUuid;
name = object.name;
assetStoreId = object.assetStoreId;
@@ -56,6 +51,8 @@ void Object::CopyWithoutConfiguration(const gd::Object& object) {
for (auto& it : object.behaviors) {
behaviors[it.first] = gd::make_unique<gd::Behavior>(*it.second);
}
configuration = object.configuration->Clone();
}
gd::ObjectConfiguration& Object::GetConfiguration() { return *configuration; }

View File

@@ -82,8 +82,6 @@ class GD_CORE_API Object {
return gd::make_unique<gd::Object>(*this);
}
void CopyWithoutConfiguration(const gd::Object& object);
/**
* \brief Return the object configuration.
*/

View File

@@ -1,57 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2025 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ObjectTools.h"
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Platform.h"
namespace gd {
bool ObjectTools::IsBehaviorCompatibleWithObject(
const gd::Platform &platform, const gd::String &objectType,
const gd::String &behaviorType,
std::unordered_set<gd::String> coveredBehaviorType) {
bool isBehaviorTypeAlreadyCovered =
!coveredBehaviorType.insert(behaviorType).second;
if (isBehaviorTypeAlreadyCovered) {
return true;
}
const gd::BehaviorMetadata &behaviorMetadata =
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
// Should not happen because the behavior was added successfully (so its
// metadata are valid) - but double check anyway and bail out if the
// behavior metadata are invalid.
return false;
}
if (!behaviorMetadata.GetObjectType().empty() &&
behaviorMetadata.GetObjectType() != objectType) {
return false;
}
for (const gd::String &requiredBehaviorType :
behaviorMetadata.GetRequiredBehaviorTypes()) {
const gd::BehaviorMetadata &requiredBehaviorMetadata =
gd::MetadataProvider::GetBehaviorMetadata(platform, requiredBehaviorType);
if (requiredBehaviorMetadata.IsHidden()) {
const gd::ObjectMetadata &objectMetadata =
gd::MetadataProvider::GetObjectMetadata(platform, objectType);
if (objectMetadata.GetDefaultBehaviors().find(requiredBehaviorType) ==
objectMetadata.GetDefaultBehaviors().end()) {
// A capability is missing in the object.
return false;
}
}
if (!gd::ObjectTools::IsBehaviorCompatibleWithObject(
platform, objectType, requiredBehaviorType, coveredBehaviorType)) {
return false;
}
}
return true;
}
} // namespace gd

View File

@@ -1,35 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2025 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/String.h"
#include <unordered_set>
namespace gd {
class Platform;
class Object;
} // namespace gd
namespace gd {
class GD_CORE_API ObjectTools {
public:
static bool IsBehaviorCompatibleWithObject(const gd::Platform &platform,
const gd::String &objectType,
const gd::String &behaviorType) {
std::unordered_set<gd::String> coveredBehaviorType;
return IsBehaviorCompatibleWithObject(platform, objectType, behaviorType,
coveredBehaviorType);
}
private:
static bool IsBehaviorCompatibleWithObject(
const gd::Platform &platform, const gd::String &objectType,
const gd::String &behaviorType,
std::unordered_set<gd::String> coveredBehaviorType);
};
} // namespace gd

View File

@@ -81,11 +81,6 @@ class GD_CORE_API ObjectsContainersList {
/**
* \brief Return the container of the variables for the specified object or
* 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::String& objectOrGroupName) const;

View File

@@ -920,7 +920,6 @@ void Project::UnserializeAndInsertExtensionsFrom(
"eventsFunctionsExtension");
std::map<gd::String, size_t> extensionNameToElementIndex;
std::map<gd::String, gd::SerializerElement> objectTypeToVariantsElement;
// First, only unserialize behaviors and objects names.
// As event based objects can contains custom behaviors and custom objects,
@@ -939,16 +938,6 @@ void Project::UnserializeAndInsertExtensionsFrom(
? GetEventsFunctionsExtension(name)
: InsertNewEventsFunctionsExtension(
name, GetEventsFunctionsExtensionsCount());
// Backup the events-based object variants
for (auto &eventsBasedObject :
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
gd::SerializerElement variantsElement;
eventsBasedObject->GetVariants().SerializeVariantsTo(variantsElement);
objectTypeToVariantsElement[gd::PlatformExtension::GetObjectFullType(
name, eventsBasedObject->GetName())] = variantsElement;
}
eventsFunctionsExtension.UnserializeExtensionDeclarationFrom(
*this, eventsFunctionsExtensionElement);
}
@@ -977,15 +966,6 @@ void Project::UnserializeAndInsertExtensionsFrom(
partiallyLoadedExtension
->UnserializeExtensionImplementationFrom(
*this, eventsFunctionsExtensionElement);
for (auto &pair : objectTypeToVariantsElement) {
auto &objectType = pair.first;
auto &variantsElement = pair.second;
auto &eventsBasedObject = GetEventsBasedObject(objectType);
eventsBasedObject.GetVariants().UnserializeVariantsFrom(*this,
variantsElement);
}
}
}

View File

@@ -21,19 +21,14 @@ void PropertyDescriptor::SerializeTo(SerializerElement& element) const {
element.AddChild("unit").SetStringValue(measurementUnit.GetName());
}
element.AddChild("label").SetStringValue(label);
if (!description.empty())
element.AddChild("description").SetStringValue(description);
if (!group.empty()) element.AddChild("group").SetStringValue(group);
if (!extraInformation.empty()) {
SerializerElement& extraInformationElement =
element.AddChild("extraInformation");
extraInformationElement.ConsiderAsArray();
for (const gd::String& information : extraInformation) {
extraInformationElement.AddChild("").SetStringValue(information);
}
element.AddChild("description").SetStringValue(description);
element.AddChild("group").SetStringValue(group);
SerializerElement& extraInformationElement =
element.AddChild("extraInformation");
extraInformationElement.ConsiderAsArray();
for (const gd::String& information : extraInformation) {
extraInformationElement.AddChild("").SetStringValue(information);
}
if (hidden) {
element.AddChild("hidden").SetBoolValue(hidden);
}
@@ -64,21 +59,16 @@ void PropertyDescriptor::UnserializeFrom(const SerializerElement& element) {
: gd::MeasurementUnit::GetUndefined();
}
label = element.GetChild("label").GetStringValue();
description = element.HasChild("description")
? element.GetChild("description").GetStringValue()
: "";
group = element.HasChild("group") ? element.GetChild("group").GetStringValue()
: "";
description = element.GetChild("description").GetStringValue();
group = element.GetChild("group").GetStringValue();
extraInformation.clear();
if (element.HasChild("extraInformation")) {
const SerializerElement& extraInformationElement =
element.GetChild("extraInformation");
extraInformationElement.ConsiderAsArray();
for (std::size_t i = 0; i < extraInformationElement.GetChildrenCount(); ++i)
extraInformation.push_back(
extraInformationElement.GetChild(i).GetStringValue());
}
const SerializerElement& extraInformationElement =
element.GetChild("extraInformation");
extraInformationElement.ConsiderAsArray();
for (std::size_t i = 0; i < extraInformationElement.GetChildrenCount(); ++i)
extraInformation.push_back(
extraInformationElement.GetChild(i).GetStringValue());
hidden = element.HasChild("hidden")
? element.GetChild("hidden").GetBoolValue()

View File

@@ -6,7 +6,6 @@
#if defined(EMSCRIPTEN)
#include <emscripten.h>
#include "GDCore/String.h"
namespace gd {
@@ -32,10 +31,5 @@ gd::String GetTranslation(const char* str) { // TODO: Inline?
str);
return gd::String(translatedStr); // TODO: Is copying necessary?
}
gd::String GetTranslation(const gd::String& str) {
return GetTranslation(str.c_str());
}
} // namespace gd
#endif

View File

@@ -8,10 +8,10 @@
/** @file
* Provide a way to mark strings to be translated.
*
*
* Strings to be translated in GDevelop Core codebase
* are marked with the underscore macro, for example: _("Hello World").
*
*
* The macro is then defined to be using the translation function
* of the underlying platform (Emscripten for GDevelop 5).
*/
@@ -26,10 +26,8 @@
#endif
namespace gd {
gd::String GetTranslation(const gd::String& str);
gd::String GetTranslation(const char* str);
} // namespace gd
}
#define _(s) gd::GetTranslation(u8##s)

View File

@@ -1,522 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
/**
* @file Tests covering events of GDevelop Core.
*/
#include "catch.hpp"
#include <algorithm>
#include <initializer_list>
#include <map>
#include "GDCore/CommonTools.h"
#include "GDCore/IDE/EventsBasedObjectVariantHelper.h"
#include "DummyPlatform.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/ProjectScopedContainers.h"
#include "GDCore/Project/Variable.h"
#include "catch.hpp"
gd::InitialInstance *
GetFirstInstanceOf(const gd::String objectName,
gd::InitialInstancesContainer &initialInstances) {
gd::InitialInstance *variantInstance = nullptr;
initialInstances.IterateOverInstances(
[&variantInstance, &objectName](gd::InitialInstance &instance) {
if (instance.GetObjectName() == objectName) {
variantInstance = &instance;
return true;
}
return false;
});
return variantInstance;
}
gd::EventsBasedObject &SetupEventsBasedObject(gd::Project &project) {
auto &eventsExtension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &eventsBasedObject = eventsExtension.GetEventsBasedObjects().InsertNew(
"MyEventsBasedObject", 0);
auto &object = eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChildObject", 0);
object.GetVariables().InsertNew("MyVariable").SetValue(123);
object.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior");
auto &instance =
eventsBasedObject.GetInitialInstances().InsertNewInitialInstance();
instance.SetObjectName("MyChildObject");
instance.GetVariables().InsertNew("MyVariable").SetValue(111);
auto &objectGroup =
eventsBasedObject.GetObjects().GetObjectGroups().InsertNew(
"MyObjectGroup");
objectGroup.AddObject("MyChildObject");
return eventsBasedObject;
}
TEST_CASE("EventsBasedObjectVariantHelper", "[common]") {
SECTION("Can add missing objects") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChildObject2", 0);
eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChildObject3", 0);
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject2"));
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject3"));
}
SECTION("Can remove objects") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChildObject2", 0);
eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChildObject3", 0);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
variant.GetInitialInstances().InsertNewInitialInstance().SetObjectName(
"MyChildObject2");
REQUIRE(variant.GetInitialInstances().HasInstancesOfObject(
"MyChildObject2") == true);
// Do the changes and launch the refactoring.
eventsBasedObject.GetObjects().RemoveObject("MyChildObject2");
eventsBasedObject.GetObjects().RemoveObject("MyChildObject3");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject2") == false);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject3") == false);
REQUIRE(variant.GetInitialInstances().HasInstancesOfObject(
"MyChildObject2") == false);
}
SECTION("Can change object type") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
eventsBasedObject.GetObjects().RemoveObject("MyChildObject");
eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::FakeObjectWithDefaultBehavior", "MyChildObject",
0);
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
REQUIRE(variant.GetObjects().GetObject("MyChildObject").GetType() ==
"MyExtension::FakeObjectWithDefaultBehavior");
REQUIRE(variant.GetInitialInstances().GetInstancesCount() == 1);
}
SECTION("Can add missing object groups") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
eventsBasedObject.GetObjects().GetObjectGroups().InsertNew("MyObjectGroup2",
0);
eventsBasedObject.GetObjects()
.GetObjectGroups()
.InsertNew("MyObjectGroup3", 0)
.AddObject("MyChildObject");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
auto &variantObjectGroups = variant.GetObjects().GetObjectGroups();
REQUIRE(variantObjectGroups.Has("MyObjectGroup"));
REQUIRE(variantObjectGroups.Has("MyObjectGroup2"));
REQUIRE(variantObjectGroups.Has("MyObjectGroup3"));
REQUIRE(
variantObjectGroups.Get("MyObjectGroup").GetAllObjectsNames().size() ==
1);
REQUIRE(
variantObjectGroups.Get("MyObjectGroup2").GetAllObjectsNames().size() ==
0);
REQUIRE(
variantObjectGroups.Get("MyObjectGroup3").GetAllObjectsNames().size() ==
1);
}
SECTION("Can remove object groups") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
// Do the changes and launch the refactoring.
eventsBasedObject.GetObjects().GetObjectGroups().InsertNew("MyObjectGroup2",
0);
eventsBasedObject.GetObjects().GetObjectGroups().InsertNew("MyObjectGroup3",
0);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
eventsBasedObject.GetObjects().GetObjectGroups().Remove("MyObjectGroup2");
eventsBasedObject.GetObjects().GetObjectGroups().Remove("MyObjectGroup3");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
auto &variantObjectGroups = variant.GetObjects().GetObjectGroups();
REQUIRE(variantObjectGroups.Has("MyObjectGroup"));
REQUIRE(variantObjectGroups.Has("MyObjectGroup2") == false);
REQUIRE(variantObjectGroups.Has("MyObjectGroup3") == false);
}
SECTION("Can add objects to groups") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChildObject2", 0);
eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChildObject3", 0);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
auto &objectGroup =
eventsBasedObject.GetObjects().GetObjectGroups().Get("MyObjectGroup");
objectGroup.AddObject("MyChildObject2");
objectGroup.AddObject("MyChildObject3");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
auto &variantObjectGroups = variant.GetObjects().GetObjectGroups();
REQUIRE(variantObjectGroups.Has("MyObjectGroup"));
REQUIRE(
variantObjectGroups.Get("MyObjectGroup").GetAllObjectsNames().size() ==
3);
}
SECTION("Can remove objects from groups") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChildObject2", 0);
eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChildObject3", 0);
auto &objectGroup =
eventsBasedObject.GetObjects().GetObjectGroups().Get("MyObjectGroup");
objectGroup.AddObject("MyChildObject2");
objectGroup.AddObject("MyChildObject3");
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
objectGroup.RemoveObject("MyChildObject2");
objectGroup.RemoveObject("MyChildObject3");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
auto &variantObjectGroups = variant.GetObjects().GetObjectGroups();
REQUIRE(variantObjectGroups.Has("MyObjectGroup"));
REQUIRE(
variantObjectGroups.Get("MyObjectGroup").GetAllObjectsNames().size() ==
1);
}
SECTION("Can add missing behaviors") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
auto &object = eventsBasedObject.GetObjects().GetObject("MyChildObject");
object.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior2");
object.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior3");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
auto &variantObject = variant.GetObjects().GetObject("MyChildObject");
REQUIRE(variantObject.HasBehaviorNamed("MyBehavior"));
REQUIRE(variantObject.HasBehaviorNamed("MyBehavior2"));
REQUIRE(variantObject.HasBehaviorNamed("MyBehavior3"));
}
SECTION("Can remove missing behaviors") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &object = eventsBasedObject.GetObjects().GetObject("MyChildObject");
object.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior2");
object.AddNewBehavior(project, "MyExtension::MyBehavior", "MyBehavior3");
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
object.RemoveBehavior("MyBehavior2");
object.RemoveBehavior("MyBehavior3");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
auto &variantObject = variant.GetObjects().GetObject("MyChildObject");
REQUIRE(variantObject.HasBehaviorNamed("MyBehavior"));
REQUIRE(variantObject.HasBehaviorNamed("MyBehavior2") == false);
REQUIRE(variantObject.HasBehaviorNamed("MyBehavior3") == false);
}
SECTION("Can change behavior type") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
auto &object = eventsBasedObject.GetObjects().GetObject("MyChildObject");
object.RemoveBehavior("MyBehavior");
object.AddNewBehavior(project, "MyExtension::MyOtherBehavior",
"MyBehavior");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
auto &variantObject = variant.GetObjects().GetObject("MyChildObject");
REQUIRE(variantObject.HasBehaviorNamed("MyBehavior"));
REQUIRE(variantObject.GetBehavior("MyBehavior").GetTypeName() ==
"MyExtension::MyOtherBehavior");
}
SECTION("Can add missing variables") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
auto &object = eventsBasedObject.GetObjects().GetObject("MyChildObject");
object.GetVariables().InsertNew("MyVariable2", 1).SetValue(456);
object.GetVariables().InsertNew("MyVariable3", 2).SetValue(789);
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
auto &variantObject = variant.GetObjects().GetObject("MyChildObject");
REQUIRE(variantObject.GetVariables().Get("MyVariable").GetValue() == 123);
REQUIRE(variantObject.GetVariables().Get("MyVariable2").GetValue() == 456);
REQUIRE(variantObject.GetVariables().Get("MyVariable3").GetValue() == 789);
{
auto *objectInstance =
GetFirstInstanceOf("MyChildObject", variant.GetInitialInstances());
REQUIRE(objectInstance != nullptr);
REQUIRE(objectInstance->GetVariables().Has("MyVariable"));
REQUIRE(objectInstance->GetVariables().Has("MyVariable2") == false);
REQUIRE(objectInstance->GetVariables().Has("MyVariable3") == false);
}
}
SECTION("Can keep variable value") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
auto &object = eventsBasedObject.GetObjects().GetObject("MyChildObject");
// Do the changes and launch the refactoring.
object.GetVariables().Get("MyVariable").SetValue(456);
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
auto &variantObject = variant.GetObjects().GetObject("MyChildObject");
REQUIRE(variantObject.GetVariables().Get("MyVariable").GetValue() == 123);
{
auto *objectInstance =
GetFirstInstanceOf("MyChildObject", variant.GetInitialInstances());
REQUIRE(objectInstance != nullptr);
REQUIRE(objectInstance->GetVariables().Get("MyVariable").GetValue() ==
111);
}
}
SECTION("Must not propagate instance variable value changes") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
{
auto *objectInstance = GetFirstInstanceOf(
"MyChildObject", eventsBasedObject.GetInitialInstances());
REQUIRE(objectInstance != nullptr);
objectInstance->GetVariables().Get("MyVariable").SetValue(222);
}
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
{
auto *objectInstance =
GetFirstInstanceOf("MyChildObject", variant.GetInitialInstances());
REQUIRE(objectInstance != nullptr);
REQUIRE(objectInstance->GetVariables().Get("MyVariable").GetValue() ==
111);
}
}
SECTION("Can move variables") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &object = eventsBasedObject.GetObjects().GetObject("MyChildObject");
object.GetVariables().InsertNew("MyVariable2", 1).SetValue(456);
object.GetVariables().InsertNew("MyVariable3", 2).SetValue(789);
{
auto *objectInstance = GetFirstInstanceOf(
"MyChildObject", eventsBasedObject.GetInitialInstances());
REQUIRE(objectInstance != nullptr);
objectInstance->GetVariables().Get("MyVariable2").SetValue(222);
objectInstance->GetVariables().Get("MyVariable3").SetValue(333);
}
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Do the changes and launch the refactoring.
object.GetVariables().Move(2, 0);
object.GetVariables().Get("MyVariable").SetValue(111);
object.GetVariables().Get("MyVariable2").SetValue(222);
object.GetVariables().Get("MyVariable3").SetValue(333);
REQUIRE(object.GetVariables().GetNameAt(0) == "MyVariable3");
REQUIRE(object.GetVariables().GetNameAt(1) == "MyVariable");
REQUIRE(object.GetVariables().GetNameAt(2) == "MyVariable2");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
auto &variantObject = variant.GetObjects().GetObject("MyChildObject");
REQUIRE(variantObject.GetVariables().Get("MyVariable").GetValue() == 123);
REQUIRE(variantObject.GetVariables().Get("MyVariable2").GetValue() == 456);
REQUIRE(variantObject.GetVariables().Get("MyVariable3").GetValue() == 789);
REQUIRE(variantObject.GetVariables().GetNameAt(0) == "MyVariable3");
REQUIRE(variantObject.GetVariables().GetNameAt(1) == "MyVariable");
REQUIRE(variantObject.GetVariables().GetNameAt(2) == "MyVariable2");
}
SECTION("Can remove variables") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
auto &object = eventsBasedObject.GetObjects().GetObject("MyChildObject");
object.GetVariables().InsertNew("MyVariable2", 1).SetValue(456);
object.GetVariables().InsertNew("MyVariable3", 2).SetValue(789);
{
auto *objectInstance = GetFirstInstanceOf(
"MyChildObject", eventsBasedObject.GetInitialInstances());
REQUIRE(objectInstance != nullptr);
objectInstance->GetVariables().Get("MyVariable2").SetValue(222);
objectInstance->GetVariables().Get("MyVariable3").SetValue(333);
}
// Do the changes and launch the refactoring.
object.GetVariables().Remove("MyVariable2");
object.GetVariables().Remove("MyVariable3");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
auto &variantObject = variant.GetObjects().GetObject("MyChildObject");
REQUIRE(variantObject.GetVariables().Has("MyVariable"));
REQUIRE(variantObject.GetVariables().Has("MyVariable2") == false);
REQUIRE(variantObject.GetVariables().Has("MyVariable3") == false);
{
auto *objectInstance =
GetFirstInstanceOf("MyChildObject", variant.GetInitialInstances());
REQUIRE(objectInstance != nullptr);
REQUIRE(objectInstance->GetVariables().Has("MyVariable"));
REQUIRE(objectInstance->GetVariables().Has("MyVariable2") == false);
REQUIRE(objectInstance->GetVariables().Has("MyVariable3") == false);
}
}
SECTION("Can change variable type") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsBasedObject = SetupEventsBasedObject(project);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
auto &object = eventsBasedObject.GetObjects().GetObject("MyChildObject");
// Do the changes and launch the refactoring.
object.GetVariables().Get("MyVariable").SetString("abc");
gd::EventsBasedObjectVariantHelper::ComplyVariantsToEventsBasedObject(
project, eventsBasedObject);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
auto &variantObject = variant.GetObjects().GetObject("MyChildObject");
REQUIRE(variantObject.GetVariables().Get("MyVariable").GetString() ==
"abc");
REQUIRE(variant.GetInitialInstances().HasInstancesOfObject("MyVariable") ==
false);
}
}

View File

@@ -33,132 +33,7 @@ using namespace gd;
TEST_CASE("ObjectAssetSerializer", "[common]") {
SECTION("Can serialize custom objects as assets with variant") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &eventsBasedObject = eventsExtension.GetEventsBasedObjects().InsertNew(
"MyEventsBasedObject", 0);
eventsBasedObject.SetFullName("My events based object");
eventsBasedObject.SetDescription("An events based object for test");
auto &childObject = eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChild", 0);
auto &childInstance =
eventsBasedObject.GetInitialInstances().InsertNewInitialInstance();
childInstance.SetObjectName("MyChild");
auto &resourceManager = project.GetResourcesManager();
gd::ImageResource imageResource;
imageResource.SetName("assets/Idle.png");
imageResource.SetFile("assets/Idle.png");
imageResource.SetSmooth(true);
resourceManager.AddResource(imageResource);
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
gd::Object &object = layout.GetObjects().InsertNewObject(
project, "MyEventsExtension::MyEventsBasedObject", "MyObject", 0);
auto *spriteConfiguration =
dynamic_cast<gd::SpriteObject *>(&childObject.GetConfiguration());
REQUIRE(spriteConfiguration != nullptr);
{
gd::Animation animation;
animation.SetName("Idle");
animation.SetDirectionsCount(1);
auto &direction = animation.GetDirection(0);
gd::Sprite frame;
frame.SetImageName("assets/Idle.png");
direction.AddSprite(frame);
spriteConfiguration->GetAnimations().AddAnimation(animation);
}
SerializerElement assetElement;
std::vector<gd::String> usedResourceNames;
ObjectAssetSerializer::SerializeTo(project, object, "My Object",
assetElement, usedResourceNames);
// This list is used to copy resource files.
REQUIRE(usedResourceNames.size() == 1);
REQUIRE(usedResourceNames[0] == "assets/Idle.png");
// Check that the project is left untouched.
REQUIRE(resourceManager.HasResource("assets/Idle.png"));
REQUIRE(resourceManager.GetResource("assets/Idle.png").GetFile() ==
"assets/Idle.png");
REQUIRE(!resourceManager.HasResource("Idle.png"));
REQUIRE(assetElement.HasChild("objectAssets"));
auto &objectAssetsElement = assetElement.GetChild("objectAssets");
objectAssetsElement.ConsiderAsArrayOf("objectAsset");
REQUIRE(objectAssetsElement.GetChildrenCount() == 1);
auto &objectAssetElement = objectAssetsElement.GetChild(0);
REQUIRE(objectAssetElement.HasChild("variants"));
auto &variantsElement = objectAssetElement.GetChild("variants");
variantsElement.ConsiderAsArrayOf("variant");
REQUIRE(variantsElement.GetChildrenCount() == 1);
auto &variantPairElement = variantsElement.GetChild(0);
REQUIRE(variantPairElement.GetStringAttribute("objectType") ==
"MyEventsExtension::MyEventsBasedObject");
REQUIRE(variantPairElement.HasChild("variant"));
auto &variantElement = variantPairElement.GetChild("variant");
REQUIRE(variantElement.GetStringAttribute("name") == "");
REQUIRE(variantElement.HasChild("objects"));
auto &objectsElement = variantElement.GetChild("objects");
objectsElement.ConsiderAsArrayOf("object");
REQUIRE(objectsElement.GetChildrenCount() == 1);
auto &childElement = objectsElement.GetChild(0);
REQUIRE(childElement.HasChild("animations"));
auto &animationsElement = childElement.GetChild("animations");
animationsElement.ConsiderAsArrayOf("animation");
REQUIRE(animationsElement.GetChildrenCount() == 1);
auto &animationElement = animationsElement.GetChild(0);
REQUIRE(animationElement.GetStringAttribute("name") == "Idle");
auto &directionsElement = animationElement.GetChild("directions");
directionsElement.ConsiderAsArrayOf("direction");
REQUIRE(directionsElement.GetChildrenCount() == 1);
auto &directionElement = directionsElement.GetChild(0);
auto &spritesElement = directionElement.GetChild("sprites");
spritesElement.ConsiderAsArrayOf("sprite");
REQUIRE(spritesElement.GetChildrenCount() == 1);
auto &spriteElement = spritesElement.GetChild(0);
REQUIRE(spriteElement.GetStringAttribute("image") == "assets/Idle.png");
REQUIRE(objectAssetElement.HasChild("requiredExtensions"));
auto &requiredExtensionsElement =
objectAssetElement.GetChild("requiredExtensions");
requiredExtensionsElement.ConsiderAsArrayOf("requiredExtension");
REQUIRE(requiredExtensionsElement.GetChildrenCount() == 1);
auto &requiredExtensionElement = requiredExtensionsElement.GetChild(0);
REQUIRE(requiredExtensionElement.GetStringAttribute("extensionName") ==
"MyEventsExtension");
// Resources are renamed according to asset script naming conventions.
REQUIRE(objectAssetElement.HasChild("resources"));
auto &resourcesElement = objectAssetElement.GetChild("resources");
resourcesElement.ConsiderAsArrayOf("resource");
REQUIRE(resourcesElement.GetChildrenCount() == 1);
{
auto &resourceElement = resourcesElement.GetChild(0);
REQUIRE(resourceElement.GetStringAttribute("name") == "assets/Idle.png");
REQUIRE(resourceElement.GetStringAttribute("file") == "assets/Idle.png");
REQUIRE(resourceElement.GetStringAttribute("kind") == "image");
REQUIRE(resourceElement.GetBoolAttribute("smoothed") == true);
}
// Resources used in object configuration are updated.
REQUIRE(objectAssetElement.HasChild("object"));
auto &objectElement = objectAssetElement.GetChild("object");
REQUIRE(objectElement.GetStringAttribute("name") == "MyObject");
REQUIRE(objectElement.GetStringAttribute("type") ==
"MyEventsExtension::MyEventsBasedObject");
}
SECTION("Can serialize custom objects as assets with children overriding") {
SECTION("Can serialize custom objects as assets") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
@@ -184,8 +59,6 @@ TEST_CASE("ObjectAssetSerializer", "[common]") {
auto &configuration = object.GetConfiguration();
auto *customObjectConfiguration =
dynamic_cast<gd::CustomObjectConfiguration *>(&configuration);
customObjectConfiguration
->SetMarkedAsOverridingEventsBasedObjectChildrenConfiguration(true);
auto *spriteConfiguration = dynamic_cast<gd::SpriteObject *>(
&customObjectConfiguration->GetChildObjectConfiguration("MyChild"));
REQUIRE(spriteConfiguration != nullptr);

View File

@@ -150,7 +150,7 @@ TEST_CASE("ObjectContainersList (GetTypeOfObject)", "[common]") {
gd::Object &object1 = layout.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyObject1", 0);
gd::Object &object2 = layout.GetObjects().InsertNewObject(
project, "MyExtension::FakeObjectWithDefaultBehavior", "MyObject2", 0);
project, "FakeObjectWithDefaultBehavior", "MyObject2", 0);
auto &group = layout.GetObjects().GetObjectGroups().InsertNew("MyGroup", 0);
group.AddObject(object1.GetName());

View File

@@ -116,11 +116,14 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
REQUIRE(setterEvent.GetConditions().size() == 0);
REQUIRE(setterEvent.GetActions().size() == 1);
auto &setterAction = setterEvent.GetActions().at(0);
REQUIRE(setterAction.GetType() == "SetNumberVariable");
REQUIRE(setterAction.GetParametersCount() == 3);
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "MovementAngle");
REQUIRE(setterAction.GetParameter(1).GetPlainString() == "=");
REQUIRE(setterAction.GetParameter(2).GetPlainString() == "Value");
REQUIRE(
setterAction.GetType() ==
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyMovementAngle");
REQUIRE(setterAction.GetParametersCount() == 4);
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterAction.GetParameter(1).GetPlainString() == "Behavior");
REQUIRE(setterAction.GetParameter(2).GetPlainString() == "=");
REQUIRE(setterAction.GetParameter(3).GetPlainString() == "Value");
}
}
@@ -203,12 +206,12 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
REQUIRE(getterEvent.GetActions().size() == 1);
auto &getterCondition = getterEvent.GetConditions().at(0);
REQUIRE(getterCondition.GetType() == "BooleanVariable");
REQUIRE(getterCondition.GetType() ==
"MyEventsExtension::MyEventsBasedBehavior::PropertyRotate");
REQUIRE(!getterCondition.IsInverted());
REQUIRE(getterCondition.GetParametersCount() == 3);
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Rotate");
REQUIRE(getterCondition.GetParameter(1).GetPlainString() == "True");
REQUIRE(getterCondition.GetParameter(2).GetPlainString() == "");
REQUIRE(getterCondition.GetParametersCount() == 2);
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Object");
REQUIRE(getterCondition.GetParameter(1).GetPlainString() == "Behavior");
auto &getterAction = getterEvent.GetActions().at(0);
REQUIRE(getterAction.GetType() == "SetReturnBoolean");
@@ -254,19 +257,19 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
REQUIRE(setterNoEvent.GetActions().size() == 1);
auto &setterNoCondition = setterNoEvent.GetConditions().at(0);
REQUIRE(setterNoCondition.GetType() == "BooleanVariable");
REQUIRE(!setterNoCondition.IsInverted());
REQUIRE(setterNoCondition.GetParametersCount() == 3);
REQUIRE(setterNoCondition.GetParameter(0).GetPlainString() == "Value");
REQUIRE(setterNoCondition.GetParameter(1).GetPlainString() == "False");
REQUIRE(setterNoCondition.GetParameter(2).GetPlainString() == "");
REQUIRE(setterNoCondition.GetType() == "GetArgumentAsBoolean");
REQUIRE(setterNoCondition.IsInverted());
REQUIRE(setterNoCondition.GetParametersCount() == 1);
REQUIRE(setterNoCondition.GetParameter(0).GetPlainString() ==
"\"Value\"");
auto &setterNoAction = setterNoEvent.GetActions().at(0);
REQUIRE(setterNoAction.GetType() == "SetBooleanVariable");
REQUIRE(setterNoAction.GetType() ==
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyRotate");
REQUIRE(setterNoAction.GetParametersCount() == 3);
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Rotate");
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "False");
REQUIRE(setterNoAction.GetParameter(2).GetPlainString() == "");
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "Behavior");
REQUIRE(setterNoAction.GetParameter(2).GetPlainString() == "no");
auto &setterYesEvent =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(1));
@@ -274,19 +277,19 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
REQUIRE(setterYesEvent.GetActions().size() == 1);
auto &setterYesCondition = setterYesEvent.GetConditions().at(0);
REQUIRE(setterYesCondition.GetType() == "BooleanVariable");
REQUIRE(setterYesCondition.GetType() == "GetArgumentAsBoolean");
REQUIRE(!setterYesCondition.IsInverted());
REQUIRE(setterYesCondition.GetParametersCount() == 3);
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() == "Value");
REQUIRE(setterYesCondition.GetParameter(1).GetPlainString() == "True");
REQUIRE(setterYesCondition.GetParameter(2).GetPlainString() == "");
REQUIRE(setterYesCondition.GetParametersCount() == 1);
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() ==
"\"Value\"");
auto &setterYesAction = setterYesEvent.GetActions().at(0);
REQUIRE(setterYesAction.GetType() == "SetBooleanVariable");
REQUIRE(setterYesAction.GetType() ==
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyRotate");
REQUIRE(setterYesAction.GetParametersCount() == 3);
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Rotate");
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "True");
REQUIRE(setterYesAction.GetParameter(2).GetPlainString() == "");
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "Behavior");
REQUIRE(setterYesAction.GetParameter(2).GetPlainString() == "yes");
}
}
SECTION("Can generate functions for a number property in an object") {
@@ -363,9 +366,11 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
REQUIRE(setterEvent.GetConditions().size() == 0);
REQUIRE(setterEvent.GetActions().size() == 1);
auto &setterAction = setterEvent.GetActions().at(0);
REQUIRE(setterAction.GetType() == "SetNumberVariable");
REQUIRE(
setterAction.GetType() ==
"MyEventsExtension::MyEventsBasedObject::SetPropertyMovementAngle");
REQUIRE(setterAction.GetParametersCount() == 3);
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "MovementAngle");
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterAction.GetParameter(1).GetPlainString() == "=");
REQUIRE(setterAction.GetParameter(2).GetPlainString() == "Value");
}
@@ -449,12 +454,11 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
REQUIRE(getterEvent.GetActions().size() == 1);
auto &getterCondition = getterEvent.GetConditions().at(0);
REQUIRE(getterCondition.GetType() == "BooleanVariable");
REQUIRE(getterCondition.GetType() ==
"MyEventsExtension::MyEventsBasedObject::PropertyRotate");
REQUIRE(!getterCondition.IsInverted());
REQUIRE(getterCondition.GetParametersCount() == 3);
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Rotate");
REQUIRE(getterCondition.GetParameter(1).GetPlainString() == "True");
REQUIRE(getterCondition.GetParameter(2).GetPlainString() == "");
REQUIRE(getterCondition.GetParametersCount() == 1);
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Object");
auto &getterAction = getterEvent.GetActions().at(0);
REQUIRE(getterAction.GetType() == "SetReturnBoolean");
@@ -496,19 +500,18 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
REQUIRE(setterNoEvent.GetActions().size() == 1);
auto &setterNoCondition = setterNoEvent.GetConditions().at(0);
REQUIRE(setterNoCondition.GetType() == "BooleanVariable");
REQUIRE(!setterNoCondition.IsInverted());
REQUIRE(setterNoCondition.GetParametersCount() == 3);
REQUIRE(setterNoCondition.GetParameter(0).GetPlainString() == "Value");
REQUIRE(setterNoCondition.GetParameter(1).GetPlainString() == "False");
REQUIRE(setterNoCondition.GetParameter(2).GetPlainString() == "");
REQUIRE(setterNoCondition.GetType() == "GetArgumentAsBoolean");
REQUIRE(setterNoCondition.IsInverted());
REQUIRE(setterNoCondition.GetParametersCount() == 1);
REQUIRE(setterNoCondition.GetParameter(0).GetPlainString() ==
"\"Value\"");
auto &setterNoAction = setterNoEvent.GetActions().at(0);
REQUIRE(setterNoAction.GetType() == "SetBooleanVariable");
REQUIRE(setterNoAction.GetParametersCount() == 3);
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Rotate");
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "False");
REQUIRE(setterNoAction.GetParameter(2).GetPlainString() == "");
REQUIRE(setterNoAction.GetType() ==
"MyEventsExtension::MyEventsBasedObject::SetPropertyRotate");
REQUIRE(setterNoAction.GetParametersCount() == 2);
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "no");
auto &setterYesEvent =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(1));
@@ -516,19 +519,18 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
REQUIRE(setterYesEvent.GetActions().size() == 1);
auto &setterYesCondition = setterYesEvent.GetConditions().at(0);
REQUIRE(setterYesCondition.GetType() == "BooleanVariable");
REQUIRE(setterYesCondition.GetType() == "GetArgumentAsBoolean");
REQUIRE(!setterYesCondition.IsInverted());
REQUIRE(setterYesCondition.GetParametersCount() == 3);
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() == "Value");
REQUIRE(setterYesCondition.GetParameter(1).GetPlainString() == "True");
REQUIRE(setterYesCondition.GetParameter(2).GetPlainString() == "");
REQUIRE(setterYesCondition.GetParametersCount() == 1);
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() ==
"\"Value\"");
auto &setterYesAction = setterYesEvent.GetActions().at(0);
REQUIRE(setterYesAction.GetType() == "SetBooleanVariable");
REQUIRE(setterYesAction.GetParametersCount() == 3);
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Rotate");
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "True");
REQUIRE(setterYesAction.GetParameter(2).GetPlainString() == "");
REQUIRE(setterYesAction.GetType() ==
"MyEventsExtension::MyEventsBasedObject::SetPropertyRotate");
REQUIRE(setterYesAction.GetParametersCount() == 2);
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "yes");
}
}
@@ -586,11 +588,9 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
REQUIRE(setterEvent.GetConditions().size() == 0);
REQUIRE(setterEvent.GetActions().size() == 1);
auto &setterAction = setterEvent.GetActions().at(0);
REQUIRE(setterAction.GetType() == "SetNumberVariable");
REQUIRE(setterAction.GetParametersCount() == 3);
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "MovementAngle");
REQUIRE(setterAction.GetParameter(1).GetPlainString() == "=");
REQUIRE(setterAction.GetParameter(2).GetPlainString() == "Value");
REQUIRE(setterAction.GetType() ==
"MyEventsExtension::MyEventsBasedBehavior::"
"SetSharedPropertyMovementAngle");
}
}

View File

@@ -19,7 +19,7 @@
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/ObjectVariableHelper.h"
#include "GDCore/IDE/GroupVariableHelper.h"
#include "GDCore/IDE/WholeProjectRefactorer.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
@@ -760,33 +760,33 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
// Check the first layout is updated.
{
REQUIRE(event.GetActions().GetCount() == 40);
REQUIRE(event.GetActions().GetCount() == 19);
// clang-format off
// All the actions using the removed variables are kept.
REQUIRE(event.GetActions()[1].GetParameter(0).GetPlainString() == "1 + MySceneVariable2");
REQUIRE(event.GetActions()[3].GetParameter(0).GetPlainString() == "1 + Object2.MyObjectVariable");
REQUIRE(event.GetActions()[5].GetParameter(0).GetPlainString() == "1 + Object2.MyObjectStructureVariable.MyChild");
REQUIRE(event.GetActions()[7].GetParameter(0).GetPlainString() == "1 + MySceneStructureVariable2.MyChild");
REQUIRE(event.GetActions()[9].GetParameter(0).GetPlainString() == "1 + MyGlobalVariable2");
REQUIRE(event.GetActions()[11].GetParameter(0).GetPlainString() == "1 + MyGlobalStructureVariable2.MyChild");
REQUIRE(event.GetActions()[13].GetParameter(0).GetPlainString() == "1 + MyExtension::GetStringWith2ObjectParamAnd2ObjectVarParam(Object2, MyObjectVariable, Object2, MyObjectVariable)");
REQUIRE(event.GetActions()[15].GetParameter(0).GetPlainString() == "1 + MyExtension::GetStringWith2ObjectParamAnd2ObjectVarParam(Object2, MyObjectStructureVariable.MyChild, Object2, MyObjectStructureVariable.MyChild)");
REQUIRE(event.GetActions()[17].GetParameter(0).GetPlainString() == "1 + Object2.GetObjectVariableAsNumber(MyObjectVariable)");
REQUIRE(event.GetActions()[19].GetParameter(0).GetPlainString() == "1 + Object2.GetObjectVariableAsNumber(MyObjectStructureVariable.MyChild)");
REQUIRE(event.GetActions()[21].GetParameter(0).GetPlainString() == "1 + Object2.GetObjectVariableAsNumber(MyObjectStructureVariable.MyChild.GrandChild)");
REQUIRE(event.GetActions()[23].GetParameter(0).GetPlainString() == "1 + MyExtension::GetGlobalVariableAsNumber(MyGlobalVariable2)");
REQUIRE(event.GetActions()[26].GetParameter(0).GetPlainString() == "1 + MyExtension::GetVariableAsNumber(MySceneVariable2)");
REQUIRE(event.GetActions()[27].GetParameter(0).GetPlainString() == "1 + MyExtension::GetVariableAsNumber(SharedVariableName)");
REQUIRE(event.GetActions()[29].GetParameter(0).GetPlainString() == "1 + MyExtension::GetGlobalVariableAsNumber(MyGlobalStructureVariable2.MyChild)");
REQUIRE(event.GetActions()[31].GetParameter(0).GetPlainString() == "1 + MyExtension::GetVariableAsNumber(MySceneStructureVariable2.MyChild)");
REQUIRE(event.GetActions()[33].GetParameter(0).GetPlainString() == "1 + MyExtension::GetGlobalVariableAsNumber(MyGlobalStructureVariable2.MyChild.GrandChild)");
REQUIRE(event.GetActions()[35].GetParameter(0).GetPlainString() == "1 + MyExtension::GetVariableAsNumber(MySceneStructureVariable2.MyChild.GrandChild)");
// All the actions using the removed variables are gone.
REQUIRE(event.GetActions()[0].GetParameter(0).GetPlainString() == "1 + MySceneVariable2");
REQUIRE(event.GetActions()[1].GetParameter(0).GetPlainString() == "1 + Object2.MyObjectVariable");
REQUIRE(event.GetActions()[2].GetParameter(0).GetPlainString() == "1 + Object2.MyObjectStructureVariable.MyChild");
REQUIRE(event.GetActions()[3].GetParameter(0).GetPlainString() == "1 + MySceneStructureVariable2.MyChild");
REQUIRE(event.GetActions()[4].GetParameter(0).GetPlainString() == "1 + MyGlobalVariable2");
REQUIRE(event.GetActions()[5].GetParameter(0).GetPlainString() == "1 + MyGlobalStructureVariable2.MyChild");
REQUIRE(event.GetActions()[6].GetParameter(0).GetPlainString() == "1 + MyExtension::GetStringWith2ObjectParamAnd2ObjectVarParam(Object2, MyObjectVariable, Object2, MyObjectVariable)");
REQUIRE(event.GetActions()[7].GetParameter(0).GetPlainString() == "1 + MyExtension::GetStringWith2ObjectParamAnd2ObjectVarParam(Object2, MyObjectStructureVariable.MyChild, Object2, MyObjectStructureVariable.MyChild)");
REQUIRE(event.GetActions()[8].GetParameter(0).GetPlainString() == "1 + Object2.GetObjectVariableAsNumber(MyObjectVariable)");
REQUIRE(event.GetActions()[9].GetParameter(0).GetPlainString() == "1 + Object2.GetObjectVariableAsNumber(MyObjectStructureVariable.MyChild)");
REQUIRE(event.GetActions()[10].GetParameter(0).GetPlainString() == "1 + Object2.GetObjectVariableAsNumber(MyObjectStructureVariable.MyChild.GrandChild)");
REQUIRE(event.GetActions()[11].GetParameter(0).GetPlainString() == "1 + MyExtension::GetGlobalVariableAsNumber(MyGlobalVariable2)");
REQUIRE(event.GetActions()[12].GetParameter(0).GetPlainString() == "1 + MyExtension::GetVariableAsNumber(MySceneVariable2)");
REQUIRE(event.GetActions()[13].GetParameter(0).GetPlainString() == "1 + MyExtension::GetVariableAsNumber(SharedVariableName)");
REQUIRE(event.GetActions()[14].GetParameter(0).GetPlainString() == "1 + MyExtension::GetGlobalVariableAsNumber(MyGlobalStructureVariable2.MyChild)");
REQUIRE(event.GetActions()[15].GetParameter(0).GetPlainString() == "1 + MyExtension::GetVariableAsNumber(MySceneStructureVariable2.MyChild)");
REQUIRE(event.GetActions()[16].GetParameter(0).GetPlainString() == "1 + MyExtension::GetGlobalVariableAsNumber(MyGlobalStructureVariable2.MyChild.GrandChild)");
REQUIRE(event.GetActions()[17].GetParameter(0).GetPlainString() == "1 + MyExtension::GetVariableAsNumber(MySceneStructureVariable2.MyChild.GrandChild)");
REQUIRE(event.GetActions()[39].GetParameter(0).GetPlainString() == "MySceneVariable2");
REQUIRE(event.GetActions()[39].GetParameter(1).GetPlainString() == "MyGlobalVariable2");
REQUIRE(event.GetActions()[39].GetParameter(2).GetPlainString() == "Object2");
REQUIRE(event.GetActions()[39].GetParameter(3).GetPlainString() == "MyObjectVariable");
REQUIRE(event.GetActions()[18].GetParameter(0).GetPlainString() == "MySceneVariable2");
REQUIRE(event.GetActions()[18].GetParameter(1).GetPlainString() == "MyGlobalVariable2");
REQUIRE(event.GetActions()[18].GetParameter(2).GetPlainString() == "Object2");
REQUIRE(event.GetActions()[18].GetParameter(3).GetPlainString() == "MyObjectVariable");
// clang-format on
}
@@ -1021,233 +1021,6 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
"MyVariable.MyRenamedChild");
}
SECTION("Can rename an object variable") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &scene = project.InsertNewLayout("Scene", 0);
auto &object = scene.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "Object", 0);
object.GetVariables().InsertNew("MyVariable").SetValue(123);
auto &instance = scene.GetInitialInstances().InsertNewInitialInstance();
instance.SetObjectName("Object");
instance.GetVariables().InsertNew("MyVariable").SetValue(456);
gd::StandardEvent &event =
dynamic_cast<gd::StandardEvent &>(scene.GetEvents().InsertNewEvent(
project, "BuiltinCommonInstructions::Standard"));
{
gd::Instruction action;
action.SetType("SetNumberObjectVariable");
action.SetParametersCount(4);
action.SetParameter(0, gd::Expression("Object"));
action.SetParameter(1, gd::Expression("MyVariable"));
action.SetParameter(2, gd::Expression("="));
action.SetParameter(3, gd::Expression("Object.MyVariable"));
event.GetActions().Insert(action);
}
// Do the changes and launch the refactoring.
object.GetVariables().ResetPersistentUuid();
gd::SerializerElement originalSerializedVariables;
object.GetVariables().SerializeTo(originalSerializedVariables);
object.GetVariables().Rename("MyVariable", "MyRenamedVariable");
auto changeset =
gd::WholeProjectRefactorer::ComputeChangesetForVariablesContainer(
originalSerializedVariables, object.GetVariables());
REQUIRE(changeset.oldToNewVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
project, object.GetVariables(), scene.GetInitialInstances(),
object.GetName(), changeset, originalSerializedVariables);
REQUIRE(event.GetActions()[0].GetParameter(1).GetPlainString() ==
"MyRenamedVariable");
REQUIRE(event.GetActions()[0].GetParameter(3).GetPlainString() ==
"Object.MyRenamedVariable");
REQUIRE(instance.GetVariables().Get("MyRenamedVariable").GetValue() == 456);
}
SECTION("Can rename an object variable (in events-based object)") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &eventsBasedObject = eventsExtension.GetEventsBasedObjects().InsertNew(
"MyEventsBasedObject", 0);
auto &object = eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "MyChildObject", 0);
object.GetVariables().InsertNew("MyVariable").SetValue(123);
auto &instance =
eventsBasedObject.GetInitialInstances().InsertNewInitialInstance();
instance.SetObjectName("MyChildObject");
instance.GetVariables().InsertNew("MyVariable").SetValue(456);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
gd::InitialInstance *variantInstance = nullptr;
variant.GetInitialInstances().IterateOverInstances(
[&variantInstance](gd::InitialInstance &instance) {
variantInstance = &instance;
return true;
});
REQUIRE(variantInstance != nullptr);
variant.GetObjects()
.GetObject("MyChildObject")
.GetVariables()
.Get("MyVariable")
.SetValue(111);
variantInstance->GetVariables().Get("MyVariable").SetValue(222);
auto &objectFunction =
eventsBasedObject.GetEventsFunctions().InsertNewEventsFunction(
"MyObjectEventsFunction", 0);
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
objectFunction.GetEvents().InsertNewEvent(
project, "BuiltinCommonInstructions::Standard"));
{
gd::Instruction action;
action.SetType("SetNumberObjectVariable");
action.SetParametersCount(4);
action.SetParameter(0, gd::Expression("MyChildObject"));
action.SetParameter(1, gd::Expression("MyVariable"));
action.SetParameter(2, gd::Expression("="));
action.SetParameter(3, gd::Expression("MyChildObject.MyVariable"));
event.GetActions().Insert(action);
}
// Do the changes and launch the refactoring.
object.GetVariables().ResetPersistentUuid();
gd::SerializerElement originalSerializedVariables;
object.GetVariables().SerializeTo(originalSerializedVariables);
object.GetVariables().Rename("MyVariable", "MyRenamedVariable");
auto changeset =
gd::WholeProjectRefactorer::ComputeChangesetForVariablesContainer(
originalSerializedVariables, object.GetVariables());
REQUIRE(changeset.oldToNewVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
project, object.GetVariables(), eventsBasedObject.GetInitialInstances(),
object.GetName(), changeset, originalSerializedVariables);
gd::ObjectVariableHelper::ApplyChangesToVariants(
eventsBasedObject, "MyChildObject", changeset);
REQUIRE(event.GetActions()[0].GetParameter(1).GetPlainString() ==
"MyRenamedVariable");
REQUIRE(event.GetActions()[0].GetParameter(3).GetPlainString() ==
"MyChildObject.MyRenamedVariable");
REQUIRE(eventsBasedObject.GetObjects().HasObjectNamed("MyChildObject"));
REQUIRE(eventsBasedObject.GetObjects()
.GetObject("MyChildObject")
.GetVariables()
.Get("MyRenamedVariable")
.GetValue() == 123);
REQUIRE(instance.GetVariables().Get("MyRenamedVariable").GetValue() == 456);
REQUIRE(variant.GetObjects().HasObjectNamed("MyChildObject"));
REQUIRE(variant.GetObjects()
.GetObject("MyChildObject")
.GetVariables()
.Get("MyRenamedVariable")
.GetValue() == 111);
REQUIRE(
variantInstance->GetVariables().Get("MyRenamedVariable").GetValue() ==
222);
}
SECTION("Can delete an object variable") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &scene = project.InsertNewLayout("Scene", 0);
auto &object = scene.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "Object", 0);
object.GetVariables().InsertNew("MyVariable").SetValue(123);
auto &instance = scene.GetInitialInstances().InsertNewInitialInstance();
instance.SetObjectName("Object");
instance.GetVariables().InsertNew("MyVariable").SetValue(456);
gd::StandardEvent &event =
dynamic_cast<gd::StandardEvent &>(scene.GetEvents().InsertNewEvent(
project, "BuiltinCommonInstructions::Standard"));
{
gd::Instruction action;
action.SetType("SetNumberObjectVariable");
action.SetParametersCount(4);
action.SetParameter(0, gd::Expression("Object"));
action.SetParameter(1, gd::Expression("MyVariable"));
action.SetParameter(2, gd::Expression("="));
action.SetParameter(3, gd::Expression("Object.MyVariable"));
event.GetActions().Insert(action);
}
// Do the changes and launch the refactoring.
object.GetVariables().ResetPersistentUuid();
gd::SerializerElement originalSerializedVariables;
object.GetVariables().SerializeTo(originalSerializedVariables);
object.GetVariables().Remove("MyVariable");
auto changeset =
gd::WholeProjectRefactorer::ComputeChangesetForVariablesContainer(
originalSerializedVariables, object.GetVariables());
REQUIRE(changeset.removedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
project, object.GetVariables(), scene.GetInitialInstances(),
object.GetName(), changeset, originalSerializedVariables);
// Events are untouched
REQUIRE(scene.GetEvents().size() == 1);
REQUIRE(event.GetActions().size() == 1);
REQUIRE(event.GetActions()[0].GetParameter(1).GetPlainString() ==
"MyVariable");
REQUIRE(event.GetActions()[0].GetParameter(3).GetPlainString() ==
"Object.MyVariable");
// Instance variables are removed
REQUIRE(!instance.GetVariables().Has("MyVariable"));
}
SECTION("Can add an object variable") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &scene = project.InsertNewLayout("Scene", 0);
auto &object = scene.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "Object", 0);
auto &instance = scene.GetInitialInstances().InsertNewInitialInstance();
instance.SetObjectName("Object");
// Do the changes and launch the refactoring.
object.GetVariables().ResetPersistentUuid();
gd::SerializerElement originalSerializedVariables;
object.GetVariables().SerializeTo(originalSerializedVariables);
object.GetVariables().InsertNew("MyVariable").SetValue(123);
auto changeset =
gd::WholeProjectRefactorer::ComputeChangesetForVariablesContainer(
originalSerializedVariables, object.GetVariables());
REQUIRE(changeset.addedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
project, object.GetVariables(), changeset, originalSerializedVariables);
// Instance variables are NOT added
REQUIRE(!instance.GetVariables().Has("MyVariable"));
}
SECTION("Can rename an object child variable") {
gd::Project project;
gd::Platform platform;
@@ -1289,9 +1062,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.modifiedVariables.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
project, object.GetVariables(), scene.GetInitialInstances(),
object.GetName(), changeset, originalSerializedVariables);
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
project, object.GetVariables(), changeset, originalSerializedVariables);
REQUIRE(event.GetActions()[0].GetParameter(1).GetPlainString() ==
"MyVariable.MyRenamedChild");
@@ -1340,9 +1112,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.modifiedVariables.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
project, object.GetVariables(), scene.GetInitialInstances(),
object.GetName(), changeset, originalSerializedVariables);
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
project, object.GetVariables(), changeset, originalSerializedVariables);
REQUIRE(event.GetActions()[0].GetParameter(3).GetPlainString() ==
"MyVariable.MyRenamedChild");
@@ -1390,9 +1161,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.modifiedVariables.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
project, object.GetVariables(), scene.GetInitialInstances(),
object.GetName(), changeset, originalSerializedVariables);
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
project, object.GetVariables(), changeset, originalSerializedVariables);
REQUIRE(event.GetActions()[0].GetParameter(3).GetPlainString() ==
"MyVariable.MyChild.MyRenamedGrandChild");
@@ -2126,9 +1896,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.typeChangedVariableNames.find("MyObjectVariable") !=
changeset.typeChangedVariableNames.end());
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
project, object.GetVariables(), scene.GetInitialInstances(),
object.GetName(), changeset, originalSerializedVariables);
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
project, object.GetVariables(), changeset, originalSerializedVariables);
// Check the the action has changed to follow the variable type.
REQUIRE(event.GetActions()[0].GetType() == "SetStringObjectVariable");
@@ -2178,9 +1947,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.typeChangedVariableNames.find("MyObjectVariable") !=
changeset.typeChangedVariableNames.end());
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
project, object.GetVariables(), scene.GetInitialInstances(),
object.GetName(), changeset, originalSerializedVariables);
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
project, object.GetVariables(), changeset, originalSerializedVariables);
// Check the the action has changed to follow the variable type.
REQUIRE(event.GetActions()[0].GetType() == "SetStringObjectVariable");
@@ -2209,7 +1977,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Count() == 1);
@@ -2241,7 +2009,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Count() == 1);
@@ -2261,7 +2029,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Count() == 0);
@@ -2282,7 +2050,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Count() == 0);
@@ -2307,7 +2075,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -2326,9 +2094,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 456);
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
@@ -2354,7 +2121,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -2373,9 +2140,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 456);
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
@@ -2401,7 +2167,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -2422,9 +2188,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 111);
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
@@ -2450,7 +2215,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -2471,9 +2236,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 0);
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
@@ -2499,7 +2263,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -2518,9 +2282,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.valueChangedVariableNames.size() == 0);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 111);
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
@@ -2555,7 +2318,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Count() == 1);
@@ -2573,9 +2336,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
originalSerializedVariables, groupVariables);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(newObject.GetVariables().Count() == 2);
REQUIRE(newObject.GetVariables().Get("MyGroupVariable").GetValue() == 123);
@@ -2607,7 +2369,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -2628,9 +2390,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables()
.Get("MyGroupVariable")
@@ -2667,7 +2428,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -2687,9 +2448,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables()
.Get("MyGroupVariable")
@@ -2726,7 +2486,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -2746,9 +2506,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables()
.Get("MyGroupVariable")
@@ -2799,7 +2558,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -2820,9 +2579,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables()
.Get("MyGroupVariable")
@@ -2855,14 +2613,11 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto &group = scene.GetObjects().GetObjectGroups().InsertNew("Group");
group.AddObject("Object");
group.AddObject("OtherObject");
auto &instance = scene.GetInitialInstances().InsertNewInitialInstance();
instance.SetObjectName("Object");
instance.GetVariables().InsertNew("MyGroupVariable").SetValue(456);
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -2880,13 +2635,11 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.removedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(!object.GetVariables().Has("MyGroupVariable"));
REQUIRE(!otherObject.GetVariables().Has("MyGroupVariable"));
REQUIRE(!instance.GetVariables().Has("MyGroupVariable"));
}
SECTION("Can add a group variable") {
@@ -2906,7 +2659,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Count() == 0);
@@ -2924,9 +2677,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.addedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 456);
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
@@ -2952,7 +2704,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Count() == 0);
@@ -2970,9 +2722,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.addedVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
// The variable kept its original value.
REQUIRE(object.GetVariables().Count() == 1);
@@ -2998,9 +2749,6 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto &group = scene.GetObjects().GetObjectGroups().InsertNew("Group");
group.AddObject("Object");
group.AddObject("OtherObject");
auto &instance = scene.GetInitialInstances().InsertNewInitialInstance();
instance.SetObjectName("Object");
instance.GetVariables().InsertNew("MyGroupVariable").SetValue(456);
gd::StandardEvent &event =
dynamic_cast<gd::StandardEvent &>(scene.GetEvents().InsertNewEvent(
@@ -3039,7 +2787,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -3058,9 +2806,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.oldToNewVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(object.GetVariables().Count() == 1);
REQUIRE(object.GetVariables().Get("MyRenamedGroupVariable").GetValue() == 123);
@@ -3083,7 +2830,6 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
"MyRenamedGroupVariable");
REQUIRE(event.GetActions()[2].GetParameter(3).GetPlainString() ==
"OtherObject.MyRenamedGroupVariable");
REQUIRE(instance.GetVariables().Get("MyRenamedGroupVariable").GetValue() == 456);
}
SECTION("Can rename a group variable when one of the object already has it") {
@@ -3141,7 +2887,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -3160,9 +2906,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.oldToNewVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
// The variable kept its original value.
REQUIRE(object.GetVariables().Count() == 1);
@@ -3247,7 +2992,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -3271,9 +3016,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.modifiedVariables.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(event.GetActions()[0].GetParameter(1).GetPlainString() ==
"MyGroupVariable.MyRenamedChild");
@@ -3323,7 +3067,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
auto projectScopedContainers = gd::ProjectScopedContainers::
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
gd::VariablesContainer groupVariables =
gd::ObjectVariableHelper::MergeVariableContainers(
gd::GroupVariableHelper::MergeVariableContainers(
projectScopedContainers.GetObjectsContainersList(), group);
REQUIRE(groupVariables.Has("MyGroupVariable"));
@@ -3342,9 +3086,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
REQUIRE(changeset.oldToNewVariableNames.size() == 1);
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
project, project.GetObjects(), scene.GetObjects(),
scene.GetInitialInstances(), groupVariables, group, changeset,
originalSerializedVariables);
project, project.GetObjects(), scene.GetObjects(), groupVariables,
group, changeset, originalSerializedVariables);
REQUIRE(event.GetActions()[0].GetParameter(1).GetPlainString() ==
"MyGroupVariable");

View File

@@ -1754,9 +1754,6 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
eventsBasedObject.GetObjects().InsertNewObject(
project, "MyExtension::Sprite", "Object2", 0);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Create the objects container for the events function
gd::ObjectsContainer parametersObjectsContainer(
gd::ObjectsContainer::SourceType::Function);
@@ -1768,10 +1765,6 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject(
project, projectScopedContainers, eventsBasedObject, "Object1",
"Object3", /* isObjectGroup =*/false);
REQUIRE(variant.GetObjects().HasObjectNamed("Object1") == false);
REQUIRE(variant.GetObjects().HasObjectNamed("Object2") == true);
REQUIRE(variant.GetObjects().HasObjectNamed("Object3") == true);
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups().size() == 1);
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups()[0].Find(
"Object1") == false);
@@ -1779,17 +1772,6 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
"Object2") == true);
REQUIRE(eventsBasedObject.GetObjects().GetObjectGroups()[0].Find(
"Object3") == true);
REQUIRE(variant.GetObjects().HasObjectNamed("Object1") == false);
REQUIRE(variant.GetObjects().HasObjectNamed("Object2") == true);
REQUIRE(variant.GetObjects().HasObjectNamed("Object3") == true);
REQUIRE(variant.GetObjects().GetObjectGroups().size() == 1);
REQUIRE(variant.GetObjects().GetObjectGroups()[0].Find("Object1") ==
false);
REQUIRE(variant.GetObjects().GetObjectGroups()[0].Find("Object2") ==
true);
REQUIRE(variant.GetObjects().GetObjectGroups()[0].Find("Object3") ==
true);
}
SECTION("Initial instances") {
@@ -1814,9 +1796,6 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
eventsBasedObject.GetInitialInstances().InsertInitialInstance(instance1);
eventsBasedObject.GetInitialInstances().InsertInitialInstance(instance2);
auto &variant = eventsBasedObject.GetVariants().InsertVariant(
eventsBasedObject.GetDefaultVariant(), 0);
// Create the objects container for the events function
gd::ObjectsContainer parametersObjectsContainer(
gd::ObjectsContainer::SourceType::Function);
@@ -1828,16 +1807,10 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject(
project, projectScopedContainers, eventsBasedObject, "Object1",
"Object3", /* isObjectGroup =*/false);
REQUIRE(eventsBasedObject.GetInitialInstances().HasInstancesOfObject(
"Object1") == false);
REQUIRE(eventsBasedObject.GetInitialInstances().HasInstancesOfObject(
"Object3") == true);
REQUIRE(variant.GetInitialInstances().HasInstancesOfObject("Object1") ==
false);
REQUIRE(variant.GetInitialInstances().HasInstancesOfObject("Object3") ==
true);
}
SECTION("Events") {

View File

@@ -1,4 +1,15 @@
namespace gdjs {
export interface Object3DDataContent {
width: float;
height: float;
depth: float;
}
/** Base parameters for {@link gdjs.RuntimeObject3D} */
export interface Object3DData extends ObjectData {
/** The base parameters of the RuntimeObject3D */
content: Object3DDataContent;
}
const getValidDimensionValue = (value: float | undefined) =>
value === undefined ? 100 : value <= 0 ? 1 : value;
@@ -24,8 +35,11 @@ namespace gdjs {
*/
export abstract class RuntimeObject3D
extends gdjs.RuntimeObject
implements gdjs.Resizable, gdjs.Scalable, gdjs.Flippable, gdjs.Base3DHandler
{
implements
gdjs.Resizable,
gdjs.Scalable,
gdjs.Flippable,
gdjs.Base3DHandler {
/**
* Position on the Z axis.
*/
@@ -70,7 +84,7 @@ namespace gdjs {
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
objectData: gdjs.Object3DData
objectData: Object3DData
) {
super(instanceContainer, objectData);
// TODO Should 0 be replaced by 0.01 instead of using the default value?

View File

@@ -117,17 +117,6 @@ namespace gdjs {
getUnrotatedAABBMaxZ(): number;
}
export interface Object3DDataContent {
width: float;
height: float;
depth: float;
}
/** Base parameters for {@link gdjs.RuntimeObject3D} */
export interface Object3DData extends ObjectData {
/** The base parameters of the RuntimeObject3D */
content: Object3DDataContent;
}
export namespace Base3DHandler {
export const is3D = (
object: gdjs.RuntimeObject
@@ -142,8 +131,7 @@ namespace gdjs {
*/
export class Base3DBehavior
extends gdjs.RuntimeBehavior
implements Base3DHandler
{
implements Base3DHandler {
private object: gdjs.RuntimeObject & Base3DHandler;
constructor(

View File

@@ -3,31 +3,31 @@ namespace gdjs {
export interface Cube3DObjectData extends Object3DData {
/** The base parameters of the Cube3D object */
content: Object3DDataContent & {
enableTextureTransparency: boolean | undefined;
facesOrientation: 'Y' | 'Z' | undefined;
enableTextureTransparency: boolean;
facesOrientation: 'Y' | 'Z';
frontFaceResourceName: string;
backFaceResourceName: string;
backFaceUpThroughWhichAxisRotation: 'X' | 'Y' | undefined;
backFaceUpThroughWhichAxisRotation: 'X' | 'Y';
leftFaceResourceName: string;
rightFaceResourceName: string;
topFaceResourceName: string;
bottomFaceResourceName: string;
frontFaceResourceRepeat: boolean | undefined;
backFaceResourceRepeat: boolean | undefined;
leftFaceResourceRepeat: boolean | undefined;
rightFaceResourceRepeat: boolean | undefined;
topFaceResourceRepeat: boolean | undefined;
bottomFaceResourceRepeat: boolean | undefined;
frontFaceResourceRepeat: boolean;
backFaceResourceRepeat: boolean;
leftFaceResourceRepeat: boolean;
rightFaceResourceRepeat: boolean;
topFaceResourceRepeat: boolean;
bottomFaceResourceRepeat: boolean;
frontFaceVisible: boolean;
backFaceVisible: boolean;
leftFaceVisible: boolean;
rightFaceVisible: boolean;
topFaceVisible: boolean;
bottomFaceVisible: boolean;
tint: string | undefined;
materialType: 'Basic' | 'StandardWithoutMetalness';
};
}
type FaceName = 'front' | 'back' | 'left' | 'right' | 'top' | 'bottom';
const faceNameToBitmaskIndex = {
front: 0,
@@ -45,7 +45,6 @@ namespace gdjs {
trfb: integer;
frn: [string, string, string, string, string, string];
mt: number;
tint: string;
};
type Cube3DObjectNetworkSyncData = Object3DNetworkSyncData &
@@ -68,11 +67,10 @@ namespace gdjs {
string,
string,
string,
string,
string
];
_materialType: gdjs.Cube3DRuntimeObject.MaterialType =
gdjs.Cube3DRuntimeObject.MaterialType.Basic;
_tint: string;
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
@@ -119,9 +117,6 @@ namespace gdjs {
objectData.content.topFaceResourceName,
objectData.content.bottomFaceResourceName,
];
this._tint = objectData.content.tint || '255;255;255';
this._materialType = this._convertMaterialType(
objectData.content.materialType
);
@@ -139,7 +134,7 @@ namespace gdjs {
* Sets the visibility of a face of the 3D box.
*
* @param faceName - The name of the face to set visibility for.
* @param enable - The visibility value to set.
* @param value - The visibility value to set.
*/
setFaceVisibility(faceName: FaceName, enable: boolean) {
const faceIndex = faceNameToBitmaskIndex[faceName];
@@ -162,7 +157,7 @@ namespace gdjs {
* Sets the texture repeat of a face of the 3D box.
*
* @param faceName - The name of the face to set visibility for.
* @param enable - The visibility value to set.
* @param value - The visibility value to set.
*/
setRepeatTextureOnFace(faceName: FaceName, enable: boolean) {
const faceIndex = faceNameToBitmaskIndex[faceName];
@@ -208,22 +203,11 @@ namespace gdjs {
if (this._faceResourceNames[faceIndex] === resourceName) {
return;
}
this._faceResourceNames[faceIndex] = resourceName;
this._renderer.updateFace(faceIndex);
}
setColor(tint: string): void {
if (this._tint === tint) {
return;
}
this._tint = tint;
this._renderer.updateTint();
}
getColor(): string {
return this._tint;
}
/** @internal */
getFaceAtIndexResourceName(faceIndex: integer): string {
return this._faceResourceNames[faceIndex];
@@ -307,10 +291,6 @@ namespace gdjs {
newObjectData.content.frontFaceResourceName
);
}
if (oldObjectData.content.tint !== newObjectData.content.tint) {
this.setColor(newObjectData.content.tint || '255;255;255');
}
if (
oldObjectData.content.backFaceResourceName !==
newObjectData.content.backFaceResourceName
@@ -362,7 +342,7 @@ namespace gdjs {
) {
this.setRepeatTextureOnFace(
'front',
newObjectData.content.frontFaceResourceRepeat || false
newObjectData.content.frontFaceResourceRepeat
);
}
if (
@@ -371,7 +351,7 @@ namespace gdjs {
) {
this.setRepeatTextureOnFace(
'back',
newObjectData.content.backFaceResourceRepeat || false
newObjectData.content.backFaceResourceRepeat
);
}
if (
@@ -380,7 +360,7 @@ namespace gdjs {
) {
this.setRepeatTextureOnFace(
'left',
newObjectData.content.leftFaceResourceRepeat || false
newObjectData.content.leftFaceResourceRepeat
);
}
if (
@@ -389,7 +369,7 @@ namespace gdjs {
) {
this.setRepeatTextureOnFace(
'right',
newObjectData.content.rightFaceResourceRepeat || false
newObjectData.content.rightFaceResourceRepeat
);
}
if (
@@ -398,7 +378,7 @@ namespace gdjs {
) {
this.setRepeatTextureOnFace(
'top',
newObjectData.content.topFaceResourceRepeat || false
newObjectData.content.topFaceResourceRepeat
);
}
if (
@@ -407,7 +387,7 @@ namespace gdjs {
) {
this.setRepeatTextureOnFace(
'bottom',
newObjectData.content.bottomFaceResourceRepeat || false
newObjectData.content.bottomFaceResourceRepeat
);
}
if (
@@ -415,14 +395,14 @@ namespace gdjs {
newObjectData.content.backFaceUpThroughWhichAxisRotation
) {
this.setBackFaceUpThroughWhichAxisRotation(
newObjectData.content.backFaceUpThroughWhichAxisRotation || 'X'
newObjectData.content.backFaceUpThroughWhichAxisRotation
);
}
if (
oldObjectData.content.facesOrientation !==
newObjectData.content.facesOrientation
) {
this.setFacesOrientation(newObjectData.content.facesOrientation || 'Y');
this.setFacesOrientation(newObjectData.content.facesOrientation);
}
if (
oldObjectData.content.materialType !==
@@ -443,7 +423,6 @@ namespace gdjs {
vfb: this._visibleFacesBitmask,
trfb: this._textureRepeatFacesBitmask,
frn: this._faceResourceNames,
tint: this._tint,
};
}
@@ -497,12 +476,6 @@ namespace gdjs {
}
}
}
if (networkSyncData.tint !== undefined) {
if (this._tint !== networkSyncData.tint) {
this._tint = networkSyncData.tint;
this._renderer.updateTint();
}
}
}
/**

View File

@@ -62,7 +62,6 @@ namespace gdjs {
forceBasicMaterial:
runtimeObject._materialType ===
gdjs.Cube3DRuntimeObject.MaterialType.Basic,
vertexColors: true,
});
};
@@ -75,13 +74,15 @@ namespace gdjs {
instanceContainer: gdjs.RuntimeInstanceContainer
) {
const geometry = new THREE.BoxGeometry(1, 1, 1);
const materials: THREE.Material[] = new Array(6)
.fill(0)
.map((_, index) =>
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[index])
);
// TODO (3D) - feature: support color instead of texture?
const materials = [
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[0]),
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[1]),
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[2]),
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[3]),
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[4]),
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[5]),
];
const boxMesh = new THREE.Mesh(geometry, materials);
super(runtimeObject, instanceContainer, boxMesh);
@@ -91,28 +92,6 @@ namespace gdjs {
this.updateSize();
this.updatePosition();
this.updateRotation();
this.updateTint();
}
updateTint() {
const tints: number[] = [];
const normalizedTint = gdjs
.rgbOrHexToRGBColor(this._cube3DRuntimeObject.getColor())
.map((component) => component / 255);
for (
let i = 0;
i < this._boxMesh.geometry.attributes.position.count;
i++
) {
tints.push(...normalizedTint);
}
this._boxMesh.geometry.setAttribute(
'color',
new THREE.BufferAttribute(new Float32Array(tints), 3)
);
}
updateFace(faceIndex: integer) {
@@ -142,11 +121,13 @@ namespace gdjs {
*/
updateTextureUvMapping(faceIndex?: number) {
// @ts-ignore - position is stored as a Float32BufferAttribute
const pos: THREE.BufferAttribute =
this._boxMesh.geometry.getAttribute('position');
const pos: THREE.BufferAttribute = this._boxMesh.geometry.getAttribute(
'position'
);
// @ts-ignore - uv is stored as a Float32BufferAttribute
const uvMapping: THREE.BufferAttribute =
this._boxMesh.geometry.getAttribute('uv');
const uvMapping: THREE.BufferAttribute = this._boxMesh.geometry.getAttribute(
'uv'
);
const startIndex =
faceIndex === undefined ? 0 : faceIndexToMaterialIndex[faceIndex] * 4;
const endIndex =
@@ -168,10 +149,9 @@ namespace gdjs {
continue;
}
const shouldRepeatTexture =
this._cube3DRuntimeObject.shouldRepeatTextureOnFaceAtIndex(
materialIndexToFaceIndex[materialIndex]
);
const shouldRepeatTexture = this._cube3DRuntimeObject.shouldRepeatTextureOnFaceAtIndex(
materialIndexToFaceIndex[materialIndex]
);
const shouldOrientateFacesTowardsY =
this._cube3DRuntimeObject.getFacesOrientation() === 'Y';
@@ -200,10 +180,12 @@ namespace gdjs {
if (shouldOrientateFacesTowardsY) {
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
} else {
[x, y] =
noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
vertexIndex % 4
];
[
x,
y,
] = noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
vertexIndex % 4
];
}
}
break;
@@ -229,10 +211,12 @@ namespace gdjs {
if (shouldOrientateFacesTowardsY) {
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
} else {
[x, y] =
noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
vertexIndex % 4
];
[
x,
y,
] = noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
vertexIndex % 4
];
x = -x;
y = -y;
}

View File

@@ -1,11 +1,21 @@
namespace gdjs {
export interface Object3DDataContent {
width: float;
height: float;
depth: float;
}
/** Base parameters for {@link gdjs.RuntimeObject3D} */
export interface Object3DData extends ObjectData {
/** The base parameters of the RuntimeObject3D */
content: Object3DDataContent;
}
/**
* Base class for 3D custom objects.
*/
export class CustomRuntimeObject3D
extends gdjs.CustomRuntimeObject
implements gdjs.Base3DHandler
{
implements gdjs.Base3DHandler {
/**
* Position on the Z axis.
*/
@@ -31,12 +41,13 @@ namespace gdjs {
constructor(
parent: gdjs.RuntimeInstanceContainer,
objectData: gdjs.Object3DData & gdjs.CustomObjectConfiguration
objectData: Object3DData & CustomObjectConfiguration
) {
super(parent, objectData);
this._renderer.reinitialize(this, parent);
}
protected override _createRender() {
protected _createRender() {
const parent = this._runtimeScene;
return new gdjs.CustomRuntimeObject3DRenderer(
this,
@@ -45,23 +56,21 @@ namespace gdjs {
);
}
protected override _reinitializeRenderer(): void {
protected _reinitializeRenderer(): void {
this.getRenderer().reinitialize(this, this.getParent());
}
override getRenderer(): gdjs.CustomRuntimeObject3DRenderer {
getRenderer(): gdjs.CustomRuntimeObject3DRenderer {
return super.getRenderer() as gdjs.CustomRuntimeObject3DRenderer;
}
override get3DRendererObject() {
get3DRendererObject() {
// It can't be null because Three.js is always loaded
// when a custom 3D object is used.
return this.getRenderer().get3DRendererObject()!;
}
override extraInitializationFromInitialInstance(
initialInstanceData: InstanceData
) {
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
super.extraInitializationFromInitialInstance(initialInstanceData);
if (initialInstanceData.depth !== undefined) {
this.setDepth(initialInstanceData.depth);
@@ -283,7 +292,7 @@ namespace gdjs {
return this._maxZ - this._minZ;
}
override _updateUntransformedHitBoxes(): void {
_updateUntransformedHitBoxes(): void {
super._updateUntransformedHitBoxes();
let minZ = Number.MAX_VALUE;

View File

@@ -6,8 +6,7 @@ namespace gdjs {
* The renderer for a {@link gdjs.CustomRuntimeObject3D} using Three.js.
*/
export class CustomRuntimeObject3DRenderer
implements gdjs.RuntimeInstanceContainerRenderer
{
implements gdjs.RuntimeInstanceContainerRenderer {
_object: gdjs.CustomRuntimeObject3D;
_instanceContainer: gdjs.CustomRuntimeObjectInstanceContainer;
_isContainerDirty: boolean = true;
@@ -44,7 +43,10 @@ namespace gdjs {
) {
this._object = object;
this._isContainerDirty = true;
this._threeGroup.clear();
const layer = parent.getLayer('');
if (layer) {
layer.getRenderer().add3DRendererObject(this._threeGroup);
}
}
_updateThreeGroup() {
@@ -137,16 +139,16 @@ namespace gdjs {
imageManager: gdjs.PixiImageManager
): ThreeAnimationFrameTextureManager {
if (!imageManager._threeAnimationFrameTextureManager) {
imageManager._threeAnimationFrameTextureManager =
new ThreeAnimationFrameTextureManager(imageManager);
imageManager._threeAnimationFrameTextureManager = new ThreeAnimationFrameTextureManager(
imageManager
);
}
return imageManager._threeAnimationFrameTextureManager;
}
}
class ThreeAnimationFrameTextureManager
implements gdjs.AnimationFrameTextureManager<THREE.Material>
{
implements gdjs.AnimationFrameTextureManager<THREE.Material> {
private _imageManager: gdjs.PixiImageManager;
constructor(imageManager: gdjs.PixiImageManager) {
@@ -157,21 +159,20 @@ namespace gdjs {
return this._imageManager.getThreeMaterial(imageName, {
useTransparentTexture: true,
forceBasicMaterial: true,
vertexColors: false,
});
}
getAnimationFrameWidth(material: THREE.Material) {
const map = (
material as THREE.MeshBasicMaterial | THREE.MeshStandardMaterial
).map;
const map = (material as
| THREE.MeshBasicMaterial
| THREE.MeshStandardMaterial).map;
return map ? map.image.width : 0;
}
getAnimationFrameHeight(material: THREE.Material) {
const map = (
material as THREE.MeshBasicMaterial | THREE.MeshStandardMaterial
).map;
const map = (material as
| THREE.MeshBasicMaterial
| THREE.MeshStandardMaterial).map;
return map ? map.image.height : 0;
}
}

View File

@@ -21,9 +21,7 @@ module.exports = {
.setExtensionInformation(
'Scene3D',
_('3D'),
_(
'Support for 3D in GDevelop: this provides 3D objects and the common features for all 3D objects.'
),
_('Support for 3D in GDevelop.'),
'Florian Rival',
'MIT'
)
@@ -38,9 +36,7 @@ module.exports = {
'Base3DBehavior',
_('3D capability'),
'Object3D',
_(
'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).'
),
_('Move the object in 3D space.'),
'',
'res/conditions/3d_box.svg',
'Base3DBehavior',
@@ -73,7 +69,7 @@ module.exports = {
_('Center Z position'),
_('the Z position of the center of rotation'),
_('the Z position of the center'),
_('Position Center'),
_('Position/Center'),
'res/conditions/3d_box.svg'
)
.addParameter('object', _('3D object'), '', false)
@@ -804,20 +800,6 @@ module.exports = {
.markAsSimple()
.setHidden()
.setFunctionName('hasAnimationEnded');
object
.addScopedAction(
'SetCrossfadeDuration',
_('Set crossfade duration'),
_('Set the crossfade duration when switching to a new animation.'),
_('Set crossfade duration of _PARAM0_ to _PARAM1_ seconds'),
_('Animations and images'),
'res/conditions/animation24.png',
'res/conditions/animation.png'
)
.addParameter('object', _('3D model'), 'Model3DObject', false)
.addParameter('number', _('Crossfade duration (in seconds)'), '', false)
.setFunctionName('setCrossfadeDuration');
}
const Cube3DObject = new gd.ObjectJsImplementation();
@@ -840,8 +822,7 @@ module.exports = {
propertyName === 'bottomFaceResourceName' ||
propertyName === 'backFaceUpThroughWhichAxisRotation' ||
propertyName === 'facesOrientation' ||
propertyName === 'materialType' ||
propertyName === 'tint'
propertyName === 'materialType'
) {
objectContent[propertyName] = newValue;
return true;
@@ -921,12 +902,6 @@ module.exports = {
.setLabel(_('Depth'))
.setMeasurementUnit(gd.MeasurementUnit.getPixel())
.setGroup(_('Default size'));
objectProperties
.getOrCreate('tint')
.setValue(objectContent.tint || '255;255;255')
.setType('Color')
.setLabel(_('Tint'))
.setGroup(_('Texture'));
objectProperties
.getOrCreate('frontFaceResourceName')
@@ -1117,7 +1092,6 @@ module.exports = {
topFaceResourceRepeat: false,
bottomFaceResourceRepeat: false,
materialType: 'Basic',
tint: '255;255;255',
};
Cube3DObject.updateInitialInstanceProperty = function (
@@ -1594,21 +1568,6 @@ module.exports = {
.addParameter('imageResource', _('Image'), '', false)
.setFunctionName('setFaceResourceName');
object
.addScopedAction(
'SetTint',
_('Tint color'),
_('Change the tint of the cube.'),
_('Change the tint of _PARAM0_ to _PARAM1_'),
_('Effects'),
'res/actions/color24.png',
'res/actions/color.png'
)
.addParameter('object', _('3D Cube'), 'Cube3DObject', false)
.addParameter('color', _('Tint'), '', false)
.getCodeExtraInformation()
.setFunctionName('setColor');
extension
.addExpressionAndConditionAndAction(
'number',
@@ -2103,10 +2062,6 @@ module.exports = {
3: [1, 0],
};
/**
* @param {*} objectConfiguration
* @returns {string | null}
*/
const getFirstVisibleFaceResourceName = (objectConfiguration) => {
const object = gd.castObject(
objectConfiguration,
@@ -2135,44 +2090,25 @@ module.exports = {
return null;
};
/** @type {THREE.MeshBasicMaterial | null} */
let transparentMaterial = null;
/**
* @returns {THREE.MeshBasicMaterial}
*/
const getTransparentMaterial = () => {
if (transparentMaterial) {
return transparentMaterial;
}
const newTransparentMaterial = new THREE.MeshBasicMaterial({
transparent: true,
opacity: 0,
// Set the alpha test to to ensure the faces behind are rendered
// (no "back face culling" that would still be done if alphaTest is not set).
alphaTest: 1,
});
transparentMaterial = newTransparentMaterial;
return newTransparentMaterial;
if (!transparentMaterial)
transparentMaterial = new THREE.MeshBasicMaterial({
transparent: true,
opacity: 0,
// Set the alpha test to to ensure the faces behind are rendered
// (no "back face culling" that would still be done if alphaTest is not set).
alphaTest: 1,
});
return transparentMaterial;
};
class RenderedCube3DObject2DInstance extends RenderedInstance {
/** @type {number} */
_defaultWidth;
/** @type {number} */
_defaultHeight;
/** @type {number} */
_defaultDepth;
/** @type {number} */
_centerX = 0;
/** @type {number} */
_centerY = 0;
/**
* The name of the resource that is rendered.
* If no face is visible, this will be null.
* @type {string | null | undefined}
*/
_renderedResourceName = undefined;
_renderFallbackObject = false;
constructor(
project,
@@ -2188,6 +2124,11 @@ module.exports = {
pixiContainer,
pixiResourcesLoader
);
// Name of the resource that is rendered.
// If no face is visible, this will be null.
this._renderedResourceName = undefined;
const object = gd.castObject(
this._associatedObjectConfiguration,
gd.ObjectJsImplementation
@@ -2204,6 +2145,7 @@ module.exports = {
this._pixiObject.addChild(this._pixiTexturedObject);
this._pixiObject.addChild(this._pixiFallbackObject);
this._pixiContainer.addChild(this._pixiObject);
this._renderFallbackObject = false;
this.updateTexture();
}
@@ -2218,10 +2160,9 @@ module.exports = {
}
static getThumbnail(project, resourcesLoader, objectConfiguration) {
const textureResourceName =
RenderedCube3DObject2DInstance._getResourceNameToDisplay(
objectConfiguration
);
const textureResourceName = RenderedCube3DObject2DInstance._getResourceNameToDisplay(
objectConfiguration
);
if (textureResourceName) {
return resourcesLoader.getResourceFullUrl(
project,
@@ -2233,20 +2174,18 @@ module.exports = {
}
updateTextureIfNeeded() {
const textureName =
RenderedCube3DObject2DInstance._getResourceNameToDisplay(
this._associatedObjectConfiguration
);
const textureName = RenderedCube3DObject2DInstance._getResourceNameToDisplay(
this._associatedObjectConfiguration
);
if (textureName === this._renderedResourceName) return;
this.updateTexture();
}
updateTexture() {
const textureName =
RenderedCube3DObject2DInstance._getResourceNameToDisplay(
this._associatedObjectConfiguration
);
const textureName = RenderedCube3DObject2DInstance._getResourceNameToDisplay(
this._associatedObjectConfiguration
);
if (!textureName) {
this._renderFallbackObject = true;
@@ -2369,17 +2308,6 @@ module.exports = {
}
class RenderedCube3DObject3DInstance extends Rendered3DInstance {
_defaultWidth = 1;
_defaultHeight = 1;
_defaultDepth = 1;
_faceResourceNames = new Array(6).fill(null);
_faceVisibilities = new Array(6).fill(null);
_shouldRepeatTextureOnFace = new Array(6).fill(null);
_facesOrientation = 'Y';
_backFaceUpThroughWhichAxisRotation = 'X';
_shouldUseTransparentTexture = false;
_tint = '';
constructor(
project,
instance,
@@ -2396,9 +2324,21 @@ module.exports = {
threeGroup,
pixiResourcesLoader
);
this._defaultWidth = 1;
this._defaultHeight = 1;
this._defaultDepth = 1;
this._pixiObject = new PIXI.Graphics();
this._pixiContainer.addChild(this._pixiObject);
this._faceResourceNames = new Array(6).fill(null);
this._faceVisibilities = new Array(6).fill(null);
this._shouldRepeatTextureOnFace = new Array(6).fill(null);
this._facesOrientation = 'Y';
this._backFaceUpThroughWhichAxisRotation = 'X';
this._shouldUseTransparentTexture = false;
const geometry = new THREE.BoxGeometry(1, 1, 1);
const materials = [
getTransparentMaterial(),
@@ -2417,9 +2357,8 @@ module.exports = {
async _updateThreeObjectMaterials() {
const getFaceMaterial = async (project, faceIndex) => {
if (!this._faceVisibilities[faceIndex]) {
if (!this._faceVisibilities[faceIndex])
return getTransparentMaterial();
}
return await this._pixiResourcesLoader.getThreeMaterial(
project,
@@ -2450,35 +2389,11 @@ module.exports = {
this._updateTextureUvMapping();
}
_updateTint() {
const tints = [];
const normalizedTint = objectsRenderingService
.hexNumberToRGBArray(
objectsRenderingService.rgbOrHexToHexNumber(this._tint)
)
.map((component) => component / 255);
for (
let i = 0;
i < this._threeObject.geometry.attributes.position.count;
i++
) {
tints.push(...normalizedTint);
}
this._threeObject.geometry.setAttribute(
'color',
new THREE.BufferAttribute(new Float32Array(tints), 3)
);
}
static _getResourceNameToDisplay(objectConfiguration) {
return getFirstVisibleFaceResourceName(objectConfiguration);
}
updateThreeObject() {
/** @type {gdjs.Cube3DObjectData} */
//@ts-ignore This works because the properties are set to `content` in JavaScript.
const object = gd.castObject(
this._associatedObjectConfiguration,
gd.ObjectJsImplementation
@@ -2506,19 +2421,13 @@ module.exports = {
let materialsDirty = false;
let uvMappingDirty = false;
let tintDirty = false;
const shouldUseTransparentTexture =
object.content.enableTextureTransparency || false;
object.content.enableTextureTransparency;
if (this._shouldUseTransparentTexture !== shouldUseTransparentTexture) {
this._shouldUseTransparentTexture = shouldUseTransparentTexture;
materialsDirty = true;
}
const tint = object.content.tint || '255;255;255';
if (this._tint !== tint) {
this._tint = tint;
tintDirty = true;
}
const faceResourceNames = [
object.content.frontFaceResourceName,
@@ -2562,12 +2471,12 @@ module.exports = {
}
const shouldRepeatTextureOnFace = [
object.content.frontFaceResourceRepeat || false,
object.content.backFaceResourceRepeat || false,
object.content.leftFaceResourceRepeat || false,
object.content.rightFaceResourceRepeat || false,
object.content.topFaceResourceRepeat || false,
object.content.bottomFaceResourceRepeat || false,
object.content.frontFaceResourceRepeat,
object.content.backFaceResourceRepeat,
object.content.leftFaceResourceRepeat,
object.content.rightFaceResourceRepeat,
object.content.topFaceResourceRepeat,
object.content.bottomFaceResourceRepeat,
];
if (
this._shouldRepeatTextureOnFace[0] !== shouldRepeatTextureOnFace[0] ||
@@ -2582,17 +2491,16 @@ module.exports = {
}
const backFaceUpThroughWhichAxisRotation =
object.content.backFaceUpThroughWhichAxisRotation || 'X';
object.content.backFaceUpThroughWhichAxisRotation;
if (
backFaceUpThroughWhichAxisRotation !==
this._backFaceUpThroughWhichAxisRotation
) {
this._backFaceUpThroughWhichAxisRotation =
backFaceUpThroughWhichAxisRotation;
this._backFaceUpThroughWhichAxisRotation = backFaceUpThroughWhichAxisRotation;
uvMappingDirty = true;
}
const facesOrientation = object.content.facesOrientation || 'Y';
const facesOrientation = object.content.facesOrientation;
if (facesOrientation !== this._facesOrientation) {
this._facesOrientation = facesOrientation;
uvMappingDirty = true;
@@ -2612,7 +2520,6 @@ module.exports = {
if (materialsDirty) this._updateThreeObjectMaterials();
if (uvMappingDirty) this._updateTextureUvMapping();
if (tintDirty) this._updateTint();
}
/**
@@ -2622,11 +2529,11 @@ module.exports = {
* for the method to work.
*/
_updateTextureUvMapping() {
/** @type {THREE.BufferAttribute} */
// @ts-ignore - position is stored as a Float32BufferAttribute
const pos = this._threeObject.geometry.getAttribute('position');
/** @type {THREE.BufferAttribute} */
const pos = this._threeObject.geometry.getAttribute('position');
// @ts-ignore - uv is stored as a Float32BufferAttribute
/** @type {THREE.BufferAttribute} */
const uvMapping = this._threeObject.geometry.getAttribute('uv');
const startIndex = 0;
const endIndex = 23;
@@ -2645,10 +2552,9 @@ module.exports = {
continue;
}
const shouldRepeatTexture =
this._shouldRepeatTextureOnFace[
materialIndexToFaceIndex[materialIndex]
];
const shouldRepeatTexture = this._shouldRepeatTextureOnFace[
materialIndexToFaceIndex[materialIndex]
];
const shouldOrientateFacesTowardsY = this._facesOrientation === 'Y';
@@ -2683,13 +2589,16 @@ module.exports = {
}
} else {
if (shouldOrientateFacesTowardsY) {
[x, y] =
noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
[x, y] = noRepeatTextureVertexIndexToUvMapping[
vertexIndex % 4
];
} else {
[x, y] =
noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
vertexIndex % 4
];
[
x,
y,
] = noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
vertexIndex % 4
];
}
}
break;
@@ -2719,13 +2628,16 @@ module.exports = {
}
} else {
if (shouldOrientateFacesTowardsY) {
[x, y] =
noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
[x, y] = noRepeatTextureVertexIndexToUvMapping[
vertexIndex % 4
];
} else {
[x, y] =
noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
vertexIndex % 4
];
[
x,
y,
] = noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
vertexIndex % 4
];
x = -x;
y = -y;
}
@@ -2874,19 +2786,6 @@ module.exports = {
const epsilon = 1 / (1 << 16);
class Model3DRendered2DInstance extends RenderedInstance {
/** @type {number} */
_defaultWidth;
/** @type {number} */
_defaultHeight;
/** @type {number} */
_defaultDepth;
/** @type {[number, number, number] | null} */
_originPoint;
/** @type {[number, number, number] | null} */
_centerPoint;
/** @type {[number, number, number]} */
_modelOriginPoint = [0, 0, 0];
constructor(
@@ -3129,15 +3028,10 @@ module.exports = {
}
}
/**
* @param {[number, number, number] | null} point1
* @param {[number, number, number] | null} point2
* @returns {boolean}
*/
const isSamePoint = (point1, point2) => {
if (!!point1 !== !!point2) return false;
// At this point || or && doesn't matter and the type checking prefer ||.
if (!point1 || !point2) return true;
if (!point1 && !point2) return true;
if (point1 && !point2) return false;
if (!point1 && point2) return false;
return (
point1[0] === point2[0] &&
point1[1] === point2[1] &&
@@ -3145,10 +3039,6 @@ module.exports = {
);
};
/**
* @param {string} location
* @returns {[number, number, number] | null}
*/
const getPointForLocation = (location) => {
switch (location) {
case 'ModelOrigin':
@@ -3167,27 +3057,8 @@ module.exports = {
};
class Model3DRendered3DInstance extends Rendered3DInstance {
_defaultWidth = 1;
_defaultHeight = 1;
_defaultDepth = 1;
_originalWidth = 1;
_originalHeight = 1;
_originalDepth = 1;
_rotationX = 0;
_rotationY = 0;
_rotationZ = 0;
_keepAspectRatio = false;
/** @type {[number, number, number] | null} */
_originPoint = null;
/** @type {[number, number, number] | null} */
_centerPoint = null;
/** @type {[number, number, number]} */
_modelOriginPoint = [0, 0, 0];
/** @type {THREE.Object3D | null} */
_clonedModel3D = null;
constructor(
project,
instance,
@@ -3205,12 +3076,29 @@ module.exports = {
pixiResourcesLoader
);
this._defaultWidth = 1;
this._defaultHeight = 1;
this._defaultDepth = 1;
this._originalWidth = 1;
this._originalHeight = 1;
this._originalDepth = 1;
this._rotationX = 0;
this._rotationY = 0;
this._rotationZ = 0;
this._keepAspectRatio = false;
this._originPoint = null;
this._centerPoint = null;
this._pixiObject = new PIXI.Graphics();
this._pixiContainer.addChild(this._pixiObject);
this._threeObject = new THREE.Group();
this._threeObject.rotation.order = 'ZYX';
this._threeGroup.add(this._threeObject);
this._threeModelGroup = null;
this._clonedModel3D = null;
}
getOriginX() {
@@ -3252,30 +3140,27 @@ module.exports = {
}
_updateDefaultTransformation() {
if (!this._clonedModel3D) {
// Model is not ready - nothing to do.
return;
}
if (!this._clonedModel3D) return; // Model is not ready - nothing to do.
if (this._threeModelGroup) {
// Remove any previous container as we will recreate it just below
this._threeObject.clear();
}
// This group hold the rotation defined by properties.
// Always restart from a new group to avoid miscomputing bounding boxes/sizes.
const threeModelGroup = new THREE.Group();
this._threeModelGroup = threeModelGroup;
threeModelGroup.rotation.order = 'ZYX';
threeModelGroup.add(this._clonedModel3D);
this._threeModelGroup = new THREE.Group();
this._threeModelGroup.rotation.order = 'ZYX';
this._threeModelGroup.add(this._clonedModel3D);
threeModelGroup.rotation.set(
this._threeModelGroup.rotation.set(
(this._rotationX * Math.PI) / 180,
(this._rotationY * Math.PI) / 180,
(this._rotationZ * Math.PI) / 180
);
threeModelGroup.updateMatrixWorld(true);
const boundingBox = new THREE.Box3().setFromObject(threeModelGroup);
this._threeModelGroup.updateMatrixWorld(true);
const boundingBox = new THREE.Box3().setFromObject(
this._threeModelGroup
);
const shouldKeepModelOrigin = !this._originPoint;
if (shouldKeepModelOrigin) {
@@ -3302,7 +3187,7 @@ module.exports = {
// Center the model.
const centerPoint = this._centerPoint;
if (centerPoint) {
threeModelGroup.position.set(
this._threeModelGroup.position.set(
-(boundingBox.min.x + modelWidth * centerPoint[0]),
// The model is flipped on Y axis.
-(boundingBox.min.y + modelHeight * (1 - centerPoint[1])),
@@ -3311,8 +3196,8 @@ module.exports = {
}
// Rotate the model.
threeModelGroup.scale.set(1, 1, 1);
threeModelGroup.rotation.set(
this._threeModelGroup.scale.set(1, 1, 1);
this._threeModelGroup.rotation.set(
(this._rotationX * Math.PI) / 180,
(this._rotationY * Math.PI) / 180,
(this._rotationZ * Math.PI) / 180
@@ -3327,8 +3212,8 @@ module.exports = {
// Flip on Y because the Y axis is on the opposite side of direct basis.
// It avoids models to be like a mirror refection.
scaleMatrix.makeScale(scaleX, -scaleY, scaleZ);
threeModelGroup.updateMatrix();
threeModelGroup.applyMatrix4(scaleMatrix);
this._threeModelGroup.updateMatrix();
this._threeModelGroup.applyMatrix4(scaleMatrix);
if (this._keepAspectRatio) {
// Reduce the object dimensions to keep aspect ratio.
@@ -3395,7 +3280,7 @@ module.exports = {
this._defaultDepth = this._originalDepth;
}
this._threeObject.add(threeModelGroup);
this._threeObject.add(this._threeModelGroup);
}
updateThreeObject() {

View File

@@ -23,7 +23,7 @@ Model3DObjectConfiguration::Model3DObjectConfiguration()
: width(100), height(100), depth(100), rotationX(0), rotationY(0),
rotationZ(0), modelResourceName(""), materialType("StandardWithoutMetalness"),
originLocation("ModelOrigin"), centerLocation("ModelOrigin"),
keepAspectRatio(true), crossfadeDuration(0.1f) {}
keepAspectRatio(true) {}
bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
const gd::String &newValue) {
@@ -71,10 +71,6 @@ bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
keepAspectRatio = newValue == "1";
return true;
}
if(propertyName == "crossfadeDuration") {
crossfadeDuration = newValue.To<double>();
return true;
}
return false;
}
@@ -171,13 +167,6 @@ Model3DObjectConfiguration::GetProperties() const {
.SetGroup(_("Points"))
.SetAdvanced(true);
objectProperties["crossfadeDuration"]
.SetValue(gd::String::From(crossfadeDuration))
.SetType("number")
.SetLabel(_("Crossfade duration"))
.SetGroup(_("Animations"))
.SetMeasurementUnit(gd::MeasurementUnit::GetSecond());
return objectProperties;
}
@@ -209,7 +198,6 @@ void Model3DObjectConfiguration::DoUnserializeFrom(
originLocation = content.GetStringAttribute("originLocation");
centerLocation = content.GetStringAttribute("centerLocation");
keepAspectRatio = content.GetBoolAttribute("keepAspectRatio");
crossfadeDuration = content.GetDoubleAttribute("crossfadeDuration");
RemoveAllAnimations();
auto &animationsElement = content.GetChild("animations");
@@ -238,7 +226,6 @@ void Model3DObjectConfiguration::DoSerializeTo(
content.SetAttribute("originLocation", originLocation);
content.SetAttribute("centerLocation", centerLocation);
content.SetAttribute("keepAspectRatio", keepAspectRatio);
content.SetAttribute("crossfadeDuration", crossfadeDuration);
auto &animationsElement = content.AddChild("animations");
animationsElement.ConsiderAsArrayOf("animation");

View File

@@ -152,7 +152,6 @@ public:
double GetRotationX() const { return rotationX; };
double GetRotationY() const { return rotationY; };
double GetRotationZ() const { return rotationZ; };
double GetCrossfadeDuration() const { return crossfadeDuration; };
const gd::String& GetModelResourceName() const { return modelResourceName; };
const gd::String& GetMaterialType() const { return materialType; };
@@ -174,7 +173,6 @@ private:
double rotationX;
double rotationY;
double rotationZ;
double crossfadeDuration;
gd::String modelResourceName;
gd::String materialType;

View File

@@ -9,7 +9,6 @@ namespace gdjs {
ai: integer;
ass: float;
ap: boolean;
cfd: float;
};
type Model3DObjectNetworkSyncData = Object3DNetworkSyncData &
@@ -37,7 +36,6 @@ namespace gdjs {
| 'BottomCenterZ'
| 'BottomCenterY';
animations: Model3DAnimation[];
crossfadeDuration: float;
};
}
@@ -65,8 +63,7 @@ namespace gdjs {
*/
export class Model3DRuntimeObject
extends gdjs.RuntimeObject3D
implements gdjs.Animatable
{
implements gdjs.Animatable {
_renderer: gdjs.Model3DRuntimeObjectRenderer;
_modelResourceName: string;
@@ -100,7 +97,6 @@ namespace gdjs {
_currentAnimationIndex: integer = 0;
_animationSpeedScale: float = 1;
_animationPaused: boolean = false;
_crossfadeDuration: float = 0;
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
@@ -125,8 +121,6 @@ namespace gdjs {
this.onModelChanged(objectData);
this._crossfadeDuration = objectData.content.crossfadeDuration || 0;
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
}
@@ -208,7 +202,6 @@ namespace gdjs {
ai: this._currentAnimationIndex,
ass: this._animationSpeedScale,
ap: this._animationPaused,
cfd: this._crossfadeDuration,
};
}
@@ -240,9 +233,6 @@ namespace gdjs {
networkSyncData.ap ? this.pauseAnimation() : this.resumeAnimation();
}
}
if (networkSyncData.cfd !== undefined) {
this._crossfadeDuration = networkSyncData.cfd;
}
}
_reloadModel(objectData: Model3DObjectData) {
@@ -285,7 +275,7 @@ namespace gdjs {
update(instanceContainer: gdjs.RuntimeInstanceContainer): void {
const elapsedTime = this.getElapsedTime() / 1000;
this._renderer.updateAnimation(elapsedTime);
this._renderer.updateAnimation(elapsedTime * this._animationSpeedScale);
}
/**
@@ -358,11 +348,6 @@ namespace gdjs {
return this._renderer.hasAnimationEnded();
}
setCrossfadeDuration(duration: number): void {
if (this._crossfadeDuration === duration) return;
this._crossfadeDuration = duration;
}
isAnimationPaused() {
return this._animationPaused;
}
@@ -383,7 +368,6 @@ namespace gdjs {
setAnimationSpeedScale(ratio: float): void {
this._animationSpeedScale = ratio;
this._renderer.setAnimationTimeScale(ratio);
}
getAnimationElapsedTime(): float {

View File

@@ -359,6 +359,7 @@ namespace gdjs {
}
playAnimation(animationName: string, shouldLoop: boolean) {
this._animationMixer.stopAllAction();
const clip = THREE.AnimationClip.findByName(
this._originalModel.animations,
animationName
@@ -369,27 +370,12 @@ namespace gdjs {
);
return;
}
const previousAction = this._action;
this._action = this._animationMixer.clipAction(clip);
// Reset the animation and play it from the start.
// `clipAction` always gives back the same action for a given animation
// and its likely to be in a finished or at least started state.
this._action.reset();
this._action.setLoop(
shouldLoop ? THREE.LoopRepeat : THREE.LoopOnce,
Number.POSITIVE_INFINITY
);
this._action.clampWhenFinished = true;
this._action.timeScale =
this._model3DRuntimeObject.getAnimationSpeedScale();
if (previousAction && previousAction !== this._action) {
this._action.crossFadeFrom(
previousAction,
this._model3DRuntimeObject._crossfadeDuration,
false
);
}
this._action.play();
// Make sure the first frame is displayed.
this._animationMixer.update(0);
@@ -405,12 +391,6 @@ namespace gdjs {
}
}
setAnimationTimeScale(timeScale: float): void {
if (this._action) {
this._action.timeScale = timeScale;
}
}
getAnimationDuration(animationName: string): float {
const clip = THREE.AnimationClip.findByName(
this._originalModel.animations,

View File

@@ -38,7 +38,7 @@ module.exports = {
.setName('Consent Cordova plugin')
.setDependencyType('cordova')
.setExportName('cordova-plugin-consent')
.setVersion('3.0.0-alpha.9')
.setVersion('3.0.0-alpha.8')
.onlyIfOtherDependencyIsExported('AdMob Cordova plugin');
extension
@@ -93,68 +93,6 @@ module.exports = {
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.setTestMode');
extension
.addAction(
'PreventAdmobAutoInitialization',
_('Prevent AdMob auto initialization'),
_(
'Prevent AdMob from initializing automatically. You will need to call "Initialize AdMob" action manually.\n' +
'This is useful if you want to control when the consent dialog will be shown (for example, after the user has accepted your game terms).'
),
_('Prevent AdMob auto initialization'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.preventAdmobAutoInitialization');
extension
.addAction(
'InitializeAdmob',
_('Initialize AdMob manually'),
_(
'Initialize AdMob manually. This will trigger the consent dialog if needed, and then load the ads.\n' +
'Use this action if you have disabled the auto init and want to control when the consent dialog will be shown.'
),
_('Initialize AdMob'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.initializeAdmob');
extension
.addCondition(
'AdmobInitializing',
_('AdMob initializing'),
_('Check if AdMob is initializing.'),
_('AdMob is initializing'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isAdmobInitializing');
extension
.addCondition(
'AdmobInitialized',
_('AdMob initialized'),
_('Check if AdMob has been initialized.'),
_('AdMob has been initialized'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isAdmobInitialized');
// App Open
extension
.addCondition(

View File

@@ -1,7 +1,6 @@
namespace gdjs {
declare var admob: any;
declare var cordova: any;
declare var consent: any;
export namespace adMob {
const logger = new gdjs.Logger('AdMob');
@@ -109,119 +108,26 @@ namespace gdjs {
let rewardedVideoRewardReceived = false; // Becomes true when the video is closed and the reward is received.
let rewardedVideoErrored = false; // Becomes true when the video fails to load.
let npaValue = '0'; // 0 means that the user has consented to personalized ads, 1 means that the user has not consented to personalized ads.
let setupTimeoutId: NodeJS.Timeout | null = null;
const askForConsentAndInitializeAdmob = async () => {
if (admobStarted) {
logger.warn('AdMob is already started.');
return;
}
if (isStarting) {
logger.warn('AdMob is already starting.');
return;
}
try {
logger.info('Starting AdMob.');
isStarting = true;
if (cordova.platformId === 'ios') {
try {
/*
trackingStatus:
0 = notDetermined
1 = restricted
2 = denied
3 = authorized
*/
let trackingStatus = await consent.trackingAuthorizationStatus();
// If tracking is not determined, we ask the user for tracking authorization.
if (trackingStatus === 0) {
trackingStatus = await consent.requestTrackingAuthorization();
}
// If tracking is restricted or denied, we set npaValue to 1.
if (trackingStatus === 1 || trackingStatus === 2) {
npaValue = '1';
}
// otherwise, we set npaValue to 0.
npaValue = '0';
} catch (error) {
logger.error(
'Error while asking for tracking authorization, continuing:',
error
);
}
}
try {
// ConsentStatus:
// Unknown = 0,
// Required = 1,
// NotRequired = 2,
// Obtained = 3,
const consentStatus = await consent.getConsentStatus();
if (consentStatus === consent.ConsentStatus.Required) {
await consent.requestInfoUpdate();
}
await consent.loadAndShowIfRequired();
} catch (error) {
logger.error('Error while asking for consent, continuing:', error);
}
// We should be looking at canRequestAds to know if we can request ads or not.
// But as we want to be able to test ads in debug or if the consent didn't work,
// we ignore this value for now.
// const canRequestAds = await consent.canRequestAds();
if (true) {
await admob.start();
logger.info('AdMob successfully started.');
isStarting = false;
admobStarted = true;
}
} catch (error) {
logger.error('Error while starting AdMob:', error);
isStarting = false;
admobStarted = false;
}
};
let npaValue = '0'; // TODO: expose an API to change this and also an automatic way using the consent SDK.
// Admob initialization listener
document.addEventListener(
'deviceready',
async () => {
// Obtain user consent ?
logger.info('Starting AdMob.');
isStarting = true;
setupTimeoutId = setTimeout(async () => {
isStarting = false; // Reset to false, as it will be set to true in askForConsentAndInitializeAdmob.
await askForConsentAndInitializeAdmob();
// Wait a bit before starting admob, to avoid the consent appearing too soon.
}, 2000);
await admob.start();
logger.info('AdMob successfully started.');
isStarting = false;
admobStarted = true;
},
false
);
export const preventAdmobAutoInitialization = () => {
if (setupTimeoutId) {
isStarting = false;
clearTimeout(setupTimeoutId);
setupTimeoutId = null;
}
};
export const initializeAdmob = async () => {
preventAdmobAutoInitialization();
await askForConsentAndInitializeAdmob();
};
export const isAdmobInitialized = () => admobStarted;
export const isAdmobInitializing = () => isStarting;
/**
* Helper to know if we are on mobile and admob is correctly initialized.
*/
@@ -428,7 +334,6 @@ namespace gdjs {
position: atTop ? 'top' : 'bottom',
size: bannerRequestedAdSizeType,
offset: 0,
npa: npaValue,
});
banner.on('load', () => {

View File

@@ -1,10 +1,10 @@
namespace gdjs {
/**
* Tools to manipulate the game window positioning and
* interactions with the operating system.
* @author arthuro555
*/
export namespace evtTools {
/**
* Tools to manipulate the game window positioning and
* interactions with the operating system.
* @author arthuro555
*/
export namespace advancedWindow {
const getElectronBrowserWindow = (runtimeScene: gdjs.RuntimeScene) => {
try {

View File

@@ -20,41 +20,25 @@ namespace gdjs {
}
export class AnchorRuntimeBehavior extends gdjs.RuntimeBehavior {
// Configuration
_relativeToOriginalWindowSize: boolean;
_relativeToOriginalWindowSize: any;
_leftEdgeAnchor: HorizontalAnchor;
_rightEdgeAnchor: HorizontalAnchor;
_topEdgeAnchor: VerticalAnchor;
_bottomEdgeAnchor: VerticalAnchor;
_topEdgeAnchor: any;
_bottomEdgeAnchor: any;
_invalidDistances: boolean = true;
_leftEdgeDistance: number = 0;
_rightEdgeDistance: number = 0;
_topEdgeDistance: number = 0;
_bottomEdgeDistance: number = 0;
_useLegacyBottomAndRightAnchors: boolean = false;
// State
_hasJustBeenCreated: boolean = true;
_leftEdgeDistance: float = 0;
_rightEdgeDistance: float = 0;
_topEdgeDistance: float = 0;
_bottomEdgeDistance: float = 0;
_oldDrawableX: float = 0;
_oldDrawableY: float = 0;
_oldWidth: float = 0;
_oldHeight: float = 0;
_parentOldMinX: float = 0;
_parentOldMinY: float = 0;
_parentOldMaxX: float = 0;
_parentOldMaxY: float = 0;
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
behaviorData,
owner: gdjs.RuntimeObject
) {
super(instanceContainer, behaviorData, owner);
this._relativeToOriginalWindowSize =
!!behaviorData.relativeToOriginalWindowSize;
this._relativeToOriginalWindowSize = !!behaviorData.relativeToOriginalWindowSize;
this._leftEdgeAnchor = behaviorData.leftEdgeAnchor;
this._rightEdgeAnchor = behaviorData.rightEdgeAnchor;
this._topEdgeAnchor = behaviorData.topEdgeAnchor;
@@ -65,7 +49,7 @@ namespace gdjs {
: behaviorData.useLegacyBottomAndRightAnchors;
}
override updateFromBehaviorData(oldBehaviorData, newBehaviorData): boolean {
updateFromBehaviorData(oldBehaviorData, newBehaviorData): boolean {
if (oldBehaviorData.leftEdgeAnchor !== newBehaviorData.leftEdgeAnchor) {
this._leftEdgeAnchor = newBehaviorData.leftEdgeAnchor;
}
@@ -96,381 +80,266 @@ namespace gdjs {
return true;
}
override onActivate(): void {
// This only has a side effect if the camera moved while the behavior was
// deactivated.
// The new position on the viewport is where the object should stay.
this._hasJustBeenCreated = true;
onActivate() {
this._invalidDistances = true;
}
override doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
if (this._hasJustBeenCreated) {
this._initializeAnchorDistances(instanceContainer);
this._hasJustBeenCreated = false;
this._oldDrawableX = this.owner.getDrawableX();
this._oldDrawableY = this.owner.getDrawableY();
this._oldWidth = this.owner.getWidth();
this._oldHeight = this.owner.getHeight();
}
this._updateAnchorDistances(instanceContainer);
this._followAnchor(instanceContainer);
this._oldDrawableX = this.owner.getDrawableX();
this._oldDrawableY = this.owner.getDrawableY();
this._oldWidth = this.owner.getWidth();
this._oldHeight = this.owner.getHeight();
}
/**
* Evaluate the anchor distance according to the object position on the
* screen.
*
* The camera is taken into account.
*/
private _initializeAnchorDistances(
instanceContainer: gdjs.RuntimeInstanceContainer
) {
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
const workingPoint: FloatPoint = gdjs.staticArray(
gdjs.AnchorRuntimeBehavior.prototype.doStepPreEvents
) as FloatPoint;
const layer = instanceContainer.getLayer(this.owner.getLayer());
if (this._relativeToOriginalWindowSize) {
this._parentOldMinX =
instanceContainer.getInitialUnrotatedViewportMinX();
this._parentOldMinY =
instanceContainer.getInitialUnrotatedViewportMinY();
this._parentOldMaxX =
instanceContainer.getInitialUnrotatedViewportMaxX();
this._parentOldMaxY =
instanceContainer.getInitialUnrotatedViewportMaxY();
} else {
this._parentOldMinX = instanceContainer.getUnrotatedViewportMinX();
this._parentOldMinY = instanceContainer.getUnrotatedViewportMinY();
this._parentOldMaxX = instanceContainer.getUnrotatedViewportMaxX();
this._parentOldMaxY = instanceContainer.getUnrotatedViewportMaxY();
}
const parentMinX = this._parentOldMinX;
const parentMinY = this._parentOldMinY;
const parentMaxX = this._parentOldMaxX;
const parentMaxY = this._parentOldMaxY;
const parentCenterX = (parentMaxX + parentMinX) / 2;
const parentCenterY = (parentMaxY + parentMinY) / 2;
const parentWidth = parentMaxX - parentMinX;
const parentHeight = parentMaxY - parentMinY;
// Calculate the distances from the window's bounds.
const topLeftPixel = this._convertInverseCoords(
instanceContainer,
layer,
this.owner.getDrawableX(),
this.owner.getDrawableY(),
workingPoint
);
// Left edge
if (this._leftEdgeAnchor === HorizontalAnchor.WindowLeft) {
this._leftEdgeDistance = topLeftPixel[0] - parentMinX;
} else if (this._leftEdgeAnchor === HorizontalAnchor.WindowRight) {
this._leftEdgeDistance = topLeftPixel[0] - parentMaxX;
} else if (this._leftEdgeAnchor === HorizontalAnchor.Proportional) {
this._leftEdgeDistance = (topLeftPixel[0] - parentMinX) / parentWidth;
} else if (this._leftEdgeAnchor === HorizontalAnchor.WindowCenter) {
this._leftEdgeDistance = topLeftPixel[0] - parentCenterX;
}
// Top edge
if (this._topEdgeAnchor === VerticalAnchor.WindowTop) {
this._topEdgeDistance = topLeftPixel[1] - parentMinY;
} else if (this._topEdgeAnchor === VerticalAnchor.WindowBottom) {
this._topEdgeDistance = topLeftPixel[1] - parentMaxY;
} else if (this._topEdgeAnchor === VerticalAnchor.Proportional) {
this._topEdgeDistance = (topLeftPixel[1] - parentMinY) / parentHeight;
} else if (this._topEdgeAnchor === VerticalAnchor.WindowCenter) {
this._topEdgeDistance = topLeftPixel[1] - parentCenterY;
}
// It's fine to reuse workingPoint as topLeftPixel is no longer used.
const bottomRightPixel = this._convertInverseCoords(
instanceContainer,
layer,
this.owner.getDrawableX() + this.owner.getWidth(),
this.owner.getDrawableY() + this.owner.getHeight(),
workingPoint
);
// Right edge
if (this._rightEdgeAnchor === HorizontalAnchor.WindowLeft) {
this._rightEdgeDistance = bottomRightPixel[0] - parentMinX;
} else if (this._rightEdgeAnchor === HorizontalAnchor.WindowRight) {
this._rightEdgeDistance = bottomRightPixel[0] - parentMaxX;
} else if (this._rightEdgeAnchor === HorizontalAnchor.Proportional) {
this._rightEdgeDistance =
(bottomRightPixel[0] - parentMinX) / parentWidth;
} else if (this._rightEdgeAnchor === HorizontalAnchor.WindowCenter) {
this._rightEdgeDistance = bottomRightPixel[0] - parentCenterX;
}
// Bottom edge
if (this._bottomEdgeAnchor === VerticalAnchor.WindowTop) {
this._bottomEdgeDistance = bottomRightPixel[1] - parentMinY;
} else if (this._bottomEdgeAnchor === VerticalAnchor.WindowBottom) {
this._bottomEdgeDistance = bottomRightPixel[1] - parentMaxY;
} else if (this._bottomEdgeAnchor === VerticalAnchor.Proportional) {
this._bottomEdgeDistance =
(bottomRightPixel[1] - parentMinY) / parentHeight;
} else if (this._bottomEdgeAnchor === VerticalAnchor.WindowCenter) {
this._bottomEdgeDistance = bottomRightPixel[1] - parentCenterY;
}
}
/**
* Update the anchor distances according to the object position change in
* the scene.
*
* The camera is not taken into account. Indeed, a camera scrolling should
* not shift the anchored object on screen.
*/
private _updateAnchorDistances(
instanceContainer: gdjs.RuntimeInstanceContainer
) {
if (
this._oldDrawableX !== this.owner.getDrawableX() ||
this._oldWidth !== this.owner.getWidth()
) {
const parentOldWidth = this._parentOldMaxX - this._parentOldMinX;
// Left edge
const deltaMinX = this.owner.getDrawableX() - this._oldDrawableX;
if (this._leftEdgeAnchor === HorizontalAnchor.Proportional) {
this._leftEdgeDistance += deltaMinX / parentOldWidth;
} else {
this._leftEdgeDistance += deltaMinX;
}
// Right edge
const deltaMaxX = deltaMinX + this.owner.getWidth() - this._oldWidth;
if (this._rightEdgeAnchor === HorizontalAnchor.Proportional) {
this._rightEdgeDistance += deltaMaxX / parentOldWidth;
} else {
this._rightEdgeDistance += deltaMaxX;
}
}
if (
this._oldDrawableY !== this.owner.getDrawableY() ||
this._oldHeight !== this.owner.getHeight()
) {
const parentOldHeight = this._parentOldMaxY - this._parentOldMinY;
// Top edge
const deltaMinY = this.owner.getDrawableY() - this._oldDrawableY;
if (this._topEdgeAnchor === VerticalAnchor.Proportional) {
this._topEdgeDistance += deltaMinY / parentOldHeight;
} else {
this._topEdgeDistance += deltaMinY;
}
// Bottom edge
const deltaMaxY = deltaMinY + this.owner.getHeight() - this._oldHeight;
if (this._bottomEdgeAnchor === VerticalAnchor.Proportional) {
this._bottomEdgeDistance += deltaMaxY / parentOldHeight;
} else {
this._bottomEdgeDistance += deltaMaxY;
}
}
}
/**
* Update the object position to keep the object on screen according to the
* anchor distances.
*
* The camera is taken into account.
*/
private _followAnchor(instanceContainer: gdjs.RuntimeInstanceContainer) {
let parentMinX = instanceContainer.getUnrotatedViewportMinX();
let parentMinY = instanceContainer.getUnrotatedViewportMinY();
let parentMaxX = instanceContainer.getUnrotatedViewportMaxX();
let parentMaxY = instanceContainer.getUnrotatedViewportMaxY();
if (
this._parentOldMinX === parentMinX &&
this._parentOldMinY === parentMinY &&
this._parentOldMaxX === parentMaxX &&
this._parentOldMaxY === parentMaxY
) {
return;
}
const workingPoint: FloatPoint = gdjs.staticArray(
gdjs.AnchorRuntimeBehavior.prototype.doStepPreEvents
) as FloatPoint;
let parentCenterX = (parentMaxX + parentMinX) / 2;
let parentCenterY = (parentMaxY + parentMinY) / 2;
let parentWidth = parentMaxX - parentMinX;
let parentHeight = parentMaxY - parentMinY;
const layer = instanceContainer.getLayer(this.owner.getLayer());
const parentCenterX = (parentMaxX + parentMinX) / 2;
const parentCenterY = (parentMaxY + parentMinY) / 2;
const parentWidth = parentMaxX - parentMinX;
const parentHeight = parentMaxY - parentMinY;
//Move and resize the object if needed
let leftPixel = 0;
let topPixel = 0;
let rightPixel = 0;
let bottomPixel = 0;
// Left edge
if (this._leftEdgeAnchor === HorizontalAnchor.WindowLeft) {
leftPixel = parentMinX + this._leftEdgeDistance;
} else if (this._leftEdgeAnchor === HorizontalAnchor.WindowRight) {
leftPixel = parentMaxX + this._leftEdgeDistance;
} else if (this._leftEdgeAnchor === HorizontalAnchor.Proportional) {
leftPixel = parentMinX + this._leftEdgeDistance * parentWidth;
} else if (this._leftEdgeAnchor === HorizontalAnchor.WindowCenter) {
leftPixel = parentCenterX + this._leftEdgeDistance;
}
// Top edge
if (this._topEdgeAnchor === VerticalAnchor.WindowTop) {
topPixel = parentMinY + this._topEdgeDistance;
} else if (this._topEdgeAnchor === VerticalAnchor.WindowBottom) {
topPixel = parentMaxY + this._topEdgeDistance;
} else if (this._topEdgeAnchor === VerticalAnchor.Proportional) {
topPixel = parentMinY + this._topEdgeDistance * parentHeight;
} else if (this._topEdgeAnchor === VerticalAnchor.WindowCenter) {
topPixel = parentCenterY + this._topEdgeDistance;
}
// Right edge
if (this._rightEdgeAnchor === HorizontalAnchor.WindowLeft) {
rightPixel = parentMinX + this._rightEdgeDistance;
} else if (this._rightEdgeAnchor === HorizontalAnchor.WindowRight) {
rightPixel = parentMaxX + this._rightEdgeDistance;
} else if (this._rightEdgeAnchor === HorizontalAnchor.Proportional) {
rightPixel = parentMinX + this._rightEdgeDistance * parentWidth;
} else if (this._rightEdgeAnchor === HorizontalAnchor.WindowCenter) {
rightPixel = parentCenterX + this._rightEdgeDistance;
}
// Bottom edge
if (this._bottomEdgeAnchor === VerticalAnchor.WindowTop) {
bottomPixel = parentMinY + this._bottomEdgeDistance;
} else if (this._bottomEdgeAnchor === VerticalAnchor.WindowBottom) {
bottomPixel = parentMaxY + this._bottomEdgeDistance;
} else if (this._bottomEdgeAnchor === VerticalAnchor.Proportional) {
bottomPixel = parentMinY + this._bottomEdgeDistance * parentHeight;
} else if (this._bottomEdgeAnchor === VerticalAnchor.WindowCenter) {
bottomPixel = parentCenterY + this._bottomEdgeDistance;
}
// It's fine to reuse workingPoint as topLeftPixel is no longer used.
const topLeftCoord = this._convertCoords(
instanceContainer,
layer,
leftPixel,
topPixel,
workingPoint
);
let left = topLeftCoord[0];
let top = topLeftCoord[1];
const bottomRightCoord = this._convertCoords(
instanceContainer,
layer,
rightPixel,
bottomPixel,
workingPoint
);
const right = bottomRightCoord[0];
const bottom = bottomRightCoord[1];
// Compatibility with GD <= 5.0.133
if (this._useLegacyBottomAndRightAnchors) {
//Move and resize the object according to the anchors
if (this._rightEdgeAnchor !== HorizontalAnchor.None) {
this.owner.setWidth(right - left);
if (this._invalidDistances) {
if (this._relativeToOriginalWindowSize) {
parentMinX = instanceContainer.getInitialUnrotatedViewportMinX();
parentMinY = instanceContainer.getInitialUnrotatedViewportMinY();
parentMaxX = instanceContainer.getInitialUnrotatedViewportMaxX();
parentMaxY = instanceContainer.getInitialUnrotatedViewportMaxY();
parentCenterX = (parentMaxX + parentMinX) / 2;
parentCenterY = (parentMaxY + parentMinY) / 2;
parentWidth = parentMaxX - parentMinX;
parentHeight = parentMaxY - parentMinY;
}
if (this._bottomEdgeAnchor !== VerticalAnchor.None) {
this.owner.setHeight(bottom - top);
//Calculate the distances from the window's bounds.
const topLeftPixel = this._relativeToOriginalWindowSize
? [this.owner.getDrawableX(), this.owner.getDrawableY()]
: this._convertInverseCoords(
instanceContainer,
layer,
this.owner.getDrawableX(),
this.owner.getDrawableY(),
workingPoint
);
// Left edge
if (this._leftEdgeAnchor === HorizontalAnchor.WindowLeft) {
this._leftEdgeDistance = topLeftPixel[0] - parentMinX;
} else if (this._leftEdgeAnchor === HorizontalAnchor.WindowRight) {
this._leftEdgeDistance = topLeftPixel[0] - parentMaxX;
} else if (this._leftEdgeAnchor === HorizontalAnchor.Proportional) {
this._leftEdgeDistance = (topLeftPixel[0] - parentMinX) / parentWidth;
} else if (this._leftEdgeAnchor === HorizontalAnchor.WindowCenter) {
this._leftEdgeDistance = topLeftPixel[0] - parentCenterX;
}
if (this._leftEdgeAnchor !== HorizontalAnchor.None) {
this.owner.setX(left + this.owner.getX() - this.owner.getDrawableX());
// Top edge
if (this._topEdgeAnchor === VerticalAnchor.WindowTop) {
this._topEdgeDistance = topLeftPixel[1] - parentMinY;
} else if (this._topEdgeAnchor === VerticalAnchor.WindowBottom) {
this._topEdgeDistance = topLeftPixel[1] - parentMaxY;
} else if (this._topEdgeAnchor === VerticalAnchor.Proportional) {
this._topEdgeDistance = (topLeftPixel[1] - parentMinY) / parentHeight;
} else if (this._topEdgeAnchor === VerticalAnchor.WindowCenter) {
this._topEdgeDistance = topLeftPixel[1] - parentCenterY;
}
if (this._topEdgeAnchor !== VerticalAnchor.None) {
this.owner.setY(top + this.owner.getY() - this.owner.getDrawableY());
// It's fine to reuse workingPoint as topLeftPixel is no longer used.
const bottomRightPixel = this._relativeToOriginalWindowSize
? [
this.owner.getDrawableX() + this.owner.getWidth(),
this.owner.getDrawableY() + this.owner.getHeight(),
]
: this._convertInverseCoords(
instanceContainer,
layer,
this.owner.getDrawableX() + this.owner.getWidth(),
this.owner.getDrawableY() + this.owner.getHeight(),
workingPoint
);
// Right edge
if (this._rightEdgeAnchor === HorizontalAnchor.WindowLeft) {
this._rightEdgeDistance = bottomRightPixel[0] - parentMinX;
} else if (this._rightEdgeAnchor === HorizontalAnchor.WindowRight) {
this._rightEdgeDistance = bottomRightPixel[0] - parentMaxX;
} else if (this._rightEdgeAnchor === HorizontalAnchor.Proportional) {
this._rightEdgeDistance =
(bottomRightPixel[0] - parentMinX) / parentWidth;
} else if (this._rightEdgeAnchor === HorizontalAnchor.WindowCenter) {
this._rightEdgeDistance = bottomRightPixel[0] - parentCenterX;
}
}
// End of compatibility code
else {
// Resize if right and left anchors are set
if (
this._rightEdgeAnchor !== HorizontalAnchor.None &&
this._leftEdgeAnchor !== HorizontalAnchor.None
) {
const width = right - left;
this.owner.setX(
this.owner.getX() === this.owner.getDrawableX()
? left
: // It uses the position of the origin relatively to the object
// size to apply it with the new size.
// This is the same as doing:
// lerp(left, right, (this.owner.getX() - this.owner.getDrawableX() / this.owner.getWidth())
// But, the division is done at the end to avoid rounding errors.
left +
((this.owner.getX() - this.owner.getDrawableX()) * width) /
this.owner.getWidth()
);
this.owner.setWidth(width);
} else {
// Bottom edge
if (this._bottomEdgeAnchor === VerticalAnchor.WindowTop) {
this._bottomEdgeDistance = bottomRightPixel[1] - parentMinY;
} else if (this._bottomEdgeAnchor === VerticalAnchor.WindowBottom) {
this._bottomEdgeDistance = bottomRightPixel[1] - parentMaxY;
} else if (this._bottomEdgeAnchor === VerticalAnchor.Proportional) {
this._bottomEdgeDistance =
(bottomRightPixel[1] - parentMinY) / parentHeight;
} else if (this._bottomEdgeAnchor === VerticalAnchor.WindowCenter) {
this._bottomEdgeDistance = bottomRightPixel[1] - parentCenterY;
}
this._invalidDistances = false;
} else {
//Move and resize the object if needed
let leftPixel = 0;
let topPixel = 0;
let rightPixel = 0;
let bottomPixel = 0;
// Left edge
if (this._leftEdgeAnchor === HorizontalAnchor.WindowLeft) {
leftPixel = parentMinX + this._leftEdgeDistance;
} else if (this._leftEdgeAnchor === HorizontalAnchor.WindowRight) {
leftPixel = parentMaxX + this._leftEdgeDistance;
} else if (this._leftEdgeAnchor === HorizontalAnchor.Proportional) {
leftPixel = parentMinX + this._leftEdgeDistance * parentWidth;
} else if (this._leftEdgeAnchor === HorizontalAnchor.WindowCenter) {
leftPixel = parentCenterX + this._leftEdgeDistance;
}
// Top edge
if (this._topEdgeAnchor === VerticalAnchor.WindowTop) {
topPixel = parentMinY + this._topEdgeDistance;
} else if (this._topEdgeAnchor === VerticalAnchor.WindowBottom) {
topPixel = parentMaxY + this._topEdgeDistance;
} else if (this._topEdgeAnchor === VerticalAnchor.Proportional) {
topPixel = parentMinY + this._topEdgeDistance * parentHeight;
} else if (this._topEdgeAnchor === VerticalAnchor.WindowCenter) {
topPixel = parentCenterY + this._topEdgeDistance;
}
// Right edge
if (this._rightEdgeAnchor === HorizontalAnchor.WindowLeft) {
rightPixel = parentMinX + this._rightEdgeDistance;
} else if (this._rightEdgeAnchor === HorizontalAnchor.WindowRight) {
rightPixel = parentMaxX + this._rightEdgeDistance;
} else if (this._rightEdgeAnchor === HorizontalAnchor.Proportional) {
rightPixel = parentMinX + this._rightEdgeDistance * parentWidth;
} else if (this._rightEdgeAnchor === HorizontalAnchor.WindowCenter) {
rightPixel = parentCenterX + this._rightEdgeDistance;
}
// Bottom edge
if (this._bottomEdgeAnchor === VerticalAnchor.WindowTop) {
bottomPixel = parentMinY + this._bottomEdgeDistance;
} else if (this._bottomEdgeAnchor === VerticalAnchor.WindowBottom) {
bottomPixel = parentMaxY + this._bottomEdgeDistance;
} else if (this._bottomEdgeAnchor === VerticalAnchor.Proportional) {
bottomPixel = parentMinY + this._bottomEdgeDistance * parentHeight;
} else if (this._bottomEdgeAnchor === VerticalAnchor.WindowCenter) {
bottomPixel = parentCenterY + this._bottomEdgeDistance;
}
// It's fine to reuse workingPoint as topLeftPixel is no longer used.
const topLeftCoord = this._convertCoords(
instanceContainer,
layer,
leftPixel,
topPixel,
workingPoint
);
let left = topLeftCoord[0];
let top = topLeftCoord[1];
const bottomRightCoord = this._convertCoords(
instanceContainer,
layer,
rightPixel,
bottomPixel,
workingPoint
);
const right = bottomRightCoord[0];
const bottom = bottomRightCoord[1];
// Compatibility with GD <= 5.0.133
if (this._useLegacyBottomAndRightAnchors) {
//Move and resize the object according to the anchors
if (this._rightEdgeAnchor !== HorizontalAnchor.None) {
this.owner.setWidth(right - left);
}
if (this._bottomEdgeAnchor !== VerticalAnchor.None) {
this.owner.setHeight(bottom - top);
}
if (this._leftEdgeAnchor !== HorizontalAnchor.None) {
this.owner.setX(
left + this.owner.getX() - this.owner.getDrawableX()
);
}
if (this._rightEdgeAnchor !== HorizontalAnchor.None) {
this.owner.setX(
right +
this.owner.getX() -
this.owner.getDrawableX() -
this.owner.getWidth()
);
}
}
// Resize if top and bottom anchors are set
if (
this._bottomEdgeAnchor !== VerticalAnchor.None &&
this._topEdgeAnchor !== VerticalAnchor.None
) {
const height = bottom - top;
this.owner.setY(
this.owner.getY() === this.owner.getDrawableY()
? top
: top +
((this.owner.getY() - this.owner.getDrawableY()) * height) /
this.owner.getHeight()
);
this.owner.setHeight(height);
} else {
if (this._topEdgeAnchor !== VerticalAnchor.None) {
this.owner.setY(
top + this.owner.getY() - this.owner.getDrawableY()
);
}
if (this._bottomEdgeAnchor !== VerticalAnchor.None) {
this.owner.setY(
bottom +
this.owner.getY() -
this.owner.getDrawableY() -
this.owner.getHeight()
}
// End of compatibility code
else {
// Resize if right and left anchors are set
if (
this._rightEdgeAnchor !== HorizontalAnchor.None &&
this._leftEdgeAnchor !== HorizontalAnchor.None
) {
const width = right - left;
this.owner.setX(
this.owner.getX() === this.owner.getDrawableX()
? left
: // It uses the position of the origin relatively to the object
// size to apply it with the new size.
// This is the same as doing:
// lerp(left, right, (this.owner.getX() - this.owner.getDrawableX() / this.owner.getWidth())
// But, the division is done at the end to avoid rounding errors.
left +
((this.owner.getX() - this.owner.getDrawableX()) * width) /
this.owner.getWidth()
);
this.owner.setWidth(width);
} else {
if (this._leftEdgeAnchor !== HorizontalAnchor.None) {
this.owner.setX(
left + this.owner.getX() - this.owner.getDrawableX()
);
}
if (this._rightEdgeAnchor !== HorizontalAnchor.None) {
this.owner.setX(
right +
this.owner.getX() -
this.owner.getDrawableX() -
this.owner.getWidth()
);
}
}
// Resize if top and bottom anchors are set
if (
this._bottomEdgeAnchor !== VerticalAnchor.None &&
this._topEdgeAnchor !== VerticalAnchor.None
) {
const height = bottom - top;
this.owner.setY(
this.owner.getY() === this.owner.getDrawableY()
? top
: top +
((this.owner.getY() - this.owner.getDrawableY()) * height) /
this.owner.getHeight()
);
this.owner.setHeight(height);
} else {
if (this._topEdgeAnchor !== VerticalAnchor.None) {
this.owner.setY(
top + this.owner.getY() - this.owner.getDrawableY()
);
}
if (this._bottomEdgeAnchor !== VerticalAnchor.None) {
this.owner.setY(
bottom +
this.owner.getY() -
this.owner.getDrawableY() -
this.owner.getHeight()
);
}
}
}
}
this._parentOldMinX = instanceContainer.getUnrotatedViewportMinX();
this._parentOldMinY = instanceContainer.getUnrotatedViewportMinY();
this._parentOldMaxX = instanceContainer.getUnrotatedViewportMaxX();
this._parentOldMaxY = instanceContainer.getUnrotatedViewportMaxY();
}
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {}

View File

@@ -1,47 +0,0 @@
// @ts-check
describe('gdjs.AnchorRuntimeBehavior', () => {
it('can fill a custom object with an child', async () => {
const runtimeGame = await gdjs.getPixiRuntimeGameWithAssets();
const runtimeScene = new gdjs.TestRuntimeScene(runtimeGame);
// The corresponding event-based object declaration is done by
// getPixiRuntimeGame.
const customObject = new gdjs.CustomRuntimeObject2D(runtimeScene, {
name: 'MyCustomObject',
type: 'MyExtension::MyLayoutedEventsBasedObject',
variant: '',
variables: [],
behaviors: [],
effects: [],
content: {},
childrenContent: {},
isInnerAreaFollowingParentSize: false,
});
runtimeScene.addObject(customObject);
customObject.setPosition(500, 250);
const childObjects = customObject
.getChildrenContainer()
.getObjects('MySprite');
if (!childObjects || childObjects.length === 0) {
throw new Error("Can't get child objects.");
}
const childObject = childObjects[0];
runtimeScene.renderAndStep(1000 / 60);
// The child object keeps its initial location.
expect(childObject.getX()).to.equal(0);
expect(childObject.getY()).to.equal(0);
expect(childObject.getWidth()).to.equal(64);
expect(childObject.getHeight()).to.equal(64);
customObject.setWidth(2000);
customObject.setHeight(3000);
runtimeScene.renderAndStep(1000 / 60);
expect(childObject.getX()).to.equal(0);
expect(childObject.getY()).to.equal(0);
expect(childObject.getWidth()).to.equal(2000);
expect(childObject.getHeight()).to.equal(3000);
});
});

View File

@@ -1,49 +1,39 @@
// @ts-check
describe('gdjs.AnchorRuntimeBehavior', () => {
describe('gdjs.AnchorRuntimeBehavior', function () {
const runtimeGame = gdjs.getPixiRuntimeGame({
propertiesOverrides: { windowHeight: 1000, windowWidth: 1000 },
});
const anchorBehaviorName = 'Anchor';
/** @type {gdjs.RuntimeGame} */
let runtimeGame;
/** @type {gdjs.RuntimeScene} */
let runtimeScene;
/** @type {gdjs.RuntimeLayer} */
let layer;
beforeEach(() => {
runtimeGame = gdjs.getPixiRuntimeGame({
propertiesOverrides: { windowHeight: 1000, windowWidth: 1000 },
});
runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
sceneData: {
layers: [
{
name: '',
visibility: true,
cameras: [],
effects: [],
ambientLightColorR: 127,
ambientLightColorB: 127,
ambientLightColorG: 127,
isLightingLayer: false,
followBaseLayerCamera: false,
},
],
variables: [],
r: 0,
v: 0,
b: 0,
mangledName: 'Scene1',
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
behaviorsSharedData: [],
objects: [],
instances: [],
usedResources: [],
},
usedExtensionsWithVariablesData: [],
});
layer = runtimeScene.getLayer('');
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
sceneData: {
layers: [
{
name: '',
visibility: true,
cameras: [],
effects: [],
ambientLightColorR: 127,
ambientLightColorB: 127,
ambientLightColorG: 127,
isLightingLayer: false,
followBaseLayerCamera: false,
},
],
variables: [],
r: 0,
v: 0,
b: 0,
mangledName: 'Scene1',
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
behaviorsSharedData: [],
objects: [],
instances: [],
usedResources: [],
},
usedExtensionsWithVariablesData: [],
});
const setGameResolutionSizeAndStep = (width, height) => {
@@ -53,11 +43,6 @@ describe('gdjs.AnchorRuntimeBehavior', () => {
runtimeScene.renderAndStep(1000 / 60);
};
const setCamera = (x, y) => {
layer.setCameraX(x);
layer.setCameraY(y);
};
function createObject(behaviorProperties) {
const object = new gdjs.TestRuntimeObject(runtimeScene, {
name: 'obj1',
@@ -129,50 +114,10 @@ describe('gdjs.AnchorRuntimeBehavior', () => {
return object;
};
describe('(anchor horizontal edge)', () => {
describe('(basic)', () => {
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window left (fixed)`, () => {
const object = createObject({ [objectEdge]: 1 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window right (fixed)`, () => {
const object = createObject({ [objectEdge]: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window center (fixed)`, () => {
const object = createObject({ [objectEdge]: 4 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1000);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the right and left edge of an object (fixed)', () => {
const object = createObject({ leftEdgeAnchor: 1, rightEdgeAnchor: 2 });
describe('(anchor horizontal edge)', function () {
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window left (fixed)`, function () {
const object = createObject({ [objectEdge]: 1 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
@@ -180,11 +125,25 @@ describe('gdjs.AnchorRuntimeBehavior', () => {
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(1010);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window right (fixed)`, function () {
const object = createObject({ [objectEdge]: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
it('anchors the left edge of an object (proportional)', () => {
const object = createObject({ leftEdgeAnchor: 3 });
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window center (fixed)`, function () {
const object = createObject({ [objectEdge]: 4 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
@@ -195,267 +154,36 @@ describe('gdjs.AnchorRuntimeBehavior', () => {
expect(object.getWidth()).to.equal(10);
});
});
describe('(moving object)', () => {
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window left (fixed)`, () => {
const object = createObject({ [objectEdge]: 1 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setGameResolutionSizeAndStep(2000, 2000);
it('anchors the right and left edge of object (fixed)', function () {
const object = createObject({ leftEdgeAnchor: 1, rightEdgeAnchor: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window right (fixed)`, () => {
const object = createObject({ [objectEdge]: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 2000);
object.setPosition(600, 700);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1600);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window center (fixed)`, () => {
const object = createObject({ [objectEdge]: 4 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1100);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the right and left edge of an object (fixed)', () => {
const object = createObject({ leftEdgeAnchor: 1, rightEdgeAnchor: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(1010);
});
it('anchors the left edge of an object (proportional)', () => {
const object = createObject({ leftEdgeAnchor: 3 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1200);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(10);
});
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(1010);
});
describe('(moving camera)', () => {
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window left (fixed)`, () => {
const object = createObject({ [objectEdge]: 1 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
it('anchors the left edge of object (proportional)', function () {
const object = createObject({ leftEdgeAnchor: 3 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(800);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window right (fixed)`, () => {
const object = createObject({ [objectEdge]: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 2000);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1800);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window center (fixed)`, () => {
const object = createObject({ [objectEdge]: 4 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1300);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the right and left edge of an object (fixed)', () => {
const object = createObject({ leftEdgeAnchor: 1, rightEdgeAnchor: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(800);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(1010);
});
it('anchors the left edge of an object (proportional)', () => {
const object = createObject({ leftEdgeAnchor: 3 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1300);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
describe('(moving object and camera)', () => {
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window left (fixed)`, () => {
const object = createObject({ [objectEdge]: 1 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(900);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window right (fixed)`, () => {
const object = createObject({ [objectEdge]: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1900);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of an object to window center (fixed)`, () => {
const object = createObject({ [objectEdge]: 4 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1400);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the right and left edge of an object (fixed)', () => {
const object = createObject({ leftEdgeAnchor: 1, rightEdgeAnchor: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(900);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(1010);
});
it('anchors the left edge of an object (proportional)', () => {
const object = createObject({ leftEdgeAnchor: 3 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(1500);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(10);
});
expect(object.getX()).to.equal(1000);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
describe('(anchor vertical edge)', () => {
describe('(basic)', () => {
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window top (fixed)`, () => {
const object = createObject({ [objectEdge]: 1 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window bottom (fixed)`, () => {
const object = createObject({ [objectEdge]: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1500);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window center (fixed)`, () => {
const object = createObject({ [objectEdge]: 4 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1000);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the top and bottom edge of object (fixed)', () => {
const object = createObject({ topEdgeAnchor: 1, bottomEdgeAnchor: 2 });
describe('(anchor vertical edge)', function () {
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window top (fixed)`, function () {
const object = createObject({ [objectEdge]: 1 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
@@ -463,11 +191,25 @@ describe('gdjs.AnchorRuntimeBehavior', () => {
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getHeight()).to.equal(1010);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window bottom (fixed)`, function () {
const object = createObject({ [objectEdge]: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
it('anchors the top edge of object (proportional)', () => {
const object = createObject({ topEdgeAnchor: 3 });
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1500);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window center (fixed)`, function () {
const object = createObject({ [objectEdge]: 4 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
@@ -478,262 +220,71 @@ describe('gdjs.AnchorRuntimeBehavior', () => {
expect(object.getWidth()).to.equal(10);
});
});
describe('(moving object)', () => {
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window top (fixed)`, () => {
const object = createObject({ [objectEdge]: 1 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setGameResolutionSizeAndStep(2000, 2000);
it('anchors the top and bottom edge of object (fixed)', function () {
const object = createObject({ topEdgeAnchor: 1, bottomEdgeAnchor: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(700);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window bottom (fixed)`, () => {
const object = createObject({ [objectEdge]: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 2000);
object.setPosition(600, 700);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(1700);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window center (fixed)`, () => {
const object = createObject({ [objectEdge]: 4 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(1200);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the top and bottom edge of object (fixed)', () => {
const object = createObject({ topEdgeAnchor: 1, bottomEdgeAnchor: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(700);
expect(object.getHeight()).to.equal(1010);
});
it('anchors the top edge of object (proportional)', () => {
const object = createObject({ topEdgeAnchor: 3 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(1400);
expect(object.getWidth()).to.equal(10);
});
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getHeight()).to.equal(1010);
});
describe('(moving camera)', () => {
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window top (fixed)`, () => {
const object = createObject({ [objectEdge]: 1 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
it('anchors the top edge of object (proportional)', function () {
const object = createObject({ topEdgeAnchor: 3 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(900);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window bottom (fixed)`, () => {
const object = createObject({ [objectEdge]: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 2000);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1900);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window center (fixed)`, () => {
const object = createObject({ [objectEdge]: 4 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1400);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the top and bottom edge of object (fixed)', () => {
const object = createObject({ topEdgeAnchor: 1, bottomEdgeAnchor: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(900);
expect(object.getHeight()).to.equal(1010);
});
it('anchors the top edge of object (proportional)', () => {
const object = createObject({ topEdgeAnchor: 3 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1400);
expect(object.getWidth()).to.equal(10);
});
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1000);
expect(object.getWidth()).to.equal(10);
});
describe('(moving object and camera)', () => {
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window top (fixed)`, () => {
const object = createObject({ [objectEdge]: 1 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
it('can fill the screen with an object (with custom origin)', function () {
setGameResolutionSizeAndStep(1000, 500);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(1100);
expect(object.getWidth()).to.equal(10);
});
const object = createSpriteWithOriginAtCenter({
leftEdgeAnchor: 1,
topEdgeAnchor: 1,
rightEdgeAnchor: 2,
bottomEdgeAnchor: 2,
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window bottom (fixed)`, () => {
const object = createObject({ [objectEdge]: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setCustomWidthAndHeight(1000, 500);
object.setPosition(500, 250);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
setGameResolutionSizeAndStep(2000, 3000);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(2100);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window center (fixed)`, () => {
const object = createObject({ [objectEdge]: 4 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(1600);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the top and bottom edge of object (fixed)', () => {
const object = createObject({ topEdgeAnchor: 1, bottomEdgeAnchor: 2 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(1100);
expect(object.getHeight()).to.equal(1010);
});
it('anchors the top edge of object (proportional)', () => {
const object = createObject({ topEdgeAnchor: 3 });
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
object.setPosition(600, 700);
setCamera(1300, 1400);
setGameResolutionSizeAndStep(2000, 2000);
expect(object.getX()).to.equal(600);
expect(object.getY()).to.equal(1800);
expect(object.getWidth()).to.equal(10);
});
expect(object.getX()).to.equal(1000);
expect(object.getY()).to.equal(1500);
expect(object.getWidth()).to.equal(2000);
expect(object.getHeight()).to.equal(3000);
});
});
it('can fill the screen with an object (with custom origin)', () => {
setGameResolutionSizeAndStep(1000, 500);
it('can fill the screen with an object using proportional anchors (with custom origin)', () => {
setGameResolutionSizeAndStep(1000, 500);
const object = createSpriteWithOriginAtCenter({
leftEdgeAnchor: 1,
topEdgeAnchor: 1,
rightEdgeAnchor: 2,
bottomEdgeAnchor: 2,
const object = createSpriteWithOriginAtCenter({
leftEdgeAnchor: 3,
topEdgeAnchor: 3,
rightEdgeAnchor: 3,
bottomEdgeAnchor: 3,
});
object.setCustomWidthAndHeight(1000, 500);
object.setPosition(500, 250);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 3000);
expect(object.getX()).to.equal(1000);
expect(object.getY()).to.equal(1500);
expect(object.getWidth()).to.equal(2000);
expect(object.getHeight()).to.equal(3000);
});
object.setCustomWidthAndHeight(1000, 500);
object.setPosition(500, 250);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 3000);
expect(object.getX()).to.equal(1000);
expect(object.getY()).to.equal(1500);
expect(object.getWidth()).to.equal(2000);
expect(object.getHeight()).to.equal(3000);
});
it('can fill the screen with an object using proportional anchors (with custom origin)', () => {
setGameResolutionSizeAndStep(1000, 500);
const object = createSpriteWithOriginAtCenter({
leftEdgeAnchor: 3,
topEdgeAnchor: 3,
rightEdgeAnchor: 3,
bottomEdgeAnchor: 3,
});
object.setCustomWidthAndHeight(1000, 500);
object.setPosition(500, 250);
runtimeScene.renderAndStep(1000 / 60);
setGameResolutionSizeAndStep(2000, 3000);
expect(object.getX()).to.equal(1000);
expect(object.getY()).to.equal(1500);
expect(object.getWidth()).to.equal(2000);
expect(object.getHeight()).to.equal(3000);
});
});

View File

@@ -54,7 +54,7 @@ module.exports = {
objectProperties
.getOrCreate('text')
.setValue(objectContent.text)
.setType('multilinestring')
.setType('textarea')
.setLabel(_('BBCode text'));
objectProperties
@@ -81,19 +81,6 @@ module.exports = {
.setLabel(_('Base alignment'))
.setGroup(_('Appearance'));
if (!objectContent.verticalTextAlignment) {
objectContent.verticalTextAlignment = 'top';
}
objectProperties
.getOrCreate('verticalTextAlignment')
.setValue(objectContent.verticalTextAlignment)
.setType('choice')
.addExtraInfo('top')
.addExtraInfo('center')
.addExtraInfo('bottom')
.setLabel(_('Vertical alignment'))
.setGroup(_('Appearance'));
objectProperties
.getOrCreate('fontFamily')
.setValue(objectContent.fontFamily)
@@ -102,6 +89,13 @@ module.exports = {
.setLabel(_('Font'))
.setGroup(_('Font'));
objectProperties
.getOrCreate('wordWrap')
.setValue(objectContent.wordWrap ? 'true' : 'false')
.setType('boolean')
.setLabel(_('Word wrapping'))
.setGroup(_('Appearance'));
objectProperties
.getOrCreate('visible')
.setValue(objectContent.visible ? 'true' : 'false')
@@ -112,14 +106,15 @@ module.exports = {
return objectProperties;
};
objectBBText.content = {
text: '[b]bold[/b] [i]italic[/i] [size=15]smaller[/size] [font=times]times[/font] font\n[spacing=12]spaced out[/spacing]\n[outline=yellow]outlined[/outline] [shadow=red]DropShadow[/shadow] ',
text:
'[b]bold[/b] [i]italic[/i] [size=15]smaller[/size] [font=times]times[/font] font\n[spacing=12]spaced out[/spacing]\n[outline=yellow]outlined[/outline] [shadow=red]DropShadow[/shadow] ',
opacity: 255,
fontSize: 20,
visible: true,
color: '0;0;0',
fontFamily: 'Arial',
align: 'left',
verticalTextAlignment: 'top',
wordWrap: true,
};
objectBBText.updateInitialInstanceProperty = function (
@@ -198,10 +193,9 @@ module.exports = {
parameterType === 'string' ||
parameterType === 'stringWithSelector'
) {
const parameterOptions =
gd.ParameterOptions.makeNewOptions().setDescription(
property.paramLabel
);
const parameterOptions = gd.ParameterOptions.makeNewOptions().setDescription(
property.paramLabel
);
if (property.options) {
parameterOptions.setTypeExtraInfo(
stringifyOptions(property.options)
@@ -251,10 +245,9 @@ module.exports = {
parameterType === 'number' ||
parameterType === 'stringWithSelector'
) {
const parameterOptions =
gd.ParameterOptions.makeNewOptions().setDescription(
property.paramLabel
);
const parameterOptions = gd.ParameterOptions.makeNewOptions().setDescription(
property.paramLabel
);
if (property.options) {
parameterOptions.setTypeExtraInfo(
stringifyOptions(property.options)
@@ -377,6 +370,19 @@ module.exports = {
expressionLabel: _('Get the text alignment'),
expressionDescription: _('Get the text alignment'),
},
{
functionName: 'WordWrap',
iconPath: 'res/actions/scaleWidth24_black.png',
type: 'boolean',
instructionLabel: _('Word wrap'),
paramLabel: _('Word wrap'),
conditionDescription: _('Check if word wrap is enabled.'),
conditionSentence: _('Word wrap is enabled'),
actionDescription: _('Set word wrap'),
actionSentence: _('Activate word wrap for _PARAM0_: _PARAM1_'),
expressionLabel: '',
expressionDescription: '',
},
{
functionName: 'WrappingWidth',
iconPath: 'res/actions/scaleWidth24_black.png',
@@ -398,35 +404,6 @@ module.exports = {
addSettersAndGettersToObject(object, setterAndGetterProperties, 'BBText');
object
.addCondition(
'IsWordWrap',
_('Word wrapping'),
_('Check if word wrapping is enabled.'),
_('_PARAM0_ word wrapping is enabled'),
'',
'res/conditions/wordWrap24_black.png',
'res/conditions/wordWrap_black.png'
)
.addParameter('object', 'BBText', 'BBText', false)
.getCodeExtraInformation()
.setFunctionName('isWrapping');
object
.addAction(
'SetWordWrap',
_('Word wrapping'),
_('De/activate word wrapping.'),
_('Activate word wrapping of _PARAM0_: _PARAM1_'),
'',
'res/actions/wordWrap24_black.png',
'res/actions/wordWrap_black.png'
)
.addParameter('object', 'BBText', 'BBText', false)
.addParameter('yesorno', _('Activate word wrapping'), '', false)
.getCodeExtraInformation()
.setFunctionName('setWrapping');
object
.addAction(
`SetFontFamily2`,
@@ -507,16 +484,14 @@ module.exports = {
instance,
associatedObjectConfiguration,
pixiContainer,
pixiResourcesLoader,
propertyOverridings
pixiResourcesLoader
) {
super(
project,
instance,
associatedObjectConfiguration,
pixiContainer,
pixiResourcesLoader,
propertyOverridings
pixiResourcesLoader
);
const bbTextStyles = {
@@ -526,6 +501,7 @@ module.exports = {
fontSize: '24px',
fill: '#cccccc',
tagStyle: 'bbcode',
wordWrap: true,
wordWrapWidth: 250, // This value is the default wrapping width of the runtime object.
align: 'left',
},
@@ -555,9 +531,7 @@ module.exports = {
gd.ObjectJsImplementation
);
const rawText = this._propertyOverridings.has('Text')
? this._propertyOverridings.get('Text')
: object.content.text;
const rawText = object.content.text;
if (rawText !== this._pixiObject.text) {
this._pixiObject.text = rawText;
}
@@ -599,18 +573,11 @@ module.exports = {
});
}
const wordWrap = this._instance.hasCustomSize();
const wordWrap = object.content.wordWrap;
if (wordWrap !== this._pixiObject._style.wordWrap) {
this._pixiObject._style.wordWrap = wordWrap;
this._pixiObject.dirty = true;
}
if (this._instance.hasCustomSize()) {
const customWidth = this.getCustomWidth();
if (this._pixiObject._style.wordWrapWidth !== customWidth) {
this._pixiObject._style.wordWrapWidth = customWidth;
this._pixiObject.dirty = true;
}
}
const align = object.content.align;
if (align !== this._pixiObject._style.align) {
@@ -618,42 +585,25 @@ module.exports = {
this._pixiObject.dirty = true;
}
if (this._instance.hasCustomSize() && this._pixiObject.width !== 0) {
const alignmentX =
object.content.align === 'right'
? 1
: object.content.align === 'center'
? 0.5
: 0;
const width = this.getCustomWidth();
// A vector from the custom size center to the renderer center.
const centerToCenterX =
(width - this._pixiObject.width) * (alignmentX - 0.5);
this._pixiObject.position.x = this._instance.getX() + width / 2;
this._pixiObject.anchor.x =
0.5 - centerToCenterX / this._pixiObject.width;
} else {
this._pixiObject.position.x =
this._instance.getX() + this._pixiObject.width / 2;
this._pixiObject.anchor.x = 0.5;
}
const alignmentY =
object.content.verticalTextAlignment === 'bottom'
? 1
: object.content.verticalTextAlignment === 'center'
? 0.5
: 0;
this._pixiObject.position.x =
this._instance.getX() + this._pixiObject.width / 2;
this._pixiObject.position.y =
this._instance.getY() + this._pixiObject.height * (0.5 - alignmentY);
this._pixiObject.anchor.y = 0.5;
this._instance.getY() + this._pixiObject.height / 2;
this._pixiObject.rotation = RenderedInstance.toRad(
this._instance.getAngle()
);
if (this._instance.hasCustomSize() && this._pixiObject) {
const customWidth = this.getCustomWidth();
if (
this._pixiObject &&
this._pixiObject._style.wordWrapWidth !== customWidth
) {
this._pixiObject._style.wordWrapWidth = customWidth;
this._pixiObject.dirty = true;
}
}
// Do not hide completely an object so it can still be manipulated
const alphaForDisplay = Math.max(
this._instance.getOpacity() / 255,
@@ -675,19 +625,6 @@ module.exports = {
getDefaultHeight() {
return this._pixiObject.height;
}
getOriginY() {
const object = gd.castObject(
this._associatedObjectConfiguration,
gd.ObjectJsImplementation
);
const height = this.getHeight();
return object.content.verticalTextAlignment === 'bottom'
? height
: object.content.verticalTextAlignment === 'center'
? height / 2
: 0;
}
}
objectsRenderingService.registerInstanceRenderer(

View File

@@ -29,9 +29,9 @@ namespace gdjs {
runtimeObject._color[2]
),
tagStyle: 'bbcode',
wordWrap: runtimeObject._wrapping,
wordWrap: runtimeObject._wordWrap,
wordWrapWidth: runtimeObject._wrappingWidth,
align: runtimeObject._textAlign as PIXI.TextStyleAlign | undefined,
align: runtimeObject._align as PIXI.TextStyleAlign | undefined,
},
});
instanceContainer
@@ -39,7 +39,10 @@ namespace gdjs {
.getRenderer()
.addRendererObject(this._pixiObject, runtimeObject.getZOrder());
this.updateAlignment();
// Set the anchor in the center, so that the object rotates around
// its center
this._pixiObject.anchor.x = 0.5;
this._pixiObject.anchor.y = 0.5;
this.updateText();
this.updatePosition();
this.updateAngle();
@@ -52,7 +55,7 @@ namespace gdjs {
updateWordWrap(): void {
//@ts-ignore Private member usage.
this._pixiObject._style.wordWrap = this._object._wrapping;
this._pixiObject._style.wordWrap = this._object._wordWrap;
this._pixiObject.dirty = true;
this.updatePosition();
}
@@ -81,7 +84,7 @@ namespace gdjs {
updateAlignment(): void {
//@ts-ignore Private member usage.
this._pixiObject._style.align = this._object._textAlign;
this._pixiObject._style.align = this._object._align;
this._pixiObject.dirty = true;
}
@@ -103,38 +106,9 @@ namespace gdjs {
}
updatePosition(): void {
if (this._object.isWrapping() && this._pixiObject.width !== 0) {
const alignmentX =
this._object._textAlign === 'right'
? 1
: this._object._textAlign === 'center'
? 0.5
: 0;
const width = this._object.getWrappingWidth();
// A vector from the custom size center to the renderer center.
const centerToCenterX =
(width - this._pixiObject.width) * (alignmentX - 0.5);
this._pixiObject.position.x = this._object.x + width / 2;
this._pixiObject.anchor.x =
0.5 - centerToCenterX / this._pixiObject.width;
} else {
this._pixiObject.position.x =
this._object.x + this._pixiObject.width / 2;
this._pixiObject.anchor.x = 0.5;
}
const alignmentY =
this._object._verticalTextAlignment === 'bottom'
? 1
: this._object._verticalTextAlignment === 'center'
? 0.5
: 0;
this._pixiObject.position.x = this._object.x + this._pixiObject.width / 2;
this._pixiObject.position.y =
this._object.y + this._pixiObject.height * (0.5 - alignmentY);
this._pixiObject.anchor.y = 0.5;
this._object.y + this._pixiObject.height / 2;
}
updateAngle(): void {

View File

@@ -19,7 +19,6 @@ namespace gdjs {
wordWrap: boolean;
/** Alignment of the text: "left", "center" or "right" */
align: 'left' | 'center' | 'right';
verticalTextAlignment: 'top' | 'center' | 'bottom';
};
};
export type BBTextObjectData = ObjectData & BBTextObjectDataType;
@@ -33,7 +32,6 @@ namespace gdjs {
wwrap: boolean;
wwidth: float;
align: string;
vta: string;
hidden: boolean;
};
@@ -45,8 +43,7 @@ namespace gdjs {
*/
export class BBTextRuntimeObject
extends gdjs.RuntimeObject
implements gdjs.OpacityHandler
{
implements gdjs.OpacityHandler {
_opacity: float;
_text: string;
@@ -54,14 +51,13 @@ namespace gdjs {
/** color in format [r, g, b], where each component is in the range [0, 255] */
_color: integer[];
_fontFamily: string;
_fontSize: float;
_fontSize: number;
_wrapping: boolean = false;
_wordWrap: boolean;
_wrappingWidth: float = 250;
_textAlign: string;
_verticalTextAlignment: string;
// This value is the default wrapping width of the runtime object.
_align: string;
_renderer: gdjs.BBTextRuntimeObjectRenderer;
// While this should rather be exposed as a property for all objects, honor the "visible"
@@ -84,26 +80,24 @@ namespace gdjs {
this._fontFamily = objectData.content.fontFamily;
// @ts-ignore - parseFloat should not be required, but GDevelop 5.0 beta 92 and below were storing it as a string.
this._fontSize = parseFloat(objectData.content.fontSize);
this._textAlign = objectData.content.align;
this._verticalTextAlignment =
objectData.content.verticalTextAlignment || 'top';
this.hidden = !objectData.content.visible;
this._wordWrap = objectData.content.wordWrap;
this._align = objectData.content.align;
this._renderer = new gdjs.BBTextRuntimeObjectRenderer(
this,
instanceContainer
);
this.hidden = !objectData.content.visible;
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
}
override getRendererObject() {
getRendererObject() {
return this._renderer.getRendererObject();
}
// @ts-ignore
override updateFromObjectData(
updateFromObjectData(
oldObjectData: BBTextObjectDataType,
newObjectData: BBTextObjectDataType
): boolean {
@@ -129,23 +123,15 @@ namespace gdjs {
this.setFontSize(newObjectData.content.fontSize);
}
if (oldObjectData.content.wordWrap !== newObjectData.content.wordWrap) {
this.setWrapping(newObjectData.content.wordWrap);
this.setWordWrap(newObjectData.content.wordWrap);
}
if (oldObjectData.content.align !== newObjectData.content.align) {
this.setTextAlignment(newObjectData.content.align);
}
if (
oldObjectData.content.verticalTextAlignment !==
newObjectData.content.verticalTextAlignment
) {
this.setVerticalTextAlignment(
newObjectData.content.verticalTextAlignment
);
this.setAlignment(newObjectData.content.align);
}
return true;
}
override getNetworkSyncData(): BBTextObjectNetworkSyncData {
getNetworkSyncData(): BBTextObjectNetworkSyncData {
return {
...super.getNetworkSyncData(),
text: this._text,
@@ -153,15 +139,14 @@ namespace gdjs {
c: this._color,
ff: this._fontFamily,
fs: this._fontSize,
wwrap: this._wrapping,
wwrap: this._wordWrap,
wwidth: this._wrappingWidth,
align: this._textAlign,
vta: this._verticalTextAlignment,
align: this._align,
hidden: this.hidden,
};
}
override updateFromNetworkSyncData(
updateFromNetworkSyncData(
networkSyncData: BBTextObjectNetworkSyncData
): void {
super.updateFromNetworkSyncData(networkSyncData);
@@ -181,29 +166,26 @@ namespace gdjs {
if (this._fontSize !== undefined) {
this.setFontSize(networkSyncData.fs);
}
if (this._wrapping !== undefined) {
this.setWrapping(networkSyncData.wwrap);
if (this._wordWrap !== undefined) {
this.setWordWrap(networkSyncData.wwrap);
}
if (this._wrappingWidth !== undefined) {
this.setWrappingWidth(networkSyncData.wwidth);
}
if (this._textAlign !== undefined) {
this.setTextAlignment(networkSyncData.align);
}
if (this._verticalTextAlignment !== undefined) {
this.setVerticalTextAlignment(networkSyncData.vta);
if (this._align !== undefined) {
this.setAlignment(networkSyncData.align);
}
if (this.hidden !== undefined) {
this.hide(networkSyncData.hidden);
}
}
override extraInitializationFromInitialInstance(
initialInstanceData: InstanceData
) {
/**
* Initialize the extra parameters that could be set for an instance.
*/
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
if (initialInstanceData.customSize) {
this.setWrappingWidth(initialInstanceData.width);
this.setWrapping(true);
} else {
this.setWrappingWidth(
// This value is the default wrapping width of the runtime object.
@@ -215,7 +197,7 @@ namespace gdjs {
}
}
override onDestroyed(): void {
onDestroyed(): void {
super.onDestroyed();
this._renderer.destroy();
}
@@ -223,7 +205,7 @@ namespace gdjs {
/**
* Set the markup text to display.
*/
setBBText(text: string): void {
setBBText(text): void {
this._text = text;
this._renderer.updateText();
this.invalidateHitboxes();
@@ -236,7 +218,7 @@ namespace gdjs {
return this._text;
}
setColor(rgbColorString: string): void {
setColor(rgbColorString): void {
this._color = gdjs.rgbOrHexToRGBColor(rgbColorString);
this._renderer.updateColor();
}
@@ -249,7 +231,7 @@ namespace gdjs {
return this._color[0] + ';' + this._color[1] + ';' + this._color[2];
}
setFontSize(fontSize: float): void {
setFontSize(fontSize): void {
this._fontSize = fontSize;
this._renderer.updateFontSize();
}
@@ -258,66 +240,47 @@ namespace gdjs {
return this._fontSize;
}
setFontFamily(fontFamily: string): void {
setFontFamily(fontFamily): void {
this._fontFamily = fontFamily;
this._renderer.updateFontFamily();
}
getFontFamily(): string {
getFontFamily() {
return this._fontFamily;
}
/**
* @deprecated Use `setTextAlignment` instead
*/
setAlignment(align: string): void {
this.setTextAlignment(align);
}
setTextAlignment(align: string): void {
this._textAlign = align;
setAlignment(align): void {
this._align = align;
this._renderer.updateAlignment();
}
/**
* @deprecated Use `getTextAlignment` instead
*/
getAlignment(): string {
return this.getTextAlignment();
}
getTextAlignment(): string {
return this._textAlign;
getAlignment() {
return this._align;
}
/**
* Set the text alignment on Y axis for multiline text objects.
* @param alignment The text alignment.
* Set object position on X axis.
* @param x The new position X of the object.
*/
setVerticalTextAlignment(alignment: string): void {
this._verticalTextAlignment = alignment;
this._renderer.updatePosition();
}
/**
* Get the text alignment on Y axis of text object.
* @return The text alignment.
*/
getVerticalTextAlignment(): string {
return this._verticalTextAlignment;
}
override setX(x: float): void {
setX(x: float): void {
super.setX(x);
this._renderer.updatePosition();
}
override setY(y: float): void {
/**
* Set object position on Y axis.
* @param y The new position Y of the object.
*/
setY(y: float): void {
super.setY(y);
this._renderer.updatePosition();
}
override setAngle(angle: float): void {
/**
* Set the angle of the object.
* @param angle The new angle of the object.
*/
setAngle(angle: float): void {
super.setAngle(angle);
this._renderer.updateAngle();
}
@@ -363,36 +326,31 @@ namespace gdjs {
return this._wrappingWidth;
}
setWrapping(wordWrap: boolean): void {
if (this._wrapping === wordWrap) return;
setWordWrap(wordWrap: boolean): void {
if (this._wordWrap === wordWrap) return;
this._wrapping = wordWrap;
this._wordWrap = wordWrap;
this._renderer.updateWordWrap();
this.invalidateHitboxes();
}
isWrapping() {
return this._wrapping;
getWordWrap() {
return this._wordWrap;
}
override getWidth(): float {
return this._wrapping ? this._wrappingWidth : this._renderer.getWidth();
/**
* Get the width of the object.
*/
getWidth(): float {
return this._renderer.getWidth();
}
override getHeight(): float {
/**
* Get the height of the object.
*/
getHeight(): float {
return this._renderer.getHeight();
}
override getDrawableY(): float {
return (
this.getY() -
(this._verticalTextAlignment === 'center'
? this.getHeight() / 2
: this._verticalTextAlignment === 'bottom'
? this.getHeight()
: 0)
);
}
}
// @ts-ignore
gdjs.registerObject('BBText::BBText', gdjs.BBTextRuntimeObject);

View File

@@ -54,7 +54,7 @@ module.exports = {
objectProperties
.getOrCreate('text')
.setValue(objectContent.text)
.setType('multilinestring')
.setType('textarea')
.setLabel(_('Text'));
objectProperties
@@ -67,19 +67,6 @@ module.exports = {
.setLabel(_('Alignment'))
.setGroup(_('Appearance'));
if (!objectContent.verticalTextAlignment) {
objectContent.verticalTextAlignment = 'top';
}
objectProperties
.getOrCreate('verticalTextAlignment')
.setValue(objectContent.verticalTextAlignment)
.setType('choice')
.addExtraInfo('top')
.addExtraInfo('center')
.addExtraInfo('bottom')
.setLabel(_('Vertical alignment'))
.setGroup(_('Appearance'));
objectProperties
.getOrCreate('bitmapFontResourceName')
.setValue(objectContent.bitmapFontResourceName)
@@ -110,10 +97,18 @@ module.exports = {
.setLabel(_('Font tint'))
.setGroup(_('Font'));
objectProperties
.getOrCreate('wordWrap')
.setValue(objectContent.wordWrap ? 'true' : 'false')
.setType('boolean')
.setLabel(_('Word wrapping'))
.setGroup(_('Appearance'));
return objectProperties;
};
bitmapTextObject.content = {
text: 'This text use the default bitmap font.\nUse a custom Bitmap Font to create your own texts.',
text:
'This text use the default bitmap font.\nUse a custom Bitmap Font to create your own texts.',
opacity: 255,
scale: 1,
fontSize: 20,
@@ -121,7 +116,7 @@ module.exports = {
bitmapFontResourceName: '',
textureAtlasResourceName: '',
align: 'left',
verticalTextAlignment: 'top',
wordWrap: true,
};
bitmapTextObject.updateInitialInstanceProperty = function (
@@ -347,7 +342,7 @@ module.exports = {
_('Alignment ("left", "right" or "center")')
)
)
.setFunctionName('getTextAlignment');
.setFunctionName('getAlignment');
object
.addAction(
@@ -367,36 +362,36 @@ module.exports = {
false
)
.getCodeExtraInformation()
.setFunctionName('setTextAlignment');
.setFunctionName('setAlignment');
object
.addCondition(
'WordWrap',
_('Word wrapping'),
_('Check if word wrapping is enabled.'),
_('_PARAM0_ word wrapping is enabled'),
_('Word wrap'),
_('Check if word wrap is enabled.'),
_('_PARAM0_ word wrap is enabled'),
'',
'res/conditions/wordWrap24_black.png',
'res/conditions/wordWrap_black.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.getCodeExtraInformation()
.setFunctionName('isWrapping');
.setFunctionName('getWordWrap');
object
.addAction(
'SetWordWrap',
_('Word wrapping'),
_('Word wrap'),
_('De/activate word wrapping.'),
_('Activate word wrapping of _PARAM0_: _PARAM1_'),
_('Activate word wrap of _PARAM0_: _PARAM1_'),
'',
'res/actions/wordWrap24_black.png',
'res/actions/wordWrap_black.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.addParameter('yesorno', _('Activate word wrapping'), '', false)
.addParameter('yesorno', _('Activate word wrap'), '', false)
.getCodeExtraInformation()
.setFunctionName('setWrapping');
.setFunctionName('setWordWrap');
object
.addExpressionAndConditionAndAction(
@@ -630,16 +625,14 @@ module.exports = {
instance,
associatedObjectConfiguration,
pixiContainer,
pixiResourcesLoader,
propertyOverridings
pixiResourcesLoader
) {
super(
project,
instance,
associatedObjectConfiguration,
pixiContainer,
pixiResourcesLoader,
propertyOverridings
pixiResourcesLoader
);
// We'll track changes of the font to trigger the loading of the new font.
@@ -665,16 +658,16 @@ module.exports = {
// Update the rendered text properties (note: Pixi is only
// applying changes if there were changed).
this._pixiObject.text = this._propertyOverridings.has('Text')
? this._propertyOverridings.get('Text')
: object.content.text;
const rawText = object.content.text;
this._pixiObject.text = rawText;
const align = object.content.align;
this._pixiObject.align = align;
const color = object.content.tint;
this._pixiObject.tint =
objectsRenderingService.rgbOrHexToHexNumber(color);
this._pixiObject.tint = objectsRenderingService.rgbOrHexToHexNumber(
color
);
const scale = object.content.scale;
this._pixiObject.scale.set(scale);
@@ -713,45 +706,20 @@ module.exports = {
}
// Set up the wrapping width if enabled.
const oldMaxWidth = this._pixiObject.maxWidth;
this._pixiObject.maxWidth = this._instance.hasCustomSize()
? this.getCustomWidth() / this._pixiObject.scale.x
: 0;
if (oldMaxWidth !== this._pixiObject.maxWidth) {
const wordWrap = object.content.wordWrap;
if (wordWrap && this._instance.hasCustomSize()) {
this._pixiObject.maxWidth =
this.getCustomWidth() / this._pixiObject.scale.x;
this._pixiObject.dirty = true;
} else {
this._pixiObject.maxWidth = 0;
this._pixiObject.dirty = true;
}
if (this._instance.hasCustomSize() && this.getDefaultWidth() !== 0) {
const alignmentX =
object.content.align === 'right'
? 1
: object.content.align === 'center'
? 0.5
: 0;
const width = this.getCustomWidth();
const renderedWidth = this.getDefaultWidth();
// A vector from the custom size center to the renderer center.
const centerToCenterX = (width - renderedWidth) * (alignmentX - 0.5);
this._pixiObject.position.x = this._instance.getX() + width / 2;
this._pixiObject.anchor.x = 0.5 - centerToCenterX / renderedWidth;
} else {
this._pixiObject.position.x =
this._instance.getX() + this.getDefaultWidth() / 2;
this._pixiObject.anchor.x = 0.5;
}
const alignmentY =
object.content.verticalTextAlignment === 'bottom'
? 1
: object.content.verticalTextAlignment === 'center'
? 0.5
: 0;
this._pixiObject.position.x =
this._instance.getX() + (this._pixiObject.textWidth * scale) / 2;
this._pixiObject.position.y =
this._instance.getY() + this.getDefaultHeight() * (0.5 - alignmentY);
this._pixiObject.anchor.y = 0.5;
this._instance.getY() + (this._pixiObject.textHeight * scale) / 2;
this._pixiObject.rotation = RenderedInstance.toRad(
this._instance.getAngle()
);
@@ -772,25 +740,18 @@ module.exports = {
releaseBitmapFont(fontName);
}
/**
* Return the width of the instance, when it's not resized.
*/
getDefaultWidth() {
return this._pixiObject.textWidth * this._pixiObject.scale.x;
return this._pixiObject.width;
}
/**
* Return the height of the instance, when it's not resized.
*/
getDefaultHeight() {
return this._pixiObject.textHeight * this._pixiObject.scale.y;
}
getOriginY() {
const object = gd.castObject(
this._associatedObjectConfiguration,
gd.ObjectJsImplementation
);
const height = this.getHeight();
return object.content.verticalTextAlignment === 'bottom'
? height
: object.content.verticalTextAlignment === 'center'
? height / 2
: 0;
return this._pixiObject.height;
}
}

View File

@@ -35,6 +35,13 @@ namespace gdjs {
.getRenderer()
.addRendererObject(this._pixiObject, runtimeObject.getZOrder());
// Set the anchor in the center, so that the object rotates around
// its center.
// @ts-ignore
this._pixiObject.anchor.x = 0.5;
// @ts-ignore
this._pixiObject.anchor.y = 0.5;
this.updateAlignment();
this.updateTextContent();
this.updateAngle();
@@ -123,7 +130,7 @@ namespace gdjs {
}
updateWrappingWidth(): void {
if (this._object._wrapping) {
if (this._object._wordWrap) {
this._pixiObject.maxWidth =
this._object._wrappingWidth / this._object._scaleX;
this._pixiObject.dirty = true;
@@ -141,41 +148,13 @@ namespace gdjs {
updateAlignment(): void {
// @ts-ignore - assume align is always a valid value.
this._pixiObject.align = this._object._textAlign;
this._pixiObject.align = this._object._align;
this.updatePosition();
}
updatePosition(): void {
if (this._object.isWrapping() && this.getWidth() !== 0) {
const alignmentX =
this._object._textAlign === 'right'
? 1
: this._object._textAlign === 'center'
? 0.5
: 0;
const width = this._object.getWrappingWidth();
const renderedWidth = this.getWidth();
// A vector from the custom size center to the renderer center.
const centerToCenterX = (width - renderedWidth) * (alignmentX - 0.5);
this._pixiObject.position.x = this._object.x + width / 2;
this._pixiObject.anchor.x = 0.5 - centerToCenterX / renderedWidth;
} else {
this._pixiObject.position.x = this._object.x + this.getWidth() / 2;
this._pixiObject.anchor.x = 0.5;
}
const alignmentY =
this._object._verticalTextAlignment === 'bottom'
? 1
: this._object._verticalTextAlignment === 'center'
? 0.5
: 0;
this._pixiObject.position.y =
this._object.y + this.getHeight() * (0.5 - alignmentY);
this._pixiObject.anchor.y = 0.5;
this._pixiObject.position.x = this._object.x + this.getWidth() / 2;
this._pixiObject.position.y = this._object.y + this.getHeight() / 2;
}
updateAngle(): void {
@@ -194,6 +173,5 @@ namespace gdjs {
return this._pixiObject.textHeight * this.getScale();
}
}
export const BitmapTextRuntimeObjectRenderer =
BitmapTextRuntimeObjectPixiRenderer;
export const BitmapTextRuntimeObjectRenderer = BitmapTextRuntimeObjectPixiRenderer;
}

View File

@@ -15,11 +15,12 @@ namespace gdjs {
textureAtlasResourceName: string;
/** The scale of the text. */
scale: float;
/** Activate word wrap if set to true. */
wordWrap: boolean;
/** Wrapping with from custom size properties. */
wrappingWidth: float;
/** Alignment of the text. */
align: 'left' | 'center' | 'right';
verticalTextAlignment: 'top' | 'center' | 'bottom';
};
};
export type BitmapTextObjectData = ObjectData & BitmapTextObjectDataType;
@@ -34,7 +35,6 @@ namespace gdjs {
wwrap: boolean;
wwidth: float;
align: string;
vta: string;
};
export type BitmapTextObjectNetworkSyncData = ObjectNetworkSyncData &
@@ -52,8 +52,7 @@ namespace gdjs {
*/
export class BitmapTextRuntimeObject
extends gdjs.RuntimeObject
implements gdjs.TextContainer, gdjs.OpacityHandler, gdjs.Scalable
{
implements gdjs.TextContainer, gdjs.OpacityHandler, gdjs.Scalable {
_opacity: float;
_text: string;
/** color in format [r, g, b], where each component is in the range [0, 255] */
@@ -62,10 +61,9 @@ namespace gdjs {
_textureAtlasResourceName: string;
_scaleX: number;
_scaleY: number;
_wrapping: boolean = false;
_wordWrap: boolean;
_wrappingWidth: float;
_textAlign: string;
_verticalTextAlignment: string;
_align: string;
_renderer: gdjs.BitmapTextRuntimeObjectPixiRenderer;
@@ -88,10 +86,9 @@ namespace gdjs {
objectData.content.textureAtlasResourceName; // texture file used with fnt/xml (bitmap font file)
this._scaleX = objectData.content.scale;
this._scaleY = objectData.content.scale;
this._wordWrap = objectData.content.wordWrap;
this._wrappingWidth = 0;
this._textAlign = objectData.content.align;
this._verticalTextAlignment =
objectData.content.verticalTextAlignment || 'top';
this._align = objectData.content.align;
this._renderer = new gdjs.BitmapTextRuntimeObjectRenderer(
this,
@@ -102,12 +99,12 @@ namespace gdjs {
this.onCreated();
}
override getRendererObject() {
getRendererObject() {
return this._renderer.getRendererObject();
}
// @ts-ignore
override updateFromObjectData(
updateFromObjectData(
oldObjectData: BitmapTextObjectDataType,
newObjectData: BitmapTextObjectDataType
): boolean {
@@ -140,22 +137,17 @@ namespace gdjs {
if (oldObjectData.content.scale !== newObjectData.content.scale) {
this.setScale(newObjectData.content.scale);
}
if (oldObjectData.content.align !== newObjectData.content.align) {
this.setTextAlignment(newObjectData.content.align);
if (oldObjectData.content.wordWrap !== newObjectData.content.wordWrap) {
this.setWordWrap(newObjectData.content.wordWrap);
}
if (
oldObjectData.content.verticalTextAlignment !==
newObjectData.content.verticalTextAlignment
) {
this.setVerticalTextAlignment(
newObjectData.content.verticalTextAlignment
);
if (oldObjectData.content.align !== newObjectData.content.align) {
this.setAlignment(newObjectData.content.align);
}
return true;
}
override getNetworkSyncData(): BitmapTextObjectNetworkSyncData {
getNetworkSyncData(): BitmapTextObjectNetworkSyncData {
return {
...super.getNetworkSyncData(),
text: this._text,
@@ -164,14 +156,13 @@ namespace gdjs {
bfrn: this._bitmapFontResourceName,
tarn: this._textureAtlasResourceName,
scale: this.getScale(),
wwrap: this._wrapping,
wwrap: this._wordWrap,
wwidth: this._wrappingWidth,
align: this._textAlign,
vta: this._verticalTextAlignment,
align: this._align,
};
}
override updateFromNetworkSyncData(
updateFromNetworkSyncData(
networkSyncData: BitmapTextObjectNetworkSyncData
): void {
super.updateFromNetworkSyncData(networkSyncData);
@@ -194,36 +185,30 @@ namespace gdjs {
if (this._scaleX !== undefined) {
this.setScale(networkSyncData.scale);
}
if (this._wrapping !== undefined) {
this.setWrapping(networkSyncData.wwrap);
if (this._wordWrap !== undefined) {
this.setWordWrap(networkSyncData.wwrap);
}
if (this._wrappingWidth !== undefined) {
this.setWrappingWidth(networkSyncData.wwidth);
}
if (this._textAlign !== undefined) {
this.setTextAlignment(networkSyncData.align);
}
if (this._verticalTextAlignment !== undefined) {
this.setVerticalTextAlignment(networkSyncData.vta);
if (this._align !== undefined) {
this.setAlignment(networkSyncData.align);
}
}
/**
* Initialize the extra parameters that could be set for an instance.
*/
override extraInitializationFromInitialInstance(
initialInstanceData: InstanceData
) {
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
if (initialInstanceData.customSize) {
this.setWrappingWidth(initialInstanceData.width);
this.setWrapping(true);
}
if (initialInstanceData.opacity !== undefined) {
this.setOpacity(initialInstanceData.opacity);
}
}
override onDestroyed(): void {
onDestroyed(): void {
super.onDestroyed();
this._renderer.onDestroy();
}
@@ -328,43 +313,38 @@ namespace gdjs {
return this._textureAtlasResourceName;
}
setTextAlignment(align: string): void {
this._textAlign = align;
setAlignment(align: string): void {
this._align = align;
this._renderer.updateAlignment();
}
getTextAlignment(): string {
return this._textAlign;
getAlignment(): string {
return this._align;
}
/**
* Set the text alignment on Y axis for multiline text objects.
* @param alignment The text alignment.
* Set object position on X axis.
* @param x The new position X of the object.
*/
setVerticalTextAlignment(alignment: string): void {
this._verticalTextAlignment = alignment;
this._renderer.updatePosition();
}
/**
* Get the text alignment on Y axis of text object.
* @return The text alignment.
*/
getVerticalTextAlignment(): string {
return this._verticalTextAlignment;
}
override setX(x: float): void {
setX(x: float): void {
super.setX(x);
this._renderer.updatePosition();
}
override setY(y: float): void {
/**
* Set object position on Y axis.
* @param y The new position Y of the object.
*/
setY(y: float): void {
super.setY(y);
this._renderer.updatePosition();
}
override setAngle(angle: float): void {
/**
* Set the angle of the object.
* @param angle The new angle of the object.
*/
setAngle(angle: float): void {
super.setAngle(angle);
this._renderer.updateAngle();
}
@@ -408,34 +388,29 @@ namespace gdjs {
return this._wrappingWidth;
}
setWrapping(wordWrap: boolean): void {
this._wrapping = wordWrap;
setWordWrap(wordWrap: boolean): void {
this._wordWrap = wordWrap;
this._renderer.updateWrappingWidth();
this.invalidateHitboxes();
}
isWrapping(): boolean {
return this._wrapping;
getWordWrap(): boolean {
return this._wordWrap;
}
override getWidth(): float {
return this._wrapping ? this._wrappingWidth : this._renderer.getWidth();
/**
* Get the width of the object.
*/
getWidth(): float {
return this._renderer.getWidth();
}
override getHeight(): float {
/**
* Get the height of the object.
*/
getHeight(): float {
return this._renderer.getHeight();
}
override getDrawableY(): float {
return (
this.getY() -
(this._verticalTextAlignment === 'center'
? this.getHeight() / 2
: this._verticalTextAlignment === 'bottom'
? this.getHeight()
: 0)
);
}
}
gdjs.registerObject(
'BitmapText::BitmapTextObject',

View File

@@ -12,7 +12,7 @@ This project is released under the MIT License.
#include "GDCore/Tools/Localization.h"
void DestroyOutsideBehavior::InitializeContent(gd::SerializerElement& content) {
content.SetAttribute("extraBorder", 300);
content.SetAttribute("extraBorder", 0);
}
#if defined(GD_IDE_ONLY)

View File

@@ -12,42 +12,35 @@ This project is released under the MIT License.
void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension) {
extension
.SetExtensionInformation(
"DestroyOutsideBehavior",
_("Destroy Outside Screen Behavior"),
_("This behavior can be used to destroy objects when they go "
"outside of the bounds of the 2D camera. Useful for 2D bullets or "
"other short-lived objects. Don't use it for 3D objects in a "
"FPS/TPS game or any game with a camera not being a top view "
"(for 3D objects, prefer comparing "
"the position, for example Z position to see if an object goes "
"outside of the bound of the map). Be careful when using this "
"behavior because if the object appears outside of the screen, it "
"will be immediately removed."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionInformation("DestroyOutsideBehavior",
_("Destroy Outside Screen Behavior"),
_("This behavior can be used to destroy "
"objects when they go outside of "
"the bounds of the camera. Useful for bullets "
"or other short-lived objects."),
"Florian Rival",
"Open source (MIT License)")
.SetCategory("Game mechanic")
.SetTags("screen")
.SetExtensionHelpPath("/behaviors/destroyoutside");
gd::BehaviorMetadata& aut =
extension
.AddBehavior("DestroyOutside",
_("Destroy when outside of the screen"),
_("DestroyOutside"),
_("Destroy objects automatically when they go "
"outside of the 2D camera borders."),
"",
"CppPlatform/Extensions/destroyoutsideicon.png",
"DestroyOutsideBehavior",
std::make_shared<DestroyOutsideBehavior>(),
std::shared_ptr<gd::BehaviorsSharedData>())
.SetQuickCustomizationVisibility(gd::QuickCustomization::Hidden);
extension.AddBehavior("DestroyOutside",
_("Destroy when outside of the screen"),
_("DestroyOutside"),
_("Destroy objects automatically when they go "
"outside of the screen's borders."),
"",
"CppPlatform/Extensions/destroyoutsideicon.png",
"DestroyOutsideBehavior",
std::make_shared<DestroyOutsideBehavior>(),
std::shared_ptr<gd::BehaviorsSharedData>())
.SetQuickCustomizationVisibility(gd::QuickCustomization::Hidden);
aut.AddCondition("ExtraBorder",
_("Additional border (extra distance before deletion)"),
_("Compare the extra distance (in pixels) the object must "
"travel beyond the screen before it gets deleted."),
_("Additional border"),
_("Compare the additional border that the object must cross "
"before being deleted."),
_("the additional border"),
_("Destroy outside configuration"),
"CppPlatform/Extensions/destroyoutsideicon24.png",
@@ -60,9 +53,9 @@ void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension) {
.SetFunctionName("GetExtraBorder");
aut.AddAction("ExtraBorder",
_("Additional border (extra distance before deletion)"),
_("Change the extra distance (in pixels) the object must "
"travel beyond the screen before it gets deleted."),
_("Additional border"),
_("Change the additional border that the object must cross "
"before being deleted."),
_("the additional border"),
_("Destroy outside configuration"),
"CppPlatform/Extensions/destroyoutsideicon24.png",

View File

@@ -46,7 +46,7 @@ namespace gdjs {
layer.getCameraY() + layer.getCameraHeight() / 2
) {
//We are outside the camera area.
this.owner.deleteFromScene();
this.owner.deleteFromScene(instanceContainer);
}
}

View File

@@ -249,16 +249,13 @@ namespace gdjs {
(clipTextEnd === 0 || clipTextEnd !== dialogueText.length)
) {
pauseScrolling = true;
setTimeout(
function () {
pauseScrolling = false;
commandCalls.splice(index, 1);
if (gdjs.dialogueTree.getVariable('debug')) {
logger.info('CMD:', call);
}
},
parseInt(call.params[1], 10)
);
setTimeout(function () {
pauseScrolling = false;
commandCalls.splice(index, 1);
if (gdjs.dialogueTree.getVariable('debug')) {
logger.info('CMD:', call);
}
}, parseInt(call.params[1], 10));
}
if (call.cmd === command) {
commandParameters = call.params;

View File

@@ -35,32 +35,25 @@ void DeclareDraggableBehaviorExtension(gd::PlatformExtension& extension) {
std::make_shared<DraggableBehavior>(),
std::shared_ptr<gd::BehaviorsSharedData>());
aut.AddCondition(
"Dragged",
_("Being dragged"),
_("Check if the object is being dragged. This means the mouse button "
"or touch is pressed on it. When the mouse button or touch is "
"released, the object is no longer being considered dragged (use "
"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")
aut.AddCondition("Dragged",
_("Being dragged"),
_("Check if the object is being dragged."),
_("_PARAM0_ is being dragged"),
_("Draggable"),
"CppPlatform/Extensions/draggableicon24.png",
"CppPlatform/Extensions/draggableicon16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "Draggable")
.SetFunctionName("IsDragged");
aut.AddCondition(
"Dropped",
_("Was just dropped"),
_("Check if the object was just dropped after being dragged (the "
"mouse button or touch was just released this frame)."),
_("_PARAM0_ was just dropped"),
_("Draggable"),
"CppPlatform/Extensions/draggableicon24.png",
"CppPlatform/Extensions/draggableicon16.png")
aut.AddCondition("Dropped",
_("Was just dropped"),
_("Check if the object was just dropped after being dragged."),
_("_PARAM0_ was just dropped"),
_("Draggable"),
"CppPlatform/Extensions/draggableicon24.png",
"CppPlatform/Extensions/draggableicon16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "Draggable")

View File

@@ -157,8 +157,9 @@ namespace gdjs {
if (!instanceContainer.touchDraggableManagers[touchId]) {
//Create the shared manager if necessary.
// @ts-ignore
instanceContainer.touchDraggableManagers[touchId] =
new DraggableManager(instanceContainer, touchId);
instanceContainer.touchDraggableManagers[
touchId
] = new DraggableManager(instanceContainer, touchId);
}
// @ts-ignore
return instanceContainer.touchDraggableManagers[touchId];

View File

@@ -22,8 +22,7 @@ namespace gdjs {
parameterName: string,
value: number
) {
const adjustmentFilter =
filter as unknown as PIXI.filters.AdjustmentFilter;
const adjustmentFilter = (filter as unknown) as PIXI.filters.AdjustmentFilter;
if (parameterName === 'gamma') {
adjustmentFilter.gamma = value;
} else if (parameterName === 'saturation') {
@@ -43,8 +42,7 @@ namespace gdjs {
}
}
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
const adjustmentFilter =
filter as unknown as PIXI.filters.AdjustmentFilter;
const adjustmentFilter = (filter as unknown) as PIXI.filters.AdjustmentFilter;
if (parameterName === 'gamma') {
return adjustmentFilter.gamma;
}
@@ -90,8 +88,7 @@ namespace gdjs {
value: boolean
) {}
getNetworkSyncData(filter: PIXI.Filter): AdjustmentFilterNetworkSyncData {
const adjustmentFilter =
filter as unknown as PIXI.filters.AdjustmentFilter;
const adjustmentFilter = (filter as unknown) as PIXI.filters.AdjustmentFilter;
return {
ga: adjustmentFilter.gamma,
sa: adjustmentFilter.saturation,
@@ -107,8 +104,7 @@ namespace gdjs {
filter: PIXI.Filter,
data: AdjustmentFilterNetworkSyncData
): void {
const adjustmentFilter =
filter as unknown as PIXI.filters.AdjustmentFilter;
const adjustmentFilter = (filter as unknown) as PIXI.filters.AdjustmentFilter;
adjustmentFilter.gamma = data.ga;
adjustmentFilter.saturation = data.sa;
adjustmentFilter.contrast = data.co;

View File

@@ -20,8 +20,7 @@ namespace gdjs {
parameterName: string,
value: number
) {
const advancedBloomFilter =
filter as unknown as PIXI.filters.AdvancedBloomFilter;
const advancedBloomFilter = (filter as unknown) as PIXI.filters.AdvancedBloomFilter;
if (parameterName === 'threshold') {
advancedBloomFilter.threshold = value;
} else if (parameterName === 'bloomScale') {
@@ -37,8 +36,7 @@ namespace gdjs {
}
}
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
const advancedBloomFilter =
filter as unknown as PIXI.filters.AdvancedBloomFilter;
const advancedBloomFilter = (filter as unknown) as PIXI.filters.AdvancedBloomFilter;
if (parameterName === 'threshold') {
return advancedBloomFilter.threshold;
}
@@ -80,8 +78,7 @@ namespace gdjs {
getNetworkSyncData(
filter: PIXI.Filter
): AdvancedBloomFilterNetworkSyncData {
const advancedBloomFilter =
filter as unknown as PIXI.filters.AdvancedBloomFilter;
const advancedBloomFilter = (filter as unknown) as PIXI.filters.AdvancedBloomFilter;
return {
th: advancedBloomFilter.threshold,
bs: advancedBloomFilter.bloomScale,
@@ -95,8 +92,7 @@ namespace gdjs {
filter: PIXI.Filter,
syncData: AdvancedBloomFilterNetworkSyncData
) {
const advancedBloomFilter =
filter as unknown as PIXI.filters.AdvancedBloomFilter;
const advancedBloomFilter = (filter as unknown) as PIXI.filters.AdvancedBloomFilter;
advancedBloomFilter.threshold = syncData.th;
advancedBloomFilter.bloomScale = syncData.bs;
advancedBloomFilter.brightness = syncData.bn;

View File

@@ -15,13 +15,13 @@ namespace gdjs {
parameterName: string,
value: number
) {
const asciiFilter = filter as unknown as PIXI.filters.AsciiFilter;
const asciiFilter = (filter as unknown) as PIXI.filters.AsciiFilter;
if (parameterName === 'size') {
asciiFilter.size = value;
}
}
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
const asciiFilter = filter as unknown as PIXI.filters.AsciiFilter;
const asciiFilter = (filter as unknown) as PIXI.filters.AsciiFilter;
if (parameterName === 'size') {
return asciiFilter.size;
}
@@ -46,14 +46,14 @@ namespace gdjs {
value: boolean
) {}
getNetworkSyncData(filter: PIXI.Filter): AsciiFilterNetworkSyncData {
const asciiFilter = filter as unknown as PIXI.filters.AsciiFilter;
const asciiFilter = (filter as unknown) as PIXI.filters.AsciiFilter;
return { size: asciiFilter.size };
}
updateFromNetworkSyncData(
filter: PIXI.Filter,
data: AsciiFilterNetworkSyncData
) {
const asciiFilter = filter as unknown as PIXI.filters.AsciiFilter;
const asciiFilter = (filter as unknown) as PIXI.filters.AsciiFilter;
asciiFilter.size = data.size;
}
})()

View File

@@ -25,7 +25,7 @@ namespace gdjs {
parameterName: string,
value: number
) {
const bevelFilter = filter as unknown as PIXI.filters.BevelFilter &
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter &
BevelFilterExtra;
if (parameterName === 'rotation') {
bevelFilter.rotation = value;
@@ -40,7 +40,7 @@ namespace gdjs {
}
}
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
const bevelFilter = filter as unknown as PIXI.filters.BevelFilter &
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter &
BevelFilterExtra;
if (parameterName === 'rotation') {
return bevelFilter.rotation;
@@ -64,7 +64,7 @@ namespace gdjs {
parameterName: string,
value: string
) {
const bevelFilter = filter as unknown as PIXI.filters.BevelFilter &
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter &
BevelFilterExtra;
if (parameterName === 'lightColor') {
bevelFilter.lightColor = gdjs.rgbOrHexStringToNumber(value);
@@ -78,7 +78,7 @@ namespace gdjs {
parameterName: string,
value: number
): void {
const bevelFilter = filter as unknown as PIXI.filters.BevelFilter &
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter &
BevelFilterExtra;
if (parameterName === 'lightColor') {
bevelFilter.lightColor = value;
@@ -88,7 +88,7 @@ namespace gdjs {
}
}
getColorParameter(filter: PIXI.Filter, parameterName: string): number {
const bevelFilter = filter as unknown as PIXI.filters.BevelFilter;
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter;
if (parameterName === 'lightColor') {
return bevelFilter.lightColor;
}
@@ -103,7 +103,7 @@ namespace gdjs {
value: boolean
) {}
getNetworkSyncData(filter: PIXI.Filter): BevelFilterNetworkSyncData {
const bevelFilter = filter as unknown as PIXI.filters.BevelFilter &
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter &
BevelFilterExtra;
return {
r: bevelFilter.rotation,
@@ -119,7 +119,7 @@ namespace gdjs {
filter: PIXI.Filter,
data: BevelFilterNetworkSyncData
) {
const bevelFilter = filter as unknown as PIXI.filters.BevelFilter &
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter &
BevelFilterExtra;
bevelFilter.rotation = data.r;
bevelFilter.thickness = data.t;

View File

@@ -16,14 +16,14 @@ namespace gdjs {
parameterName: string,
value: number
) {
const colorMatrix = filter as unknown as PIXI.ColorMatrixFilter;
const colorMatrix = (filter as unknown) as PIXI.ColorMatrixFilter;
if (parameterName !== 'opacity') {
return;
}
colorMatrix.alpha = gdjs.PixiFiltersTools.clampValue(value, 0, 1);
}
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
const colorMatrix = filter as unknown as PIXI.ColorMatrixFilter;
const colorMatrix = (filter as unknown) as PIXI.ColorMatrixFilter;
if (parameterName === 'opacity') {
return colorMatrix.alpha;
}
@@ -50,14 +50,14 @@ namespace gdjs {
getNetworkSyncData(
filter: PIXI.Filter
): BlackAndWhiteFilterNetworkSyncData {
const colorMatrix = filter as unknown as PIXI.ColorMatrixFilter;
const colorMatrix = (filter as unknown) as PIXI.ColorMatrixFilter;
return { a: colorMatrix.alpha };
}
updateFromNetworkSyncData(
filter: PIXI.Filter,
data: BlackAndWhiteFilterNetworkSyncData
) {
const colorMatrix = filter as unknown as PIXI.ColorMatrixFilter;
const colorMatrix = (filter as unknown) as PIXI.ColorMatrixFilter;
colorMatrix.alpha = data.a;
}
})()

View File

@@ -16,7 +16,7 @@ namespace gdjs {
parameterName: string,
value: number
) {
const blendingModeFilter = filter as unknown as PIXI.AlphaFilter;
const blendingModeFilter = (filter as unknown) as PIXI.AlphaFilter;
if (parameterName === 'alpha') {
blendingModeFilter.alpha = value;
} else if (parameterName === 'blendmode') {
@@ -24,7 +24,7 @@ namespace gdjs {
}
}
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
const blendingModeFilter = filter as unknown as PIXI.AlphaFilter;
const blendingModeFilter = (filter as unknown) as PIXI.AlphaFilter;
if (parameterName === 'alpha') {
return blendingModeFilter.alpha;
}
@@ -54,7 +54,7 @@ namespace gdjs {
getNetworkSyncData(
filter: PIXI.Filter
): BlendingModeFilterNetworkSyncData {
const blendingModeFilter = filter as unknown as PIXI.AlphaFilter;
const blendingModeFilter = (filter as unknown) as PIXI.AlphaFilter;
return {
a: blendingModeFilter.alpha,
bm: blendingModeFilter.blendMode,
@@ -64,7 +64,7 @@ namespace gdjs {
filter: PIXI.Filter,
data: BlendingModeFilterNetworkSyncData
) {
const blendingModeFilter = filter as unknown as PIXI.AlphaFilter;
const blendingModeFilter = (filter as unknown) as PIXI.AlphaFilter;
blendingModeFilter.alpha = data.a;
blendingModeFilter.blendMode = data.bm;
}

View File

@@ -20,7 +20,7 @@ namespace gdjs {
parameterName: string,
value: number
) {
const brightnessFilter = filter as unknown as PIXI.ColorMatrixFilter &
const brightnessFilter = (filter as unknown) as PIXI.ColorMatrixFilter &
BrightnessFilterExtra;
if (parameterName !== 'brightness') {
return;
@@ -30,7 +30,7 @@ namespace gdjs {
brightnessFilter.brightness(brightness, false);
}
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
const brightnessFilter = filter as unknown as PIXI.ColorMatrixFilter &
const brightnessFilter = (filter as unknown) as PIXI.ColorMatrixFilter &
BrightnessFilterExtra;
if (parameterName === 'brightness') {
return brightnessFilter.__brightness;
@@ -56,7 +56,7 @@ namespace gdjs {
value: boolean
) {}
getNetworkSyncData(filter: PIXI.Filter): BrightnessFilterNetworkSyncData {
const brightnessFilter = filter as unknown as PIXI.ColorMatrixFilter &
const brightnessFilter = (filter as unknown) as PIXI.ColorMatrixFilter &
BrightnessFilterExtra;
return { b: brightnessFilter.__brightness };
}
@@ -64,7 +64,7 @@ namespace gdjs {
filter: PIXI.Filter,
data: BrightnessFilterNetworkSyncData
) {
const brightnessFilter = filter as unknown as PIXI.ColorMatrixFilter &
const brightnessFilter = (filter as unknown) as PIXI.ColorMatrixFilter &
BrightnessFilterExtra;
brightnessFilter.__brightness = data.b;
brightnessFilter.brightness(data.b, false);

View File

@@ -18,8 +18,7 @@ namespace gdjs {
parameterName: string,
value: number
) {
const bulgePinchFilter =
filter as unknown as PIXI.filters.BulgePinchFilter;
const bulgePinchFilter = (filter as unknown) as PIXI.filters.BulgePinchFilter;
if (parameterName === 'centerX') {
bulgePinchFilter.center[0] = value;
} else if (parameterName === 'centerY') {
@@ -35,8 +34,7 @@ namespace gdjs {
}
}
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
const bulgePinchFilter =
filter as unknown as PIXI.filters.BulgePinchFilter;
const bulgePinchFilter = (filter as unknown) as PIXI.filters.BulgePinchFilter;
if (parameterName === 'centerX') {
return bulgePinchFilter.center[0];
}
@@ -70,8 +68,7 @@ namespace gdjs {
value: boolean
) {}
getNetworkSyncData(filter: PIXI.Filter): BulgePinchFilterNetworkSyncData {
const bulgePinchFilter =
filter as unknown as PIXI.filters.BulgePinchFilter;
const bulgePinchFilter = (filter as unknown) as PIXI.filters.BulgePinchFilter;
return {
cx: bulgePinchFilter.center[0],
cy: bulgePinchFilter.center[1],
@@ -83,8 +80,7 @@ namespace gdjs {
filter: PIXI.Filter,
data: BulgePinchFilterNetworkSyncData
) {
const bulgePinchFilter =
filter as unknown as PIXI.filters.BulgePinchFilter;
const bulgePinchFilter = (filter as unknown) as PIXI.filters.BulgePinchFilter;
bulgePinchFilter.center[0] = data.cx;
bulgePinchFilter.center[1] = data.cy;
bulgePinchFilter.radius = data.r;

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