mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
142 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
35e9297844 | ||
![]() |
cedb9429c7 | ||
![]() |
d844b4d380 | ||
![]() |
e4265553e0 | ||
![]() |
2524b0b9d2 | ||
![]() |
20d16b8a57 | ||
![]() |
67aa1ce062 | ||
![]() |
1759dda870 | ||
![]() |
03dce1d90a | ||
![]() |
4e9556e948 | ||
![]() |
a02b8dcfe0 | ||
![]() |
416ef44ee1 | ||
![]() |
aa90621899 | ||
![]() |
3d3f04f63e | ||
![]() |
e1cc21c225 | ||
![]() |
9f90bf595e | ||
![]() |
94d49d8c36 | ||
![]() |
1d8c435fe0 | ||
![]() |
573eafe777 | ||
![]() |
15ff9bedd9 | ||
![]() |
9431ee7316 | ||
![]() |
333de61ead | ||
![]() |
1433a5f65c | ||
![]() |
ab1e566aef | ||
![]() |
1a4f9317d1 | ||
![]() |
af4a6a9313 | ||
![]() |
5f3066d35a | ||
![]() |
3d4f4c1441 | ||
![]() |
4da5efcff2 | ||
![]() |
dde472fd31 | ||
![]() |
94e8cf2229 | ||
![]() |
17f1bff1cd | ||
![]() |
a0c0c3d7b0 | ||
![]() |
41b255fdd9 | ||
![]() |
085b425431 | ||
![]() |
5957738070 | ||
![]() |
7caeae93d6 | ||
![]() |
ae09ad50ec | ||
![]() |
495b99356d | ||
![]() |
e432a7fa67 | ||
![]() |
8ba69ce338 | ||
![]() |
767b632db9 | ||
![]() |
49749fbd88 | ||
![]() |
99873e5c76 | ||
![]() |
3e87e5f76a | ||
![]() |
be5cc49928 | ||
![]() |
4bdf7172a6 | ||
![]() |
9f9f7824ef | ||
![]() |
b24e0b79bd | ||
![]() |
827b2cf3d8 | ||
![]() |
7a4142a1c9 | ||
![]() |
78671abb91 | ||
![]() |
11df078b74 | ||
![]() |
9001bfd8e2 | ||
![]() |
0d2778c8db | ||
![]() |
ee98e8a329 | ||
![]() |
a2e48fdd6c | ||
![]() |
187018cdd3 | ||
![]() |
c7622c3abe | ||
![]() |
7dca48b8bd | ||
![]() |
e9c625abc6 | ||
![]() |
71f7b59ab5 | ||
![]() |
8630452b89 | ||
![]() |
b1a91bdc4c | ||
![]() |
638c661138 | ||
![]() |
5dfd26c6f6 | ||
![]() |
a79e87dc7a | ||
![]() |
6490c1c4ad | ||
![]() |
05963806f1 | ||
![]() |
c4e1d2e5f8 | ||
![]() |
92f13abafc | ||
![]() |
ae3438b5f9 | ||
![]() |
ff572a2777 | ||
![]() |
e2320ec717 | ||
![]() |
bce459b2d2 | ||
![]() |
95dddc48b6 | ||
![]() |
d39f210630 | ||
![]() |
090649f125 | ||
![]() |
7c8c02911c | ||
![]() |
0c6a28c0a1 | ||
![]() |
b9d5974356 | ||
![]() |
74a1e11cfc | ||
![]() |
c712d0bb9e | ||
![]() |
828e6e031a | ||
![]() |
727f991c01 | ||
![]() |
5d4523b925 | ||
![]() |
3f7cbc731a | ||
![]() |
c1dfa34f0d | ||
![]() |
cf39de49d6 | ||
![]() |
5b325dd8ec | ||
![]() |
1f42331cbf | ||
![]() |
224f17b90a | ||
![]() |
3541d356e0 | ||
![]() |
63e79d678a | ||
![]() |
812153ffb3 | ||
![]() |
c62ea9e10a | ||
![]() |
04c63b2c74 | ||
![]() |
dcc3bae17e | ||
![]() |
441834cad5 | ||
![]() |
d4352ba5d9 | ||
![]() |
163239d08d | ||
![]() |
e3e9b41672 | ||
![]() |
7ba7c220e9 | ||
![]() |
617bf2c5b9 | ||
![]() |
d647d1e397 | ||
![]() |
c5bf9730aa | ||
![]() |
c5022596b8 | ||
![]() |
6e61c48898 | ||
![]() |
75fc55bac4 | ||
![]() |
8a4916fd93 | ||
![]() |
b008863281 | ||
![]() |
f0377771a8 | ||
![]() |
299ef90f93 | ||
![]() |
800c3333d4 | ||
![]() |
303ebfaf1b | ||
![]() |
288e4f4b75 | ||
![]() |
15db4be4a1 | ||
![]() |
925ffa74ec | ||
![]() |
752d047464 | ||
![]() |
7a21f9533e | ||
![]() |
9820770fb3 | ||
![]() |
a92784295a | ||
![]() |
81f6c62bb1 | ||
![]() |
a1bbb1c14c | ||
![]() |
9154144228 | ||
![]() |
c0176dfb2b | ||
![]() |
23cd527d94 | ||
![]() |
fa2cdb1624 | ||
![]() |
03eca4de4b | ||
![]() |
841484e5b7 | ||
![]() |
b88c5b08f5 | ||
![]() |
3f2043f248 | ||
![]() |
6941e64418 | ||
![]() |
fb7bb9181d | ||
![]() |
7ee50a2568 | ||
![]() |
90cdc875a9 | ||
![]() |
47d0fba205 | ||
![]() |
db745369dc | ||
![]() |
7c49346bed | ||
![]() |
b9a7786ab0 | ||
![]() |
76c09908c8 | ||
![]() |
b6e186e775 |
47
.github/workflows/update-extension-translations.yml
vendored
Normal file
47
.github/workflows/update-extension-translations.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# 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.
|
@@ -141,7 +141,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
"res/function32.png")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
.MarkAsAdvanced()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
@@ -177,7 +178,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", gd::ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
@@ -191,7 +193,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string", gd::ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -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());
|
||||
@@ -415,7 +415,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("SetNumberObjectVariable",
|
||||
_("Change variable value"),
|
||||
_("Change object variable value"),
|
||||
_("Modify the number value of an object variable."),
|
||||
_("the variable _PARAM1_"),
|
||||
_("Variables"),
|
||||
@@ -430,7 +430,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddAction("SetStringObjectVariable",
|
||||
_("Change text variable"),
|
||||
_("Change object variable value"),
|
||||
_("Modify the text of an object variable."),
|
||||
_("the variable _PARAM1_"),
|
||||
_("Variables"),
|
||||
@@ -445,7 +445,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddAction("SetBooleanObjectVariable",
|
||||
_("Change boolean variable"),
|
||||
_("Change object variable value"),
|
||||
_("Modify the boolean value of an object variable."),
|
||||
_("Change the variable _PARAM1_ of _PARAM0_: _PARAM2_"),
|
||||
_("Variables"),
|
||||
@@ -461,7 +461,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddCondition("NumberObjectVariable",
|
||||
_("Variable value"),
|
||||
_("Object variable value"),
|
||||
_("Compare the number value of an object variable."),
|
||||
_("the variable _PARAM1_"),
|
||||
_("Variables"),
|
||||
@@ -476,7 +476,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddCondition("StringObjectVariable",
|
||||
_("Text variable"),
|
||||
_("Object variable value"),
|
||||
_("Compare the text of an object variable."),
|
||||
_("the variable _PARAM1_"),
|
||||
_("Variables"),
|
||||
@@ -491,7 +491,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddCondition("BooleanObjectVariable",
|
||||
_("Boolean variable"),
|
||||
_("Object variable value"),
|
||||
_("Compare the boolean value of an object variable."),
|
||||
_("The variable _PARAM1_ of _PARAM0_ is _PARAM2_"),
|
||||
_("Variables"),
|
||||
@@ -574,7 +574,7 @@ 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"))
|
||||
@@ -587,7 +587,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("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"))
|
||||
@@ -601,7 +601,7 @@ 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"))
|
||||
@@ -808,10 +808,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
obj.AddAction(
|
||||
"PushStringToObjectVariable",
|
||||
_("Add text variable"),
|
||||
_("Add value to object array 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"))
|
||||
@@ -822,10 +822,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddAction("PushNumberToObjectVariable",
|
||||
_("Add variable array value"),
|
||||
_("Add value to object array variable"),
|
||||
_("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"))
|
||||
@@ -837,10 +837,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
obj.AddAction(
|
||||
"PushBooleanToObjectVariable",
|
||||
_("Add boolean variable"),
|
||||
_("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"),
|
||||
_("Variables ❯ Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
@@ -856,7 +856,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"))
|
||||
@@ -874,7 +874,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"))
|
||||
@@ -891,7 +891,7 @@ 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"))
|
||||
@@ -905,7 +905,7 @@ 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"))
|
||||
@@ -920,7 +920,7 @@ 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"))
|
||||
@@ -937,7 +937,7 @@ 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"))
|
||||
@@ -951,7 +951,7 @@ 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"))
|
||||
@@ -966,7 +966,7 @@ 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"))
|
||||
@@ -977,7 +977,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("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"))
|
||||
@@ -988,7 +988,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("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"))
|
||||
@@ -999,7 +999,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("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"))
|
||||
@@ -1408,7 +1408,7 @@ 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"))
|
||||
|
@@ -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_"),
|
||||
_("Create objects from the external layout named _PARAM1_ at position _PARAM2_;_PARAM3_;_PARAM4_"),
|
||||
"",
|
||||
"res/ribbon_default/externallayout32.png",
|
||||
"res/ribbon_default/externallayout32.png")
|
||||
|
@@ -151,7 +151,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
||||
extension
|
||||
.AddExpression("abs",
|
||||
_("Absolute value"),
|
||||
_("Absolute value"),
|
||||
_("Return the non-negative value by removing the sign. "
|
||||
"The absolute value of -8 is 8."),
|
||||
"",
|
||||
"res/mathfunction.png")
|
||||
.AddParameter("expression", _("Expression"));
|
||||
|
@@ -79,7 +79,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
|
||||
extension
|
||||
.AddAction("SetStringVariable",
|
||||
_("Change text variable"),
|
||||
_("Change variable value"),
|
||||
_("Modify the text (string) of a variable."),
|
||||
_("the variable _PARAM0_"),
|
||||
"",
|
||||
@@ -92,7 +92,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
extension
|
||||
.AddAction(
|
||||
"SetBooleanVariable",
|
||||
_("Change boolean variable"),
|
||||
_("Change variable value"),
|
||||
_("Modify the boolean value of a variable."),
|
||||
_("Change the variable _PARAM0_: _PARAM1_"),
|
||||
"",
|
||||
@@ -180,7 +180,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
extension
|
||||
.AddAction(
|
||||
"PushString",
|
||||
_("Add text variable"),
|
||||
_("Add value to array variable"),
|
||||
_("Adds a text (string) at the end of a array variable."),
|
||||
_("Add the value _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
@@ -193,7 +193,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
|
||||
extension
|
||||
.AddAction("PushNumber",
|
||||
_("Add variable array value"),
|
||||
_("Add value to array variable"),
|
||||
_("Adds a number at the end of an array variable."),
|
||||
_("Add the value _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
@@ -206,7 +206,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
|
||||
extension
|
||||
.AddAction("PushBoolean",
|
||||
_("Add boolean variable"),
|
||||
_("Add value to array variable"),
|
||||
_("Adds a boolean at the end of an array variable."),
|
||||
_("Add the value _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
@@ -283,26 +283,28 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
@@ -310,13 +312,14 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddCondition("VariableChildExists",
|
||||
@@ -324,13 +327,14 @@ 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
|
||||
@@ -339,13 +343,14 @@ 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
|
||||
@@ -353,7 +358,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", "")
|
||||
@@ -365,13 +370,14 @@ 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
|
||||
@@ -379,13 +385,14 @@ 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
|
||||
@@ -394,20 +401,21 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
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", "")
|
||||
@@ -420,26 +428,28 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
@@ -447,12 +457,13 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddAction("ToggleSceneVariableAsBoolean",
|
||||
@@ -461,24 +472,26 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
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
|
||||
@@ -486,13 +499,14 @@ 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
|
||||
@@ -501,12 +515,13 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddAction("ToggleGlobalVariableAsBoolean",
|
||||
@@ -515,11 +530,12 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
@@ -527,14 +543,15 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
@@ -542,14 +559,15 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddAction("VariableClearChildren",
|
||||
@@ -557,12 +575,13 @@ 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
|
||||
@@ -571,12 +590,13 @@ 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
|
||||
@@ -585,7 +605,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"))
|
||||
@@ -595,6 +615,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"end of the array."))
|
||||
.SetHelpPath("/all-features/variables/structures-and-arrays/")
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -603,13 +624,14 @@ 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
|
||||
@@ -617,13 +639,14 @@ 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
|
||||
@@ -631,13 +654,14 @@ 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
|
||||
@@ -647,13 +671,14 @@ 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
|
||||
@@ -662,7 +687,7 @@ 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"))
|
||||
@@ -670,6 +695,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.SetHelpPath("/all-features/variables/structures-and-arrays/")
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -678,11 +704,12 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
@@ -690,11 +717,12 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddStrExpression(
|
||||
@@ -702,11 +730,12 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
@@ -714,11 +743,12 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
@@ -726,7 +756,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"))
|
||||
@@ -736,6 +766,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"end of the array."))
|
||||
.SetHelpPath("/all-features/variables/structures-and-arrays/")
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -745,13 +776,14 @@ 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
|
||||
@@ -760,13 +792,14 @@ 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
|
||||
@@ -774,13 +807,14 @@ 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
|
||||
@@ -788,13 +822,14 @@ 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
|
||||
@@ -803,7 +838,7 @@ 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"))
|
||||
@@ -811,6 +846,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.SetHelpPath("/all-features/variables/structures-and-arrays/")
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -818,22 +854,24 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddStrExpression(
|
||||
@@ -841,11 +879,12 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
@@ -853,21 +892,23 @@ 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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddExpression("VariableChildCount",
|
||||
@@ -883,37 +924,41 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
.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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
|
||||
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();
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.SetHidden();
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -101,7 +101,7 @@ const gd::String &ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
} else if (propertyType == "KeyboardKey") {
|
||||
return keyboardKeyValueType;
|
||||
}
|
||||
// For "String", "Resource" or default
|
||||
// For "String", "Resource", "MultilineString" or default
|
||||
return stringValueType;
|
||||
};
|
||||
|
||||
|
@@ -18,8 +18,8 @@
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/IDE/PlatformManager.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/ObjectConfiguration.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Project/ObjectConfiguration.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,12 +244,10 @@ 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];
|
||||
}
|
||||
|
||||
@@ -353,8 +351,7 @@ 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();
|
||||
}
|
||||
|
||||
@@ -386,7 +383,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;
|
||||
}
|
||||
@@ -406,7 +403,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;
|
||||
}
|
||||
@@ -423,7 +420,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;
|
||||
}
|
||||
@@ -440,7 +437,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;
|
||||
}
|
||||
@@ -468,7 +465,8 @@ PlatformExtension::GetAllStrExpressions() {
|
||||
return strExpressionsInfos;
|
||||
}
|
||||
|
||||
const std::vector<gd::DependencyMetadata>& PlatformExtension::GetAllDependencies() const {
|
||||
const std::vector<gd::DependencyMetadata>&
|
||||
PlatformExtension::GetAllDependencies() const {
|
||||
return extensionDependenciesMetadata;
|
||||
}
|
||||
|
||||
@@ -476,7 +474,8 @@ 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;
|
||||
}
|
||||
|
||||
@@ -615,37 +614,6 @@ 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();
|
||||
@@ -791,41 +759,42 @@ 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::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) {
|
||||
@@ -834,7 +803,8 @@ gd::String PlatformExtension::GetExtensionFromFullObjectType(const gd::String& t
|
||||
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) {
|
||||
|
@@ -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,12 +440,6 @@ 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
|
||||
@@ -640,12 +634,6 @@ 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.
|
||||
|
@@ -73,6 +73,7 @@ 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;
|
||||
|
@@ -3,9 +3,10 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GroupVariableHelper.h"
|
||||
#include "ObjectVariableHelper.h"
|
||||
|
||||
#include "GDCore/IDE/WholeProjectRefactorer.h"
|
||||
#include "GDCore/Project/InitialInstancesContainer.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectGroup.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
@@ -16,7 +17,7 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
void GroupVariableHelper::FillAnyVariableBetweenObjects(
|
||||
void ObjectVariableHelper::FillAnyVariableBetweenObjects(
|
||||
gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::ObjectsContainer &objectsContainer,
|
||||
const gd::ObjectGroup &objectGroup) {
|
||||
@@ -65,7 +66,7 @@ void GroupVariableHelper::FillAnyVariableBetweenObjects(
|
||||
}
|
||||
}
|
||||
|
||||
gd::VariablesContainer GroupVariableHelper::MergeVariableContainers(
|
||||
gd::VariablesContainer ObjectVariableHelper::MergeVariableContainers(
|
||||
const gd::ObjectsContainersList &objectsContainersList,
|
||||
const gd::ObjectGroup &objectGroup) {
|
||||
gd::VariablesContainer mergedVariablesContainer;
|
||||
@@ -113,7 +114,7 @@ gd::VariablesContainer GroupVariableHelper::MergeVariableContainers(
|
||||
return mergedVariablesContainer;
|
||||
}
|
||||
|
||||
void GroupVariableHelper::FillMissingGroupVariablesToObjects(
|
||||
void ObjectVariableHelper::FillMissingGroupVariablesToObjects(
|
||||
gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::ObjectsContainer &objectsContainer, const gd::ObjectGroup &objectGroup,
|
||||
const gd::SerializerElement &originalSerializedVariables) {
|
||||
@@ -145,7 +146,7 @@ void GroupVariableHelper::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 GroupVariableHelper::ApplyChangesToObjects(
|
||||
void ObjectVariableHelper::ApplyChangesToObjects(
|
||||
gd::ObjectsContainer &globalObjectsContainer,
|
||||
gd::ObjectsContainer &objectsContainer,
|
||||
const gd::VariablesContainer &groupVariablesContainer,
|
||||
@@ -193,4 +194,48 @@ void GroupVariableHelper::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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} // namespace gd
|
@@ -8,6 +8,7 @@
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
|
||||
namespace gd {
|
||||
class InitialInstancesContainer;
|
||||
class ObjectsContainersList;
|
||||
class ObjectsContainer;
|
||||
class ObjectGroup;
|
||||
@@ -22,7 +23,7 @@ namespace gd {
|
||||
*
|
||||
* This is used by the object group variable editor.
|
||||
*/
|
||||
class GD_CORE_API GroupVariableHelper {
|
||||
class GD_CORE_API ObjectVariableHelper {
|
||||
public:
|
||||
/**
|
||||
* Copy every variable from every object of the group to the other objects
|
||||
@@ -70,6 +71,17 @@ public:
|
||||
const gd::VariablesContainer &groupVariablesContainer,
|
||||
const gd::ObjectGroup &objectGroup,
|
||||
const gd::VariablesChangeset &changeset);
|
||||
|
||||
static void ApplyChangesToObjectInstances(
|
||||
gd::VariablesContainer &objectVariablesContainer,
|
||||
gd::InitialInstancesContainer &initialInstancesContainer,
|
||||
const gd::String &objectName, const gd::VariablesChangeset &changeset);
|
||||
|
||||
private:
|
||||
static void ApplyChangesToVariableContainer(
|
||||
const gd::VariablesContainer &originalVariablesContainer,
|
||||
gd::VariablesContainer &destinationVariablesContainer,
|
||||
const gd::VariablesChangeset &changeset, bool shouldApplyValueChanges);
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
} // namespace gd
|
@@ -42,6 +42,9 @@ 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;
|
||||
@@ -59,9 +62,9 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
property.GetLabel().empty() ? property.GetName() : property.GetLabel();
|
||||
|
||||
gd::String descriptionSubject =
|
||||
(property.GetType() == "Boolean" ? "if " : "the ") +
|
||||
(primitiveType == "boolean" ? "if " : "the ") +
|
||||
UnCapitalizeFirstLetter(propertyLabel) +
|
||||
(isSharedProperties || property.GetType() == "Boolean"
|
||||
(isSharedProperties || primitiveType == "boolean"
|
||||
? "."
|
||||
: " of the object.") +
|
||||
(property.GetDescription().empty() ? ""
|
||||
@@ -71,19 +74,7 @@ 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(
|
||||
@@ -99,7 +90,7 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
.SetName(legacyExpressionType)
|
||||
.SetExtraInfo(GetStringifiedExtraInfo(property));
|
||||
getter.SetFullName(propertyLabel).SetGroup(functionGroupName);
|
||||
if (property.GetType() == "Boolean") {
|
||||
if (primitiveType == "boolean") {
|
||||
getter.SetFunctionType(gd::EventsFunction::Condition)
|
||||
.SetDescription("Check " + descriptionSubject)
|
||||
.SetSentence("_PARAM0_ " + UnCapitalizeFirstLetter(propertyLabel));
|
||||
@@ -112,13 +103,12 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
auto &event =
|
||||
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().InsertNewEvent(
|
||||
project, "BuiltinCommonInstructions::Standard", 0));
|
||||
if (property.GetType() == "Boolean") {
|
||||
if (primitiveType == "boolean") {
|
||||
gd::Instruction condition;
|
||||
condition.SetType(getterType);
|
||||
condition.AddParameter("Object");
|
||||
if (isBehavior) {
|
||||
condition.AddParameter("Behavior");
|
||||
}
|
||||
condition.SetType("BooleanVariable");
|
||||
condition.AddParameter(propertyName);
|
||||
condition.AddParameter("True");
|
||||
condition.AddParameter("");
|
||||
event.GetConditions().Insert(condition, 0);
|
||||
|
||||
gd::Instruction action;
|
||||
@@ -127,6 +117,8 @@ 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);
|
||||
@@ -136,7 +128,7 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
if (!functionsContainer.HasEventsFunctionNamed(setterName)) {
|
||||
auto &setter = functionsContainer.InsertNewEventsFunction(
|
||||
setterName, functionsContainer.GetEventsFunctionsCount());
|
||||
if (property.GetType() == "Boolean") {
|
||||
if (primitiveType == "boolean") {
|
||||
setter.SetFunctionType(gd::EventsFunction::Action)
|
||||
.SetFullName(propertyLabel)
|
||||
.SetGroup(functionGroupName)
|
||||
@@ -177,26 +169,24 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
setter.SetGetterName(getterName);
|
||||
}
|
||||
|
||||
if (property.GetType() == "Boolean") {
|
||||
if (primitiveType == "boolean") {
|
||||
{
|
||||
auto &event =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().InsertNewEvent(
|
||||
project, "BuiltinCommonInstructions::Standard", 0));
|
||||
|
||||
gd::Instruction condition;
|
||||
condition.SetType("GetArgumentAsBoolean");
|
||||
condition.AddParameter("\"Value\"");
|
||||
condition.SetType("BooleanVariable");
|
||||
condition.AddParameter("Value");
|
||||
condition.AddParameter("True");
|
||||
condition.AddParameter("");
|
||||
event.GetConditions().Insert(condition, 0);
|
||||
|
||||
gd::Instruction action;
|
||||
action.SetType(setterType);
|
||||
action.AddParameter("Object");
|
||||
if (isBehavior) {
|
||||
action.AddParameter("Behavior");
|
||||
action.AddParameter("yes");
|
||||
} else {
|
||||
action.AddParameter("yes");
|
||||
}
|
||||
action.SetType("SetBooleanVariable");
|
||||
action.AddParameter(propertyName);
|
||||
action.AddParameter("True");
|
||||
action.AddParameter("");
|
||||
event.GetActions().Insert(action, 0);
|
||||
}
|
||||
{
|
||||
@@ -205,20 +195,17 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
project, "BuiltinCommonInstructions::Standard", 0));
|
||||
|
||||
gd::Instruction condition;
|
||||
condition.SetType("GetArgumentAsBoolean");
|
||||
condition.AddParameter("\"Value\"");
|
||||
condition.SetInverted(true);
|
||||
condition.SetType("BooleanVariable");
|
||||
condition.AddParameter("Value");
|
||||
condition.AddParameter("False");
|
||||
condition.AddParameter("");
|
||||
event.GetConditions().Insert(condition, 0);
|
||||
|
||||
gd::Instruction action;
|
||||
action.SetType(setterType);
|
||||
action.AddParameter("Object");
|
||||
if (isBehavior) {
|
||||
action.AddParameter("Behavior");
|
||||
action.AddParameter("no");
|
||||
} else {
|
||||
action.AddParameter("no");
|
||||
}
|
||||
action.SetType("SetBooleanVariable");
|
||||
action.AddParameter(propertyName);
|
||||
action.AddParameter("False");
|
||||
action.AddParameter("");
|
||||
event.GetActions().Insert(action, 0);
|
||||
}
|
||||
} else {
|
||||
@@ -227,16 +214,11 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
project, "BuiltinCommonInstructions::Standard", 0));
|
||||
|
||||
gd::Instruction action;
|
||||
action.SetType(setterType);
|
||||
action.AddParameter("Object");
|
||||
if (isBehavior) {
|
||||
action.AddParameter("Behavior");
|
||||
action.AddParameter("=");
|
||||
action.AddParameter("Value");
|
||||
} else {
|
||||
action.AddParameter("=");
|
||||
action.AddParameter("Value");
|
||||
}
|
||||
action.SetType(primitiveType == "number" ? "SetNumberVariable"
|
||||
: "SetStringVariable");
|
||||
action.AddParameter(propertyName);
|
||||
action.AddParameter("=");
|
||||
action.AddParameter("Value");
|
||||
event.GetActions().Insert(action, 0);
|
||||
}
|
||||
}
|
||||
|
@@ -3,8 +3,7 @@
|
||||
* Copyright 2008-2022 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_PROPERTYFUNCTIONGENERATOR_H
|
||||
#define GDCORE_PROPERTYFUNCTIONGENERATOR_H
|
||||
#pragma once
|
||||
|
||||
namespace gd {
|
||||
class String;
|
||||
@@ -73,5 +72,3 @@ class GD_CORE_API PropertyFunctionGenerator {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_PROPERTYFUNCTIONGENERATOR_H
|
||||
|
@@ -11,7 +11,7 @@
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/DependenciesAnalyzer.h"
|
||||
#include "GDCore/IDE/GroupVariableHelper.h"
|
||||
#include "GDCore/IDE/ObjectVariableHelper.h"
|
||||
#include "GDCore/IDE/EventBasedBehaviorBrowser.h"
|
||||
#include "GDCore/IDE/EventBasedObjectBrowser.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
@@ -314,9 +314,16 @@ void WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
|
||||
variablesContainer.SerializeTo(editedSerializedVariables);
|
||||
variablesContainer.UnserializeFrom(originalSerializedVariables);
|
||||
|
||||
// Rename and remove variables
|
||||
// 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;
|
||||
gd::EventsVariableReplacer eventsVariableReplacer(
|
||||
project.GetCurrentPlatform(), changeset, changeset.removedVariableNames,
|
||||
project.GetCurrentPlatform(), changeset, removedVariableNames,
|
||||
variablesContainer);
|
||||
gd::ProjectBrowserHelper::ExposeProjectEvents(project,
|
||||
eventsVariableReplacer);
|
||||
@@ -333,9 +340,25 @@ 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,
|
||||
@@ -355,11 +378,15 @@ void WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
}
|
||||
auto &object = hasObject ? objectsContainer.GetObject(objectName)
|
||||
: globalObjectsContainer.GetObject(objectName);
|
||||
auto &variablesContainer = object.GetVariables();
|
||||
auto &objectVariablesContainer = object.GetVariables();
|
||||
|
||||
gd::ObjectVariableHelper::ApplyChangesToObjectInstances(
|
||||
objectVariablesContainer, initialInstancesContainer, objectName,
|
||||
changeset);
|
||||
|
||||
gd::EventsVariableReplacer eventsVariableReplacer(
|
||||
project.GetCurrentPlatform(), changeset,
|
||||
removedVariableNames, variablesContainer);
|
||||
removedVariableNames, objectVariablesContainer);
|
||||
gd::ProjectBrowserHelper::ExposeProjectEvents(project,
|
||||
eventsVariableReplacer);
|
||||
}
|
||||
@@ -372,12 +399,12 @@ void WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
eventsVariableReplacer);
|
||||
|
||||
// Apply changes to objects.
|
||||
gd::GroupVariableHelper::FillMissingGroupVariablesToObjects(
|
||||
gd::ObjectVariableHelper::FillMissingGroupVariablesToObjects(
|
||||
globalObjectsContainer,
|
||||
objectsContainer,
|
||||
objectGroup,
|
||||
originalSerializedVariables);
|
||||
gd::GroupVariableHelper::ApplyChangesToObjects(
|
||||
gd::ObjectVariableHelper::ApplyChangesToObjects(
|
||||
globalObjectsContainer, objectsContainer, groupVariablesContainer,
|
||||
objectGroup, changeset);
|
||||
|
||||
|
@@ -32,6 +32,7 @@ class UnfilledRequiredBehaviorPropertyProblem;
|
||||
class ProjectBrowser;
|
||||
class SerializerElement;
|
||||
class ProjectScopedContainers;
|
||||
class InitialInstancesContainer;
|
||||
struct VariablesRenamingChangesetNode;
|
||||
} // namespace gd
|
||||
|
||||
@@ -80,13 +81,23 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
|
||||
/**
|
||||
* \brief Refactor the project according to the changes (renaming or deletion)
|
||||
* made to variables.
|
||||
* made to global or scene 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.
|
||||
@@ -94,6 +105,7 @@ 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,
|
||||
|
@@ -47,6 +47,7 @@ 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;
|
||||
@@ -81,6 +82,7 @@ void EventsFunctionsExtension::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("previewIconUrl", previewIconUrl);
|
||||
element.SetAttribute("iconUrl", iconUrl);
|
||||
element.SetAttribute("helpPath", helpPath);
|
||||
element.SetAttribute("gdevelopVersion", gdevelopVersion);
|
||||
auto& dependenciesElement = element.AddChild("dependencies");
|
||||
dependenciesElement.ConsiderAsArray();
|
||||
for (auto& dependency : dependencies)
|
||||
@@ -126,6 +128,7 @@ void EventsFunctionsExtension::UnserializeExtensionDeclarationFrom(
|
||||
previewIconUrl = element.GetStringAttribute("previewIconUrl");
|
||||
iconUrl = element.GetStringAttribute("iconUrl");
|
||||
helpPath = element.GetStringAttribute("helpPath");
|
||||
gdevelopVersion = element.GetStringAttribute("gdevelopVersion");
|
||||
|
||||
if (element.HasChild("origin")) {
|
||||
gd::String originName =
|
||||
|
@@ -134,6 +134,19 @@ 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.
|
||||
*/
|
||||
@@ -385,6 +398,7 @@ 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::SerializableWithNameList<EventsBasedBehavior> eventsBasedBehaviors;
|
||||
gd::SerializableWithNameList<EventsBasedObject> eventsBasedObjects;
|
||||
std::vector<gd::DependencyMetadata> dependencies;
|
||||
|
@@ -41,6 +41,11 @@ void InitialInstancesContainer::IterateOverInstances(
|
||||
for (auto& instance : initialInstances) func(instance);
|
||||
}
|
||||
|
||||
void InitialInstancesContainer::IterateOverInstances(
|
||||
const std::function< void(gd::InitialInstance &) >& func) {
|
||||
for (auto& instance : initialInstances) func(instance);
|
||||
}
|
||||
|
||||
void InitialInstancesContainer::IterateOverInstancesWithZOrdering(
|
||||
gd::InitialInstanceFunctor& func, const gd::String& layerName) {
|
||||
std::vector<std::reference_wrapper<gd::InitialInstance>> sortedInstances;
|
||||
|
@@ -87,6 +87,13 @@ 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< void(gd::InitialInstance &) >& func);
|
||||
|
||||
/**
|
||||
* Get the instances on the specified layer,
|
||||
* sort them regarding their Z order and then apply \a func on them.
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#if defined(EMSCRIPTEN)
|
||||
#include <emscripten.h>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
@@ -31,5 +32,10 @@ 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
|
||||
|
@@ -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,8 +26,10 @@
|
||||
#endif
|
||||
|
||||
namespace gd {
|
||||
gd::String GetTranslation(const gd::String& str);
|
||||
|
||||
gd::String GetTranslation(const char* str);
|
||||
}
|
||||
} // namespace gd
|
||||
|
||||
#define _(s) gd::GetTranslation(u8##s)
|
||||
|
||||
|
@@ -116,14 +116,11 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
||||
REQUIRE(setterEvent.GetConditions().size() == 0);
|
||||
REQUIRE(setterEvent.GetActions().size() == 1);
|
||||
auto &setterAction = setterEvent.GetActions().at(0);
|
||||
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");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,12 +203,12 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
||||
REQUIRE(getterEvent.GetActions().size() == 1);
|
||||
|
||||
auto &getterCondition = getterEvent.GetConditions().at(0);
|
||||
REQUIRE(getterCondition.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedBehavior::PropertyRotate");
|
||||
REQUIRE(getterCondition.GetType() == "BooleanVariable");
|
||||
REQUIRE(!getterCondition.IsInverted());
|
||||
REQUIRE(getterCondition.GetParametersCount() == 2);
|
||||
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(getterCondition.GetParameter(1).GetPlainString() == "Behavior");
|
||||
REQUIRE(getterCondition.GetParametersCount() == 3);
|
||||
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Rotate");
|
||||
REQUIRE(getterCondition.GetParameter(1).GetPlainString() == "True");
|
||||
REQUIRE(getterCondition.GetParameter(2).GetPlainString() == "");
|
||||
|
||||
auto &getterAction = getterEvent.GetActions().at(0);
|
||||
REQUIRE(getterAction.GetType() == "SetReturnBoolean");
|
||||
@@ -257,19 +254,19 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
||||
REQUIRE(setterNoEvent.GetActions().size() == 1);
|
||||
|
||||
auto &setterNoCondition = setterNoEvent.GetConditions().at(0);
|
||||
REQUIRE(setterNoCondition.GetType() == "GetArgumentAsBoolean");
|
||||
REQUIRE(setterNoCondition.IsInverted());
|
||||
REQUIRE(setterNoCondition.GetParametersCount() == 1);
|
||||
REQUIRE(setterNoCondition.GetParameter(0).GetPlainString() ==
|
||||
"\"Value\"");
|
||||
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() == "");
|
||||
|
||||
auto &setterNoAction = setterNoEvent.GetActions().at(0);
|
||||
REQUIRE(setterNoAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyRotate");
|
||||
REQUIRE(setterNoAction.GetType() == "SetBooleanVariable");
|
||||
REQUIRE(setterNoAction.GetParametersCount() == 3);
|
||||
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "Behavior");
|
||||
REQUIRE(setterNoAction.GetParameter(2).GetPlainString() == "no");
|
||||
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Rotate");
|
||||
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "False");
|
||||
REQUIRE(setterNoAction.GetParameter(2).GetPlainString() == "");
|
||||
|
||||
auto &setterYesEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(1));
|
||||
@@ -277,19 +274,19 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
||||
REQUIRE(setterYesEvent.GetActions().size() == 1);
|
||||
|
||||
auto &setterYesCondition = setterYesEvent.GetConditions().at(0);
|
||||
REQUIRE(setterYesCondition.GetType() == "GetArgumentAsBoolean");
|
||||
REQUIRE(setterYesCondition.GetType() == "BooleanVariable");
|
||||
REQUIRE(!setterYesCondition.IsInverted());
|
||||
REQUIRE(setterYesCondition.GetParametersCount() == 1);
|
||||
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() ==
|
||||
"\"Value\"");
|
||||
REQUIRE(setterYesCondition.GetParametersCount() == 3);
|
||||
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() == "Value");
|
||||
REQUIRE(setterYesCondition.GetParameter(1).GetPlainString() == "True");
|
||||
REQUIRE(setterYesCondition.GetParameter(2).GetPlainString() == "");
|
||||
|
||||
auto &setterYesAction = setterYesEvent.GetActions().at(0);
|
||||
REQUIRE(setterYesAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyRotate");
|
||||
REQUIRE(setterYesAction.GetType() == "SetBooleanVariable");
|
||||
REQUIRE(setterYesAction.GetParametersCount() == 3);
|
||||
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "Behavior");
|
||||
REQUIRE(setterYesAction.GetParameter(2).GetPlainString() == "yes");
|
||||
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Rotate");
|
||||
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "True");
|
||||
REQUIRE(setterYesAction.GetParameter(2).GetPlainString() == "");
|
||||
}
|
||||
}
|
||||
SECTION("Can generate functions for a number property in an object") {
|
||||
@@ -366,11 +363,9 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
||||
REQUIRE(setterEvent.GetConditions().size() == 0);
|
||||
REQUIRE(setterEvent.GetActions().size() == 1);
|
||||
auto &setterAction = setterEvent.GetActions().at(0);
|
||||
REQUIRE(
|
||||
setterAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedObject::SetPropertyMovementAngle");
|
||||
REQUIRE(setterAction.GetType() == "SetNumberVariable");
|
||||
REQUIRE(setterAction.GetParametersCount() == 3);
|
||||
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "MovementAngle");
|
||||
REQUIRE(setterAction.GetParameter(1).GetPlainString() == "=");
|
||||
REQUIRE(setterAction.GetParameter(2).GetPlainString() == "Value");
|
||||
}
|
||||
@@ -454,11 +449,12 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
||||
REQUIRE(getterEvent.GetActions().size() == 1);
|
||||
|
||||
auto &getterCondition = getterEvent.GetConditions().at(0);
|
||||
REQUIRE(getterCondition.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedObject::PropertyRotate");
|
||||
REQUIRE(getterCondition.GetType() == "BooleanVariable");
|
||||
REQUIRE(!getterCondition.IsInverted());
|
||||
REQUIRE(getterCondition.GetParametersCount() == 1);
|
||||
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(getterCondition.GetParametersCount() == 3);
|
||||
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Rotate");
|
||||
REQUIRE(getterCondition.GetParameter(1).GetPlainString() == "True");
|
||||
REQUIRE(getterCondition.GetParameter(2).GetPlainString() == "");
|
||||
|
||||
auto &getterAction = getterEvent.GetActions().at(0);
|
||||
REQUIRE(getterAction.GetType() == "SetReturnBoolean");
|
||||
@@ -500,18 +496,19 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
||||
REQUIRE(setterNoEvent.GetActions().size() == 1);
|
||||
|
||||
auto &setterNoCondition = setterNoEvent.GetConditions().at(0);
|
||||
REQUIRE(setterNoCondition.GetType() == "GetArgumentAsBoolean");
|
||||
REQUIRE(setterNoCondition.IsInverted());
|
||||
REQUIRE(setterNoCondition.GetParametersCount() == 1);
|
||||
REQUIRE(setterNoCondition.GetParameter(0).GetPlainString() ==
|
||||
"\"Value\"");
|
||||
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() == "");
|
||||
|
||||
auto &setterNoAction = setterNoEvent.GetActions().at(0);
|
||||
REQUIRE(setterNoAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedObject::SetPropertyRotate");
|
||||
REQUIRE(setterNoAction.GetParametersCount() == 2);
|
||||
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "no");
|
||||
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() == "");
|
||||
|
||||
auto &setterYesEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(1));
|
||||
@@ -519,18 +516,19 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
||||
REQUIRE(setterYesEvent.GetActions().size() == 1);
|
||||
|
||||
auto &setterYesCondition = setterYesEvent.GetConditions().at(0);
|
||||
REQUIRE(setterYesCondition.GetType() == "GetArgumentAsBoolean");
|
||||
REQUIRE(setterYesCondition.GetType() == "BooleanVariable");
|
||||
REQUIRE(!setterYesCondition.IsInverted());
|
||||
REQUIRE(setterYesCondition.GetParametersCount() == 1);
|
||||
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() ==
|
||||
"\"Value\"");
|
||||
REQUIRE(setterYesCondition.GetParametersCount() == 3);
|
||||
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() == "Value");
|
||||
REQUIRE(setterYesCondition.GetParameter(1).GetPlainString() == "True");
|
||||
REQUIRE(setterYesCondition.GetParameter(2).GetPlainString() == "");
|
||||
|
||||
auto &setterYesAction = setterYesEvent.GetActions().at(0);
|
||||
REQUIRE(setterYesAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedObject::SetPropertyRotate");
|
||||
REQUIRE(setterYesAction.GetParametersCount() == 2);
|
||||
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "yes");
|
||||
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() == "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,9 +586,11 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
||||
REQUIRE(setterEvent.GetConditions().size() == 0);
|
||||
REQUIRE(setterEvent.GetActions().size() == 1);
|
||||
auto &setterAction = setterEvent.GetActions().at(0);
|
||||
REQUIRE(setterAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedBehavior::"
|
||||
"SetSharedPropertyMovementAngle");
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/GroupVariableHelper.h"
|
||||
#include "GDCore/IDE/ObjectVariableHelper.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() == 19);
|
||||
REQUIRE(event.GetActions().GetCount() == 40);
|
||||
|
||||
// clang-format off
|
||||
// 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)");
|
||||
// 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)");
|
||||
|
||||
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");
|
||||
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");
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
@@ -1021,6 +1021,140 @@ 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 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;
|
||||
@@ -1062,8 +1196,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
|
||||
REQUIRE(changeset.modifiedVariables.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
|
||||
project, object.GetVariables(), changeset, originalSerializedVariables);
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
|
||||
project, object.GetVariables(), scene.GetInitialInstances(),
|
||||
object.GetName(), changeset, originalSerializedVariables);
|
||||
|
||||
REQUIRE(event.GetActions()[0].GetParameter(1).GetPlainString() ==
|
||||
"MyVariable.MyRenamedChild");
|
||||
@@ -1112,8 +1247,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
|
||||
REQUIRE(changeset.modifiedVariables.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
|
||||
project, object.GetVariables(), changeset, originalSerializedVariables);
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
|
||||
project, object.GetVariables(), scene.GetInitialInstances(),
|
||||
object.GetName(), changeset, originalSerializedVariables);
|
||||
|
||||
REQUIRE(event.GetActions()[0].GetParameter(3).GetPlainString() ==
|
||||
"MyVariable.MyRenamedChild");
|
||||
@@ -1161,8 +1297,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
|
||||
REQUIRE(changeset.modifiedVariables.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
|
||||
project, object.GetVariables(), changeset, originalSerializedVariables);
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
|
||||
project, object.GetVariables(), scene.GetInitialInstances(),
|
||||
object.GetName(), changeset, originalSerializedVariables);
|
||||
|
||||
REQUIRE(event.GetActions()[0].GetParameter(3).GetPlainString() ==
|
||||
"MyVariable.MyChild.MyRenamedGrandChild");
|
||||
@@ -1896,8 +2033,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.typeChangedVariableNames.find("MyObjectVariable") !=
|
||||
changeset.typeChangedVariableNames.end());
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
|
||||
project, object.GetVariables(), changeset, originalSerializedVariables);
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
|
||||
project, object.GetVariables(), scene.GetInitialInstances(),
|
||||
object.GetName(), changeset, originalSerializedVariables);
|
||||
|
||||
// Check the the action has changed to follow the variable type.
|
||||
REQUIRE(event.GetActions()[0].GetType() == "SetStringObjectVariable");
|
||||
@@ -1947,8 +2085,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.typeChangedVariableNames.find("MyObjectVariable") !=
|
||||
changeset.typeChangedVariableNames.end());
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForVariablesContainer(
|
||||
project, object.GetVariables(), changeset, originalSerializedVariables);
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForObjectVariablesContainer(
|
||||
project, object.GetVariables(), scene.GetInitialInstances(),
|
||||
object.GetName(), changeset, originalSerializedVariables);
|
||||
|
||||
// Check the the action has changed to follow the variable type.
|
||||
REQUIRE(event.GetActions()[0].GetType() == "SetStringObjectVariable");
|
||||
@@ -1977,7 +2116,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Count() == 1);
|
||||
@@ -2009,7 +2148,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Count() == 1);
|
||||
@@ -2029,7 +2168,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Count() == 0);
|
||||
@@ -2050,7 +2189,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Count() == 0);
|
||||
@@ -2075,7 +2214,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2094,8 +2233,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 456);
|
||||
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
|
||||
@@ -2121,7 +2261,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2140,8 +2280,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 456);
|
||||
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
|
||||
@@ -2167,7 +2308,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2188,8 +2329,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 111);
|
||||
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
|
||||
@@ -2215,7 +2357,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2236,8 +2378,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 0);
|
||||
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
|
||||
@@ -2263,7 +2406,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2282,8 +2425,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.valueChangedVariableNames.size() == 0);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 111);
|
||||
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
|
||||
@@ -2318,7 +2462,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Count() == 1);
|
||||
@@ -2336,8 +2480,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
originalSerializedVariables, groupVariables);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(newObject.GetVariables().Count() == 2);
|
||||
REQUIRE(newObject.GetVariables().Get("MyGroupVariable").GetValue() == 123);
|
||||
@@ -2369,7 +2514,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2390,8 +2535,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables()
|
||||
.Get("MyGroupVariable")
|
||||
@@ -2428,7 +2574,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2448,8 +2594,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables()
|
||||
.Get("MyGroupVariable")
|
||||
@@ -2486,7 +2633,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2506,8 +2653,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables()
|
||||
.Get("MyGroupVariable")
|
||||
@@ -2558,7 +2706,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2579,8 +2727,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.valueChangedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables()
|
||||
.Get("MyGroupVariable")
|
||||
@@ -2613,11 +2762,14 @@ 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::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2635,11 +2787,13 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.removedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), 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") {
|
||||
@@ -2659,7 +2813,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Count() == 0);
|
||||
@@ -2677,8 +2831,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.addedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables().Get("MyGroupVariable").GetValue() == 456);
|
||||
REQUIRE(otherObject.GetVariables().Get("MyGroupVariable").GetValue() ==
|
||||
@@ -2704,7 +2859,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Count() == 0);
|
||||
@@ -2722,8 +2877,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.addedVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
// The variable kept its original value.
|
||||
REQUIRE(object.GetVariables().Count() == 1);
|
||||
@@ -2749,6 +2905,9 @@ 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(
|
||||
@@ -2787,7 +2946,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2806,8 +2965,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.oldToNewVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(object.GetVariables().Count() == 1);
|
||||
REQUIRE(object.GetVariables().Get("MyRenamedGroupVariable").GetValue() == 123);
|
||||
@@ -2830,6 +2990,7 @@ 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") {
|
||||
@@ -2887,7 +3048,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -2906,8 +3067,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.oldToNewVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
// The variable kept its original value.
|
||||
REQUIRE(object.GetVariables().Count() == 1);
|
||||
@@ -2992,7 +3154,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -3016,8 +3178,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.modifiedVariables.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(event.GetActions()[0].GetParameter(1).GetPlainString() ==
|
||||
"MyGroupVariable.MyRenamedChild");
|
||||
@@ -3067,7 +3230,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
gd::VariablesContainer groupVariables =
|
||||
gd::GroupVariableHelper::MergeVariableContainers(
|
||||
gd::ObjectVariableHelper::MergeVariableContainers(
|
||||
projectScopedContainers.GetObjectsContainersList(), group);
|
||||
|
||||
REQUIRE(groupVariables.Has("MyGroupVariable"));
|
||||
@@ -3086,8 +3249,9 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
REQUIRE(changeset.oldToNewVariableNames.size() == 1);
|
||||
|
||||
gd::WholeProjectRefactorer::ApplyRefactoringForGroupVariablesContainer(
|
||||
project, project.GetObjects(), scene.GetObjects(), groupVariables,
|
||||
group, changeset, originalSerializedVariables);
|
||||
project, project.GetObjects(), scene.GetObjects(),
|
||||
scene.GetInitialInstances(), groupVariables, group, changeset,
|
||||
originalSerializedVariables);
|
||||
|
||||
REQUIRE(event.GetActions()[0].GetParameter(1).GetPlainString() ==
|
||||
"MyGroupVariable");
|
||||
|
@@ -1,15 +1,4 @@
|
||||
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;
|
||||
|
||||
@@ -35,11 +24,8 @@ 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.
|
||||
*/
|
||||
@@ -84,7 +70,7 @@ namespace gdjs {
|
||||
|
||||
constructor(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
objectData: Object3DData
|
||||
objectData: gdjs.Object3DData
|
||||
) {
|
||||
super(instanceContainer, objectData);
|
||||
// TODO Should 0 be replaced by 0.01 instead of using the default value?
|
||||
|
@@ -117,6 +117,17 @@ 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
|
||||
@@ -131,7 +142,8 @@ namespace gdjs {
|
||||
*/
|
||||
export class Base3DBehavior
|
||||
extends gdjs.RuntimeBehavior
|
||||
implements Base3DHandler {
|
||||
implements Base3DHandler
|
||||
{
|
||||
private object: gdjs.RuntimeObject & Base3DHandler;
|
||||
|
||||
constructor(
|
||||
|
@@ -3,31 +3,31 @@ namespace gdjs {
|
||||
export interface Cube3DObjectData extends Object3DData {
|
||||
/** The base parameters of the Cube3D object */
|
||||
content: Object3DDataContent & {
|
||||
enableTextureTransparency: boolean;
|
||||
facesOrientation: 'Y' | 'Z';
|
||||
enableTextureTransparency: boolean | undefined;
|
||||
facesOrientation: 'Y' | 'Z' | undefined;
|
||||
frontFaceResourceName: string;
|
||||
backFaceResourceName: string;
|
||||
backFaceUpThroughWhichAxisRotation: 'X' | 'Y';
|
||||
backFaceUpThroughWhichAxisRotation: 'X' | 'Y' | undefined;
|
||||
leftFaceResourceName: string;
|
||||
rightFaceResourceName: string;
|
||||
topFaceResourceName: string;
|
||||
bottomFaceResourceName: string;
|
||||
frontFaceResourceRepeat: boolean;
|
||||
backFaceResourceRepeat: boolean;
|
||||
leftFaceResourceRepeat: boolean;
|
||||
rightFaceResourceRepeat: boolean;
|
||||
topFaceResourceRepeat: boolean;
|
||||
bottomFaceResourceRepeat: boolean;
|
||||
frontFaceResourceRepeat: boolean | undefined;
|
||||
backFaceResourceRepeat: boolean | undefined;
|
||||
leftFaceResourceRepeat: boolean | undefined;
|
||||
rightFaceResourceRepeat: boolean | undefined;
|
||||
topFaceResourceRepeat: boolean | undefined;
|
||||
bottomFaceResourceRepeat: boolean | undefined;
|
||||
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,6 +45,7 @@ namespace gdjs {
|
||||
trfb: integer;
|
||||
frn: [string, string, string, string, string, string];
|
||||
mt: number;
|
||||
tint: string;
|
||||
};
|
||||
|
||||
type Cube3DObjectNetworkSyncData = Object3DNetworkSyncData &
|
||||
@@ -67,10 +68,11 @@ namespace gdjs {
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string
|
||||
string,
|
||||
];
|
||||
_materialType: gdjs.Cube3DRuntimeObject.MaterialType =
|
||||
gdjs.Cube3DRuntimeObject.MaterialType.Basic;
|
||||
_tint: string;
|
||||
|
||||
constructor(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
@@ -117,6 +119,9 @@ namespace gdjs {
|
||||
objectData.content.topFaceResourceName,
|
||||
objectData.content.bottomFaceResourceName,
|
||||
];
|
||||
|
||||
this._tint = objectData.content.tint || '255;255;255';
|
||||
|
||||
this._materialType = this._convertMaterialType(
|
||||
objectData.content.materialType
|
||||
);
|
||||
@@ -134,7 +139,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 value - The visibility value to set.
|
||||
* @param enable - The visibility value to set.
|
||||
*/
|
||||
setFaceVisibility(faceName: FaceName, enable: boolean) {
|
||||
const faceIndex = faceNameToBitmaskIndex[faceName];
|
||||
@@ -157,7 +162,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 value - The visibility value to set.
|
||||
* @param enable - The visibility value to set.
|
||||
*/
|
||||
setRepeatTextureOnFace(faceName: FaceName, enable: boolean) {
|
||||
const faceIndex = faceNameToBitmaskIndex[faceName];
|
||||
@@ -203,11 +208,22 @@ 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];
|
||||
@@ -291,6 +307,10 @@ 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
|
||||
@@ -342,7 +362,7 @@ namespace gdjs {
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'front',
|
||||
newObjectData.content.frontFaceResourceRepeat
|
||||
newObjectData.content.frontFaceResourceRepeat || false
|
||||
);
|
||||
}
|
||||
if (
|
||||
@@ -351,7 +371,7 @@ namespace gdjs {
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'back',
|
||||
newObjectData.content.backFaceResourceRepeat
|
||||
newObjectData.content.backFaceResourceRepeat || false
|
||||
);
|
||||
}
|
||||
if (
|
||||
@@ -360,7 +380,7 @@ namespace gdjs {
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'left',
|
||||
newObjectData.content.leftFaceResourceRepeat
|
||||
newObjectData.content.leftFaceResourceRepeat || false
|
||||
);
|
||||
}
|
||||
if (
|
||||
@@ -369,7 +389,7 @@ namespace gdjs {
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'right',
|
||||
newObjectData.content.rightFaceResourceRepeat
|
||||
newObjectData.content.rightFaceResourceRepeat || false
|
||||
);
|
||||
}
|
||||
if (
|
||||
@@ -378,7 +398,7 @@ namespace gdjs {
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'top',
|
||||
newObjectData.content.topFaceResourceRepeat
|
||||
newObjectData.content.topFaceResourceRepeat || false
|
||||
);
|
||||
}
|
||||
if (
|
||||
@@ -387,7 +407,7 @@ namespace gdjs {
|
||||
) {
|
||||
this.setRepeatTextureOnFace(
|
||||
'bottom',
|
||||
newObjectData.content.bottomFaceResourceRepeat
|
||||
newObjectData.content.bottomFaceResourceRepeat || false
|
||||
);
|
||||
}
|
||||
if (
|
||||
@@ -395,14 +415,14 @@ namespace gdjs {
|
||||
newObjectData.content.backFaceUpThroughWhichAxisRotation
|
||||
) {
|
||||
this.setBackFaceUpThroughWhichAxisRotation(
|
||||
newObjectData.content.backFaceUpThroughWhichAxisRotation
|
||||
newObjectData.content.backFaceUpThroughWhichAxisRotation || 'X'
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.facesOrientation !==
|
||||
newObjectData.content.facesOrientation
|
||||
) {
|
||||
this.setFacesOrientation(newObjectData.content.facesOrientation);
|
||||
this.setFacesOrientation(newObjectData.content.facesOrientation || 'Y');
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.materialType !==
|
||||
@@ -423,6 +443,7 @@ namespace gdjs {
|
||||
vfb: this._visibleFacesBitmask,
|
||||
trfb: this._textureRepeatFacesBitmask,
|
||||
frn: this._faceResourceNames,
|
||||
tint: this._tint,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -476,6 +497,12 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (networkSyncData.tint !== undefined) {
|
||||
if (this._tint !== networkSyncData.tint) {
|
||||
this._tint = networkSyncData.tint;
|
||||
this._renderer.updateTint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -62,6 +62,7 @@ namespace gdjs {
|
||||
forceBasicMaterial:
|
||||
runtimeObject._materialType ===
|
||||
gdjs.Cube3DRuntimeObject.MaterialType.Basic,
|
||||
vertexColors: true,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -74,15 +75,13 @@ namespace gdjs {
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer
|
||||
) {
|
||||
const geometry = new THREE.BoxGeometry(1, 1, 1);
|
||||
// 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 materials: THREE.Material[] = new Array(6)
|
||||
.fill(0)
|
||||
.map((_, index) =>
|
||||
getFaceMaterial(runtimeObject, materialIndexToFaceIndex[index])
|
||||
);
|
||||
|
||||
const boxMesh = new THREE.Mesh(geometry, materials);
|
||||
|
||||
super(runtimeObject, instanceContainer, boxMesh);
|
||||
@@ -92,6 +91,28 @@ 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) {
|
||||
@@ -121,13 +142,11 @@ 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 =
|
||||
@@ -149,9 +168,10 @@ namespace gdjs {
|
||||
continue;
|
||||
}
|
||||
|
||||
const shouldRepeatTexture = this._cube3DRuntimeObject.shouldRepeatTextureOnFaceAtIndex(
|
||||
materialIndexToFaceIndex[materialIndex]
|
||||
);
|
||||
const shouldRepeatTexture =
|
||||
this._cube3DRuntimeObject.shouldRepeatTextureOnFaceAtIndex(
|
||||
materialIndexToFaceIndex[materialIndex]
|
||||
);
|
||||
|
||||
const shouldOrientateFacesTowardsY =
|
||||
this._cube3DRuntimeObject.getFacesOrientation() === 'Y';
|
||||
@@ -180,12 +200,10 @@ namespace gdjs {
|
||||
if (shouldOrientateFacesTowardsY) {
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
} else {
|
||||
[
|
||||
x,
|
||||
y,
|
||||
] = noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
|
||||
vertexIndex % 4
|
||||
];
|
||||
[x, y] =
|
||||
noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
|
||||
vertexIndex % 4
|
||||
];
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -211,12 +229,10 @@ namespace gdjs {
|
||||
if (shouldOrientateFacesTowardsY) {
|
||||
[x, y] = noRepeatTextureVertexIndexToUvMapping[vertexIndex % 4];
|
||||
} else {
|
||||
[
|
||||
x,
|
||||
y,
|
||||
] = noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
|
||||
vertexIndex % 4
|
||||
];
|
||||
[x, y] =
|
||||
noRepeatTextureVertexIndexToUvMappingForLeftAndRightFacesTowardsZ[
|
||||
vertexIndex % 4
|
||||
];
|
||||
x = -x;
|
||||
y = -y;
|
||||
}
|
||||
|
@@ -1,21 +1,11 @@
|
||||
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.
|
||||
*/
|
||||
@@ -41,13 +31,13 @@ namespace gdjs {
|
||||
|
||||
constructor(
|
||||
parent: gdjs.RuntimeInstanceContainer,
|
||||
objectData: Object3DData & CustomObjectConfiguration
|
||||
objectData: gdjs.Object3DData & gdjs.CustomObjectConfiguration
|
||||
) {
|
||||
super(parent, objectData);
|
||||
this._renderer.reinitialize(this, parent);
|
||||
}
|
||||
|
||||
protected _createRender() {
|
||||
protected override _createRender() {
|
||||
const parent = this._runtimeScene;
|
||||
return new gdjs.CustomRuntimeObject3DRenderer(
|
||||
this,
|
||||
@@ -56,21 +46,23 @@ namespace gdjs {
|
||||
);
|
||||
}
|
||||
|
||||
protected _reinitializeRenderer(): void {
|
||||
protected override _reinitializeRenderer(): void {
|
||||
this.getRenderer().reinitialize(this, this.getParent());
|
||||
}
|
||||
|
||||
getRenderer(): gdjs.CustomRuntimeObject3DRenderer {
|
||||
override getRenderer(): gdjs.CustomRuntimeObject3DRenderer {
|
||||
return super.getRenderer() as gdjs.CustomRuntimeObject3DRenderer;
|
||||
}
|
||||
|
||||
get3DRendererObject() {
|
||||
override get3DRendererObject() {
|
||||
// It can't be null because Three.js is always loaded
|
||||
// when a custom 3D object is used.
|
||||
return this.getRenderer().get3DRendererObject()!;
|
||||
}
|
||||
|
||||
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
|
||||
override extraInitializationFromInitialInstance(
|
||||
initialInstanceData: InstanceData
|
||||
) {
|
||||
super.extraInitializationFromInitialInstance(initialInstanceData);
|
||||
if (initialInstanceData.depth !== undefined) {
|
||||
this.setDepth(initialInstanceData.depth);
|
||||
@@ -292,7 +284,7 @@ namespace gdjs {
|
||||
return this._maxZ - this._minZ;
|
||||
}
|
||||
|
||||
_updateUntransformedHitBoxes(): void {
|
||||
override _updateUntransformedHitBoxes(): void {
|
||||
super._updateUntransformedHitBoxes();
|
||||
|
||||
let minZ = Number.MAX_VALUE;
|
||||
|
@@ -6,7 +6,8 @@ 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;
|
||||
@@ -139,16 +140,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) {
|
||||
@@ -159,20 +160,21 @@ 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;
|
||||
}
|
||||
}
|
||||
|
@@ -69,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)
|
||||
@@ -800,6 +800,20 @@ 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();
|
||||
@@ -822,7 +836,8 @@ module.exports = {
|
||||
propertyName === 'bottomFaceResourceName' ||
|
||||
propertyName === 'backFaceUpThroughWhichAxisRotation' ||
|
||||
propertyName === 'facesOrientation' ||
|
||||
propertyName === 'materialType'
|
||||
propertyName === 'materialType' ||
|
||||
propertyName === 'tint'
|
||||
) {
|
||||
objectContent[propertyName] = newValue;
|
||||
return true;
|
||||
@@ -902,6 +917,12 @@ 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')
|
||||
@@ -1092,6 +1113,7 @@ module.exports = {
|
||||
topFaceResourceRepeat: false,
|
||||
bottomFaceResourceRepeat: false,
|
||||
materialType: 'Basic',
|
||||
tint: '255;255;255',
|
||||
};
|
||||
|
||||
Cube3DObject.updateInitialInstanceProperty = function (
|
||||
@@ -1568,6 +1590,21 @@ 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',
|
||||
@@ -2062,6 +2099,10 @@ module.exports = {
|
||||
3: [1, 0],
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {*} objectConfiguration
|
||||
* @returns {string | null}
|
||||
*/
|
||||
const getFirstVisibleFaceResourceName = (objectConfiguration) => {
|
||||
const object = gd.castObject(
|
||||
objectConfiguration,
|
||||
@@ -2090,25 +2131,44 @@ module.exports = {
|
||||
return null;
|
||||
};
|
||||
|
||||
/** @type {THREE.MeshBasicMaterial | null} */
|
||||
let transparentMaterial = null;
|
||||
/**
|
||||
* @returns {THREE.MeshBasicMaterial}
|
||||
*/
|
||||
const getTransparentMaterial = () => {
|
||||
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;
|
||||
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;
|
||||
};
|
||||
|
||||
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,
|
||||
@@ -2124,11 +2184,6 @@ 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
|
||||
@@ -2145,7 +2200,6 @@ module.exports = {
|
||||
this._pixiObject.addChild(this._pixiTexturedObject);
|
||||
this._pixiObject.addChild(this._pixiFallbackObject);
|
||||
this._pixiContainer.addChild(this._pixiObject);
|
||||
this._renderFallbackObject = false;
|
||||
this.updateTexture();
|
||||
}
|
||||
|
||||
@@ -2160,9 +2214,10 @@ module.exports = {
|
||||
}
|
||||
|
||||
static getThumbnail(project, resourcesLoader, objectConfiguration) {
|
||||
const textureResourceName = RenderedCube3DObject2DInstance._getResourceNameToDisplay(
|
||||
objectConfiguration
|
||||
);
|
||||
const textureResourceName =
|
||||
RenderedCube3DObject2DInstance._getResourceNameToDisplay(
|
||||
objectConfiguration
|
||||
);
|
||||
if (textureResourceName) {
|
||||
return resourcesLoader.getResourceFullUrl(
|
||||
project,
|
||||
@@ -2174,18 +2229,20 @@ 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;
|
||||
@@ -2308,6 +2365,17 @@ 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,
|
||||
@@ -2324,21 +2392,9 @@ 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(),
|
||||
@@ -2357,8 +2413,9 @@ 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,
|
||||
@@ -2389,11 +2446,35 @@ 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
|
||||
@@ -2421,13 +2502,19 @@ module.exports = {
|
||||
|
||||
let materialsDirty = false;
|
||||
let uvMappingDirty = false;
|
||||
let tintDirty = false;
|
||||
|
||||
const shouldUseTransparentTexture =
|
||||
object.content.enableTextureTransparency;
|
||||
object.content.enableTextureTransparency || false;
|
||||
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,
|
||||
@@ -2471,12 +2558,12 @@ module.exports = {
|
||||
}
|
||||
|
||||
const shouldRepeatTextureOnFace = [
|
||||
object.content.frontFaceResourceRepeat,
|
||||
object.content.backFaceResourceRepeat,
|
||||
object.content.leftFaceResourceRepeat,
|
||||
object.content.rightFaceResourceRepeat,
|
||||
object.content.topFaceResourceRepeat,
|
||||
object.content.bottomFaceResourceRepeat,
|
||||
object.content.frontFaceResourceRepeat || false,
|
||||
object.content.backFaceResourceRepeat || false,
|
||||
object.content.leftFaceResourceRepeat || false,
|
||||
object.content.rightFaceResourceRepeat || false,
|
||||
object.content.topFaceResourceRepeat || false,
|
||||
object.content.bottomFaceResourceRepeat || false,
|
||||
];
|
||||
if (
|
||||
this._shouldRepeatTextureOnFace[0] !== shouldRepeatTextureOnFace[0] ||
|
||||
@@ -2491,16 +2578,17 @@ module.exports = {
|
||||
}
|
||||
|
||||
const backFaceUpThroughWhichAxisRotation =
|
||||
object.content.backFaceUpThroughWhichAxisRotation;
|
||||
object.content.backFaceUpThroughWhichAxisRotation || 'X';
|
||||
if (
|
||||
backFaceUpThroughWhichAxisRotation !==
|
||||
this._backFaceUpThroughWhichAxisRotation
|
||||
) {
|
||||
this._backFaceUpThroughWhichAxisRotation = backFaceUpThroughWhichAxisRotation;
|
||||
this._backFaceUpThroughWhichAxisRotation =
|
||||
backFaceUpThroughWhichAxisRotation;
|
||||
uvMappingDirty = true;
|
||||
}
|
||||
|
||||
const facesOrientation = object.content.facesOrientation;
|
||||
const facesOrientation = object.content.facesOrientation || 'Y';
|
||||
if (facesOrientation !== this._facesOrientation) {
|
||||
this._facesOrientation = facesOrientation;
|
||||
uvMappingDirty = true;
|
||||
@@ -2520,6 +2608,7 @@ module.exports = {
|
||||
|
||||
if (materialsDirty) this._updateThreeObjectMaterials();
|
||||
if (uvMappingDirty) this._updateTextureUvMapping();
|
||||
if (tintDirty) this._updateTint();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2529,11 +2618,11 @@ module.exports = {
|
||||
* for the method to work.
|
||||
*/
|
||||
_updateTextureUvMapping() {
|
||||
/** @type {THREE.BufferAttribute} */
|
||||
// @ts-ignore - position is stored as a Float32BufferAttribute
|
||||
/** @type {THREE.BufferAttribute} */
|
||||
const pos = this._threeObject.geometry.getAttribute('position');
|
||||
// @ts-ignore - uv is stored as a Float32BufferAttribute
|
||||
/** @type {THREE.BufferAttribute} */
|
||||
// @ts-ignore - uv is stored as a Float32BufferAttribute
|
||||
const uvMapping = this._threeObject.geometry.getAttribute('uv');
|
||||
const startIndex = 0;
|
||||
const endIndex = 23;
|
||||
@@ -2552,9 +2641,10 @@ module.exports = {
|
||||
continue;
|
||||
}
|
||||
|
||||
const shouldRepeatTexture = this._shouldRepeatTextureOnFace[
|
||||
materialIndexToFaceIndex[materialIndex]
|
||||
];
|
||||
const shouldRepeatTexture =
|
||||
this._shouldRepeatTextureOnFace[
|
||||
materialIndexToFaceIndex[materialIndex]
|
||||
];
|
||||
|
||||
const shouldOrientateFacesTowardsY = this._facesOrientation === 'Y';
|
||||
|
||||
@@ -2589,16 +2679,13 @@ 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;
|
||||
@@ -2628,16 +2715,13 @@ 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;
|
||||
}
|
||||
@@ -2786,6 +2870,19 @@ 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(
|
||||
@@ -3028,10 +3125,15 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {[number, number, number] | null} point1
|
||||
* @param {[number, number, number] | null} point2
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isSamePoint = (point1, point2) => {
|
||||
if (!point1 && !point2) return true;
|
||||
if (point1 && !point2) return false;
|
||||
if (!point1 && point2) return false;
|
||||
if (!!point1 !== !!point2) return false;
|
||||
// At this point || or && doesn't matter and the type checking prefer ||.
|
||||
if (!point1 || !point2) return true;
|
||||
return (
|
||||
point1[0] === point2[0] &&
|
||||
point1[1] === point2[1] &&
|
||||
@@ -3039,6 +3141,10 @@ module.exports = {
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} location
|
||||
* @returns {[number, number, number] | null}
|
||||
*/
|
||||
const getPointForLocation = (location) => {
|
||||
switch (location) {
|
||||
case 'ModelOrigin':
|
||||
@@ -3057,8 +3163,27 @@ 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,
|
||||
@@ -3076,29 +3201,12 @@ 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() {
|
||||
@@ -3140,27 +3248,30 @@ module.exports = {
|
||||
}
|
||||
|
||||
_updateDefaultTransformation() {
|
||||
if (!this._clonedModel3D) return; // Model is not ready - nothing to do.
|
||||
if (!this._clonedModel3D) {
|
||||
// Model is not ready - nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
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.
|
||||
this._threeModelGroup = new THREE.Group();
|
||||
this._threeModelGroup.rotation.order = 'ZYX';
|
||||
this._threeModelGroup.add(this._clonedModel3D);
|
||||
const threeModelGroup = new THREE.Group();
|
||||
this._threeModelGroup = threeModelGroup;
|
||||
threeModelGroup.rotation.order = 'ZYX';
|
||||
threeModelGroup.add(this._clonedModel3D);
|
||||
|
||||
this._threeModelGroup.rotation.set(
|
||||
threeModelGroup.rotation.set(
|
||||
(this._rotationX * Math.PI) / 180,
|
||||
(this._rotationY * Math.PI) / 180,
|
||||
(this._rotationZ * Math.PI) / 180
|
||||
);
|
||||
this._threeModelGroup.updateMatrixWorld(true);
|
||||
const boundingBox = new THREE.Box3().setFromObject(
|
||||
this._threeModelGroup
|
||||
);
|
||||
threeModelGroup.updateMatrixWorld(true);
|
||||
const boundingBox = new THREE.Box3().setFromObject(threeModelGroup);
|
||||
|
||||
const shouldKeepModelOrigin = !this._originPoint;
|
||||
if (shouldKeepModelOrigin) {
|
||||
@@ -3187,7 +3298,7 @@ module.exports = {
|
||||
// Center the model.
|
||||
const centerPoint = this._centerPoint;
|
||||
if (centerPoint) {
|
||||
this._threeModelGroup.position.set(
|
||||
threeModelGroup.position.set(
|
||||
-(boundingBox.min.x + modelWidth * centerPoint[0]),
|
||||
// The model is flipped on Y axis.
|
||||
-(boundingBox.min.y + modelHeight * (1 - centerPoint[1])),
|
||||
@@ -3196,8 +3307,8 @@ module.exports = {
|
||||
}
|
||||
|
||||
// Rotate the model.
|
||||
this._threeModelGroup.scale.set(1, 1, 1);
|
||||
this._threeModelGroup.rotation.set(
|
||||
threeModelGroup.scale.set(1, 1, 1);
|
||||
threeModelGroup.rotation.set(
|
||||
(this._rotationX * Math.PI) / 180,
|
||||
(this._rotationY * Math.PI) / 180,
|
||||
(this._rotationZ * Math.PI) / 180
|
||||
@@ -3212,8 +3323,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);
|
||||
this._threeModelGroup.updateMatrix();
|
||||
this._threeModelGroup.applyMatrix4(scaleMatrix);
|
||||
threeModelGroup.updateMatrix();
|
||||
threeModelGroup.applyMatrix4(scaleMatrix);
|
||||
|
||||
if (this._keepAspectRatio) {
|
||||
// Reduce the object dimensions to keep aspect ratio.
|
||||
@@ -3280,7 +3391,7 @@ module.exports = {
|
||||
this._defaultDepth = this._originalDepth;
|
||||
}
|
||||
|
||||
this._threeObject.add(this._threeModelGroup);
|
||||
this._threeObject.add(threeModelGroup);
|
||||
}
|
||||
|
||||
updateThreeObject() {
|
||||
|
@@ -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) {}
|
||||
keepAspectRatio(true), crossfadeDuration(0.1f) {}
|
||||
|
||||
bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
|
||||
const gd::String &newValue) {
|
||||
@@ -71,6 +71,10 @@ bool Model3DObjectConfiguration::UpdateProperty(const gd::String &propertyName,
|
||||
keepAspectRatio = newValue == "1";
|
||||
return true;
|
||||
}
|
||||
if(propertyName == "crossfadeDuration") {
|
||||
crossfadeDuration = newValue.To<double>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -167,6 +171,13 @@ 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;
|
||||
}
|
||||
|
||||
@@ -198,6 +209,7 @@ 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");
|
||||
@@ -226,6 +238,7 @@ 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");
|
||||
|
@@ -152,6 +152,7 @@ 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; };
|
||||
@@ -173,6 +174,7 @@ private:
|
||||
double rotationX;
|
||||
double rotationY;
|
||||
double rotationZ;
|
||||
double crossfadeDuration;
|
||||
|
||||
gd::String modelResourceName;
|
||||
gd::String materialType;
|
||||
|
@@ -9,6 +9,7 @@ namespace gdjs {
|
||||
ai: integer;
|
||||
ass: float;
|
||||
ap: boolean;
|
||||
cfd: float;
|
||||
};
|
||||
|
||||
type Model3DObjectNetworkSyncData = Object3DNetworkSyncData &
|
||||
@@ -36,6 +37,7 @@ namespace gdjs {
|
||||
| 'BottomCenterZ'
|
||||
| 'BottomCenterY';
|
||||
animations: Model3DAnimation[];
|
||||
crossfadeDuration: float;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -63,7 +65,8 @@ namespace gdjs {
|
||||
*/
|
||||
export class Model3DRuntimeObject
|
||||
extends gdjs.RuntimeObject3D
|
||||
implements gdjs.Animatable {
|
||||
implements gdjs.Animatable
|
||||
{
|
||||
_renderer: gdjs.Model3DRuntimeObjectRenderer;
|
||||
|
||||
_modelResourceName: string;
|
||||
@@ -97,6 +100,7 @@ namespace gdjs {
|
||||
_currentAnimationIndex: integer = 0;
|
||||
_animationSpeedScale: float = 1;
|
||||
_animationPaused: boolean = false;
|
||||
_crossfadeDuration: float = 0;
|
||||
|
||||
constructor(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
@@ -121,6 +125,8 @@ 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();
|
||||
}
|
||||
@@ -202,6 +208,7 @@ namespace gdjs {
|
||||
ai: this._currentAnimationIndex,
|
||||
ass: this._animationSpeedScale,
|
||||
ap: this._animationPaused,
|
||||
cfd: this._crossfadeDuration,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -233,6 +240,9 @@ namespace gdjs {
|
||||
networkSyncData.ap ? this.pauseAnimation() : this.resumeAnimation();
|
||||
}
|
||||
}
|
||||
if (networkSyncData.cfd !== undefined) {
|
||||
this._crossfadeDuration = networkSyncData.cfd;
|
||||
}
|
||||
}
|
||||
|
||||
_reloadModel(objectData: Model3DObjectData) {
|
||||
@@ -275,7 +285,7 @@ namespace gdjs {
|
||||
|
||||
update(instanceContainer: gdjs.RuntimeInstanceContainer): void {
|
||||
const elapsedTime = this.getElapsedTime() / 1000;
|
||||
this._renderer.updateAnimation(elapsedTime * this._animationSpeedScale);
|
||||
this._renderer.updateAnimation(elapsedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,6 +358,11 @@ namespace gdjs {
|
||||
return this._renderer.hasAnimationEnded();
|
||||
}
|
||||
|
||||
setCrossfadeDuration(duration: number): void {
|
||||
if (this._crossfadeDuration === duration) return;
|
||||
this._crossfadeDuration = duration;
|
||||
}
|
||||
|
||||
isAnimationPaused() {
|
||||
return this._animationPaused;
|
||||
}
|
||||
@@ -368,6 +383,7 @@ namespace gdjs {
|
||||
|
||||
setAnimationSpeedScale(ratio: float): void {
|
||||
this._animationSpeedScale = ratio;
|
||||
this._renderer.setAnimationTimeScale(ratio);
|
||||
}
|
||||
|
||||
getAnimationElapsedTime(): float {
|
||||
|
@@ -359,7 +359,6 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
playAnimation(animationName: string, shouldLoop: boolean) {
|
||||
this._animationMixer.stopAllAction();
|
||||
const clip = THREE.AnimationClip.findByName(
|
||||
this._originalModel.animations,
|
||||
animationName
|
||||
@@ -370,12 +369,27 @@ 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);
|
||||
@@ -391,6 +405,12 @@ 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,
|
||||
|
@@ -38,7 +38,7 @@ module.exports = {
|
||||
.setName('Consent Cordova plugin')
|
||||
.setDependencyType('cordova')
|
||||
.setExportName('cordova-plugin-consent')
|
||||
.setVersion('3.0.0-alpha.8')
|
||||
.setVersion('3.0.0-alpha.9')
|
||||
.onlyIfOtherDependencyIsExported('AdMob Cordova plugin');
|
||||
|
||||
extension
|
||||
@@ -93,6 +93,68 @@ 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(
|
||||
|
@@ -1,6 +1,7 @@
|
||||
namespace gdjs {
|
||||
declare var admob: any;
|
||||
declare var cordova: any;
|
||||
declare var consent: any;
|
||||
|
||||
export namespace adMob {
|
||||
const logger = new gdjs.Logger('AdMob');
|
||||
@@ -108,26 +109,119 @@ 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'; // TODO: expose an API to change this and also an automatic way using the consent SDK.
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
// Admob initialization listener
|
||||
document.addEventListener(
|
||||
'deviceready',
|
||||
async () => {
|
||||
// Obtain user consent ?
|
||||
|
||||
logger.info('Starting AdMob.');
|
||||
isStarting = true;
|
||||
|
||||
await admob.start();
|
||||
|
||||
logger.info('AdMob successfully started.');
|
||||
isStarting = false;
|
||||
admobStarted = 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);
|
||||
},
|
||||
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.
|
||||
*/
|
||||
@@ -334,6 +428,7 @@ namespace gdjs {
|
||||
position: atTop ? 'top' : 'bottom',
|
||||
size: bannerRequestedAdSizeType,
|
||||
offset: 0,
|
||||
npa: npaValue,
|
||||
});
|
||||
|
||||
banner.on('load', () => {
|
||||
|
@@ -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 {
|
||||
|
@@ -20,25 +20,41 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
export class AnchorRuntimeBehavior extends gdjs.RuntimeBehavior {
|
||||
_relativeToOriginalWindowSize: any;
|
||||
// Configuration
|
||||
|
||||
_relativeToOriginalWindowSize: boolean;
|
||||
_leftEdgeAnchor: HorizontalAnchor;
|
||||
_rightEdgeAnchor: HorizontalAnchor;
|
||||
_topEdgeAnchor: any;
|
||||
_bottomEdgeAnchor: any;
|
||||
_invalidDistances: boolean = true;
|
||||
_leftEdgeDistance: number = 0;
|
||||
_rightEdgeDistance: number = 0;
|
||||
_topEdgeDistance: number = 0;
|
||||
_bottomEdgeDistance: number = 0;
|
||||
_topEdgeAnchor: VerticalAnchor;
|
||||
_bottomEdgeAnchor: VerticalAnchor;
|
||||
_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;
|
||||
@@ -80,266 +96,307 @@ namespace gdjs {
|
||||
return true;
|
||||
}
|
||||
|
||||
onActivate() {
|
||||
this._invalidDistances = true;
|
||||
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
|
||||
const objectHasMoved =
|
||||
this._oldDrawableX !== this.owner.getDrawableX() ||
|
||||
this._oldDrawableY !== this.owner.getDrawableY() ||
|
||||
this._oldWidth !== this.owner.getWidth() ||
|
||||
this._oldHeight !== this.owner.getHeight();
|
||||
if (objectHasMoved) {
|
||||
this._updateAnchorDistances(instanceContainer);
|
||||
}
|
||||
const parentHasResized =
|
||||
this._parentOldMinX !== instanceContainer.getUnrotatedViewportMinX() ||
|
||||
this._parentOldMinY !== instanceContainer.getUnrotatedViewportMinY() ||
|
||||
this._parentOldMaxX !== instanceContainer.getUnrotatedViewportMaxX() ||
|
||||
this._parentOldMaxY !== instanceContainer.getUnrotatedViewportMaxY();
|
||||
if (parentHasResized) {
|
||||
this._followAnchor(instanceContainer);
|
||||
}
|
||||
}
|
||||
|
||||
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
|
||||
private _updateAnchorDistances(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer
|
||||
) {
|
||||
const workingPoint: FloatPoint = gdjs.staticArray(
|
||||
gdjs.AnchorRuntimeBehavior.prototype.doStepPreEvents
|
||||
) as FloatPoint;
|
||||
let parentMinX = instanceContainer.getUnrotatedViewportMinX();
|
||||
let parentMinY = instanceContainer.getUnrotatedViewportMinY();
|
||||
let parentMaxX = instanceContainer.getUnrotatedViewportMaxX();
|
||||
let parentMaxY = instanceContainer.getUnrotatedViewportMaxY();
|
||||
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());
|
||||
if (this._invalidDistances) {
|
||||
|
||||
let parentMinX = this._parentOldMinX;
|
||||
let parentMinY = this._parentOldMinY;
|
||||
let parentMaxX = this._parentOldMaxX;
|
||||
let parentMaxY = this._parentOldMaxY;
|
||||
if (this._hasJustBeenCreated) {
|
||||
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;
|
||||
} else {
|
||||
parentMinX = instanceContainer.getUnrotatedViewportMinX();
|
||||
parentMinY = instanceContainer.getUnrotatedViewportMinY();
|
||||
parentMaxX = instanceContainer.getUnrotatedViewportMaxX();
|
||||
parentMaxY = instanceContainer.getUnrotatedViewportMaxY();
|
||||
}
|
||||
}
|
||||
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._relativeToOriginalWindowSize
|
||||
? [this.owner.getDrawableX(), this.owner.getDrawableY()]
|
||||
: this._convertInverseCoords(
|
||||
instanceContainer,
|
||||
layer,
|
||||
this.owner.getDrawableX(),
|
||||
this.owner.getDrawableY(),
|
||||
workingPoint
|
||||
);
|
||||
//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;
|
||||
// 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._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;
|
||||
}
|
||||
|
||||
// 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._hasJustBeenCreated = false;
|
||||
}
|
||||
|
||||
private _followAnchor(instanceContainer: gdjs.RuntimeInstanceContainer) {
|
||||
const workingPoint: FloatPoint = gdjs.staticArray(
|
||||
gdjs.AnchorRuntimeBehavior.prototype.doStepPreEvents
|
||||
) as FloatPoint;
|
||||
const layer = instanceContainer.getLayer(this.owner.getLayer());
|
||||
|
||||
let parentMinX = instanceContainer.getUnrotatedViewportMinX();
|
||||
let parentMinY = instanceContainer.getUnrotatedViewportMinY();
|
||||
let parentMaxX = instanceContainer.getUnrotatedViewportMaxX();
|
||||
let parentMaxY = instanceContainer.getUnrotatedViewportMaxY();
|
||||
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);
|
||||
}
|
||||
|
||||
// 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._bottomEdgeAnchor !== VerticalAnchor.None) {
|
||||
this.owner.setHeight(bottom - top);
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (this._leftEdgeAnchor !== HorizontalAnchor.None) {
|
||||
this.owner.setX(left + this.owner.getX() - this.owner.getDrawableX());
|
||||
}
|
||||
|
||||
// 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;
|
||||
if (this._topEdgeAnchor !== VerticalAnchor.None) {
|
||||
this.owner.setY(top + this.owner.getY() - this.owner.getDrawableY());
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
// 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()
|
||||
);
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
if (this._bottomEdgeAnchor !== VerticalAnchor.None) {
|
||||
this.owner.setY(
|
||||
this.owner.getY() === this.owner.getDrawableY()
|
||||
? top
|
||||
: top +
|
||||
((this.owner.getY() - this.owner.getDrawableY()) * height) /
|
||||
this.owner.getHeight()
|
||||
bottom +
|
||||
this.owner.getY() -
|
||||
this.owner.getDrawableY() -
|
||||
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._oldDrawableX = this.owner.getDrawableX();
|
||||
this._oldDrawableY = this.owner.getDrawableY();
|
||||
this._oldWidth = this.owner.getWidth();
|
||||
this._oldHeight = this.owner.getHeight();
|
||||
|
||||
this._parentOldMinX = instanceContainer.getUnrotatedViewportMinX();
|
||||
this._parentOldMinY = instanceContainer.getUnrotatedViewportMinY();
|
||||
this._parentOldMaxX = instanceContainer.getUnrotatedViewportMaxX();
|
||||
this._parentOldMaxY = instanceContainer.getUnrotatedViewportMaxY();
|
||||
}
|
||||
|
||||
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {}
|
||||
|
@@ -54,7 +54,7 @@ module.exports = {
|
||||
objectProperties
|
||||
.getOrCreate('text')
|
||||
.setValue(objectContent.text)
|
||||
.setType('textarea')
|
||||
.setType('multilinestring')
|
||||
.setLabel(_('BBCode text'));
|
||||
|
||||
objectProperties
|
||||
@@ -81,6 +81,19 @@ 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)
|
||||
@@ -89,13 +102,6 @@ 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')
|
||||
@@ -106,15 +112,14 @@ 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',
|
||||
wordWrap: true,
|
||||
verticalTextAlignment: 'top',
|
||||
};
|
||||
|
||||
objectBBText.updateInitialInstanceProperty = function (
|
||||
@@ -193,9 +198,10 @@ 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)
|
||||
@@ -245,9 +251,10 @@ 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)
|
||||
@@ -370,19 +377,6 @@ 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',
|
||||
@@ -404,6 +398,35 @@ 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`,
|
||||
@@ -501,7 +524,6 @@ 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',
|
||||
},
|
||||
@@ -573,11 +595,18 @@ module.exports = {
|
||||
});
|
||||
}
|
||||
|
||||
const wordWrap = object.content.wordWrap;
|
||||
const wordWrap = this._instance.hasCustomSize();
|
||||
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) {
|
||||
@@ -585,25 +614,42 @@ module.exports = {
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
|
||||
this._pixiObject.position.x =
|
||||
this._instance.getX() + this._pixiObject.width / 2;
|
||||
if (this._instance.hasCustomSize()) {
|
||||
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.y =
|
||||
this._instance.getY() + this._pixiObject.height / 2;
|
||||
this._instance.getY() + this._pixiObject.height * (0.5 - alignmentY);
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
|
||||
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,
|
||||
@@ -625,6 +671,19 @@ 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(
|
||||
|
@@ -29,9 +29,9 @@ namespace gdjs {
|
||||
runtimeObject._color[2]
|
||||
),
|
||||
tagStyle: 'bbcode',
|
||||
wordWrap: runtimeObject._wordWrap,
|
||||
wordWrap: runtimeObject._wrapping,
|
||||
wordWrapWidth: runtimeObject._wrappingWidth,
|
||||
align: runtimeObject._align as PIXI.TextStyleAlign | undefined,
|
||||
align: runtimeObject._textAlign as PIXI.TextStyleAlign | undefined,
|
||||
},
|
||||
});
|
||||
instanceContainer
|
||||
@@ -39,10 +39,7 @@ namespace gdjs {
|
||||
.getRenderer()
|
||||
.addRendererObject(this._pixiObject, runtimeObject.getZOrder());
|
||||
|
||||
// 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.updateAlignment();
|
||||
this.updateText();
|
||||
this.updatePosition();
|
||||
this.updateAngle();
|
||||
@@ -55,7 +52,7 @@ namespace gdjs {
|
||||
|
||||
updateWordWrap(): void {
|
||||
//@ts-ignore Private member usage.
|
||||
this._pixiObject._style.wordWrap = this._object._wordWrap;
|
||||
this._pixiObject._style.wordWrap = this._object._wrapping;
|
||||
this._pixiObject.dirty = true;
|
||||
this.updatePosition();
|
||||
}
|
||||
@@ -84,7 +81,7 @@ namespace gdjs {
|
||||
|
||||
updateAlignment(): void {
|
||||
//@ts-ignore Private member usage.
|
||||
this._pixiObject._style.align = this._object._align;
|
||||
this._pixiObject._style.align = this._object._textAlign;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
|
||||
@@ -106,9 +103,38 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
updatePosition(): void {
|
||||
this._pixiObject.position.x = this._object.x + this._pixiObject.width / 2;
|
||||
if (this._object.isWrapping()) {
|
||||
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.y =
|
||||
this._object.y + this._pixiObject.height / 2;
|
||||
this._object.y + this._pixiObject.height * (0.5 - alignmentY);
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
}
|
||||
|
||||
updateAngle(): void {
|
||||
|
@@ -19,6 +19,7 @@ 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;
|
||||
@@ -32,6 +33,7 @@ namespace gdjs {
|
||||
wwrap: boolean;
|
||||
wwidth: float;
|
||||
align: string;
|
||||
vta: string;
|
||||
hidden: boolean;
|
||||
};
|
||||
|
||||
@@ -43,7 +45,8 @@ namespace gdjs {
|
||||
*/
|
||||
export class BBTextRuntimeObject
|
||||
extends gdjs.RuntimeObject
|
||||
implements gdjs.OpacityHandler {
|
||||
implements gdjs.OpacityHandler
|
||||
{
|
||||
_opacity: float;
|
||||
|
||||
_text: string;
|
||||
@@ -51,13 +54,14 @@ namespace gdjs {
|
||||
/** color in format [r, g, b], where each component is in the range [0, 255] */
|
||||
_color: integer[];
|
||||
_fontFamily: string;
|
||||
_fontSize: number;
|
||||
_fontSize: float;
|
||||
|
||||
_wordWrap: boolean;
|
||||
_wrapping: boolean = false;
|
||||
_wrappingWidth: float = 250;
|
||||
|
||||
// This value is the default wrapping width of the runtime object.
|
||||
_align: string;
|
||||
_textAlign: string;
|
||||
_verticalTextAlignment: string;
|
||||
|
||||
_renderer: gdjs.BBTextRuntimeObjectRenderer;
|
||||
|
||||
// While this should rather be exposed as a property for all objects, honor the "visible"
|
||||
@@ -80,24 +84,26 @@ 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._wordWrap = objectData.content.wordWrap;
|
||||
this._align = objectData.content.align;
|
||||
this._textAlign = objectData.content.align;
|
||||
this._verticalTextAlignment =
|
||||
objectData.content.verticalTextAlignment || 'top';
|
||||
this.hidden = !objectData.content.visible;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
getRendererObject() {
|
||||
override getRendererObject() {
|
||||
return this._renderer.getRendererObject();
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
updateFromObjectData(
|
||||
override updateFromObjectData(
|
||||
oldObjectData: BBTextObjectDataType,
|
||||
newObjectData: BBTextObjectDataType
|
||||
): boolean {
|
||||
@@ -123,15 +129,23 @@ namespace gdjs {
|
||||
this.setFontSize(newObjectData.content.fontSize);
|
||||
}
|
||||
if (oldObjectData.content.wordWrap !== newObjectData.content.wordWrap) {
|
||||
this.setWordWrap(newObjectData.content.wordWrap);
|
||||
this.setWrapping(newObjectData.content.wordWrap);
|
||||
}
|
||||
if (oldObjectData.content.align !== newObjectData.content.align) {
|
||||
this.setAlignment(newObjectData.content.align);
|
||||
this.setTextAlignment(newObjectData.content.align);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.verticalTextAlignment !==
|
||||
newObjectData.content.verticalTextAlignment
|
||||
) {
|
||||
this.setVerticalTextAlignment(
|
||||
newObjectData.content.verticalTextAlignment
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
getNetworkSyncData(): BBTextObjectNetworkSyncData {
|
||||
override getNetworkSyncData(): BBTextObjectNetworkSyncData {
|
||||
return {
|
||||
...super.getNetworkSyncData(),
|
||||
text: this._text,
|
||||
@@ -139,14 +153,15 @@ namespace gdjs {
|
||||
c: this._color,
|
||||
ff: this._fontFamily,
|
||||
fs: this._fontSize,
|
||||
wwrap: this._wordWrap,
|
||||
wwrap: this._wrapping,
|
||||
wwidth: this._wrappingWidth,
|
||||
align: this._align,
|
||||
align: this._textAlign,
|
||||
vta: this._verticalTextAlignment,
|
||||
hidden: this.hidden,
|
||||
};
|
||||
}
|
||||
|
||||
updateFromNetworkSyncData(
|
||||
override updateFromNetworkSyncData(
|
||||
networkSyncData: BBTextObjectNetworkSyncData
|
||||
): void {
|
||||
super.updateFromNetworkSyncData(networkSyncData);
|
||||
@@ -166,26 +181,29 @@ namespace gdjs {
|
||||
if (this._fontSize !== undefined) {
|
||||
this.setFontSize(networkSyncData.fs);
|
||||
}
|
||||
if (this._wordWrap !== undefined) {
|
||||
this.setWordWrap(networkSyncData.wwrap);
|
||||
if (this._wrapping !== undefined) {
|
||||
this.setWrapping(networkSyncData.wwrap);
|
||||
}
|
||||
if (this._wrappingWidth !== undefined) {
|
||||
this.setWrappingWidth(networkSyncData.wwidth);
|
||||
}
|
||||
if (this._align !== undefined) {
|
||||
this.setAlignment(networkSyncData.align);
|
||||
if (this._textAlign !== undefined) {
|
||||
this.setTextAlignment(networkSyncData.align);
|
||||
}
|
||||
if (this._verticalTextAlignment !== undefined) {
|
||||
this.setVerticalTextAlignment(networkSyncData.vta);
|
||||
}
|
||||
if (this.hidden !== undefined) {
|
||||
this.hide(networkSyncData.hidden);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the extra parameters that could be set for an instance.
|
||||
*/
|
||||
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
|
||||
override 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.
|
||||
@@ -197,7 +215,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
onDestroyed(): void {
|
||||
override onDestroyed(): void {
|
||||
super.onDestroyed();
|
||||
this._renderer.destroy();
|
||||
}
|
||||
@@ -205,7 +223,7 @@ namespace gdjs {
|
||||
/**
|
||||
* Set the markup text to display.
|
||||
*/
|
||||
setBBText(text): void {
|
||||
setBBText(text: string): void {
|
||||
this._text = text;
|
||||
this._renderer.updateText();
|
||||
this.invalidateHitboxes();
|
||||
@@ -218,7 +236,7 @@ namespace gdjs {
|
||||
return this._text;
|
||||
}
|
||||
|
||||
setColor(rgbColorString): void {
|
||||
setColor(rgbColorString: string): void {
|
||||
this._color = gdjs.rgbOrHexToRGBColor(rgbColorString);
|
||||
this._renderer.updateColor();
|
||||
}
|
||||
@@ -231,7 +249,7 @@ namespace gdjs {
|
||||
return this._color[0] + ';' + this._color[1] + ';' + this._color[2];
|
||||
}
|
||||
|
||||
setFontSize(fontSize): void {
|
||||
setFontSize(fontSize: float): void {
|
||||
this._fontSize = fontSize;
|
||||
this._renderer.updateFontSize();
|
||||
}
|
||||
@@ -240,47 +258,66 @@ namespace gdjs {
|
||||
return this._fontSize;
|
||||
}
|
||||
|
||||
setFontFamily(fontFamily): void {
|
||||
setFontFamily(fontFamily: string): void {
|
||||
this._fontFamily = fontFamily;
|
||||
this._renderer.updateFontFamily();
|
||||
}
|
||||
|
||||
getFontFamily() {
|
||||
getFontFamily(): string {
|
||||
return this._fontFamily;
|
||||
}
|
||||
|
||||
setAlignment(align): void {
|
||||
this._align = align;
|
||||
/**
|
||||
* @deprecated Use `setTextAlignment` instead
|
||||
*/
|
||||
setAlignment(align: string): void {
|
||||
this.setTextAlignment(align);
|
||||
}
|
||||
|
||||
setTextAlignment(align: string): void {
|
||||
this._textAlign = align;
|
||||
this._renderer.updateAlignment();
|
||||
}
|
||||
|
||||
getAlignment() {
|
||||
return this._align;
|
||||
/**
|
||||
* @deprecated Use `getTextAlignment` instead
|
||||
*/
|
||||
getAlignment(): string {
|
||||
return this.getTextAlignment();
|
||||
}
|
||||
|
||||
getTextAlignment(): string {
|
||||
return this._textAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set object position on X axis.
|
||||
* @param x The new position X of the object.
|
||||
* Set the text alignment on Y axis for multiline text objects.
|
||||
* @param alignment The text alignment.
|
||||
*/
|
||||
setX(x: float): void {
|
||||
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 {
|
||||
super.setX(x);
|
||||
this._renderer.updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set object position on Y axis.
|
||||
* @param y The new position Y of the object.
|
||||
*/
|
||||
setY(y: float): void {
|
||||
override setY(y: float): void {
|
||||
super.setY(y);
|
||||
this._renderer.updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the angle of the object.
|
||||
* @param angle The new angle of the object.
|
||||
*/
|
||||
setAngle(angle: float): void {
|
||||
override setAngle(angle: float): void {
|
||||
super.setAngle(angle);
|
||||
this._renderer.updateAngle();
|
||||
}
|
||||
@@ -326,31 +363,36 @@ namespace gdjs {
|
||||
return this._wrappingWidth;
|
||||
}
|
||||
|
||||
setWordWrap(wordWrap: boolean): void {
|
||||
if (this._wordWrap === wordWrap) return;
|
||||
setWrapping(wordWrap: boolean): void {
|
||||
if (this._wrapping === wordWrap) return;
|
||||
|
||||
this._wordWrap = wordWrap;
|
||||
this._wrapping = wordWrap;
|
||||
this._renderer.updateWordWrap();
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
|
||||
getWordWrap() {
|
||||
return this._wordWrap;
|
||||
isWrapping() {
|
||||
return this._wrapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of the object.
|
||||
*/
|
||||
getWidth(): float {
|
||||
override getWidth(): float {
|
||||
return this._renderer.getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of the object.
|
||||
*/
|
||||
getHeight(): float {
|
||||
override 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);
|
||||
|
@@ -54,7 +54,7 @@ module.exports = {
|
||||
objectProperties
|
||||
.getOrCreate('text')
|
||||
.setValue(objectContent.text)
|
||||
.setType('textarea')
|
||||
.setType('multilinestring')
|
||||
.setLabel(_('Text'));
|
||||
|
||||
objectProperties
|
||||
@@ -67,6 +67,19 @@ 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)
|
||||
@@ -97,18 +110,10 @@ 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,
|
||||
@@ -116,7 +121,7 @@ module.exports = {
|
||||
bitmapFontResourceName: '',
|
||||
textureAtlasResourceName: '',
|
||||
align: 'left',
|
||||
wordWrap: true,
|
||||
verticalTextAlignment: 'top',
|
||||
};
|
||||
|
||||
bitmapTextObject.updateInitialInstanceProperty = function (
|
||||
@@ -342,7 +347,7 @@ module.exports = {
|
||||
_('Alignment ("left", "right" or "center")')
|
||||
)
|
||||
)
|
||||
.setFunctionName('getAlignment');
|
||||
.setFunctionName('getTextAlignment');
|
||||
|
||||
object
|
||||
.addAction(
|
||||
@@ -362,36 +367,36 @@ module.exports = {
|
||||
false
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setAlignment');
|
||||
.setFunctionName('setTextAlignment');
|
||||
|
||||
object
|
||||
.addCondition(
|
||||
'WordWrap',
|
||||
_('Word wrap'),
|
||||
_('Check if word wrap is enabled.'),
|
||||
_('_PARAM0_ word wrap is enabled'),
|
||||
_('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', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('getWordWrap');
|
||||
.setFunctionName('isWrapping');
|
||||
|
||||
object
|
||||
.addAction(
|
||||
'SetWordWrap',
|
||||
_('Word wrap'),
|
||||
_('Word wrapping'),
|
||||
_('De/activate word wrapping.'),
|
||||
_('Activate word wrap of _PARAM0_: _PARAM1_'),
|
||||
_('Activate word wrapping of _PARAM0_: _PARAM1_'),
|
||||
'',
|
||||
'res/actions/wordWrap24_black.png',
|
||||
'res/actions/wordWrap_black.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.addParameter('yesorno', _('Activate word wrap'), '', false)
|
||||
.addParameter('yesorno', _('Activate word wrapping'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setWordWrap');
|
||||
.setFunctionName('setWrapping');
|
||||
|
||||
object
|
||||
.addExpressionAndConditionAndAction(
|
||||
@@ -665,9 +670,8 @@ module.exports = {
|
||||
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);
|
||||
@@ -706,20 +710,46 @@ module.exports = {
|
||||
}
|
||||
|
||||
// Set up the wrapping width if enabled.
|
||||
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;
|
||||
const oldMaxWidth = this._pixiObject.maxWidth;
|
||||
this._pixiObject.maxWidth = this._instance.hasCustomSize()
|
||||
? this.getCustomWidth() / this._pixiObject.scale.x
|
||||
: 0;
|
||||
if (oldMaxWidth !== this._pixiObject.maxWidth) {
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
|
||||
this._pixiObject.position.x =
|
||||
this._instance.getX() + (this._pixiObject.textWidth * scale) / 2;
|
||||
if (this._instance.hasCustomSize()) {
|
||||
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.y =
|
||||
this._instance.getY() + (this._pixiObject.textHeight * scale) / 2;
|
||||
this._instance.getY() + this._pixiObject.height * (0.5 - alignmentY);
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
|
||||
this._pixiObject.rotation = RenderedInstance.toRad(
|
||||
this._instance.getAngle()
|
||||
);
|
||||
@@ -740,19 +770,26 @@ module.exports = {
|
||||
releaseBitmapFont(fontName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the width of the instance, when it's not resized.
|
||||
*/
|
||||
getDefaultWidth() {
|
||||
return this._pixiObject.width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the height of the instance, when it's not resized.
|
||||
*/
|
||||
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(
|
||||
|
@@ -35,13 +35,6 @@ 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();
|
||||
@@ -130,7 +123,7 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
updateWrappingWidth(): void {
|
||||
if (this._object._wordWrap) {
|
||||
if (this._object._wrapping) {
|
||||
this._pixiObject.maxWidth =
|
||||
this._object._wrappingWidth / this._object._scaleX;
|
||||
this._pixiObject.dirty = true;
|
||||
@@ -148,13 +141,43 @@ namespace gdjs {
|
||||
|
||||
updateAlignment(): void {
|
||||
// @ts-ignore - assume align is always a valid value.
|
||||
this._pixiObject.align = this._object._align;
|
||||
this._pixiObject.align = this._object._textAlign;
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
updatePosition(): void {
|
||||
this._pixiObject.position.x = this._object.x + this.getWidth() / 2;
|
||||
this._pixiObject.position.y = this._object.y + this.getHeight() / 2;
|
||||
if (this._object.isWrapping()) {
|
||||
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.y =
|
||||
this._object.y + this._pixiObject.height * (0.5 - alignmentY);
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
}
|
||||
|
||||
updateAngle(): void {
|
||||
@@ -173,5 +196,6 @@ namespace gdjs {
|
||||
return this._pixiObject.textHeight * this.getScale();
|
||||
}
|
||||
}
|
||||
export const BitmapTextRuntimeObjectRenderer = BitmapTextRuntimeObjectPixiRenderer;
|
||||
export const BitmapTextRuntimeObjectRenderer =
|
||||
BitmapTextRuntimeObjectPixiRenderer;
|
||||
}
|
||||
|
@@ -15,12 +15,11 @@ 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;
|
||||
@@ -35,6 +34,7 @@ namespace gdjs {
|
||||
wwrap: boolean;
|
||||
wwidth: float;
|
||||
align: string;
|
||||
vta: string;
|
||||
};
|
||||
|
||||
export type BitmapTextObjectNetworkSyncData = ObjectNetworkSyncData &
|
||||
@@ -52,7 +52,8 @@ 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] */
|
||||
@@ -61,9 +62,10 @@ namespace gdjs {
|
||||
_textureAtlasResourceName: string;
|
||||
_scaleX: number;
|
||||
_scaleY: number;
|
||||
_wordWrap: boolean;
|
||||
_wrapping: boolean = false;
|
||||
_wrappingWidth: float;
|
||||
_align: string;
|
||||
_textAlign: string;
|
||||
_verticalTextAlignment: string;
|
||||
|
||||
_renderer: gdjs.BitmapTextRuntimeObjectPixiRenderer;
|
||||
|
||||
@@ -86,9 +88,10 @@ 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._align = objectData.content.align;
|
||||
this._textAlign = objectData.content.align;
|
||||
this._verticalTextAlignment =
|
||||
objectData.content.verticalTextAlignment || 'top';
|
||||
|
||||
this._renderer = new gdjs.BitmapTextRuntimeObjectRenderer(
|
||||
this,
|
||||
@@ -99,12 +102,12 @@ namespace gdjs {
|
||||
this.onCreated();
|
||||
}
|
||||
|
||||
getRendererObject() {
|
||||
override getRendererObject() {
|
||||
return this._renderer.getRendererObject();
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
updateFromObjectData(
|
||||
override updateFromObjectData(
|
||||
oldObjectData: BitmapTextObjectDataType,
|
||||
newObjectData: BitmapTextObjectDataType
|
||||
): boolean {
|
||||
@@ -137,17 +140,22 @@ namespace gdjs {
|
||||
if (oldObjectData.content.scale !== newObjectData.content.scale) {
|
||||
this.setScale(newObjectData.content.scale);
|
||||
}
|
||||
if (oldObjectData.content.wordWrap !== newObjectData.content.wordWrap) {
|
||||
this.setWordWrap(newObjectData.content.wordWrap);
|
||||
}
|
||||
if (oldObjectData.content.align !== newObjectData.content.align) {
|
||||
this.setAlignment(newObjectData.content.align);
|
||||
this.setTextAlignment(newObjectData.content.align);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.verticalTextAlignment !==
|
||||
newObjectData.content.verticalTextAlignment
|
||||
) {
|
||||
this.setVerticalTextAlignment(
|
||||
newObjectData.content.verticalTextAlignment
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getNetworkSyncData(): BitmapTextObjectNetworkSyncData {
|
||||
override getNetworkSyncData(): BitmapTextObjectNetworkSyncData {
|
||||
return {
|
||||
...super.getNetworkSyncData(),
|
||||
text: this._text,
|
||||
@@ -156,13 +164,14 @@ namespace gdjs {
|
||||
bfrn: this._bitmapFontResourceName,
|
||||
tarn: this._textureAtlasResourceName,
|
||||
scale: this.getScale(),
|
||||
wwrap: this._wordWrap,
|
||||
wwrap: this._wrapping,
|
||||
wwidth: this._wrappingWidth,
|
||||
align: this._align,
|
||||
align: this._textAlign,
|
||||
vta: this._verticalTextAlignment,
|
||||
};
|
||||
}
|
||||
|
||||
updateFromNetworkSyncData(
|
||||
override updateFromNetworkSyncData(
|
||||
networkSyncData: BitmapTextObjectNetworkSyncData
|
||||
): void {
|
||||
super.updateFromNetworkSyncData(networkSyncData);
|
||||
@@ -185,30 +194,36 @@ namespace gdjs {
|
||||
if (this._scaleX !== undefined) {
|
||||
this.setScale(networkSyncData.scale);
|
||||
}
|
||||
if (this._wordWrap !== undefined) {
|
||||
this.setWordWrap(networkSyncData.wwrap);
|
||||
if (this._wrapping !== undefined) {
|
||||
this.setWrapping(networkSyncData.wwrap);
|
||||
}
|
||||
if (this._wrappingWidth !== undefined) {
|
||||
this.setWrappingWidth(networkSyncData.wwidth);
|
||||
}
|
||||
if (this._align !== undefined) {
|
||||
this.setAlignment(networkSyncData.align);
|
||||
if (this._textAlign !== undefined) {
|
||||
this.setTextAlignment(networkSyncData.align);
|
||||
}
|
||||
if (this._verticalTextAlignment !== undefined) {
|
||||
this.setVerticalTextAlignment(networkSyncData.vta);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the extra parameters that could be set for an instance.
|
||||
*/
|
||||
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
|
||||
override extraInitializationFromInitialInstance(
|
||||
initialInstanceData: InstanceData
|
||||
) {
|
||||
if (initialInstanceData.customSize) {
|
||||
this.setWrappingWidth(initialInstanceData.width);
|
||||
this.setWrapping(true);
|
||||
}
|
||||
if (initialInstanceData.opacity !== undefined) {
|
||||
this.setOpacity(initialInstanceData.opacity);
|
||||
}
|
||||
}
|
||||
|
||||
onDestroyed(): void {
|
||||
override onDestroyed(): void {
|
||||
super.onDestroyed();
|
||||
this._renderer.onDestroy();
|
||||
}
|
||||
@@ -313,38 +328,43 @@ namespace gdjs {
|
||||
return this._textureAtlasResourceName;
|
||||
}
|
||||
|
||||
setAlignment(align: string): void {
|
||||
this._align = align;
|
||||
setTextAlignment(align: string): void {
|
||||
this._textAlign = align;
|
||||
this._renderer.updateAlignment();
|
||||
}
|
||||
|
||||
getAlignment(): string {
|
||||
return this._align;
|
||||
getTextAlignment(): string {
|
||||
return this._textAlign;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set object position on X axis.
|
||||
* @param x The new position X of the object.
|
||||
* Set the text alignment on Y axis for multiline text objects.
|
||||
* @param alignment The text alignment.
|
||||
*/
|
||||
setX(x: float): void {
|
||||
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 {
|
||||
super.setX(x);
|
||||
this._renderer.updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set object position on Y axis.
|
||||
* @param y The new position Y of the object.
|
||||
*/
|
||||
setY(y: float): void {
|
||||
override setY(y: float): void {
|
||||
super.setY(y);
|
||||
this._renderer.updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the angle of the object.
|
||||
* @param angle The new angle of the object.
|
||||
*/
|
||||
setAngle(angle: float): void {
|
||||
override setAngle(angle: float): void {
|
||||
super.setAngle(angle);
|
||||
this._renderer.updateAngle();
|
||||
}
|
||||
@@ -388,29 +408,34 @@ namespace gdjs {
|
||||
return this._wrappingWidth;
|
||||
}
|
||||
|
||||
setWordWrap(wordWrap: boolean): void {
|
||||
this._wordWrap = wordWrap;
|
||||
setWrapping(wordWrap: boolean): void {
|
||||
this._wrapping = wordWrap;
|
||||
this._renderer.updateWrappingWidth();
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
|
||||
getWordWrap(): boolean {
|
||||
return this._wordWrap;
|
||||
isWrapping(): boolean {
|
||||
return this._wrapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of the object.
|
||||
*/
|
||||
getWidth(): float {
|
||||
override getWidth(): float {
|
||||
return this._renderer.getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of the object.
|
||||
*/
|
||||
getHeight(): float {
|
||||
override 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',
|
||||
|
@@ -249,13 +249,16 @@ 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;
|
||||
|
@@ -157,9 +157,8 @@ 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];
|
||||
|
@@ -22,7 +22,8 @@ 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') {
|
||||
@@ -42,7 +43,8 @@ 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;
|
||||
}
|
||||
@@ -88,7 +90,8 @@ 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,
|
||||
@@ -104,7 +107,8 @@ 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;
|
||||
|
@@ -20,7 +20,8 @@ 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') {
|
||||
@@ -36,7 +37,8 @@ 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;
|
||||
}
|
||||
@@ -78,7 +80,8 @@ 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,
|
||||
@@ -92,7 +95,8 @@ 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;
|
||||
|
@@ -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;
|
||||
}
|
||||
})()
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
})()
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -18,7 +18,8 @@ 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') {
|
||||
@@ -34,7 +35,8 @@ 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];
|
||||
}
|
||||
@@ -68,7 +70,8 @@ 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],
|
||||
@@ -80,7 +83,8 @@ 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;
|
||||
|
@@ -29,7 +29,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const colorMapFilter = (filter as unknown) as PIXI.filters.ColorMapFilter;
|
||||
const colorMapFilter = filter as unknown as PIXI.filters.ColorMapFilter;
|
||||
if (parameterName === 'mix') {
|
||||
colorMapFilter.mix = gdjs.PixiFiltersTools.clampValue(
|
||||
value / 100,
|
||||
@@ -39,7 +39,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const colorMapFilter = (filter as unknown) as PIXI.filters.ColorMapFilter;
|
||||
const colorMapFilter = filter as unknown as PIXI.filters.ColorMapFilter;
|
||||
if (parameterName === 'mix') {
|
||||
return colorMapFilter.mix;
|
||||
}
|
||||
@@ -63,20 +63,20 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: boolean
|
||||
) {
|
||||
const colorMapFilter = (filter as unknown) as PIXI.filters.ColorMapFilter;
|
||||
const colorMapFilter = filter as unknown as PIXI.filters.ColorMapFilter;
|
||||
if (parameterName === 'nearest') {
|
||||
colorMapFilter.nearest = value;
|
||||
}
|
||||
}
|
||||
getNetworkSyncData(filter: PIXI.Filter): ColorMapFilterNetworkSyncData {
|
||||
const colorMapFilter = (filter as unknown) as PIXI.filters.ColorMapFilter;
|
||||
const colorMapFilter = filter as unknown as PIXI.filters.ColorMapFilter;
|
||||
return { mix: colorMapFilter.mix, near: colorMapFilter.nearest };
|
||||
}
|
||||
updateFromNetworkSyncData(
|
||||
filter: PIXI.Filter,
|
||||
data: ColorMapFilterNetworkSyncData
|
||||
) {
|
||||
const colorMapFilter = (filter as unknown) as PIXI.filters.ColorMapFilter;
|
||||
const colorMapFilter = filter as unknown as PIXI.filters.ColorMapFilter;
|
||||
colorMapFilter.mix = data.mix;
|
||||
colorMapFilter.nearest = data.near;
|
||||
}
|
||||
|
@@ -23,15 +23,17 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
const colorReplaceFilter =
|
||||
filter as unknown as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
if (parameterName === 'epsilon') {
|
||||
colorReplaceFilter.epsilon = value;
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
const colorReplaceFilter =
|
||||
filter as unknown as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
if (parameterName === 'epsilon') {
|
||||
return colorReplaceFilter.epsilon;
|
||||
}
|
||||
@@ -42,8 +44,9 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: string
|
||||
) {
|
||||
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
const colorReplaceFilter =
|
||||
filter as unknown as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
if (parameterName === 'originalColor') {
|
||||
colorReplaceFilter.originalColor = gdjs.rgbOrHexStringToNumber(value);
|
||||
} else if (parameterName === 'newColor') {
|
||||
@@ -55,8 +58,9 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
): void {
|
||||
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
const colorReplaceFilter =
|
||||
filter as unknown as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
if (parameterName === 'originalColor') {
|
||||
colorReplaceFilter.originalColor = value;
|
||||
} else if (parameterName === 'newColor') {
|
||||
@@ -64,8 +68,9 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getColorParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
const colorReplaceFilter =
|
||||
filter as unknown as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
if (parameterName === 'originalColor') {
|
||||
return colorReplaceFilter.originalColor;
|
||||
} else if (parameterName === 'newColor') {
|
||||
@@ -81,8 +86,9 @@ namespace gdjs {
|
||||
getNetworkSyncData(
|
||||
filter: PIXI.Filter
|
||||
): ColorReplaceFilterNetworkSyncData {
|
||||
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
const colorReplaceFilter =
|
||||
filter as unknown as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
return {
|
||||
e: colorReplaceFilter.epsilon,
|
||||
oc: colorReplaceFilter.originalColor,
|
||||
@@ -93,8 +99,9 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: ColorReplaceFilterNetworkSyncData
|
||||
) {
|
||||
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
const colorReplaceFilter =
|
||||
filter as unknown as PIXI.filters.ColorReplaceFilter &
|
||||
ColorReplaceFilterExtra;
|
||||
colorReplaceFilter.epsilon = data.e;
|
||||
colorReplaceFilter.originalColor = data.oc;
|
||||
colorReplaceFilter.newColor = data.nc;
|
||||
|
@@ -23,13 +23,13 @@ namespace gdjs {
|
||||
new (class extends gdjs.PixiFiltersTools.PixiFilterCreator {
|
||||
makePIXIFilter(layer, effectData) {
|
||||
const filter = new PIXI.filters.CRTFilter();
|
||||
const crtFilter = (filter as unknown) as PIXI.filters.CRTFilter &
|
||||
const crtFilter = filter as unknown as PIXI.filters.CRTFilter &
|
||||
CRTFilterExtra;
|
||||
crtFilter._animationTimer = 0;
|
||||
return crtFilter;
|
||||
}
|
||||
updatePreRender(filter: PIXI.Filter, target: EffectsTarget) {
|
||||
const crtFilter = (filter as unknown) as PIXI.filters.CRTFilter &
|
||||
const crtFilter = filter as unknown as PIXI.filters.CRTFilter &
|
||||
CRTFilterExtra;
|
||||
if (crtFilter.animationSpeed !== 0) {
|
||||
// Multiply by 10 so that the default value is a sensible speed
|
||||
@@ -49,7 +49,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const crtFilter = (filter as unknown) as PIXI.filters.CRTFilter &
|
||||
const crtFilter = filter as unknown as PIXI.filters.CRTFilter &
|
||||
CRTFilterExtra;
|
||||
if (parameterName === 'lineWidth') {
|
||||
crtFilter.lineWidth = value;
|
||||
@@ -76,7 +76,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const crtFilter = (filter as unknown) as PIXI.filters.CRTFilter &
|
||||
const crtFilter = filter as unknown as PIXI.filters.CRTFilter &
|
||||
CRTFilterExtra;
|
||||
if (parameterName === 'lineWidth') {
|
||||
return crtFilter.lineWidth;
|
||||
@@ -131,13 +131,13 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: boolean
|
||||
) {
|
||||
const crtFilter = (filter as unknown) as PIXI.filters.CRTFilter;
|
||||
const crtFilter = filter as unknown as PIXI.filters.CRTFilter;
|
||||
if (parameterName === 'verticalLine') {
|
||||
crtFilter.verticalLine = value;
|
||||
}
|
||||
}
|
||||
getNetworkSyncData(filter: PIXI.Filter): CRTFilterNetworkSyncData {
|
||||
const crtFilter = (filter as unknown) as PIXI.filters.CRTFilter &
|
||||
const crtFilter = filter as unknown as PIXI.filters.CRTFilter &
|
||||
CRTFilterExtra;
|
||||
return {
|
||||
lw: crtFilter.lineWidth,
|
||||
@@ -158,7 +158,7 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: CRTFilterNetworkSyncData
|
||||
) {
|
||||
const crtFilter = (filter as unknown) as PIXI.filters.CRTFilter &
|
||||
const crtFilter = filter as unknown as PIXI.filters.CRTFilter &
|
||||
CRTFilterExtra;
|
||||
crtFilter.lineWidth = data.lw;
|
||||
crtFilter.lineContrast = data.lc;
|
||||
|
@@ -25,7 +25,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const displacementFilter = (filter as unknown) as PIXI.DisplacementFilter;
|
||||
const displacementFilter = filter as unknown as PIXI.DisplacementFilter;
|
||||
if (parameterName === 'scaleX') {
|
||||
displacementFilter.scale.x = value;
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const displacementFilter = (filter as unknown) as PIXI.DisplacementFilter;
|
||||
const displacementFilter = filter as unknown as PIXI.DisplacementFilter;
|
||||
if (parameterName === 'scaleX') {
|
||||
return displacementFilter.scale.x;
|
||||
}
|
||||
@@ -64,7 +64,7 @@ namespace gdjs {
|
||||
getNetworkSyncData(
|
||||
filter: PIXI.Filter
|
||||
): DisplacementFilterNetworkSyncData {
|
||||
const displacementFilter = (filter as unknown) as PIXI.DisplacementFilter;
|
||||
const displacementFilter = filter as unknown as PIXI.DisplacementFilter;
|
||||
return {
|
||||
sx: displacementFilter.scale.x,
|
||||
sy: displacementFilter.scale.y,
|
||||
@@ -74,7 +74,7 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: DisplacementFilterNetworkSyncData
|
||||
) {
|
||||
const displacementFilter = (filter as unknown) as PIXI.DisplacementFilter;
|
||||
const displacementFilter = filter as unknown as PIXI.DisplacementFilter;
|
||||
displacementFilter.scale.x = data.sx;
|
||||
displacementFilter.scale.y = data.sy;
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const dotFilter = (filter as unknown) as PIXI.filters.DotFilter;
|
||||
const dotFilter = filter as unknown as PIXI.filters.DotFilter;
|
||||
if (parameterName === 'scale') {
|
||||
dotFilter.scale = value;
|
||||
} else if (parameterName === 'angle') {
|
||||
@@ -24,7 +24,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const dotFilter = (filter as unknown) as PIXI.filters.DotFilter;
|
||||
const dotFilter = filter as unknown as PIXI.filters.DotFilter;
|
||||
if (parameterName === 'scale') {
|
||||
return dotFilter.scale;
|
||||
}
|
||||
@@ -52,14 +52,14 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): DotFilterNetworkSyncData {
|
||||
const dotFilter = (filter as unknown) as PIXI.filters.DotFilter;
|
||||
const dotFilter = filter as unknown as PIXI.filters.DotFilter;
|
||||
return { s: dotFilter.scale, a: dotFilter.angle };
|
||||
}
|
||||
updateFromNetworkSyncData(
|
||||
filter: PIXI.Filter,
|
||||
data: DotFilterNetworkSyncData
|
||||
) {
|
||||
const dotFilter = (filter as unknown) as PIXI.filters.DotFilter;
|
||||
const dotFilter = filter as unknown as PIXI.filters.DotFilter;
|
||||
dotFilter.scale = data.s;
|
||||
dotFilter.angle = data.a;
|
||||
}
|
||||
|
@@ -22,7 +22,8 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter =
|
||||
filter as unknown as PIXI.filters.DropShadowFilter;
|
||||
if (parameterName === 'blur') {
|
||||
dropShadowFilter.blur = value;
|
||||
} else if (parameterName === 'quality') {
|
||||
@@ -38,7 +39,8 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter =
|
||||
filter as unknown as PIXI.filters.DropShadowFilter;
|
||||
if (parameterName === 'blur') {
|
||||
return dropShadowFilter.blur;
|
||||
}
|
||||
@@ -64,7 +66,8 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: string
|
||||
) {
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter =
|
||||
filter as unknown as PIXI.filters.DropShadowFilter;
|
||||
if (parameterName === 'color') {
|
||||
dropShadowFilter.color = gdjs.rgbOrHexStringToNumber(value);
|
||||
}
|
||||
@@ -74,13 +77,15 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
): void {
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter =
|
||||
filter as unknown as PIXI.filters.DropShadowFilter;
|
||||
if (parameterName === 'color') {
|
||||
dropShadowFilter.color = value;
|
||||
}
|
||||
}
|
||||
getColorParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter =
|
||||
filter as unknown as PIXI.filters.DropShadowFilter;
|
||||
if (parameterName === 'color') {
|
||||
return dropShadowFilter.color;
|
||||
}
|
||||
@@ -91,13 +96,15 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: boolean
|
||||
) {
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter =
|
||||
filter as unknown as PIXI.filters.DropShadowFilter;
|
||||
if (parameterName === 'shadowOnly') {
|
||||
dropShadowFilter.shadowOnly = value;
|
||||
}
|
||||
}
|
||||
getNetworkSyncData(filter: PIXI.Filter): DropShadowFilterNetworkSyncData {
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter =
|
||||
filter as unknown as PIXI.filters.DropShadowFilter;
|
||||
return {
|
||||
b: dropShadowFilter.blur,
|
||||
q: dropShadowFilter.quality,
|
||||
@@ -113,7 +120,8 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: DropShadowFilterNetworkSyncData
|
||||
) {
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter =
|
||||
filter as unknown as PIXI.filters.DropShadowFilter;
|
||||
dropShadowFilter.blur = data.b;
|
||||
dropShadowFilter.quality = data.q;
|
||||
dropShadowFilter.alpha = data.a;
|
||||
|
@@ -24,13 +24,13 @@ namespace gdjs {
|
||||
new (class extends gdjs.PixiFiltersTools.PixiFilterCreator {
|
||||
makePIXIFilter(layer, effectData) {
|
||||
const filter = new PIXI.filters.GlitchFilter();
|
||||
const glitchFilter = (filter as unknown) as PIXI.filters.GlitchFilter &
|
||||
const glitchFilter = filter as unknown as PIXI.filters.GlitchFilter &
|
||||
GlitchFilterExtra;
|
||||
glitchFilter._animationTimer = 0;
|
||||
return glitchFilter;
|
||||
}
|
||||
updatePreRender(filter: PIXI.Filter, target: EffectsTarget) {
|
||||
const glitchFilter = (filter as unknown) as PIXI.filters.GlitchFilter &
|
||||
const glitchFilter = filter as unknown as PIXI.filters.GlitchFilter &
|
||||
GlitchFilterExtra;
|
||||
if (glitchFilter.animationFrequency !== 0) {
|
||||
glitchFilter._animationTimer += target.getElapsedTime() / 1000;
|
||||
@@ -48,7 +48,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const glitchFilter = (filter as unknown) as PIXI.filters.GlitchFilter &
|
||||
const glitchFilter = filter as unknown as PIXI.filters.GlitchFilter &
|
||||
GlitchFilterExtra;
|
||||
if (parameterName === 'slices') {
|
||||
glitchFilter.slices = value;
|
||||
@@ -79,7 +79,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const glitchFilter = (filter as unknown) as PIXI.filters.GlitchFilter &
|
||||
const glitchFilter = filter as unknown as PIXI.filters.GlitchFilter &
|
||||
GlitchFilterExtra;
|
||||
if (parameterName === 'slices') {
|
||||
return glitchFilter.slices;
|
||||
@@ -140,14 +140,14 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: boolean
|
||||
) {
|
||||
const glitchFilter = (filter as unknown) as PIXI.filters.GlitchFilter &
|
||||
const glitchFilter = filter as unknown as PIXI.filters.GlitchFilter &
|
||||
GlitchFilterExtra;
|
||||
if (parameterName === 'average') {
|
||||
glitchFilter.average = value;
|
||||
}
|
||||
}
|
||||
getNetworkSyncData(filter: PIXI.Filter): GlitchFilterNetworkSyncData {
|
||||
const glitchFilter = (filter as unknown) as PIXI.filters.GlitchFilter &
|
||||
const glitchFilter = filter as unknown as PIXI.filters.GlitchFilter &
|
||||
GlitchFilterExtra;
|
||||
return {
|
||||
s: glitchFilter.slices,
|
||||
@@ -170,7 +170,7 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: GlitchFilterNetworkSyncData
|
||||
) {
|
||||
const glitchFilter = (filter as unknown) as PIXI.filters.GlitchFilter &
|
||||
const glitchFilter = filter as unknown as PIXI.filters.GlitchFilter &
|
||||
GlitchFilterExtra;
|
||||
glitchFilter.slices = data.s;
|
||||
glitchFilter.offset = data.o;
|
||||
|
@@ -21,7 +21,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter &
|
||||
const glowFilter = filter as unknown as PIXI.filters.GlowFilter &
|
||||
GlowFilterExtra;
|
||||
if (parameterName === 'innerStrength') {
|
||||
glowFilter.innerStrength = value;
|
||||
@@ -32,7 +32,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter &
|
||||
const glowFilter = filter as unknown as PIXI.filters.GlowFilter &
|
||||
GlowFilterExtra;
|
||||
if (parameterName === 'innerStrength') {
|
||||
return glowFilter.innerStrength;
|
||||
@@ -50,7 +50,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: string
|
||||
) {
|
||||
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter &
|
||||
const glowFilter = filter as unknown as PIXI.filters.GlowFilter &
|
||||
GlowFilterExtra;
|
||||
if (parameterName === 'color') {
|
||||
glowFilter.color = gdjs.rgbOrHexStringToNumber(value);
|
||||
@@ -61,14 +61,14 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
): void {
|
||||
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter &
|
||||
const glowFilter = filter as unknown as PIXI.filters.GlowFilter &
|
||||
GlowFilterExtra;
|
||||
if (parameterName === 'color') {
|
||||
glowFilter.color = value;
|
||||
}
|
||||
}
|
||||
getColorParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter &
|
||||
const glowFilter = filter as unknown as PIXI.filters.GlowFilter &
|
||||
GlowFilterExtra;
|
||||
if (parameterName === 'color') {
|
||||
return glowFilter.color;
|
||||
@@ -81,7 +81,7 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): GlowFilterNetworkSyncData {
|
||||
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter &
|
||||
const glowFilter = filter as unknown as PIXI.filters.GlowFilter &
|
||||
GlowFilterExtra;
|
||||
return {
|
||||
is: glowFilter.innerStrength,
|
||||
@@ -94,7 +94,7 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: GlowFilterNetworkSyncData
|
||||
): void {
|
||||
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter &
|
||||
const glowFilter = filter as unknown as PIXI.filters.GlowFilter &
|
||||
GlowFilterExtra;
|
||||
glowFilter.innerStrength = data.is;
|
||||
glowFilter.outerStrength = data.os;
|
||||
|
@@ -24,7 +24,7 @@ namespace gdjs {
|
||||
return godrayFilter;
|
||||
}
|
||||
updatePreRender(filter: PIXI.Filter, target: EffectsTarget) {
|
||||
const godrayFilter = (filter as unknown) as PIXI.filters.GodrayFilter &
|
||||
const godrayFilter = filter as unknown as PIXI.filters.GodrayFilter &
|
||||
GodrayFilterExtra;
|
||||
if (godrayFilter.animationSpeed !== 0) {
|
||||
godrayFilter.time +=
|
||||
@@ -36,7 +36,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const godrayFilter = (filter as unknown) as PIXI.filters.GodrayFilter &
|
||||
const godrayFilter = filter as unknown as PIXI.filters.GodrayFilter &
|
||||
GodrayFilterExtra;
|
||||
if (parameterName === 'lacunarity') {
|
||||
godrayFilter.lacunarity = value;
|
||||
@@ -57,7 +57,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const godrayFilter = (filter as unknown) as PIXI.filters.GodrayFilter &
|
||||
const godrayFilter = filter as unknown as PIXI.filters.GodrayFilter &
|
||||
GodrayFilterExtra;
|
||||
if (parameterName === 'lacunarity') {
|
||||
return godrayFilter.lacunarity;
|
||||
@@ -103,14 +103,14 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: boolean
|
||||
) {
|
||||
const godrayFilter = (filter as unknown) as PIXI.filters.GodrayFilter &
|
||||
const godrayFilter = filter as unknown as PIXI.filters.GodrayFilter &
|
||||
GodrayFilterExtra;
|
||||
if (parameterName === 'parallel') {
|
||||
godrayFilter.parallel = value;
|
||||
}
|
||||
}
|
||||
getNetworkSyncData(filter: PIXI.Filter): GodrayFilterNetworkSyncData {
|
||||
const godrayFilter = (filter as unknown) as PIXI.filters.GodrayFilter &
|
||||
const godrayFilter = filter as unknown as PIXI.filters.GodrayFilter &
|
||||
GodrayFilterExtra;
|
||||
return {
|
||||
la: godrayFilter.lacunarity,
|
||||
@@ -128,7 +128,7 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: GodrayFilterNetworkSyncData
|
||||
) {
|
||||
const godrayFilter = (filter as unknown) as PIXI.filters.GodrayFilter &
|
||||
const godrayFilter = filter as unknown as PIXI.filters.GodrayFilter &
|
||||
GodrayFilterExtra;
|
||||
godrayFilter.lacunarity = data.la;
|
||||
godrayFilter.angle = data.a;
|
||||
|
@@ -18,7 +18,8 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const kawaseBlurFilter = (filter as unknown) as PIXI.filters.KawaseBlurFilter;
|
||||
const kawaseBlurFilter =
|
||||
filter as unknown as PIXI.filters.KawaseBlurFilter;
|
||||
if (parameterName === 'pixelizeX') {
|
||||
kawaseBlurFilter.pixelSize[0] = value;
|
||||
} else if (parameterName === 'pixelizeY') {
|
||||
@@ -30,7 +31,8 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const kawaseBlurFilter = (filter as unknown) as PIXI.filters.KawaseBlurFilter;
|
||||
const kawaseBlurFilter =
|
||||
filter as unknown as PIXI.filters.KawaseBlurFilter;
|
||||
if (parameterName === 'pixelizeX') {
|
||||
return kawaseBlurFilter.pixelSize[0];
|
||||
}
|
||||
@@ -64,7 +66,8 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): KawaseBlurFilterNetworkSyncData {
|
||||
const kawaseBlurFilter = (filter as unknown) as PIXI.filters.KawaseBlurFilter;
|
||||
const kawaseBlurFilter =
|
||||
filter as unknown as PIXI.filters.KawaseBlurFilter;
|
||||
return {
|
||||
px: kawaseBlurFilter.pixelSize[0],
|
||||
py: kawaseBlurFilter.pixelSize[1],
|
||||
@@ -76,7 +79,8 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: KawaseBlurFilterNetworkSyncData
|
||||
) {
|
||||
const kawaseBlurFilter = (filter as unknown) as PIXI.filters.KawaseBlurFilter;
|
||||
const kawaseBlurFilter =
|
||||
filter as unknown as PIXI.filters.KawaseBlurFilter;
|
||||
kawaseBlurFilter.pixelSize[0] = data.px;
|
||||
kawaseBlurFilter.pixelSize[1] = data.py;
|
||||
kawaseBlurFilter.blur = data.b;
|
||||
|
@@ -15,13 +15,13 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const noiseFilter = (filter as unknown) as PIXI.NoiseFilter;
|
||||
const noiseFilter = filter as unknown as PIXI.NoiseFilter;
|
||||
if (parameterName === 'noise') {
|
||||
noiseFilter.noise = gdjs.PixiFiltersTools.clampValue(value, 0, 1);
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const noiseFilter = (filter as unknown) as PIXI.NoiseFilter;
|
||||
const noiseFilter = filter as unknown as PIXI.NoiseFilter;
|
||||
if (parameterName === 'noise') {
|
||||
return noiseFilter.noise;
|
||||
}
|
||||
@@ -46,14 +46,14 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): NoiseFilterNetworkSyncData {
|
||||
const noiseFilter = (filter as unknown) as PIXI.NoiseFilter;
|
||||
const noiseFilter = filter as unknown as PIXI.NoiseFilter;
|
||||
return { n: noiseFilter.noise };
|
||||
}
|
||||
updateFromNetworkSyncData(
|
||||
filter: PIXI.Filter,
|
||||
data: NoiseFilterNetworkSyncData
|
||||
) {
|
||||
const noiseFilter = (filter as unknown) as PIXI.NoiseFilter;
|
||||
const noiseFilter = filter as unknown as PIXI.NoiseFilter;
|
||||
noiseFilter.noise = data.n;
|
||||
}
|
||||
})()
|
||||
|
@@ -20,13 +20,13 @@ namespace gdjs {
|
||||
new (class extends gdjs.PixiFiltersTools.PixiFilterCreator {
|
||||
makePIXIFilter(layer, effectData) {
|
||||
const filter = new PIXI.filters.OldFilmFilter();
|
||||
const oldFilmFilter = (filter as unknown) as PIXI.filters.OldFilmFilter &
|
||||
const oldFilmFilter = filter as unknown as PIXI.filters.OldFilmFilter &
|
||||
OldFilmFilterExtra;
|
||||
oldFilmFilter._animationTimer = 0;
|
||||
return oldFilmFilter;
|
||||
}
|
||||
updatePreRender(filter: PIXI.Filter, target: EffectsTarget) {
|
||||
const oldFilmFilter = (filter as unknown) as PIXI.filters.OldFilmFilter &
|
||||
const oldFilmFilter = filter as unknown as PIXI.filters.OldFilmFilter &
|
||||
OldFilmFilterExtra;
|
||||
if (oldFilmFilter.animationFrequency !== 0) {
|
||||
oldFilmFilter._animationTimer += target.getElapsedTime() / 1000;
|
||||
@@ -44,7 +44,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const oldFilmFilter = (filter as unknown) as PIXI.filters.OldFilmFilter &
|
||||
const oldFilmFilter = filter as unknown as PIXI.filters.OldFilmFilter &
|
||||
OldFilmFilterExtra;
|
||||
if (parameterName === 'sepia') {
|
||||
oldFilmFilter.sepia = value;
|
||||
@@ -69,7 +69,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const oldFilmFilter = (filter as unknown) as PIXI.filters.OldFilmFilter &
|
||||
const oldFilmFilter = filter as unknown as PIXI.filters.OldFilmFilter &
|
||||
OldFilmFilterExtra;
|
||||
if (parameterName === 'sepia') {
|
||||
return oldFilmFilter.sepia;
|
||||
@@ -122,7 +122,7 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): OldFilmFilterNetworkSyncData {
|
||||
const oldFilmFilter = (filter as unknown) as PIXI.filters.OldFilmFilter &
|
||||
const oldFilmFilter = filter as unknown as PIXI.filters.OldFilmFilter &
|
||||
OldFilmFilterExtra;
|
||||
return {
|
||||
se: oldFilmFilter.sepia,
|
||||
@@ -141,7 +141,7 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: OldFilmFilterNetworkSyncData
|
||||
) {
|
||||
const oldFilmFilter = (filter as unknown) as PIXI.filters.OldFilmFilter &
|
||||
const oldFilmFilter = filter as unknown as PIXI.filters.OldFilmFilter &
|
||||
OldFilmFilterExtra;
|
||||
oldFilmFilter.sepia = data.se;
|
||||
oldFilmFilter.noise = data.n;
|
||||
|
@@ -17,7 +17,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
|
||||
const outlineFilter = filter as unknown as PIXI.filters.OutlineFilter;
|
||||
if (parameterName === 'thickness') {
|
||||
outlineFilter.thickness = value;
|
||||
} else if (parameterName === 'padding') {
|
||||
@@ -25,7 +25,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
|
||||
const outlineFilter = filter as unknown as PIXI.filters.OutlineFilter;
|
||||
if (parameterName === 'thickness') {
|
||||
return outlineFilter.thickness;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: string
|
||||
) {
|
||||
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
|
||||
const outlineFilter = filter as unknown as PIXI.filters.OutlineFilter;
|
||||
if (parameterName === 'color') {
|
||||
outlineFilter.color = gdjs.rgbOrHexStringToNumber(value);
|
||||
}
|
||||
@@ -49,13 +49,13 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
): void {
|
||||
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
|
||||
const outlineFilter = filter as unknown as PIXI.filters.OutlineFilter;
|
||||
if (parameterName === 'color') {
|
||||
outlineFilter.color = value;
|
||||
}
|
||||
}
|
||||
getColorParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
|
||||
const outlineFilter = filter as unknown as PIXI.filters.OutlineFilter;
|
||||
if (parameterName === 'color') {
|
||||
return outlineFilter.color;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): OutlineFilterNetworkSyncData {
|
||||
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
|
||||
const outlineFilter = filter as unknown as PIXI.filters.OutlineFilter;
|
||||
return {
|
||||
t: outlineFilter.thickness,
|
||||
p: outlineFilter.padding,
|
||||
@@ -78,7 +78,7 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: OutlineFilterNetworkSyncData
|
||||
) {
|
||||
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
|
||||
const outlineFilter = filter as unknown as PIXI.filters.OutlineFilter;
|
||||
outlineFilter.thickness = data.t;
|
||||
outlineFilter.padding = data.p;
|
||||
outlineFilter.color = data.c;
|
||||
|
@@ -21,15 +21,17 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const pixelateFilter = (filter as unknown) as PIXI.filters.PixelateFilter &
|
||||
PixelateFilterExtra;
|
||||
const pixelateFilter =
|
||||
filter as unknown as PIXI.filters.PixelateFilter &
|
||||
PixelateFilterExtra;
|
||||
if (parameterName === 'size') {
|
||||
pixelateFilter.size = value;
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const pixelateFilter = (filter as unknown) as PIXI.filters.PixelateFilter &
|
||||
PixelateFilterExtra;
|
||||
const pixelateFilter =
|
||||
filter as unknown as PIXI.filters.PixelateFilter &
|
||||
PixelateFilterExtra;
|
||||
if (parameterName === 'size') {
|
||||
return pixelateFilter.size;
|
||||
}
|
||||
@@ -54,16 +56,18 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): PixelateFilterNetworkSyncData {
|
||||
const pixelateFilter = (filter as unknown) as PIXI.filters.PixelateFilter &
|
||||
PixelateFilterExtra;
|
||||
const pixelateFilter =
|
||||
filter as unknown as PIXI.filters.PixelateFilter &
|
||||
PixelateFilterExtra;
|
||||
return { s: pixelateFilter.size };
|
||||
}
|
||||
updateFromNetworkSyncData(
|
||||
filter: PIXI.Filter,
|
||||
data: PixelateFilterNetworkSyncData
|
||||
) {
|
||||
const pixelateFilter = (filter as unknown) as PIXI.filters.PixelateFilter &
|
||||
PixelateFilterExtra;
|
||||
const pixelateFilter =
|
||||
filter as unknown as PIXI.filters.PixelateFilter &
|
||||
PixelateFilterExtra;
|
||||
pixelateFilter.size = data.s;
|
||||
}
|
||||
})()
|
||||
|
@@ -1,26 +1,32 @@
|
||||
declare namespace PIXI.filters {
|
||||
export class DropShadowFilter extends PIXI.Filter {
|
||||
constructor(options?: DropShadowFilterOptions);
|
||||
/** @deprecated */
|
||||
rotation: number;
|
||||
/** @deprecated */
|
||||
distance: number;
|
||||
offset: PIXI.Point;
|
||||
alpha: number;
|
||||
blur: number;
|
||||
color: number;
|
||||
distance: number;
|
||||
kernels: number[];
|
||||
pixelSize: number | number[] | PIXI.Point;
|
||||
quality: number;
|
||||
rotation: number;
|
||||
shadowOnly: boolean;
|
||||
}
|
||||
export interface DropShadowFilterOptions {
|
||||
/** @deprecated */
|
||||
rotation?: number;
|
||||
/** @deprecated */
|
||||
distance?: number;
|
||||
offset: PIXI.Point;
|
||||
alpha?: number;
|
||||
blur?: number;
|
||||
color?: number;
|
||||
distance?: number;
|
||||
kernels?: number[];
|
||||
pixelSize?: number | number[] | PIXI.Point;
|
||||
quality?: number;
|
||||
resolution?: number;
|
||||
rotation?: number;
|
||||
shadowOnly?: boolean;
|
||||
}
|
||||
}
|
||||
|
@@ -20,8 +20,9 @@ namespace gdjs {
|
||||
return radialBlurFilter;
|
||||
}
|
||||
updatePreRender(filter: PIXI.Filter, target: EffectsTarget) {
|
||||
const radialBlurFilter = (filter as unknown) as PIXI.filters.RadialBlurFilter &
|
||||
RadialBlurFilterExtra;
|
||||
const radialBlurFilter =
|
||||
filter as unknown as PIXI.filters.RadialBlurFilter &
|
||||
RadialBlurFilterExtra;
|
||||
radialBlurFilter.center[0] = Math.round(
|
||||
radialBlurFilter._centerX * target.getWidth()
|
||||
);
|
||||
@@ -34,8 +35,9 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const radialBlurFilter = (filter as unknown) as PIXI.filters.RadialBlurFilter &
|
||||
RadialBlurFilterExtra;
|
||||
const radialBlurFilter =
|
||||
filter as unknown as PIXI.filters.RadialBlurFilter &
|
||||
RadialBlurFilterExtra;
|
||||
if (parameterName === 'radius') {
|
||||
radialBlurFilter.radius = value < 0 ? -1 : value;
|
||||
} else if (parameterName === 'angle') {
|
||||
@@ -55,8 +57,9 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const radialBlurFilter = (filter as unknown) as PIXI.filters.RadialBlurFilter &
|
||||
RadialBlurFilterExtra;
|
||||
const radialBlurFilter =
|
||||
filter as unknown as PIXI.filters.RadialBlurFilter &
|
||||
RadialBlurFilterExtra;
|
||||
if (parameterName === 'radius') {
|
||||
radialBlurFilter.radius;
|
||||
}
|
||||
@@ -96,8 +99,9 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): RadialBlurFilterNetworkSyncData {
|
||||
const radialBlurFilter = (filter as unknown) as PIXI.filters.RadialBlurFilter &
|
||||
RadialBlurFilterExtra;
|
||||
const radialBlurFilter =
|
||||
filter as unknown as PIXI.filters.RadialBlurFilter &
|
||||
RadialBlurFilterExtra;
|
||||
return {
|
||||
r: radialBlurFilter.radius,
|
||||
a: radialBlurFilter.angle,
|
||||
@@ -111,8 +115,9 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: RadialBlurFilterNetworkSyncData
|
||||
) {
|
||||
const radialBlurFilter = (filter as unknown) as PIXI.filters.RadialBlurFilter &
|
||||
RadialBlurFilterExtra;
|
||||
const radialBlurFilter =
|
||||
filter as unknown as PIXI.filters.RadialBlurFilter &
|
||||
RadialBlurFilterExtra;
|
||||
radialBlurFilter.radius = data.r;
|
||||
radialBlurFilter.angle = data.a;
|
||||
radialBlurFilter.kernelSize = data.ks;
|
||||
|
@@ -40,8 +40,9 @@ namespace gdjs {
|
||||
return reflectionFilter;
|
||||
}
|
||||
updatePreRender(filter: PIXI.Filter, target: EffectsTarget) {
|
||||
const reflectionFilter = (filter as unknown) as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
const reflectionFilter =
|
||||
filter as unknown as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
if (reflectionFilter.animationSpeed !== 0) {
|
||||
reflectionFilter.time +=
|
||||
(target.getElapsedTime() / 1000) * reflectionFilter.animationSpeed;
|
||||
@@ -52,8 +53,9 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const reflectionFilter = (filter as unknown) as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
const reflectionFilter =
|
||||
filter as unknown as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
if (parameterName === 'boundary') {
|
||||
reflectionFilter.boundary = value;
|
||||
}
|
||||
@@ -80,8 +82,9 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const reflectionFilter = (filter as unknown) as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
const reflectionFilter =
|
||||
filter as unknown as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
if (parameterName === 'boundary') {
|
||||
return reflectionFilter.boundary;
|
||||
}
|
||||
@@ -126,15 +129,17 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: boolean
|
||||
) {
|
||||
const reflectionFilter = (filter as unknown) as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
const reflectionFilter =
|
||||
filter as unknown as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
if (parameterName === 'mirror') {
|
||||
reflectionFilter.mirror = value;
|
||||
}
|
||||
}
|
||||
getNetworkSyncData(filter: PIXI.Filter): ReflectionFilterNetworkSyncData {
|
||||
const reflectionFilter = (filter as unknown) as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
const reflectionFilter =
|
||||
filter as unknown as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
return {
|
||||
b: reflectionFilter.boundary,
|
||||
ams: reflectionFilter.amplitude[0],
|
||||
@@ -151,8 +156,9 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: ReflectionFilterNetworkSyncData
|
||||
) {
|
||||
const reflectionFilter = (filter as unknown) as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
const reflectionFilter =
|
||||
filter as unknown as PIXI.filters.ReflectionFilter &
|
||||
ReflectionFilterExtra;
|
||||
reflectionFilter.boundary = data.b;
|
||||
reflectionFilter.amplitude[0] = data.ams;
|
||||
reflectionFilter.amplitude[1] = data.ame;
|
||||
|
@@ -20,7 +20,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const rgbSplitFilter = (filter as unknown) as PIXI.filters.RGBSplitFilter;
|
||||
const rgbSplitFilter = filter as unknown as PIXI.filters.RGBSplitFilter;
|
||||
if (parameterName === 'redX') {
|
||||
rgbSplitFilter.red.x = value;
|
||||
} else if (parameterName === 'redY') {
|
||||
@@ -36,7 +36,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const rgbSplitFilter = (filter as unknown) as PIXI.filters.RGBSplitFilter;
|
||||
const rgbSplitFilter = filter as unknown as PIXI.filters.RGBSplitFilter;
|
||||
if (parameterName === 'redX') {
|
||||
return rgbSplitFilter.red.x;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): RGBSplitFilterNetworkSyncData {
|
||||
const rgbSplitFilter = (filter as unknown) as PIXI.filters.RGBSplitFilter;
|
||||
const rgbSplitFilter = filter as unknown as PIXI.filters.RGBSplitFilter;
|
||||
return {
|
||||
rX: rgbSplitFilter.red.x,
|
||||
rY: rgbSplitFilter.red.y,
|
||||
@@ -90,7 +90,7 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: RGBSplitFilterNetworkSyncData
|
||||
) {
|
||||
const rgbSplitFilter = (filter as unknown) as PIXI.filters.RGBSplitFilter;
|
||||
const rgbSplitFilter = filter as unknown as PIXI.filters.RGBSplitFilter;
|
||||
rgbSplitFilter.red.x = data.rX;
|
||||
rgbSplitFilter.red.y = data.rY;
|
||||
rgbSplitFilter.green.x = data.gX;
|
||||
|
@@ -16,7 +16,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const colorMatrixFilter = (filter as unknown) as PIXI.ColorMatrixFilter;
|
||||
const colorMatrixFilter = filter as unknown as PIXI.ColorMatrixFilter;
|
||||
if (parameterName === 'opacity') {
|
||||
colorMatrixFilter.alpha = gdjs.PixiFiltersTools.clampValue(
|
||||
value,
|
||||
@@ -26,7 +26,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const colorMatrixFilter = (filter as unknown) as PIXI.ColorMatrixFilter;
|
||||
const colorMatrixFilter = filter as unknown as PIXI.ColorMatrixFilter;
|
||||
if (parameterName === 'opacity') {
|
||||
return colorMatrixFilter.alpha;
|
||||
}
|
||||
@@ -51,14 +51,14 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): SepiaFilterNetworkSyncData {
|
||||
const colorMatrixFilter = (filter as unknown) as PIXI.ColorMatrixFilter;
|
||||
const colorMatrixFilter = filter as unknown as PIXI.ColorMatrixFilter;
|
||||
return { a: colorMatrixFilter.alpha };
|
||||
}
|
||||
updateFromNetworkSyncData(
|
||||
filter: PIXI.Filter,
|
||||
data: SepiaFilterNetworkSyncData
|
||||
) {
|
||||
const colorMatrixFilter = (filter as unknown) as PIXI.ColorMatrixFilter;
|
||||
const colorMatrixFilter = filter as unknown as PIXI.ColorMatrixFilter;
|
||||
colorMatrixFilter.alpha = data.a;
|
||||
}
|
||||
})()
|
||||
|
@@ -22,8 +22,9 @@ namespace gdjs {
|
||||
return shockwaveFilter;
|
||||
}
|
||||
updatePreRender(filter: PIXI.Filter, target: EffectsTarget) {
|
||||
const shockwaveFilter = (filter as unknown) as PIXI.filters.ShockwaveFilter &
|
||||
ShockwaveFilterExtra;
|
||||
const shockwaveFilter =
|
||||
filter as unknown as PIXI.filters.ShockwaveFilter &
|
||||
ShockwaveFilterExtra;
|
||||
if (shockwaveFilter.speed !== 0) {
|
||||
shockwaveFilter.time += target.getElapsedTime() / 1000;
|
||||
}
|
||||
|
@@ -16,7 +16,8 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const tiltShiftFilter = (filter as unknown) as PIXI.filters.TiltShiftFilter;
|
||||
const tiltShiftFilter =
|
||||
filter as unknown as PIXI.filters.TiltShiftFilter;
|
||||
if (parameterName === 'blur') {
|
||||
tiltShiftFilter.blur = value;
|
||||
} else if (parameterName === 'gradientBlur') {
|
||||
@@ -24,7 +25,8 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const tiltShiftFilter = (filter as unknown) as PIXI.filters.TiltShiftFilter;
|
||||
const tiltShiftFilter =
|
||||
filter as unknown as PIXI.filters.TiltShiftFilter;
|
||||
if (parameterName === 'blur') {
|
||||
return tiltShiftFilter.blur;
|
||||
}
|
||||
@@ -52,14 +54,16 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): TiltShiftFilterNetworkSyncData {
|
||||
const tiltShiftFilter = (filter as unknown) as PIXI.filters.TiltShiftFilter;
|
||||
const tiltShiftFilter =
|
||||
filter as unknown as PIXI.filters.TiltShiftFilter;
|
||||
return { b: tiltShiftFilter.blur, gb: tiltShiftFilter.gradientBlur };
|
||||
}
|
||||
updateFromNetworkSyncData(
|
||||
filter: PIXI.Filter,
|
||||
data: TiltShiftFilterNetworkSyncData
|
||||
) {
|
||||
const tiltShiftFilter = (filter as unknown) as PIXI.filters.TiltShiftFilter;
|
||||
const tiltShiftFilter =
|
||||
filter as unknown as PIXI.filters.TiltShiftFilter;
|
||||
tiltShiftFilter.blur = data.b;
|
||||
tiltShiftFilter.gradientBlur = data.gb;
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ namespace gdjs {
|
||||
return twistFilter;
|
||||
}
|
||||
updatePreRender(filter: PIXI.Filter, target: EffectsTarget) {
|
||||
const twistFilter = (filter as unknown) as PIXI.filters.TwistFilter &
|
||||
const twistFilter = filter as unknown as PIXI.filters.TwistFilter &
|
||||
TwistFilterExtra;
|
||||
twistFilter.offset.x = Math.round(
|
||||
twistFilter._offsetX * target.getWidth()
|
||||
@@ -34,7 +34,7 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const twistFilter = (filter as unknown) as PIXI.filters.TwistFilter &
|
||||
const twistFilter = filter as unknown as PIXI.filters.TwistFilter &
|
||||
TwistFilterExtra;
|
||||
if (parameterName === 'radius') {
|
||||
twistFilter.radius = value;
|
||||
@@ -49,7 +49,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const twistFilter = (filter as unknown) as PIXI.filters.TwistFilter &
|
||||
const twistFilter = filter as unknown as PIXI.filters.TwistFilter &
|
||||
TwistFilterExtra;
|
||||
if (parameterName === 'radius') {
|
||||
return twistFilter.radius;
|
||||
@@ -87,7 +87,7 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): TwistFilterNetworkSyncData {
|
||||
const twistFilter = (filter as unknown) as PIXI.filters.TwistFilter &
|
||||
const twistFilter = filter as unknown as PIXI.filters.TwistFilter &
|
||||
TwistFilterExtra;
|
||||
return {
|
||||
r: twistFilter.radius,
|
||||
@@ -101,7 +101,7 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: TwistFilterNetworkSyncData
|
||||
) {
|
||||
const twistFilter = (filter as unknown) as PIXI.filters.TwistFilter &
|
||||
const twistFilter = filter as unknown as PIXI.filters.TwistFilter &
|
||||
TwistFilterExtra;
|
||||
twistFilter.radius = data.r;
|
||||
twistFilter.angle = data.a;
|
||||
|
@@ -19,8 +19,9 @@ namespace gdjs {
|
||||
return zoomBlurFilter;
|
||||
}
|
||||
updatePreRender(filter: PIXI.Filter, target: EffectsTarget) {
|
||||
const zoomBlurFilter = (filter as unknown) as PIXI.filters.ZoomBlurFilter &
|
||||
ZoomBlurFilterExtra;
|
||||
const zoomBlurFilter =
|
||||
filter as unknown as PIXI.filters.ZoomBlurFilter &
|
||||
ZoomBlurFilterExtra;
|
||||
zoomBlurFilter.center[0] = Math.round(
|
||||
zoomBlurFilter._centerX * target.getWidth()
|
||||
);
|
||||
@@ -33,8 +34,9 @@ namespace gdjs {
|
||||
parameterName: string,
|
||||
value: number
|
||||
) {
|
||||
const zoomBlurFilter = (filter as unknown) as PIXI.filters.ZoomBlurFilter &
|
||||
ZoomBlurFilterExtra;
|
||||
const zoomBlurFilter =
|
||||
filter as unknown as PIXI.filters.ZoomBlurFilter &
|
||||
ZoomBlurFilterExtra;
|
||||
if (parameterName === 'centerX') {
|
||||
zoomBlurFilter._centerX = value;
|
||||
} else if (parameterName === 'centerY') {
|
||||
@@ -52,8 +54,9 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
getDoubleParameter(filter: PIXI.Filter, parameterName: string): number {
|
||||
const zoomBlurFilter = (filter as unknown) as PIXI.filters.ZoomBlurFilter &
|
||||
ZoomBlurFilterExtra;
|
||||
const zoomBlurFilter =
|
||||
filter as unknown as PIXI.filters.ZoomBlurFilter &
|
||||
ZoomBlurFilterExtra;
|
||||
if (parameterName === 'centerX') {
|
||||
return zoomBlurFilter._centerX;
|
||||
}
|
||||
@@ -90,8 +93,9 @@ namespace gdjs {
|
||||
value: boolean
|
||||
) {}
|
||||
getNetworkSyncData(filter: PIXI.Filter): ZoomBlurFilterNetworkSyncData {
|
||||
const zoomBlurFilter = (filter as unknown) as PIXI.filters.ZoomBlurFilter &
|
||||
ZoomBlurFilterExtra;
|
||||
const zoomBlurFilter =
|
||||
filter as unknown as PIXI.filters.ZoomBlurFilter &
|
||||
ZoomBlurFilterExtra;
|
||||
return {
|
||||
cx: zoomBlurFilter._centerX,
|
||||
cy: zoomBlurFilter._centerY,
|
||||
@@ -104,8 +108,9 @@ namespace gdjs {
|
||||
filter: PIXI.Filter,
|
||||
data: ZoomBlurFilterNetworkSyncData
|
||||
) {
|
||||
const zoomBlurFilter = (filter as unknown) as PIXI.filters.ZoomBlurFilter &
|
||||
ZoomBlurFilterExtra;
|
||||
const zoomBlurFilter =
|
||||
filter as unknown as PIXI.filters.ZoomBlurFilter &
|
||||
ZoomBlurFilterExtra;
|
||||
zoomBlurFilter._centerX = data.cx;
|
||||
zoomBlurFilter._centerY = data.cy;
|
||||
zoomBlurFilter.innerRadius = data.ir;
|
||||
|
@@ -50,12 +50,12 @@ namespace gdjs {
|
||||
// `effectData.booleanParameters.someBoolean`
|
||||
logger.info(
|
||||
'The PIXI texture found for the Dummy Effect (not actually used):',
|
||||
(layer
|
||||
.getRuntimeScene()
|
||||
.getGame()
|
||||
.getImageManager() as gdjs.PixiImageManager).getPIXITexture(
|
||||
effectData.stringParameters.someImage
|
||||
)
|
||||
(
|
||||
layer
|
||||
.getRuntimeScene()
|
||||
.getGame()
|
||||
.getImageManager() as gdjs.PixiImageManager
|
||||
).getPIXITexture(effectData.stringParameters.someImage)
|
||||
);
|
||||
return filter;
|
||||
}
|
||||
|
@@ -148,17 +148,22 @@ namespace gdjs {
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoading = true;
|
||||
FBInstant.getInterstitialAdAsync(adPlacementId)
|
||||
.then(function (interstitial) {
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitial = interstitial;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitial =
|
||||
interstitial;
|
||||
return interstitial.loadAsync();
|
||||
})
|
||||
.then(function () {
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoading = false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoaded = true;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoading =
|
||||
false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoaded =
|
||||
true;
|
||||
logger.info('Facebook Instant Games interstitial preloaded.');
|
||||
})
|
||||
.catch(function (err) {
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoading = false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoaded = false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoading =
|
||||
false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoaded =
|
||||
false;
|
||||
logger.error('Interstitial failed to preload: ' + err.message);
|
||||
errorVariable.setString(err.message || 'Unknown error');
|
||||
});
|
||||
@@ -181,7 +186,8 @@ namespace gdjs {
|
||||
errorVariable.setString(err.message || 'Unknown error');
|
||||
})
|
||||
.then(function () {
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoaded = false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedInterstitialLoaded =
|
||||
false;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -199,20 +205,26 @@ namespace gdjs {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoading = true;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoading =
|
||||
true;
|
||||
FBInstant.getRewardedVideoAsync(adPlacementId)
|
||||
.then(function (rewardedVideo) {
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideo = rewardedVideo;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideo =
|
||||
rewardedVideo;
|
||||
return rewardedVideo.loadAsync();
|
||||
})
|
||||
.then(function () {
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoading = false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoaded = true;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoading =
|
||||
false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoaded =
|
||||
true;
|
||||
logger.info('Facebook Instant Games rewarded video preloaded.');
|
||||
})
|
||||
.catch(function (err) {
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoading = false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoaded = false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoading =
|
||||
false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoaded =
|
||||
false;
|
||||
logger.error('Rewarded video failed to preload: ' + err.message);
|
||||
errorVariable.setString(err.message || 'Unknown error');
|
||||
});
|
||||
@@ -235,7 +247,8 @@ namespace gdjs {
|
||||
errorVariable.setString(err.message || 'Unknown error');
|
||||
})
|
||||
.then(function () {
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoaded = false;
|
||||
gdjs.evtTools.facebookInstantGames._preloadedRewardedVideoLoaded =
|
||||
false;
|
||||
});
|
||||
};
|
||||
|
||||
|
@@ -4528,7 +4528,8 @@ declare namespace firebase.auth {
|
||||
* @hidden
|
||||
*/
|
||||
class RecaptchaVerifier_Instance
|
||||
implements firebase.auth.ApplicationVerifier {
|
||||
implements firebase.auth.ApplicationVerifier
|
||||
{
|
||||
constructor(
|
||||
container: any | string,
|
||||
parameters?: Object | null,
|
||||
@@ -9509,9 +9510,9 @@ declare namespace firebase.firestore {
|
||||
* `exists` property will always be true and `data()` will never return
|
||||
* 'undefined'.
|
||||
*/
|
||||
export class QueryDocumentSnapshot<T = DocumentData> extends DocumentSnapshot<
|
||||
T
|
||||
> {
|
||||
export class QueryDocumentSnapshot<
|
||||
T = DocumentData,
|
||||
> extends DocumentSnapshot<T> {
|
||||
private constructor();
|
||||
|
||||
/**
|
||||
|
@@ -146,8 +146,8 @@ namespace gdjs {
|
||||
? 'endAt'
|
||||
: 'endBefore'
|
||||
: includeSelf
|
||||
? 'startAt'
|
||||
: 'startAfter'
|
||||
? 'startAt'
|
||||
: 'startAfter'
|
||||
](value)
|
||||
);
|
||||
};
|
||||
|
@@ -10,7 +10,8 @@ namespace gdjs {
|
||||
* Set the interval between auto-config updates.
|
||||
*/
|
||||
export const setAutoUpdateInterval = (interval: integer) => {
|
||||
firebase.remoteConfig().settings.minimumFetchIntervalMillis = interval;
|
||||
firebase.remoteConfig().settings.minimumFetchIntervalMillis =
|
||||
interval;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -37,7 +37,7 @@ module.exports = {
|
||||
extension
|
||||
.registerProperty('FirebaseConfig')
|
||||
.setLabel(_('Firebase configuration string'))
|
||||
.setType('textarea');
|
||||
.setType('multilinestring');
|
||||
|
||||
/* ====== ANALYTICS ====== */
|
||||
extension
|
||||
@@ -422,7 +422,7 @@ module.exports = {
|
||||
_('Is the user email address verified'),
|
||||
_('Checks if the email address of the user got verified.'),
|
||||
_('The email of the user is verified'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
@@ -440,7 +440,7 @@ module.exports = {
|
||||
'GetUserEmail',
|
||||
_('User email address'),
|
||||
_('Return the user email address.'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
@@ -457,7 +457,7 @@ module.exports = {
|
||||
'GetAccountCreationTime',
|
||||
_('Accounts creation time'),
|
||||
_('Return the accounts creation time.'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
@@ -474,7 +474,7 @@ module.exports = {
|
||||
'GetLastLoginTime',
|
||||
_('User last login time'),
|
||||
_('Return the user last login time.'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
@@ -491,7 +491,7 @@ module.exports = {
|
||||
'GetUserDisplayName',
|
||||
_('User display name'),
|
||||
_('Return the user display name.'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
@@ -508,7 +508,7 @@ module.exports = {
|
||||
'GetPhoneNumber',
|
||||
_('User phone number'),
|
||||
_('Return the user phone number.'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
@@ -528,7 +528,7 @@ module.exports = {
|
||||
'Return the user Unique IDentifier. Use that to link data to an ' +
|
||||
'user instead of the name or email.'
|
||||
),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
@@ -545,7 +545,7 @@ module.exports = {
|
||||
'GetTenantID',
|
||||
_('User tenant ID'),
|
||||
_('Return the user tenant ID. For advanced usage only.'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
@@ -562,7 +562,7 @@ module.exports = {
|
||||
'GetRefreshToken',
|
||||
_('User refresh token'),
|
||||
_('Return the user refresh token. For advanced usage only.'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
@@ -579,7 +579,7 @@ module.exports = {
|
||||
'GetPhotoURL',
|
||||
_('Profile picture URL'),
|
||||
_('Gets an URL to the user profile picture.'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
@@ -597,7 +597,7 @@ module.exports = {
|
||||
_('Send a password reset email'),
|
||||
_('Send a password reset link per email.'),
|
||||
_('Send a password reset email'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
@@ -619,7 +619,7 @@ module.exports = {
|
||||
_('Send a verification email'),
|
||||
_('Send a link per email to verify the user email.'),
|
||||
_('Send a verification email'),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
@@ -638,7 +638,7 @@ module.exports = {
|
||||
_('Display name'),
|
||||
_('Sets the user display name.'),
|
||||
_("Set the user's display name to _PARAM0_"),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
@@ -658,7 +658,7 @@ module.exports = {
|
||||
_('Profile picture'),
|
||||
_('Change the user profile picture URL to a new one.'),
|
||||
_("Change the user's profile picture URL to _PARAM0_"),
|
||||
_('Authentication/User Management'),
|
||||
_('Authentication ❯ User Management'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
@@ -684,7 +684,7 @@ module.exports = {
|
||||
_(
|
||||
"Change the user's email to _PARAM0_ and store result in _PARAM4_ (send verification email: _PARAM3_)"
|
||||
),
|
||||
_('Authentication/User Management/Advanced'),
|
||||
_('Authentication ❯ User Management ❯ Advanced'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
@@ -725,7 +725,7 @@ module.exports = {
|
||||
_(
|
||||
"Change the user's email to _PARAM0_ and store result in _PARAM2_ (send verification email: _PARAM1_)"
|
||||
),
|
||||
_('Authentication/User Management/Advanced'),
|
||||
_('Authentication ❯ User Management ❯ Advanced'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
@@ -764,7 +764,7 @@ module.exports = {
|
||||
'Change the user password to _PARAM2_ and store result in ' +
|
||||
'_PARAM4_ (send verification email: _PARAM3_)'
|
||||
),
|
||||
_('Authentication/User Management/Advanced'),
|
||||
_('Authentication ❯ User Management ❯ Advanced'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
@@ -806,7 +806,7 @@ module.exports = {
|
||||
'Change the user password to _PARAM0_ and store result in ' +
|
||||
'_PARAM2_ (send verification email: _PARAM1_)'
|
||||
),
|
||||
_('Authentication/User Management/Advanced'),
|
||||
_('Authentication ❯ User Management ❯ Advanced'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
@@ -842,7 +842,7 @@ module.exports = {
|
||||
'Deletes the user account.'
|
||||
),
|
||||
_('Delete the user account and store result in _PARAM2_'),
|
||||
_('Authentication/User Management/Advanced'),
|
||||
_('Authentication ❯ User Management ❯ Advanced'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
@@ -873,7 +873,7 @@ module.exports = {
|
||||
'This is the same as "Delete the user account" but reauthenticates via an external provider.'
|
||||
),
|
||||
_('Delete the user account and store result in _PARAM0_'),
|
||||
_('Authentication/User Management/Advanced'),
|
||||
_('Authentication ❯ User Management ❯ Advanced'),
|
||||
'JsPlatform/Extensions/firebase.png',
|
||||
'JsPlatform/Extensions/firebase.png'
|
||||
)
|
||||
|
@@ -519,9 +519,9 @@ describeIfOnline('Firebase extension end-to-end tests', function () {
|
||||
|
||||
// Delete the temporary namespace to not bloat the DB
|
||||
after(async () =>
|
||||
(
|
||||
await firebase.firestore().collection(namespace).get()
|
||||
).forEach(({ ref }) => ref.delete())
|
||||
(await firebase.firestore().collection(namespace).get()).forEach(
|
||||
({ ref }) => ref.delete()
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
|
1
Extensions/JsExtensionTypes.d.ts
vendored
1
Extensions/JsExtensionTypes.d.ts
vendored
@@ -189,6 +189,7 @@ declare type ObjectsRenderingService = {
|
||||
objectConfiguration: gd.ObjectConfiguration
|
||||
) => string;
|
||||
rgbOrHexToHexNumber: (value: string) => number;
|
||||
hexNumberToRGBArray: (value: number) => [number, number, number];
|
||||
registerClearCache: (clearCache: (_: any) => void) => void;
|
||||
};
|
||||
|
||||
|
@@ -223,9 +223,8 @@ namespace gdjs {
|
||||
let _leaderboardViewIframeLoading: boolean = false;
|
||||
let _leaderboardViewIframeLoaded: boolean = false;
|
||||
let _errorTimeoutId: NodeJS.Timeout | null = null;
|
||||
let _leaderboardMessageListener:
|
||||
| ((event: MessageEvent) => void)
|
||||
| null = null;
|
||||
let _leaderboardMessageListener: ((event: MessageEvent) => void) | null =
|
||||
null;
|
||||
|
||||
const _loaderContainer: HTMLDivElement = document.createElement('div');
|
||||
_loaderContainer.style.backgroundColor = '#000000';
|
||||
@@ -319,9 +318,8 @@ namespace gdjs {
|
||||
};
|
||||
let leaderboardEntryCreationUrl = `${baseUrl}/game/${gdjs.projectData.properties.projectUuid}/leaderboard/${leaderboardId}/entry`;
|
||||
if (authenticatedPlayerData) {
|
||||
headers[
|
||||
'Authorization'
|
||||
] = `player-game-token ${authenticatedPlayerData.playerToken}`;
|
||||
headers['Authorization'] =
|
||||
`player-game-token ${authenticatedPlayerData.playerToken}`;
|
||||
leaderboardEntryCreationUrl += `?playerId=${authenticatedPlayerData.playerId}`;
|
||||
} else {
|
||||
// In case playerName is empty, the backend will generate a random name.
|
||||
@@ -397,10 +395,8 @@ namespace gdjs {
|
||||
new ScoreSavingState());
|
||||
|
||||
try {
|
||||
const {
|
||||
closeSaving,
|
||||
closeSavingWithError,
|
||||
} = scoreSavingState.startSaving({ playerName, score });
|
||||
const { closeSaving, closeSavingWithError } =
|
||||
scoreSavingState.startSaving({ playerName, score });
|
||||
|
||||
try {
|
||||
const leaderboardEntry = await saveScore({
|
||||
@@ -443,10 +439,8 @@ namespace gdjs {
|
||||
new ScoreSavingState());
|
||||
|
||||
try {
|
||||
const {
|
||||
closeSaving,
|
||||
closeSavingWithError,
|
||||
} = scoreSavingState.startSaving({ playerId, score });
|
||||
const { closeSaving, closeSavingWithError } =
|
||||
scoreSavingState.startSaving({ playerId, score });
|
||||
|
||||
try {
|
||||
const leaderboardEntryId = await saveScore({
|
||||
@@ -866,9 +860,8 @@ namespace gdjs {
|
||||
|
||||
resetLeaderboardDisplayErrorTimeout(runtimeScene);
|
||||
|
||||
_leaderboardViewIframe = computeLeaderboardDisplayingIframe(
|
||||
targetUrl
|
||||
);
|
||||
_leaderboardViewIframe =
|
||||
computeLeaderboardDisplayingIframe(targetUrl);
|
||||
if (typeof window !== 'undefined') {
|
||||
_leaderboardMessageListener = (event: MessageEvent) => {
|
||||
receiveMessageFromLeaderboardView(
|
||||
|
@@ -235,7 +235,8 @@ module.exports = {
|
||||
class RenderedLightObjectInstance extends RenderedInstance {
|
||||
_radius = 0;
|
||||
_color = 0;
|
||||
_radiusGraphics = null;
|
||||
/** @type {PIXI.Graphics} The circle to show the radius of the light */
|
||||
_radiusGraphics;
|
||||
|
||||
constructor(
|
||||
project,
|
||||
@@ -259,7 +260,6 @@ module.exports = {
|
||||
lightIconSprite.anchor.x = 0.5;
|
||||
lightIconSprite.anchor.y = 0.5;
|
||||
|
||||
// The circle to show the radius of the light.
|
||||
this._radiusGraphics = new PIXI.Graphics();
|
||||
|
||||
this._pixiObject = new PIXI.Container();
|
||||
|
@@ -18,9 +18,8 @@ namespace gdjs {
|
||||
if (!instanceContainer._lightObstaclesManager) {
|
||||
// Create the shared manager if necessary.
|
||||
// @ts-ignore
|
||||
instanceContainer._lightObstaclesManager = new gdjs.LightObstaclesManager(
|
||||
instanceContainer
|
||||
);
|
||||
instanceContainer._lightObstaclesManager =
|
||||
new gdjs.LightObstaclesManager(instanceContainer);
|
||||
}
|
||||
// @ts-ignore
|
||||
return instanceContainer._lightObstaclesManager;
|
||||
@@ -70,9 +69,8 @@ namespace gdjs {
|
||||
searchArea.maxX = x + radius;
|
||||
// @ts-ignore
|
||||
searchArea.maxY = y + radius;
|
||||
const nearbyObstacles: gdjs.BehaviorRBushAABB<
|
||||
gdjs.LightObstacleRuntimeBehavior
|
||||
>[] = this._obstacleRBush.search(searchArea);
|
||||
const nearbyObstacles: gdjs.BehaviorRBushAABB<gdjs.LightObstacleRuntimeBehavior>[] =
|
||||
this._obstacleRBush.search(searchArea);
|
||||
result.length = 0;
|
||||
nearbyObstacles.forEach((nearbyObstacle) =>
|
||||
result.push(nearbyObstacle.behavior)
|
||||
@@ -85,9 +83,8 @@ namespace gdjs {
|
||||
_oldY: float = 0;
|
||||
_oldWidth: float = 0;
|
||||
_oldHeight: float = 0;
|
||||
currentRBushAABB: gdjs.BehaviorRBushAABB<
|
||||
LightObstacleRuntimeBehavior
|
||||
> | null = null;
|
||||
currentRBushAABB: gdjs.BehaviorRBushAABB<LightObstacleRuntimeBehavior> | null =
|
||||
null;
|
||||
_manager: any;
|
||||
_registeredInManager: boolean = false;
|
||||
|
||||
|
@@ -197,11 +197,11 @@ namespace gdjs {
|
||||
const texture = this._object.getTexture();
|
||||
this._texture =
|
||||
texture !== ''
|
||||
? (this._instanceContainer
|
||||
.getGame()
|
||||
.getImageManager() as gdjs.PixiImageManager).getPIXITexture(
|
||||
texture
|
||||
)
|
||||
? (
|
||||
this._instanceContainer
|
||||
.getGame()
|
||||
.getImageManager() as gdjs.PixiImageManager
|
||||
).getPIXITexture(texture)
|
||||
: null;
|
||||
}
|
||||
|
||||
@@ -466,35 +466,38 @@ namespace gdjs {
|
||||
const xdiff = flattenVertices[i][0] - this._object.x;
|
||||
const ydiff = flattenVertices[i][1] - this._object.y;
|
||||
const angle = Math.atan2(ydiff, xdiff);
|
||||
const closestVertex = LightRuntimeObjectPixiRenderer._computeClosestIntersectionPoint(
|
||||
this._object,
|
||||
angle,
|
||||
obstaclePolygons,
|
||||
boundingSquareHalfDiag
|
||||
);
|
||||
const closestVertex =
|
||||
LightRuntimeObjectPixiRenderer._computeClosestIntersectionPoint(
|
||||
this._object,
|
||||
angle,
|
||||
obstaclePolygons,
|
||||
boundingSquareHalfDiag
|
||||
);
|
||||
if (closestVertex) {
|
||||
closestVertices.push({ vertex: closestVertex, angle: angle });
|
||||
}
|
||||
|
||||
// TODO: Check whether we need to raycast these two extra rays or not.
|
||||
const closestVertexOffsetLeft = LightRuntimeObjectPixiRenderer._computeClosestIntersectionPoint(
|
||||
this._object,
|
||||
angle + 0.0001,
|
||||
obstaclePolygons,
|
||||
boundingSquareHalfDiag
|
||||
);
|
||||
const closestVertexOffsetLeft =
|
||||
LightRuntimeObjectPixiRenderer._computeClosestIntersectionPoint(
|
||||
this._object,
|
||||
angle + 0.0001,
|
||||
obstaclePolygons,
|
||||
boundingSquareHalfDiag
|
||||
);
|
||||
if (closestVertexOffsetLeft) {
|
||||
closestVertices.push({
|
||||
vertex: closestVertexOffsetLeft,
|
||||
angle: angle + 0.0001,
|
||||
});
|
||||
}
|
||||
const closestVertexOffsetRight = LightRuntimeObjectPixiRenderer._computeClosestIntersectionPoint(
|
||||
this._object,
|
||||
angle - 0.0001,
|
||||
obstaclePolygons,
|
||||
boundingSquareHalfDiag
|
||||
);
|
||||
const closestVertexOffsetRight =
|
||||
LightRuntimeObjectPixiRenderer._computeClosestIntersectionPoint(
|
||||
this._object,
|
||||
angle - 0.0001,
|
||||
obstaclePolygons,
|
||||
boundingSquareHalfDiag
|
||||
);
|
||||
if (closestVertexOffsetRight) {
|
||||
closestVertices.push({
|
||||
vertex: closestVertexOffsetRight,
|
||||
|
@@ -47,9 +47,8 @@ namespace gdjs {
|
||||
this._color = gdjs.rgbOrHexToRGBColor(lightObjectData.content.color);
|
||||
this._debugMode = lightObjectData.content.debugMode;
|
||||
this._texture = lightObjectData.content.texture;
|
||||
this._obstaclesManager = gdjs.LightObstaclesManager.getManager(
|
||||
runtimeScene
|
||||
);
|
||||
this._obstaclesManager =
|
||||
gdjs.LightObstaclesManager.getManager(runtimeScene);
|
||||
this._renderer = new gdjs.LightRuntimeObjectRenderer(this, runtimeScene);
|
||||
this._instanceContainer = runtimeScene;
|
||||
|
||||
|
@@ -194,12 +194,11 @@ namespace gdjs {
|
||||
|
||||
export namespace evtTools {
|
||||
export namespace linkedObjects {
|
||||
gdjs.registerObjectDeletedFromSceneCallback(function (
|
||||
instanceContainer,
|
||||
obj
|
||||
) {
|
||||
LinksManager.getManager(instanceContainer).removeAllLinksOf(obj);
|
||||
});
|
||||
gdjs.registerObjectDeletedFromSceneCallback(
|
||||
function (instanceContainer, obj) {
|
||||
LinksManager.getManager(instanceContainer).removeAllLinksOf(obj);
|
||||
}
|
||||
);
|
||||
|
||||
export const linkObjects = function (
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
@@ -245,9 +244,10 @@ namespace gdjs {
|
||||
if (obj === null) {
|
||||
return false;
|
||||
}
|
||||
const linkedObjectMap = LinksManager.getManager(
|
||||
instanceContainer
|
||||
)._getMapOfObjectsLinkedWith(obj);
|
||||
const linkedObjectMap =
|
||||
LinksManager.getManager(instanceContainer)._getMapOfObjectsLinkedWith(
|
||||
obj
|
||||
);
|
||||
|
||||
let pickedSomething = false;
|
||||
for (const contextObjectName in objectsLists.items) {
|
||||
|
@@ -31,6 +31,128 @@ module.exports = {
|
||||
.addInstructionOrExpressionGroupMetadata(_('Multiplayer'))
|
||||
.setIcon('JsPlatform/Extensions/multiplayer.svg');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'QuickJoinLobby',
|
||||
_('Join the next available lobby'),
|
||||
_(
|
||||
'Join the next available lobby. The player will join the game instantly if this is possible.'
|
||||
),
|
||||
_('Join the next available lobby'),
|
||||
_('Lobbies'),
|
||||
'JsPlatform/Extensions/multiplayer.svg',
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Display loader while searching for a lobby.'),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.setDefaultValue('yes')
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Display game lobbies if no lobby can be joined directly.'),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.setDefaultValue('yes')
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationtools.js'
|
||||
)
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayercomponents.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName('gdjs.multiplayer.authenticateAndQuickJoinLobby');
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
'IsSearchingForLobbyToJoin',
|
||||
_('Is searching for a lobby to join'),
|
||||
_('Is searching for a lobby to join.'),
|
||||
_('Is searching for a lobby to join'),
|
||||
_('Lobbies'),
|
||||
'JsPlatform/Extensions/multiplayer.svg',
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationtools.js'
|
||||
)
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayercomponents.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName('gdjs.multiplayer.isSearchingForLobbyToJoin');
|
||||
|
||||
extension
|
||||
.addCondition(
|
||||
'QuickJoinJustFailed',
|
||||
_('Quick join failed to join a lobby'),
|
||||
_('Quick join failed to join a lobby.'),
|
||||
_('Quick join failed to join a lobby'),
|
||||
_('Lobbies'),
|
||||
'JsPlatform/Extensions/multiplayer.svg',
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.setHelpPath('/all-features/multiplayer')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationtools.js'
|
||||
)
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayercomponents.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName('gdjs.multiplayer.hasQuickJoinJustFailed');
|
||||
|
||||
extension
|
||||
.addStrExpression(
|
||||
'QuickJoinFailureReason',
|
||||
_('Quick join action failure reason'),
|
||||
_(
|
||||
"Returns the reason why the Quick join action failed. It can either be 'FULL' if all lobbies were occupied, 'NOT_ENOUGH_PLAYERS' if the lobby's configuration requires more than 1 player to start the game and no other players were available. It can also take the value 'UNKNOWN'."
|
||||
),
|
||||
_('Lobbies'),
|
||||
'JsPlatform/Extensions/multiplayer.svg'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/Multiplayer/peer.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/peerJsHelper.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationcomponents.js'
|
||||
)
|
||||
.addIncludeFile(
|
||||
'Extensions/PlayerAuthentication/playerauthenticationtools.js'
|
||||
)
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayercomponents.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/messageManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayerVariablesManager.js')
|
||||
.addIncludeFile('Extensions/Multiplayer/multiplayertools.js')
|
||||
.setFunctionName('gdjs.multiplayer.getQuickJoinFailureReason');
|
||||
|
||||
extension
|
||||
.addAction(
|
||||
'OpenGameLobbies',
|
||||
|
@@ -149,18 +149,16 @@ namespace gdjs {
|
||||
let lastSceneSyncTimestamp = 0;
|
||||
let lastSentSceneSyncData: LayoutNetworkSyncData | null = null;
|
||||
let numberOfForcedSceneUpdates = 0;
|
||||
let lastReceivedSceneSyncDataUpdates = new SavedSyncDataUpdates<
|
||||
LayoutNetworkSyncData
|
||||
>();
|
||||
let lastReceivedSceneSyncDataUpdates =
|
||||
new SavedSyncDataUpdates<LayoutNetworkSyncData>();
|
||||
|
||||
// The number of times per second the game data should be synchronized.
|
||||
const gameSyncDataSyncRate = 1;
|
||||
let lastGameSyncTimestamp = 0;
|
||||
let lastSentGameSyncData: GameNetworkSyncData | null = null;
|
||||
let numberOfForcedGameUpdates = 0;
|
||||
let lastReceivedGameSyncDataUpdates = new SavedSyncDataUpdates<
|
||||
GameNetworkSyncData
|
||||
>();
|
||||
let lastReceivedGameSyncDataUpdates =
|
||||
new SavedSyncDataUpdates<GameNetworkSyncData>();
|
||||
|
||||
// Send heartbeat messages from host to players, ensuring their connection is still alive,
|
||||
// measure the ping, and send other useful info.
|
||||
@@ -261,9 +259,8 @@ namespace gdjs {
|
||||
_lastClockReceivedByInstanceByScene[sceneNetworkId] = {};
|
||||
}
|
||||
|
||||
_lastClockReceivedByInstanceByScene[sceneNetworkId][
|
||||
instanceNetworkId
|
||||
] = clock;
|
||||
_lastClockReceivedByInstanceByScene[sceneNetworkId][instanceNetworkId] =
|
||||
clock;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -407,7 +404,8 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const changeInstanceOwnerMessageNamePrefix = '#changeInstanceOwner';
|
||||
const changeInstanceOwnerMessageNameRegex = /#changeInstanceOwner#owner_(\d+)#object_(.+)#instance_(.+)/;
|
||||
const changeInstanceOwnerMessageNameRegex =
|
||||
/#changeInstanceOwner#owner_(\d+)#object_(.+)#instance_(.+)/;
|
||||
const createChangeInstanceOwnerMessage = ({
|
||||
objectOwner,
|
||||
objectName,
|
||||
@@ -446,15 +444,15 @@ namespace gdjs {
|
||||
};
|
||||
};
|
||||
const instanceOwnerChangedMessageNamePrefix = '#instanceOwnerChanged';
|
||||
const instanceOwnerChangedMessageNameRegex = /#instanceOwnerChanged#owner_(\d+)#object_(.+)#instance_(.+)/;
|
||||
const createInstanceOwnerChangedMessageNameFromChangeInstanceOwnerMessage = (
|
||||
messageName: string
|
||||
): string => {
|
||||
return messageName.replace(
|
||||
changeInstanceOwnerMessageNamePrefix,
|
||||
instanceOwnerChangedMessageNamePrefix
|
||||
);
|
||||
};
|
||||
const instanceOwnerChangedMessageNameRegex =
|
||||
/#instanceOwnerChanged#owner_(\d+)#object_(.+)#instance_(.+)/;
|
||||
const createInstanceOwnerChangedMessageNameFromChangeInstanceOwnerMessage =
|
||||
(messageName: string): string => {
|
||||
return messageName.replace(
|
||||
changeInstanceOwnerMessageNamePrefix,
|
||||
instanceOwnerChangedMessageNamePrefix
|
||||
);
|
||||
};
|
||||
const handleChangeInstanceOwnerMessagesReceived = (
|
||||
runtimeScene: gdjs.RuntimeScene
|
||||
) => {
|
||||
@@ -524,7 +522,8 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentPlayerObjectOwnership = behavior.getPlayerObjectOwnership();
|
||||
const currentPlayerObjectOwnership =
|
||||
behavior.getPlayerObjectOwnership();
|
||||
// Change is coherent if:
|
||||
const ownershipChangeIsCoherent =
|
||||
// the object is changing ownership from the same owner the host knew about,
|
||||
@@ -550,9 +549,10 @@ namespace gdjs {
|
||||
);
|
||||
behavior.playerNumber = newOwner;
|
||||
|
||||
const instanceOwnerChangedMessageName = createInstanceOwnerChangedMessageNameFromChangeInstanceOwnerMessage(
|
||||
messageName
|
||||
);
|
||||
const instanceOwnerChangedMessageName =
|
||||
createInstanceOwnerChangedMessageNameFromChangeInstanceOwnerMessage(
|
||||
messageName
|
||||
);
|
||||
|
||||
debugLogger.info(
|
||||
`Sending acknowledgment of ownership change of object ${objectName} from ${previousOwner} to ${newOwner} with instance network ID ${instanceNetworkId} to ${messageSender}.`
|
||||
@@ -594,7 +594,8 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const updateInstanceMessageNamePrefix = '#updateInstance';
|
||||
const updateInstanceMessageNameRegex = /#updateInstance#owner_(\d+)#object_(.+)#instance_(.+)#scene_(.+)/;
|
||||
const updateInstanceMessageNameRegex =
|
||||
/#updateInstance#owner_(\d+)#object_(.+)#instance_(.+)#scene_(.+)/;
|
||||
const createUpdateInstanceMessage = ({
|
||||
objectOwner,
|
||||
objectName,
|
||||
@@ -757,7 +758,8 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const changeVariableOwnerMessageNamePrefix = '#changeVariableOwner';
|
||||
const changeVariableOwnerMessageNameRegex = /#changeVariableOwner#owner_(\d+)#variable_(.+)/;
|
||||
const changeVariableOwnerMessageNameRegex =
|
||||
/#changeVariableOwner#owner_(\d+)#variable_(.+)/;
|
||||
const createChangeVariableOwnerMessage = ({
|
||||
variableOwner,
|
||||
variableNetworkId,
|
||||
@@ -782,15 +784,15 @@ namespace gdjs {
|
||||
};
|
||||
};
|
||||
const variableOwnerChangedMessageNamePrefix = '#variableOwnerChanged';
|
||||
const variableOwnerChangedMessageNameRegex = /#variableOwnerChanged#owner_(\d+)#variable_(.+)/;
|
||||
const createVariableOwnerChangedMessageNameFromChangeVariableOwnerMessage = (
|
||||
messageName: string
|
||||
): string => {
|
||||
return messageName.replace(
|
||||
changeVariableOwnerMessageNamePrefix,
|
||||
variableOwnerChangedMessageNamePrefix
|
||||
);
|
||||
};
|
||||
const variableOwnerChangedMessageNameRegex =
|
||||
/#variableOwnerChanged#owner_(\d+)#variable_(.+)/;
|
||||
const createVariableOwnerChangedMessageNameFromChangeVariableOwnerMessage =
|
||||
(messageName: string): string => {
|
||||
return messageName.replace(
|
||||
changeVariableOwnerMessageNamePrefix,
|
||||
variableOwnerChangedMessageNamePrefix
|
||||
);
|
||||
};
|
||||
const handleChangeVariableOwnerMessagesReceived = (
|
||||
runtimeScene: gdjs.RuntimeScene
|
||||
) => {
|
||||
@@ -885,9 +887,10 @@ namespace gdjs {
|
||||
);
|
||||
variable.setPlayerOwnership(newOwner);
|
||||
|
||||
const variableOwnerChangedMessageName = createVariableOwnerChangedMessageNameFromChangeVariableOwnerMessage(
|
||||
messageName
|
||||
);
|
||||
const variableOwnerChangedMessageName =
|
||||
createVariableOwnerChangedMessageNameFromChangeVariableOwnerMessage(
|
||||
messageName
|
||||
);
|
||||
|
||||
debugLogger.info(
|
||||
`Sending acknowledgment of ownership change of variable with ID ${variableNetworkId} from ${previousOwner} to ${newOwner} to ${messageSender}.`
|
||||
@@ -1081,9 +1084,10 @@ namespace gdjs {
|
||||
changeInstanceOwnerMessageNamePrefix
|
||||
)
|
||||
) {
|
||||
const matches = changeInstanceOwnerMessageNameRegex.exec(
|
||||
originalMessageName
|
||||
);
|
||||
const matches =
|
||||
changeInstanceOwnerMessageNameRegex.exec(
|
||||
originalMessageName
|
||||
);
|
||||
if (!matches) {
|
||||
// This should not happen, if it does, remove the acknowledgment and return.
|
||||
delete expectedMessageAcknowledgements[
|
||||
@@ -1146,9 +1150,10 @@ namespace gdjs {
|
||||
changeVariableOwnerMessageNamePrefix
|
||||
)
|
||||
) {
|
||||
const matches = changeVariableOwnerMessageNameRegex.exec(
|
||||
originalMessageName
|
||||
);
|
||||
const matches =
|
||||
changeVariableOwnerMessageNameRegex.exec(
|
||||
originalMessageName
|
||||
);
|
||||
if (!matches) {
|
||||
// This should not happen, if it does, remove the acknowledgment and return.
|
||||
delete expectedMessageAcknowledgements[
|
||||
@@ -1229,7 +1234,8 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const destroyInstanceMessageNamePrefix = '#destroyInstance';
|
||||
const destroyInstanceMessageNameRegex = /#destroyInstance#owner_(\d+)#object_(.+)#instance_(.+)#scene_(.+)/;
|
||||
const destroyInstanceMessageNameRegex =
|
||||
/#destroyInstance#owner_(\d+)#object_(.+)#instance_(.+)#scene_(.+)/;
|
||||
const createDestroyInstanceMessage = ({
|
||||
objectOwner,
|
||||
objectName,
|
||||
@@ -1250,7 +1256,8 @@ namespace gdjs {
|
||||
};
|
||||
};
|
||||
const instanceDestroyedMessageNamePrefix = '#instanceDestroyed';
|
||||
const instanceDestroyedMessageNameRegex = /#instanceDestroyed#owner_(\d+)#object_(.+)#instance_(.+)/;
|
||||
const instanceDestroyedMessageNameRegex =
|
||||
/#instanceDestroyed#owner_(\d+)#object_(.+)#instance_(.+)/;
|
||||
const createInstanceDestroyedMessageNameFromDestroyInstanceMessage = (
|
||||
messageName: string
|
||||
): string => {
|
||||
@@ -1315,9 +1322,10 @@ namespace gdjs {
|
||||
instanceNetworkId,
|
||||
});
|
||||
|
||||
const instanceDestroyedMessageName = createInstanceDestroyedMessageNameFromDestroyInstanceMessage(
|
||||
messageName
|
||||
);
|
||||
const instanceDestroyedMessageName =
|
||||
createInstanceDestroyedMessageNameFromDestroyInstanceMessage(
|
||||
messageName
|
||||
);
|
||||
|
||||
if (!instance) {
|
||||
debugLogger.info(
|
||||
@@ -1420,9 +1428,8 @@ namespace gdjs {
|
||||
userMessageData,
|
||||
senderPlayerNumber: currentPlayerNumber,
|
||||
});
|
||||
const acknowledgmentMessageName = createAcknowledgeCustomMessageNameFromCustomMessage(
|
||||
messageName
|
||||
);
|
||||
const acknowledgmentMessageName =
|
||||
createAcknowledgeCustomMessageNameFromCustomMessage(messageName);
|
||||
addExpectedMessageAcknowledgement({
|
||||
originalMessageName: messageName,
|
||||
originalData: messageData,
|
||||
@@ -1441,9 +1448,8 @@ namespace gdjs {
|
||||
// If we are the host, we can consider this messaged as received
|
||||
// and add it to the list of custom messages to process on top of the messages received.
|
||||
if (gdjs.multiplayer.isCurrentPlayerHost()) {
|
||||
const messagesList = gdjs.multiplayerPeerJsHelper.getOrCreateMessagesList(
|
||||
messageName
|
||||
);
|
||||
const messagesList =
|
||||
gdjs.multiplayerPeerJsHelper.getOrCreateMessagesList(messageName);
|
||||
messagesList.pushMessage(
|
||||
messageData,
|
||||
gdjs.multiplayerPeerJsHelper.getCurrentId()
|
||||
@@ -1467,9 +1473,8 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const hasCustomMessageBeenReceived = (userMessageName: string) => {
|
||||
const customMessageName = getCustomMessageNameFromUserMessageName(
|
||||
userMessageName
|
||||
);
|
||||
const customMessageName =
|
||||
getCustomMessageNameFromUserMessageName(userMessageName);
|
||||
const p2pMessagesMap = gdjs.multiplayerPeerJsHelper.getAllMessagesMap();
|
||||
const messagesList = p2pMessagesMap.get(customMessageName);
|
||||
if (!messagesList) return; // No message received.
|
||||
@@ -1499,9 +1504,8 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const getCustomMessageData = (userMessageName: string) => {
|
||||
const customMessageName = getCustomMessageNameFromUserMessageName(
|
||||
userMessageName
|
||||
);
|
||||
const customMessageName =
|
||||
getCustomMessageNameFromUserMessageName(userMessageName);
|
||||
const p2pMessagesMap = gdjs.multiplayerPeerJsHelper.getAllMessagesMap();
|
||||
const messagesList = p2pMessagesMap.get(customMessageName);
|
||||
if (!messagesList) return; // No message received.
|
||||
@@ -1531,9 +1535,8 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const getCustomMessageSender = (userMessageName: string): number => {
|
||||
const customMessageName = getCustomMessageNameFromUserMessageName(
|
||||
userMessageName
|
||||
);
|
||||
const customMessageName =
|
||||
getCustomMessageNameFromUserMessageName(userMessageName);
|
||||
const p2pMessagesMap = gdjs.multiplayerPeerJsHelper.getAllMessagesMap();
|
||||
const messagesList = p2pMessagesMap.get(customMessageName);
|
||||
if (!messagesList) return 0;
|
||||
@@ -1593,9 +1596,8 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
const acknowledgmentMessageName = createAcknowledgeCustomMessageNameFromCustomMessage(
|
||||
messageName
|
||||
);
|
||||
const acknowledgmentMessageName =
|
||||
createAcknowledgeCustomMessageNameFromCustomMessage(messageName);
|
||||
debugLogger.info(
|
||||
`Sending acknowledgment of custom message ${messageName} to ${messageSender}.`
|
||||
);
|
||||
@@ -1681,9 +1683,8 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
const isSceneSyncDataDifferent = isSceneDifferentFromLastSync(
|
||||
sceneNetworkSyncData
|
||||
);
|
||||
const isSceneSyncDataDifferent =
|
||||
isSceneDifferentFromLastSync(sceneNetworkSyncData);
|
||||
const shouldSyncScene =
|
||||
!hasSceneBeenSyncedRecently() ||
|
||||
isSceneSyncDataDifferent ||
|
||||
@@ -1845,9 +1846,8 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
const isGameSyncDataDifferent = isGameDifferentFromLastSync(
|
||||
gameNetworkSyncData
|
||||
);
|
||||
const isGameSyncDataDifferent =
|
||||
isGameDifferentFromLastSync(gameNetworkSyncData);
|
||||
const shouldSyncGame =
|
||||
!hasGameBeenSyncedRecently() ||
|
||||
isGameSyncDataDifferent ||
|
||||
@@ -1945,12 +1945,12 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const heartbeatMessageNamePrefix = '#heartbeat';
|
||||
const heartbeastMessageRegex = /#heartbeat#(.+)/;
|
||||
const heartbeatMessageRegex = /#heartbeat#(.+)/;
|
||||
const createHeartbeatMessage = (): {
|
||||
messageName: string;
|
||||
messageData: any;
|
||||
} => {
|
||||
// If we create the heartbeat meassage, we are the host,
|
||||
// If we create the heartbeat message, we are the host.
|
||||
// Ensure our player number is correctly set when the first heartbeat is sent.
|
||||
_playersInfo[gdjs.multiplayer.getCurrentPlayerNumber()] = {
|
||||
ping: 0, // we are the host, so we don't need to compute the ping.
|
||||
@@ -2028,7 +2028,7 @@ namespace gdjs {
|
||||
messages.forEach((message) => {
|
||||
const messageData = message.getData();
|
||||
const messageSender = message.getSender();
|
||||
const matches = heartbeastMessageRegex.exec(messageName);
|
||||
const matches = heartbeatMessageRegex.exec(messageName);
|
||||
if (!matches) {
|
||||
return;
|
||||
}
|
||||
@@ -2039,10 +2039,11 @@ namespace gdjs {
|
||||
// If we are not the host, save what the host told us about the other players info
|
||||
// and respond with a heartbeat immediately, informing the host of our playerId and username.
|
||||
if (!gdjs.multiplayer.isCurrentPlayerHost()) {
|
||||
const currentPlayerNumber = gdjs.multiplayer.getCurrentPlayerNumber();
|
||||
const currentlyKnownPlayerNumbers = Object.keys(
|
||||
_playersInfo
|
||||
).map((playerNumber) => parseInt(playerNumber, 10));
|
||||
const currentPlayerNumber =
|
||||
gdjs.multiplayer.getCurrentPlayerNumber();
|
||||
const currentlyKnownPlayerNumbers = Object.keys(_playersInfo).map(
|
||||
(playerNumber) => parseInt(playerNumber, 10)
|
||||
);
|
||||
const receivedPlayerNumbers = Object.keys(
|
||||
messageData.playersInfo
|
||||
).map((playerNumber) => parseInt(playerNumber, 10));
|
||||
@@ -2061,18 +2062,19 @@ namespace gdjs {
|
||||
);
|
||||
_playerNumbersWhoJustJoined.push(...newPlayerNumbers);
|
||||
// Or players who have disconnected.
|
||||
const playerNumbersWhoHaveDisconnected = currentlyKnownPlayerNumbers.filter(
|
||||
(playerNumber) => !receivedPlayerNumbers.includes(playerNumber)
|
||||
);
|
||||
const playerNumbersWhoHaveDisconnected =
|
||||
currentlyKnownPlayerNumbers.filter(
|
||||
(playerNumber) =>
|
||||
!receivedPlayerNumbers.includes(playerNumber)
|
||||
);
|
||||
_playerNumbersWhoJustLeft.push(
|
||||
...playerNumbersWhoHaveDisconnected
|
||||
);
|
||||
for (const playerNumber of playerNumbersWhoHaveDisconnected) {
|
||||
// Temporarily save the username in another variable to be used for the notification,
|
||||
// as we're deleting its playerInfo just after.
|
||||
_temporaryPlayerNumberToUsername[
|
||||
playerNumber
|
||||
] = getPlayerUsername(playerNumber);
|
||||
_temporaryPlayerNumberToUsername[playerNumber] =
|
||||
getPlayerUsername(playerNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2188,14 +2190,14 @@ namespace gdjs {
|
||||
_playerNumbersWhoJustLeft.push(playerNumber);
|
||||
// Temporarily save the username in another variable to be used for the notification,
|
||||
// as we're deleting its playerInfo just after.
|
||||
_temporaryPlayerNumberToUsername[playerNumber] = getPlayerUsername(
|
||||
playerNumber
|
||||
);
|
||||
_temporaryPlayerNumberToUsername[playerNumber] =
|
||||
getPlayerUsername(playerNumber);
|
||||
clearPlayerTempData(playerNumber);
|
||||
|
||||
// If Host has disconnected, either switch host or stop the game.
|
||||
if (peerId && peerId === gdjs.multiplayer.hostPeerId) {
|
||||
const shouldEndLobbyGame = gdjs.multiplayer.shouldEndLobbyWhenHostLeaves();
|
||||
const shouldEndLobbyGame =
|
||||
gdjs.multiplayer.shouldEndLobbyWhenHostLeaves();
|
||||
if (shouldEndLobbyGame) {
|
||||
logger.info('Host has disconnected, ending the game.');
|
||||
|
||||
@@ -2243,7 +2245,8 @@ namespace gdjs {
|
||||
peerId: string;
|
||||
}[] = [];
|
||||
|
||||
const justDisconnectedPeers = gdjs.multiplayerPeerJsHelper.getJustDisconnectedPeers();
|
||||
const justDisconnectedPeers =
|
||||
gdjs.multiplayerPeerJsHelper.getJustDisconnectedPeers();
|
||||
if (justDisconnectedPeers.length) {
|
||||
for (const disconnectedPeer of justDisconnectedPeers) {
|
||||
const disconnectedPlayerNumber =
|
||||
@@ -2273,7 +2276,8 @@ namespace gdjs {
|
||||
behavior &&
|
||||
behavior.getPlayerObjectOwnership() === playerNumber
|
||||
) {
|
||||
const actionOnPlayerDisconnect = behavior.getActionOnPlayerDisconnect();
|
||||
const actionOnPlayerDisconnect =
|
||||
behavior.getActionOnPlayerDisconnect();
|
||||
if (actionOnPlayerDisconnect === 'DestroyObject') {
|
||||
// No need to remove the ownership, as the destroy message will be sent to all players.
|
||||
instance.deleteFromScene(runtimeScene);
|
||||
|
@@ -78,9 +78,10 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
const variableName = currentSceneVariables.getVariableNameInContainerByLoopingThroughAllVariables(
|
||||
variable
|
||||
);
|
||||
const variableName =
|
||||
currentSceneVariables.getVariableNameInContainerByLoopingThroughAllVariables(
|
||||
variable
|
||||
);
|
||||
|
||||
if (!variableName) {
|
||||
logger.error('Variable is being synchronized but has no name.');
|
||||
@@ -98,9 +99,10 @@ namespace gdjs {
|
||||
|
||||
// TODO: prevent returning a networkID if this is not a root variable.
|
||||
|
||||
const variableName = runtimeGameVariables.getVariableNameInContainerByLoopingThroughAllVariables(
|
||||
variable
|
||||
);
|
||||
const variableName =
|
||||
runtimeGameVariables.getVariableNameInContainerByLoopingThroughAllVariables(
|
||||
variable
|
||||
);
|
||||
if (!variableName) {
|
||||
logger.error('Variable is being synchronized but has no name.');
|
||||
return;
|
||||
@@ -171,9 +173,8 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
const { type: variableType } = getVariableTypeAndNameFromNetworkId(
|
||||
variableNetworkId
|
||||
);
|
||||
const { type: variableType } =
|
||||
getVariableTypeAndNameFromNetworkId(variableNetworkId);
|
||||
|
||||
debugLogger.info(
|
||||
`Adding variable to be synchronized: ${variableNetworkId} (type: ${variableType}) from owner ${previousVariablePlayerNumber} to ${newVariablePlayerNumber}.`
|
||||
@@ -220,21 +221,20 @@ namespace gdjs {
|
||||
for (const variableNetworkId in variableOwnershipChangesToSyncAtEndOfFrame) {
|
||||
const variableData =
|
||||
variableOwnershipChangesToSyncAtEndOfFrame[variableNetworkId];
|
||||
const {
|
||||
messageName,
|
||||
messageData,
|
||||
} = gdjs.multiplayerMessageManager.createChangeVariableOwnerMessage({
|
||||
variableNetworkId,
|
||||
variableOwner: variableData.previousVariableOwner,
|
||||
newVariableOwner: variableData.newVariableOwner,
|
||||
});
|
||||
const { messageName, messageData } =
|
||||
gdjs.multiplayerMessageManager.createChangeVariableOwnerMessage({
|
||||
variableNetworkId,
|
||||
variableOwner: variableData.previousVariableOwner,
|
||||
newVariableOwner: variableData.newVariableOwner,
|
||||
});
|
||||
// Before sending the change owner message, if we are becoming the new owner,
|
||||
// we want to ensure this message is acknowledged, by everyone we're connected to.
|
||||
if (variableData.newVariableOwner === currentPlayerNumber) {
|
||||
const otherPeerIds = gdjs.multiplayerPeerJsHelper.getAllPeers();
|
||||
const variableOwnerChangedMessageName = gdjs.multiplayerMessageManager.createVariableOwnerChangedMessageNameFromChangeVariableOwnerMessage(
|
||||
messageName
|
||||
);
|
||||
const variableOwnerChangedMessageName =
|
||||
gdjs.multiplayerMessageManager.createVariableOwnerChangedMessageNameFromChangeVariableOwnerMessage(
|
||||
messageName
|
||||
);
|
||||
gdjs.multiplayerMessageManager.addExpectedMessageAcknowledgement({
|
||||
originalMessageName: messageName,
|
||||
originalData: messageData,
|
||||
|
@@ -1,6 +1,7 @@
|
||||
namespace gdjs {
|
||||
const logger = new gdjs.Logger('Multiplayer');
|
||||
export namespace multiplayerComponents {
|
||||
const loaderContainerId = 'loader-container';
|
||||
const lobbiesRootContainerId = 'lobbies-root-container';
|
||||
const lobbiesFrameContainerId = 'lobbies-frame-container';
|
||||
const lobbiesCloseContainerId = 'lobbies-close-container';
|
||||
@@ -117,6 +118,66 @@ namespace gdjs {
|
||||
return lobbiesIframe;
|
||||
};
|
||||
|
||||
export const displayLoader = (
|
||||
runtimeScene: gdjs.RuntimeScene,
|
||||
yesOrNo: boolean
|
||||
) => {
|
||||
const domElementContainer = getDomElementContainer(runtimeScene);
|
||||
if (!domElementContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (yesOrNo) {
|
||||
const loaderContainer: HTMLDivElement = document.createElement('div');
|
||||
loaderContainer.id = loaderContainerId;
|
||||
loaderContainer.style.backgroundColor = '#000000';
|
||||
loaderContainer.style.display = 'flex';
|
||||
loaderContainer.style.height = '100%';
|
||||
loaderContainer.style.width = '100%';
|
||||
loaderContainer.style.justifyContent = 'center';
|
||||
loaderContainer.style.alignItems = 'center';
|
||||
loaderContainer.style.position = 'relative';
|
||||
loaderContainer.style.zIndex = '2';
|
||||
const loader = document.createElement('img');
|
||||
loader.setAttribute('width', '50px');
|
||||
loader.setAttribute(
|
||||
'src',
|
||||
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAyNCAyNCI+CjxjaXJjbGUgb3BhY2l0eT0nMC4yNScgY3g9IjEyIiBjeT0iMTIiIHI9IjEwIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iNCI+PC9jaXJjbGU+CjxwYXRoIG9wYWNpdHk9JzAuNzUnIGZpbGw9IiNGRkZGRkYiIGQ9Ik00IDEyYTggOCAwIDAxOC04VjBDNS4zNzMgMCAwIDUuMzczIDAgMTJoNHptMiA1LjI5MUE3Ljk2MiA3Ljk2MiAwIDAxNCAxMkgwYzAgMy4wNDIgMS4xMzUgNS44MjQgMyA3LjkzOGwzLTIuNjQ3eiI+PC9wYXRoPgo8L3N2Zz4='
|
||||
);
|
||||
try {
|
||||
loader.animate(
|
||||
[{ transform: 'rotate(0deg)' }, { transform: 'rotate(359deg)' }],
|
||||
{
|
||||
duration: 3000,
|
||||
iterations: Infinity,
|
||||
}
|
||||
);
|
||||
} catch {
|
||||
logger.warn('Animation not supported, loader will be fixed.');
|
||||
}
|
||||
loaderContainer.appendChild(loader);
|
||||
if (
|
||||
domElementContainer.children &&
|
||||
domElementContainer.children.length > 0
|
||||
) {
|
||||
domElementContainer.insertBefore(
|
||||
loaderContainer,
|
||||
domElementContainer.children[0]
|
||||
);
|
||||
} else {
|
||||
domElementContainer.appendChild(loaderContainer);
|
||||
}
|
||||
} else {
|
||||
const loaderContainer = domElementContainer.querySelector(
|
||||
`#${loaderContainerId}`
|
||||
);
|
||||
if (!loaderContainer) return;
|
||||
try {
|
||||
domElementContainer.removeChild(loaderContainer);
|
||||
} catch {}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a DOM element that will contain the loader or a message if the game is not registered,
|
||||
* and adds it to the dom container.
|
||||
@@ -562,8 +623,8 @@ namespace gdjs {
|
||||
type === 'success'
|
||||
? '#0E062D'
|
||||
: type === 'warning'
|
||||
? '#FFA500'
|
||||
: '#FF0000';
|
||||
? '#FFA500'
|
||||
: '#FF0000';
|
||||
// Space the notifications vertically, based on how many there are.
|
||||
divContainer.style.top = `${12 + notificationContainerIds.length * 32}px`;
|
||||
divContainer.style.right = '16px';
|
||||
|
@@ -130,7 +130,8 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
private _hasObjectBeenSyncedWithinMaxRate() {
|
||||
const objectMaxSyncRate = gdjs.multiplayer.getObjectsSynchronizationRate();
|
||||
const objectMaxSyncRate =
|
||||
gdjs.multiplayer.getObjectsSynchronizationRate();
|
||||
return (
|
||||
getTimeNow() - this._lastObjectSyncTimestamp < 1000 / objectMaxSyncRate
|
||||
);
|
||||
@@ -287,8 +288,8 @@ namespace gdjs {
|
||||
// )}`
|
||||
// );
|
||||
|
||||
const areBasicObjectNetworkSyncDataDifferent = this._isBasicObjectNetworkSyncDataDifferentFromLastSync(
|
||||
{
|
||||
const areBasicObjectNetworkSyncDataDifferent =
|
||||
this._isBasicObjectNetworkSyncDataDifferentFromLastSync({
|
||||
x: objectNetworkSyncData.x,
|
||||
y: objectNetworkSyncData.y,
|
||||
z: objectNetworkSyncData.z,
|
||||
@@ -299,8 +300,7 @@ namespace gdjs {
|
||||
if: objectNetworkSyncData.if,
|
||||
pfx: objectNetworkSyncData.pfx,
|
||||
pfy: objectNetworkSyncData.pfy,
|
||||
}
|
||||
);
|
||||
});
|
||||
const shouldSyncObjectBasicInfo =
|
||||
!this._hasObjectBasicInfoBeenSyncedRecently() ||
|
||||
areBasicObjectNetworkSyncDataDifferent ||
|
||||
@@ -348,16 +348,14 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
messageName: updateMessageName,
|
||||
messageData: updateMessageData,
|
||||
} = gdjs.multiplayerMessageManager.createUpdateInstanceMessage({
|
||||
objectOwner: this.playerNumber,
|
||||
objectName,
|
||||
instanceNetworkId,
|
||||
objectNetworkSyncData,
|
||||
sceneNetworkId,
|
||||
});
|
||||
const { messageName: updateMessageName, messageData: updateMessageData } =
|
||||
gdjs.multiplayerMessageManager.createUpdateInstanceMessage({
|
||||
objectOwner: this.playerNumber,
|
||||
objectName,
|
||||
instanceNetworkId,
|
||||
objectNetworkSyncData,
|
||||
sceneNetworkId,
|
||||
});
|
||||
this._sendDataToPeersWithIncreasedClock(
|
||||
updateMessageName,
|
||||
updateMessageData
|
||||
@@ -440,16 +438,14 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
// Ensure we send a final update before the object is destroyed, if it had a networkId.
|
||||
const {
|
||||
messageName: updateMessageName,
|
||||
messageData: updateMessageData,
|
||||
} = gdjs.multiplayerMessageManager.createUpdateInstanceMessage({
|
||||
objectOwner: this.playerNumber,
|
||||
objectName,
|
||||
instanceNetworkId,
|
||||
objectNetworkSyncData: this.owner.getNetworkSyncData(),
|
||||
sceneNetworkId,
|
||||
});
|
||||
const { messageName: updateMessageName, messageData: updateMessageData } =
|
||||
gdjs.multiplayerMessageManager.createUpdateInstanceMessage({
|
||||
objectOwner: this.playerNumber,
|
||||
objectName,
|
||||
instanceNetworkId,
|
||||
objectNetworkSyncData: this.owner.getNetworkSyncData(),
|
||||
sceneNetworkId,
|
||||
});
|
||||
this._sendDataToPeersWithIncreasedClock(
|
||||
updateMessageName,
|
||||
updateMessageData
|
||||
@@ -470,9 +466,10 @@ namespace gdjs {
|
||||
instanceNetworkId,
|
||||
sceneNetworkId,
|
||||
});
|
||||
const destroyedMessageName = gdjs.multiplayerMessageManager.createInstanceDestroyedMessageNameFromDestroyInstanceMessage(
|
||||
destroyMessageName
|
||||
);
|
||||
const destroyedMessageName =
|
||||
gdjs.multiplayerMessageManager.createInstanceDestroyedMessageNameFromDestroyInstanceMessage(
|
||||
destroyMessageName
|
||||
);
|
||||
gdjs.multiplayerMessageManager.addExpectedMessageAcknowledgement({
|
||||
originalMessageName: destroyMessageName,
|
||||
originalData: {
|
||||
@@ -552,18 +549,16 @@ namespace gdjs {
|
||||
// When changing the ownership of an object with a networkId, we send a message to the host to ensure it is aware of the change,
|
||||
// and can either accept it and broadcast it to other players, or reject it and do nothing with it.
|
||||
// We expect an acknowledgment from the host, if not, we will retry and eventually revert the ownership.
|
||||
const {
|
||||
messageName,
|
||||
messageData,
|
||||
} = gdjs.multiplayerMessageManager.createChangeInstanceOwnerMessage({
|
||||
objectOwner: previousObjectPlayerNumber,
|
||||
objectName,
|
||||
instanceNetworkId,
|
||||
newObjectOwner: newObjectPlayerNumber,
|
||||
instanceX: this.owner.getX(),
|
||||
instanceY: this.owner.getY(),
|
||||
sceneNetworkId,
|
||||
});
|
||||
const { messageName, messageData } =
|
||||
gdjs.multiplayerMessageManager.createChangeInstanceOwnerMessage({
|
||||
objectOwner: previousObjectPlayerNumber,
|
||||
objectName,
|
||||
instanceNetworkId,
|
||||
newObjectOwner: newObjectPlayerNumber,
|
||||
instanceX: this.owner.getX(),
|
||||
instanceY: this.owner.getY(),
|
||||
sceneNetworkId,
|
||||
});
|
||||
// Before sending the changeOwner message, if we are becoming the new owner,
|
||||
// we want to ensure this message is acknowledged, by everyone we're connected to.
|
||||
// If we are the host, we are connected to everyone, so we expect an acknowledgment from everyone.
|
||||
@@ -571,9 +566,10 @@ namespace gdjs {
|
||||
// In both cases, this represents the list of peers the current user is connected to.
|
||||
if (newObjectPlayerNumber === currentPlayerNumber) {
|
||||
const otherPeerIds = gdjs.multiplayerPeerJsHelper.getAllPeers();
|
||||
const changeOwnerAcknowledgedMessageName = gdjs.multiplayerMessageManager.createInstanceOwnerChangedMessageNameFromChangeInstanceOwnerMessage(
|
||||
messageName
|
||||
);
|
||||
const changeOwnerAcknowledgedMessageName =
|
||||
gdjs.multiplayerMessageManager.createInstanceOwnerChangedMessageNameFromChangeInstanceOwnerMessage(
|
||||
messageName
|
||||
);
|
||||
gdjs.multiplayerMessageManager.addExpectedMessageAcknowledgement({
|
||||
originalMessageName: messageName,
|
||||
originalData: {
|
||||
@@ -583,7 +579,8 @@ namespace gdjs {
|
||||
expectedMessageName: changeOwnerAcknowledgedMessageName,
|
||||
otherPeerIds,
|
||||
// If we are not the host, we should revert the ownership if the host does not acknowledge the change.
|
||||
shouldCancelMessageIfTimesOut: !gdjs.multiplayer.isCurrentPlayerHost(),
|
||||
shouldCancelMessageIfTimesOut:
|
||||
!gdjs.multiplayer.isCurrentPlayerHost(),
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,17 @@ namespace gdjs {
|
||||
}[];
|
||||
};
|
||||
|
||||
type Lobby = {
|
||||
id: string;
|
||||
status: 'waiting' | 'starting' | 'playing' | 'migrating' | 'migrated';
|
||||
};
|
||||
|
||||
type QuickJoinLobbyResponse =
|
||||
| { status: 'join-game'; lobby: Lobby }
|
||||
| { status: 'join-lobby'; lobby: Lobby }
|
||||
| { status: 'not-enough-players' }
|
||||
| { status: 'full' };
|
||||
|
||||
const getTimeNow =
|
||||
window.performance && typeof window.performance.now === 'function'
|
||||
? window.performance.now.bind(window.performance)
|
||||
@@ -90,6 +101,12 @@ namespace gdjs {
|
||||
let _hasLobbyGameJustStarted = false;
|
||||
export let _isLobbyGameRunning = false;
|
||||
let _hasLobbyGameJustEnded = false;
|
||||
let _quickJoinLobbyJustFailed = false;
|
||||
let _quickJoinLobbyFailureReason:
|
||||
| 'FULL'
|
||||
| 'NOT_ENOUGH_PLAYERS'
|
||||
| 'UNKNOWN'
|
||||
| null = null;
|
||||
let _lobbyId: string | null = null;
|
||||
let _connectionId: string | null = null;
|
||||
|
||||
@@ -98,6 +115,13 @@ namespace gdjs {
|
||||
let _lobbyChangeHostRequestInitiatedAt: number | null = null;
|
||||
let _isChangingHost = false;
|
||||
let _lobbyNewHostPickedAt: number | null = null;
|
||||
let _actionAfterJoiningLobby:
|
||||
| 'OPEN_LOBBY_PAGE'
|
||||
| 'JOIN_GAME'
|
||||
| 'START_GAME'
|
||||
| null = null;
|
||||
let _isQuickJoiningOrStartingAGame = false;
|
||||
let _lastQuickJoinRequestDoneAt: number | null = null;
|
||||
|
||||
// Communication methods.
|
||||
let _lobbiesMessageCallback: ((event: MessageEvent) => void) | null = null;
|
||||
@@ -206,6 +230,7 @@ namespace gdjs {
|
||||
|
||||
_hasLobbyGameJustStarted = false;
|
||||
_hasLobbyGameJustEnded = false;
|
||||
_quickJoinLobbyJustFailed = false;
|
||||
});
|
||||
|
||||
const getLobbiesWindowUrl = ({
|
||||
@@ -253,6 +278,11 @@ namespace gdjs {
|
||||
if (playerToken) {
|
||||
url.searchParams.set('playerToken', playerToken);
|
||||
}
|
||||
const platformInfo = runtimeGame.getPlatformInfo();
|
||||
url.searchParams.set(
|
||||
'scm',
|
||||
platformInfo.supportedCompressionMethods.join(',')
|
||||
);
|
||||
// Increment this value when a new feature is introduced so we can
|
||||
// adapt the interface of the lobbies.
|
||||
url.searchParams.set('multiplayerVersion', '2');
|
||||
@@ -362,7 +392,8 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const handleLeavingPlayer = (runtimeScene: gdjs.RuntimeScene) => {
|
||||
const lastestPlayerWhoJustLeft = gdjs.multiplayerMessageManager.getLatestPlayerWhoJustLeft();
|
||||
const lastestPlayerWhoJustLeft =
|
||||
gdjs.multiplayerMessageManager.getLatestPlayerWhoJustLeft();
|
||||
if (lastestPlayerWhoJustLeft) {
|
||||
const playerUsername = getPlayerUsername(lastestPlayerWhoJustLeft);
|
||||
gdjs.multiplayerComponents.displayPlayerLeftNotification(
|
||||
@@ -386,7 +417,8 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const handleJoiningPlayer = (runtimeScene: gdjs.RuntimeScene) => {
|
||||
const lastestPlayerWhoJustJoined = gdjs.multiplayerMessageManager.getLatestPlayerWhoJustJoined();
|
||||
const lastestPlayerWhoJustJoined =
|
||||
gdjs.multiplayerMessageManager.getLatestPlayerWhoJustJoined();
|
||||
if (lastestPlayerWhoJustJoined) {
|
||||
const playerUsername = getPlayerUsername(lastestPlayerWhoJustJoined);
|
||||
gdjs.multiplayerComponents.displayPlayerJoinedNotification(
|
||||
@@ -592,8 +624,16 @@ namespace gdjs {
|
||||
logger.error('Malformed message received');
|
||||
return;
|
||||
}
|
||||
|
||||
handlePeerIdEvent({ peerId, compressionMethod });
|
||||
const retryData = { times: 2, delayInMs: 500 };
|
||||
try {
|
||||
gdjs.evtTools.network.retryIfFailed(retryData, async () => {
|
||||
handlePeerIdEvent({ peerId, compressionMethod });
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Handling peerId message from websocket failed (after {${retryData.times}} times with a delay of ${retryData.delayInMs}ms). Not trying anymore.`
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -616,9 +656,8 @@ namespace gdjs {
|
||||
return;
|
||||
}
|
||||
|
||||
const lobbiesIframe = gdjs.multiplayerComponents.getLobbiesIframe(
|
||||
runtimeScene
|
||||
);
|
||||
const lobbiesIframe =
|
||||
gdjs.multiplayerComponents.getLobbiesIframe(runtimeScene);
|
||||
|
||||
if (!lobbiesIframe || !lobbiesIframe.contentWindow) {
|
||||
return;
|
||||
@@ -634,6 +673,17 @@ namespace gdjs {
|
||||
};
|
||||
};
|
||||
|
||||
const onPeerUnavailable = (runtimeScene: gdjs.RuntimeScene) => {
|
||||
gdjs.multiplayerComponents.displayConnectionErrorNotification(
|
||||
runtimeScene
|
||||
);
|
||||
handleLeaveLobbyEvent();
|
||||
_actionAfterJoiningLobby = null;
|
||||
_quickJoinLobbyFailureReason = null;
|
||||
if (_isQuickJoiningOrStartingAGame)
|
||||
onLobbyQuickJoinFinished(runtimeScene);
|
||||
};
|
||||
|
||||
const handleConnectionIdReceived = function ({
|
||||
runtimeScene,
|
||||
connectionId,
|
||||
@@ -679,10 +729,13 @@ namespace gdjs {
|
||||
brokerServerConfig.port,
|
||||
brokerServerConfig.path,
|
||||
brokerServerConfig.key,
|
||||
brokerServerConfig.secure
|
||||
brokerServerConfig.secure,
|
||||
{ onPeerUnavailable: () => onPeerUnavailable(runtimeScene) }
|
||||
);
|
||||
} else {
|
||||
gdjs.multiplayerPeerJsHelper.useDefaultBrokerServer();
|
||||
gdjs.multiplayerPeerJsHelper.useDefaultBrokerServer({
|
||||
onPeerUnavailable: () => onPeerUnavailable(runtimeScene),
|
||||
});
|
||||
}
|
||||
|
||||
_connectionId = connectionId;
|
||||
@@ -690,10 +743,31 @@ namespace gdjs {
|
||||
// We save the lobbyId here as this is the moment when the player is really connected to the lobby.
|
||||
_lobbyId = lobbyId;
|
||||
|
||||
if (_actionAfterJoiningLobby === 'OPEN_LOBBY_PAGE') {
|
||||
openLobbiesWindow(runtimeScene);
|
||||
onLobbyQuickJoinFinished(runtimeScene);
|
||||
return;
|
||||
} else if (_actionAfterJoiningLobby === 'JOIN_GAME') {
|
||||
handleJoinGameMessage();
|
||||
return;
|
||||
} else if (_actionAfterJoiningLobby === 'START_GAME') {
|
||||
const retryData = { times: 2, delayInMs: 500 };
|
||||
try {
|
||||
gdjs.evtTools.network.retryIfFailed(retryData, async () => {
|
||||
sendPeerId();
|
||||
handleStartGameMessage();
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Sending of peerId message from websocket failed (after {${retryData.times}} times with a delay of ${retryData.delayInMs}ms). Not trying anymore.`
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Then we inform the lobbies window that the player has joined.
|
||||
const lobbiesIframe = gdjs.multiplayerComponents.getLobbiesIframe(
|
||||
runtimeScene
|
||||
);
|
||||
const lobbiesIframe =
|
||||
gdjs.multiplayerComponents.getLobbiesIframe(runtimeScene);
|
||||
|
||||
if (!lobbiesIframe || !lobbiesIframe.contentWindow) {
|
||||
logger.error(
|
||||
@@ -742,9 +816,8 @@ namespace gdjs {
|
||||
|
||||
// If the player is in the lobby, tell the lobbies window that the lobby has been updated,
|
||||
// as well as the player position.
|
||||
const lobbiesIframe = gdjs.multiplayerComponents.getLobbiesIframe(
|
||||
runtimeScene
|
||||
);
|
||||
const lobbiesIframe =
|
||||
gdjs.multiplayerComponents.getLobbiesIframe(runtimeScene);
|
||||
|
||||
if (!lobbiesIframe || !lobbiesIframe.contentWindow) {
|
||||
return;
|
||||
@@ -776,9 +849,8 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
// Just pass along the message to the iframe so that it can display the countdown.
|
||||
const lobbiesIframe = gdjs.multiplayerComponents.getLobbiesIframe(
|
||||
runtimeScene
|
||||
);
|
||||
const lobbiesIframe =
|
||||
gdjs.multiplayerComponents.getLobbiesIframe(runtimeScene);
|
||||
|
||||
if (!lobbiesIframe || !lobbiesIframe.contentWindow) {
|
||||
logger.info('The lobbies iframe is not opened, not sending message.');
|
||||
@@ -818,6 +890,8 @@ namespace gdjs {
|
||||
}),
|
||||
dev: isUsingGDevelopDevelopmentEnvironment,
|
||||
});
|
||||
// TODO: if 404, there's chance that it means the lobby is now closed. Display a message
|
||||
// to the player?
|
||||
} catch (error) {
|
||||
logger.error('Error while sending heartbeat, retrying:', error);
|
||||
try {
|
||||
@@ -873,6 +947,8 @@ namespace gdjs {
|
||||
logger.info('Lobby game has started.');
|
||||
// In case we're joining an existing lobby, read the saved messages to catch-up with the game state.
|
||||
gdjs.multiplayerMessageManager.handleSavedUpdateMessages(runtimeScene);
|
||||
if (_isQuickJoiningOrStartingAGame)
|
||||
onLobbyQuickJoinFinished(runtimeScene);
|
||||
_isReadyToSendOrReceiveGameUpdateMessages = true;
|
||||
_hasLobbyGameJustStarted = true;
|
||||
_isLobbyGameRunning = true;
|
||||
@@ -926,7 +1002,7 @@ namespace gdjs {
|
||||
logger.error(
|
||||
'No peerId found, the player does not seem connected to the broker server.'
|
||||
);
|
||||
return;
|
||||
throw new Error('Missing player peerId.');
|
||||
}
|
||||
|
||||
if (currentPeerId === peerId) {
|
||||
@@ -990,10 +1066,15 @@ namespace gdjs {
|
||||
const handleJoinGameMessage = function () {
|
||||
if (!_websocket) {
|
||||
logger.error(
|
||||
'No connection to send the start countdown message. Are you connected to a lobby?'
|
||||
'No connection to send the join game message. Are you connected to a lobby?'
|
||||
);
|
||||
return;
|
||||
}
|
||||
// TODO: When the message is sent, it is expected to then receive a "peerId" message
|
||||
// from the websocket. This "peerId" message might not be sent for different reasons.
|
||||
// Should there be a security that checks if the "peerId" message has been received
|
||||
// in the next 10s or something more global that checks the lobby status after the player
|
||||
// has committed to open a connection with it?
|
||||
|
||||
_websocket.send(
|
||||
JSON.stringify({
|
||||
@@ -1199,13 +1280,15 @@ namespace gdjs {
|
||||
);
|
||||
|
||||
// First look for players who left during the migration.
|
||||
const playerNumbersConnectedBeforeMigration = gdjs.multiplayerMessageManager
|
||||
.getConnectedPlayers()
|
||||
.map((player) => player.playerNumber);
|
||||
const playerNumbersWhoLeftDuringMigration = playerNumbersConnectedBeforeMigration.filter(
|
||||
(playerNumberBeforeMigration) =>
|
||||
!expectedNewOtherPlayerNumbers.includes(playerNumberBeforeMigration)
|
||||
);
|
||||
const playerNumbersConnectedBeforeMigration =
|
||||
gdjs.multiplayerMessageManager
|
||||
.getConnectedPlayers()
|
||||
.map((player) => player.playerNumber);
|
||||
const playerNumbersWhoLeftDuringMigration =
|
||||
playerNumbersConnectedBeforeMigration.filter(
|
||||
(playerNumberBeforeMigration) =>
|
||||
!expectedNewOtherPlayerNumbers.includes(playerNumberBeforeMigration)
|
||||
);
|
||||
playerNumbersWhoLeftDuringMigration.map((playerNumberWhoLeft) => {
|
||||
logger.info(
|
||||
`Player ${playerNumberWhoLeft} left during the host migration. Marking as disconnected.`
|
||||
@@ -1217,13 +1300,14 @@ namespace gdjs {
|
||||
});
|
||||
|
||||
// Then check if all expected players are connected.
|
||||
const playerNumbersWhoDidNotConnect = expectedNewOtherPlayerNumbers.filter(
|
||||
(otherPlayerNumber) =>
|
||||
otherPlayerNumber !== playerNumber && // We don't look for ourselves
|
||||
!gdjs.multiplayerMessageManager.hasReceivedHeartbeatFromPlayer(
|
||||
otherPlayerNumber
|
||||
)
|
||||
);
|
||||
const playerNumbersWhoDidNotConnect =
|
||||
expectedNewOtherPlayerNumbers.filter(
|
||||
(otherPlayerNumber) =>
|
||||
otherPlayerNumber !== playerNumber && // We don't look for ourselves
|
||||
!gdjs.multiplayerMessageManager.hasReceivedHeartbeatFromPlayer(
|
||||
otherPlayerNumber
|
||||
)
|
||||
);
|
||||
|
||||
if (playerNumbersWhoDidNotConnect.length === 0) {
|
||||
logger.info('All expected players are connected. Resuming the game.');
|
||||
@@ -1388,7 +1472,7 @@ namespace gdjs {
|
||||
logger.error(
|
||||
"No peerId found, the player doesn't seem connected to the broker server."
|
||||
);
|
||||
return;
|
||||
throw new Error('Missing player peerId.');
|
||||
}
|
||||
|
||||
_websocket.send(
|
||||
@@ -1433,7 +1517,7 @@ namespace gdjs {
|
||||
if (!event.data.lobbyId) {
|
||||
throw new Error('Malformed message.');
|
||||
}
|
||||
|
||||
_actionAfterJoiningLobby = null;
|
||||
handleJoinLobbyEvent(runtimeScene, event.data.lobbyId);
|
||||
break;
|
||||
}
|
||||
@@ -1469,9 +1553,8 @@ namespace gdjs {
|
||||
};
|
||||
|
||||
const sendSessionInformation = (runtimeScene: gdjs.RuntimeScene) => {
|
||||
const lobbiesIframe = gdjs.multiplayerComponents.getLobbiesIframe(
|
||||
runtimeScene
|
||||
);
|
||||
const lobbiesIframe =
|
||||
gdjs.multiplayerComponents.getLobbiesIframe(runtimeScene);
|
||||
if (!lobbiesIframe || !lobbiesIframe.contentWindow) {
|
||||
// Cannot send the message if the iframe is not opened.
|
||||
return;
|
||||
@@ -1519,6 +1602,159 @@ namespace gdjs {
|
||||
);
|
||||
};
|
||||
|
||||
const onLobbyQuickJoinFinished = (runtimeScene: gdjs.RuntimeScene) => {
|
||||
_isQuickJoiningOrStartingAGame = false;
|
||||
_actionAfterJoiningLobby = null;
|
||||
gdjs.multiplayerComponents.displayLoader(runtimeScene, false);
|
||||
};
|
||||
|
||||
const quickJoinLobby = async (
|
||||
runtimeScene: gdjs.RuntimeScene,
|
||||
displayLoader: boolean,
|
||||
openLobbiesPageIfFailure: boolean
|
||||
) => {
|
||||
if (_isQuickJoiningOrStartingAGame) return;
|
||||
const _gameId = gdjs.projectData.properties.projectUuid;
|
||||
if (!_gameId) {
|
||||
handleLobbiesError(
|
||||
runtimeScene,
|
||||
'The game ID is missing, the quick join lobby action cannot continue.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
_quickJoinLobbyFailureReason = null;
|
||||
_isQuickJoiningOrStartingAGame = true;
|
||||
if (displayLoader) {
|
||||
gdjs.multiplayerComponents.displayLoader(runtimeScene, true);
|
||||
}
|
||||
|
||||
const quickJoinLobbyRelativeUrl = `/play/game/${_gameId}/public-lobby/action/quick-join`;
|
||||
const platformInfo = runtimeScene.getGame().getPlatformInfo();
|
||||
|
||||
try {
|
||||
const quickJoinLobbyResponse: QuickJoinLobbyResponse =
|
||||
await gdjs.evtTools.network.retryIfFailed({ times: 2 }, () =>
|
||||
fetchAsPlayer({
|
||||
relativeUrl: quickJoinLobbyRelativeUrl,
|
||||
method: 'POST',
|
||||
dev: isUsingGDevelopDevelopmentEnvironment,
|
||||
body: JSON.stringify({
|
||||
isPreview: runtimeScene.getGame().isPreview(),
|
||||
gameVersion: runtimeScene.getGame().getGameData().properties
|
||||
.version,
|
||||
supportedCompressionMethods:
|
||||
platformInfo.supportedCompressionMethods,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
if (
|
||||
quickJoinLobbyResponse.status === 'full' ||
|
||||
quickJoinLobbyResponse.status === 'not-enough-players'
|
||||
) {
|
||||
_quickJoinLobbyJustFailed = true;
|
||||
_quickJoinLobbyFailureReason =
|
||||
quickJoinLobbyResponse.status === 'full'
|
||||
? 'FULL'
|
||||
: 'NOT_ENOUGH_PLAYERS';
|
||||
onLobbyQuickJoinFinished(runtimeScene);
|
||||
if (openLobbiesPageIfFailure) {
|
||||
openLobbiesWindow(runtimeScene);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (quickJoinLobbyResponse.status === 'join-game') {
|
||||
if (quickJoinLobbyResponse.lobby.status === 'waiting') {
|
||||
_actionAfterJoiningLobby = 'START_GAME';
|
||||
} else if (quickJoinLobbyResponse.lobby.status === 'playing') {
|
||||
_actionAfterJoiningLobby = 'JOIN_GAME';
|
||||
} else {
|
||||
throw new Error(
|
||||
`Lobby in wrong status: ${quickJoinLobbyResponse.status}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (_connectionId) {
|
||||
// Already connected to a lobby.
|
||||
onLobbyQuickJoinFinished(runtimeScene);
|
||||
openLobbiesWindow(runtimeScene);
|
||||
return;
|
||||
} else {
|
||||
_actionAfterJoiningLobby = 'OPEN_LOBBY_PAGE';
|
||||
}
|
||||
}
|
||||
handleJoinLobbyEvent(runtimeScene, quickJoinLobbyResponse.lobby.id);
|
||||
} catch (error) {
|
||||
logger.error('An error occurred while joining a lobby:', error);
|
||||
_quickJoinLobbyJustFailed = true;
|
||||
_quickJoinLobbyFailureReason = 'UNKNOWN';
|
||||
onLobbyQuickJoinFinished(runtimeScene);
|
||||
if (openLobbiesPageIfFailure) {
|
||||
openLobbiesWindow(runtimeScene);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const authenticateAndQuickJoinLobby = async (
|
||||
runtimeScene: gdjs.RuntimeScene,
|
||||
displayLoader: boolean,
|
||||
openLobbiesPageIfFailure: boolean
|
||||
) => {
|
||||
const requestDoneAt = Date.now();
|
||||
if (_lastQuickJoinRequestDoneAt) {
|
||||
if (requestDoneAt - _lastQuickJoinRequestDoneAt < 500) {
|
||||
_lastQuickJoinRequestDoneAt = requestDoneAt;
|
||||
logger.warn(
|
||||
'Last request to quick join a lobby was sent too little time ago. Ignoring this one.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
_lastQuickJoinRequestDoneAt = requestDoneAt;
|
||||
}
|
||||
|
||||
const playerId = gdjs.playerAuthentication.getUserId();
|
||||
const playerToken = gdjs.playerAuthentication.getUserToken();
|
||||
if (!playerId || !playerToken) {
|
||||
_isWaitingForLogin = true;
|
||||
const { status } =
|
||||
await gdjs.playerAuthentication.openAuthenticationWindow(runtimeScene)
|
||||
.promise;
|
||||
_isWaitingForLogin = false;
|
||||
|
||||
if (status === 'logged') {
|
||||
await quickJoinLobby(
|
||||
runtimeScene,
|
||||
displayLoader,
|
||||
openLobbiesPageIfFailure
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
await quickJoinLobby(
|
||||
runtimeScene,
|
||||
displayLoader,
|
||||
openLobbiesPageIfFailure
|
||||
);
|
||||
};
|
||||
|
||||
export const isSearchingForLobbyToJoin = (
|
||||
runtimeScene: gdjs.RuntimeScene
|
||||
) => {
|
||||
return _isQuickJoiningOrStartingAGame;
|
||||
};
|
||||
|
||||
export const hasQuickJoinJustFailed = (runtimeScene: gdjs.RuntimeScene) => {
|
||||
return _quickJoinLobbyJustFailed;
|
||||
};
|
||||
|
||||
export const getQuickJoinFailureReason = () => {
|
||||
return _quickJoinLobbyFailureReason;
|
||||
};
|
||||
|
||||
/**
|
||||
* Action to display the lobbies window to the user.
|
||||
*/
|
||||
@@ -1567,11 +1803,9 @@ namespace gdjs {
|
||||
const playerToken = gdjs.playerAuthentication.getUserToken();
|
||||
if (!playerId || !playerToken) {
|
||||
_isWaitingForLogin = true;
|
||||
const {
|
||||
status,
|
||||
} = await gdjs.playerAuthentication.openAuthenticationWindow(
|
||||
runtimeScene
|
||||
).promise;
|
||||
const { status } =
|
||||
await gdjs.playerAuthentication.openAuthenticationWindow(runtimeScene)
|
||||
.promise;
|
||||
_isWaitingForLogin = false;
|
||||
|
||||
if (status === 'logged') {
|
||||
@@ -1640,9 +1874,8 @@ namespace gdjs {
|
||||
export const isLobbiesWindowOpen = function (
|
||||
runtimeScene: gdjs.RuntimeScene
|
||||
): boolean {
|
||||
const lobbiesRootContainer = gdjs.multiplayerComponents.getLobbiesRootContainer(
|
||||
runtimeScene
|
||||
);
|
||||
const lobbiesRootContainer =
|
||||
gdjs.multiplayerComponents.getLobbiesRootContainer(runtimeScene);
|
||||
return !!lobbiesRootContainer;
|
||||
};
|
||||
|
||||
|
@@ -11,6 +11,10 @@ namespace gdjs {
|
||||
data: Uint8Array | string;
|
||||
};
|
||||
|
||||
type PeerJSInitOptions = {
|
||||
onPeerUnavailable?: () => void;
|
||||
};
|
||||
|
||||
export type CompressionMethod = 'none' | 'cs:gzip' | 'cs:deflate';
|
||||
|
||||
/**
|
||||
@@ -100,6 +104,8 @@ namespace gdjs {
|
||||
*/
|
||||
let ready = false;
|
||||
|
||||
let _peerIdToConnectToOnceReady: string | null = null;
|
||||
|
||||
/**
|
||||
* List of IDs of peers that just disconnected.
|
||||
*/
|
||||
@@ -228,6 +234,14 @@ namespace gdjs {
|
||||
return newMessagesList;
|
||||
};
|
||||
|
||||
const _onReady = () => {
|
||||
ready = true;
|
||||
if (_peerIdToConnectToOnceReady) {
|
||||
connect(_peerIdToConnectToOnceReady);
|
||||
_peerIdToConnectToOnceReady = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal function called when a connection with a remote peer is initiated.
|
||||
* @param connection The DataConnection of the peer
|
||||
@@ -289,14 +303,28 @@ namespace gdjs {
|
||||
* Internal function called to initialize PeerJS after it
|
||||
* has been configured.
|
||||
*/
|
||||
const loadPeerJS = () => {
|
||||
const initializePeerJS = (initOptions: PeerJSInitOptions = {}) => {
|
||||
if (peer !== null) return;
|
||||
peer = new Peer(peerConfig);
|
||||
peer.on('open', () => {
|
||||
ready = true;
|
||||
_onReady();
|
||||
});
|
||||
peer.on('error', (errorMessage) => {
|
||||
logger.error('PeerJS error:', errorMessage);
|
||||
peer.on('error', (error) => {
|
||||
// TODO: Support other error types listed in https://peerjs.com/docs/#peeron-error
|
||||
if (
|
||||
initOptions.onPeerUnavailable &&
|
||||
// @ts-ignore - PeerJS adds `type` on errors, but it doesn't show in their TS types.
|
||||
error.type === 'peer-unavailable'
|
||||
) {
|
||||
logger.error('Peer is unavailable.');
|
||||
initOptions.onPeerUnavailable();
|
||||
} else {
|
||||
logger.error(
|
||||
// @ts-ignore - PeerJS adds `type` on errors, but it doesn't show in their TS types.
|
||||
`PeerJS error (${error.type || 'unknown'}):`,
|
||||
error
|
||||
);
|
||||
}
|
||||
});
|
||||
peer.on('connection', (connection) => {
|
||||
connection.on('open', () => {
|
||||
@@ -306,17 +334,21 @@ namespace gdjs {
|
||||
});
|
||||
peer.on('close', () => {
|
||||
peer = null;
|
||||
loadPeerJS();
|
||||
initializePeerJS(initOptions);
|
||||
});
|
||||
peer.on('disconnected', peer.reconnect);
|
||||
};
|
||||
export const useDefaultBrokerServer = initializePeerJS;
|
||||
|
||||
/**
|
||||
* Connects to another p2p client.
|
||||
* @param id - The other client's ID.
|
||||
*/
|
||||
export const connect = (id: string) => {
|
||||
if (peer === null) return;
|
||||
if (peer === null || !ready) {
|
||||
_peerIdToConnectToOnceReady = id;
|
||||
return;
|
||||
}
|
||||
const connection = peer.connect(id);
|
||||
connection.on('open', () => {
|
||||
_onConnect(connection);
|
||||
@@ -365,13 +397,15 @@ namespace gdjs {
|
||||
* @param path The path (part of the url after the host) to the broker server.
|
||||
* @param key Optional password to connect to the broker server.
|
||||
* @param ssl Use ssl?
|
||||
* @param peerJSInitOptions @see PeerJSInitOptions
|
||||
*/
|
||||
export const useCustomBrokerServer = (
|
||||
host: string,
|
||||
port: number,
|
||||
path: string,
|
||||
key: string,
|
||||
ssl: boolean
|
||||
ssl: boolean,
|
||||
peerJSInitOptions: PeerJSInitOptions = {}
|
||||
) => {
|
||||
Object.assign(peerConfig, {
|
||||
host,
|
||||
@@ -381,11 +415,9 @@ namespace gdjs {
|
||||
// All servers have "peerjs" as default key
|
||||
key: key.length === 0 ? 'peerjs' : key,
|
||||
});
|
||||
loadPeerJS();
|
||||
initializePeerJS(peerJSInitOptions);
|
||||
};
|
||||
|
||||
export const useDefaultBrokerServer = loadPeerJS;
|
||||
|
||||
/**
|
||||
* Adds an ICE server candidate, and removes the default ones provided by PeerJs. Must be called before connecting to a broker.
|
||||
* @param urls The URL of the STUN/TURN server.
|
||||
@@ -422,8 +454,8 @@ namespace gdjs {
|
||||
* @see Peer.id
|
||||
*/
|
||||
export const getCurrentId = (): string => {
|
||||
if (peer == undefined) return '';
|
||||
return peer.id || '';
|
||||
if (peer === null) return '';
|
||||
return peer.id;
|
||||
};
|
||||
|
||||
/**
|
||||
|
18
Extensions/Multiplayer/peerjs.d.ts
vendored
18
Extensions/Multiplayer/peerjs.d.ts
vendored
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
declare class EventEmitter<
|
||||
EventTypes extends EventEmitter.ValidEventTypes = string | symbol,
|
||||
Context extends any = any
|
||||
Context extends any = any,
|
||||
> {
|
||||
static prefixed: string | boolean;
|
||||
|
||||
@@ -87,7 +87,7 @@ declare namespace EventEmitter {
|
||||
export interface EventEmitterStatic {
|
||||
new <
|
||||
EventTypes extends ValidEventTypes = string | symbol,
|
||||
Context = any
|
||||
Context = any,
|
||||
>(): EventEmitter<EventTypes, Context>;
|
||||
}
|
||||
|
||||
@@ -110,13 +110,13 @@ declare namespace EventEmitter {
|
||||
[K in keyof T]: T[K] extends (...args: any[]) => void
|
||||
? Parameters<T[K]>
|
||||
: T[K] extends any[]
|
||||
? T[K]
|
||||
: any[];
|
||||
? T[K]
|
||||
: any[];
|
||||
};
|
||||
|
||||
export type EventListener<
|
||||
T extends ValidEventTypes,
|
||||
K extends EventNames<T>
|
||||
K extends EventNames<T>,
|
||||
> = T extends string | symbol
|
||||
? (...args: any[]) => void
|
||||
: (
|
||||
@@ -125,7 +125,7 @@ declare namespace EventEmitter {
|
||||
|
||||
export type EventArgs<
|
||||
T extends ValidEventTypes,
|
||||
K extends EventNames<T>
|
||||
K extends EventNames<T>,
|
||||
> = Parameters<EventListener<T, K>>;
|
||||
|
||||
export const EventEmitter: EventEmitterStatic;
|
||||
@@ -170,9 +170,7 @@ declare namespace Peer {
|
||||
validateId(id: string): boolean;
|
||||
pack: any;
|
||||
unpack: any;
|
||||
chunk(
|
||||
blob: Blob
|
||||
): {
|
||||
chunk(blob: Blob): {
|
||||
__peerData: number;
|
||||
n: number;
|
||||
total: number;
|
||||
@@ -267,7 +265,7 @@ declare namespace Peer {
|
||||
};
|
||||
abstract class BaseConnection<
|
||||
T extends EventEmitter.ValidEventTypes,
|
||||
TT
|
||||
TT,
|
||||
> extends EventEmitter<T & BaseConnectionEvents> {
|
||||
readonly peer: string;
|
||||
provider: Peer<TT>;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user