Compare commits

..

3 Commits

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

View File

@@ -301,13 +301,7 @@ workflows:
- build-gdevelop_js-wasm-only
gdevelop_js-wasm-extra-checks:
jobs:
- build-gdevelop_js-debug-sanitizers-and-extra-checks:
# Extra checks are resource intensive so don't all run them.
filters:
branches:
only:
- master
- /experimental-build.*/
- build-gdevelop_js-debug-sanitizers-and-extra-checks
builds:
jobs:
- build-macos:

View File

@@ -255,6 +255,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Angle"),
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angular speed (in degrees per second)"))
.AddCodeOnlyParameter("currentScene", "")
@@ -268,6 +269,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Angle"),
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle to rotate towards (in degrees)"))
.AddParameter("expression", _("Angular speed (in degrees per second)"))
@@ -283,6 +285,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Angle"),
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
@@ -301,12 +304,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/force24.png",
"res/actions/force.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Speed on X axis (in pixels per second)"))
.AddParameter("expression", _("Speed on Y axis (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.SetHelpPath("/tutorials/how-to-move-objects/");
.SetDefaultValue("0");
obj.AddAction("AddForceAL",
_("Add a force (angle)"),
@@ -318,12 +321,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/force24.png",
"res/actions/force.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle"))
.AddParameter("expression", _("Speed (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddAction(
@@ -336,13 +339,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/force24.png",
"res/actions/force.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
.AddParameter("expression", _("Speed (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddAction(
@@ -357,13 +360,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/forceTourne24.png",
"res/actions/forceTourne.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", "X position of the center")
.AddParameter("expression", "Y position of the center")
.AddParameter("expression", "Speed (in Degrees per seconds)")
.AddParameter("expression", "Distance (in pixels)")
.AddParameter("forceMultiplier", "Force multiplier")
.SetHelpPath("/tutorials/how-to-move-objects/")
.SetHidden();
obj.AddAction("Arreter",
@@ -373,8 +376,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/arreter24.png",
"res/actions/arreter.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddAction("Delete",
@@ -426,7 +429,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddAction("SetStringObjectVariable",
@@ -441,7 +443,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddAction("SetBooleanObjectVariable",
@@ -457,7 +458,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
// This parameter allows to keep the operand expression
// when the editor switch between variable instructions.
.AddCodeOnlyParameter("yesorno", _("Value"))
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddCondition("NumberObjectVariable",
@@ -472,7 +472,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddCondition("StringObjectVariable",
@@ -487,7 +486,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddCondition("BooleanObjectVariable",
@@ -504,7 +502,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
// This parameter allows to keep the operand expression
// when the editor switch between variable instructions.
.AddCodeOnlyParameter("yesorno", _("Value"))
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForLayoutEventsOnly();
obj.AddAction("ModVarObjet",
@@ -517,7 +514,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.SetHelpPath("/all-features/variables/object-variables/")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly();
@@ -532,7 +528,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.SetHelpPath("/all-features/variables/object-variables/")
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly();
@@ -549,7 +544,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.AddParameter("trueorfalse", _("New Value:"))
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddAction(
@@ -566,7 +560,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddCondition("ObjectVariableChildExists",
@@ -580,7 +573,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Structure variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddAction("ObjectVariableRemoveChild",
@@ -593,7 +585,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddAction("ObjectVariableClearChildren",
@@ -606,7 +597,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array or structure variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddAction("Cache",
@@ -701,8 +691,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/conditions/arret24.png",
"res/conditions/arret.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddCondition("Vitesse",
@@ -712,10 +702,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/conditions/vitesse24.png",
"res/conditions/vitesse.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
// Deprecated
@@ -732,7 +722,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Tolerance, in degrees"))
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddCondition("IsTotalForceAngleAround",
@@ -746,7 +735,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Tolerance, in degrees"))
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddCondition("VarObjet",
@@ -761,7 +749,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddCondition("VarObjetTxt",
@@ -776,7 +763,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddCondition("ObjectVariableAsBoolean",
@@ -791,7 +777,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.AddParameter("trueorfalse", _("Check if the value is"))
.SetDefaultValue("true")
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddCondition("VarObjetDef",
@@ -817,7 +802,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForLayoutEventsOnly();
@@ -831,7 +815,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForLayoutEventsOnly();
@@ -846,7 +829,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForLayoutEventsOnly();
@@ -865,7 +847,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.SetParameterLongDescription(_("The content of the object variable will "
"*be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetHidden();
@@ -883,7 +864,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.SetParameterLongDescription(_("The content of the object variable will "
"*be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddAction(
@@ -897,7 +877,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly();
@@ -911,7 +890,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly();
@@ -926,7 +904,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly();
@@ -943,7 +920,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddCondition(
@@ -958,7 +934,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
obj.AddStrExpression(
@@ -969,8 +944,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("objectvar", _("Array variable"));
obj.AddExpression(
"ArrayVariableFirstNumber",
@@ -980,8 +954,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("objectvar", _("Array variable"));
obj.AddStrExpression(
"ArrayVariableLastString",
@@ -991,8 +964,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("objectvar", _("Array variable"));
obj.AddExpression(
"ArrayVariableLastNumber",
@@ -1002,8 +974,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("objectvar", _("Array variable"));
obj.AddCondition("BehaviorActivated",
_("Behavior activated"),
@@ -1038,12 +1009,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/forceVers24.png",
"res/actions/forceVers.png")
.AddParameter("object", _("Object"))
.AddParameter("objectPtr", _("Target Object"))
.AddParameter("expression", _("Speed (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddAction(
@@ -1058,13 +1029,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/forceTourne24.png",
"res/actions/forceTourne.png")
.AddParameter("object", _("Object"))
.AddParameter("objectPtr", _("Rotate around this object"))
.AddParameter("expression", _("Speed (in degrees per second)"))
.AddParameter("expression", _("Distance (in pixels)"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
obj.AddAction("MettreAutour",
@@ -1092,10 +1063,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/ecarter24.png",
"res/actions/ecarter.png")
.SetHidden()
.AddParameter("object", _("Object"))
.AddParameter("objectList", "Object 2 (won't move)")
.SetHelpPath("/tutorials/how-to-move-objects/");
.AddParameter("objectList", "Object 2 (won't move)");
// Deprecated action
obj.AddAction("Ecarter",
@@ -1119,6 +1090,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Position"),
"res/actions/ecarter24.png",
"res/actions/ecarter.png")
.AddParameter("object", _("Object"))
.AddParameter("objectList", _("Objects (won't move)"))
.AddParameter("yesorno",
@@ -1127,7 +1099,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"",
true)
.SetDefaultValue("no")
.SetHelpPath("/all-features/collisions/")
.MarkAsSimple();
obj.AddCondition("CollisionPoint",
@@ -1140,7 +1111,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("expression", _("X position of the point"))
.AddParameter("expression", _("Y position of the point"))
.SetHelpPath("/all-features/collisions/")
.MarkAsSimple();
extension
@@ -1172,7 +1142,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.AddParameter("expression", _("Time in seconds"))
.SetHelpPath("/all-features/timers-and-time/")
.SetHidden();
obj.AddCondition(
@@ -1188,7 +1157,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.AddParameter("relationalOperator", _("Sign of the test"), "time")
.AddParameter("expression", _("Time in seconds"))
.SetHelpPath("/all-features/timers-and-time/")
.SetManipulatedType("number");
obj.AddCondition("ObjectTimerPaused",
@@ -1200,7 +1168,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/timerPaused.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/")
.MarkAsAdvanced();
obj.AddAction(
@@ -1213,8 +1180,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/timer24.png",
"res/actions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/");
.AddParameter("identifier", _("Timer's name"), "objectTimer");
obj.AddAction("PauseObjectTimer",
_("Pause an object timer"),
@@ -1225,7 +1191,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/pauseTimer.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/")
.MarkAsAdvanced();
obj.AddAction("UnPauseObjectTimer",
@@ -1237,7 +1202,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/unPauseTimer.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/")
.MarkAsAdvanced();
obj.AddAction("RemoveObjectTimer",
@@ -1249,7 +1213,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/")
.MarkAsAdvanced();
obj.AddExpression("X",
@@ -1278,32 +1241,28 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("X coordinate of the sum of forces"),
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/");
.AddParameter("object", _("Object"));
obj.AddExpression("ForceY",
_("Y coordinate of the sum of forces"),
_("Y coordinate of the sum of forces"),
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/");
.AddParameter("object", _("Object"));
obj.AddExpression("ForceAngle",
_("Angle of the sum of forces"),
_("Angle of the sum of forces (in degrees)"),
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/");
.AddParameter("object", _("Object"));
obj.AddExpression("ForceLength",
_("Length of the sum of forces"),
_("Length of the sum of forces"),
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/");
.AddParameter("object", _("Object"));
obj.AddExpression("Longueur",
_("Length of the sum of forces"),
@@ -1311,7 +1270,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"))
.SetHelpPath("/tutorials/how-to-move-objects/")
.SetHidden();
obj.AddExpression("Width",
@@ -1411,8 +1369,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array or structure variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("objectvar", _("Array or structure variable"));
obj.AddStrExpression("VariableString",
_("Text variable"),
@@ -1421,7 +1378,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.SetHelpPath("/all-features/variables/object-variables/")
.SetRelevantForFunctionEventsOnly();
obj.AddExpression("ObjectTimerElapsedTime",
@@ -1430,8 +1386,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Timers"),
"res/actions/time.png")
.AddParameter("object", _("Object"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.SetHelpPath("/all-features/timers-and-time/");
.AddParameter("identifier", _("Timer's name"), "objectTimer");
obj.AddExpression("AngleToObject",
_("Angle between two objects"),
@@ -1651,7 +1606,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/doMove24.png",
"res/actions/doMove.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
extension
@@ -1667,7 +1621,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectList", _("Object 2"))
.AddParameter("expression", _("Tolerance, in degrees"))
.AddCodeOnlyParameter("conditionInverted", "")
.SetHelpPath("/tutorials/how-to-move-objects/")
.MarkAsAdvanced();
extension
@@ -1800,7 +1753,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"",
true)
.SetDefaultValue("no")
.SetHelpPath("/all-features/collisions/")
.MarkAsSimple();
extension
@@ -1863,7 +1815,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Scene variable where to store the Y position of the intersection. "
"If no intersection is found, the variable won't be changed."))
.AddCodeOnlyParameter("conditionInverted", "")
.SetHelpPath("/all-features/collisions/")
.MarkAsAdvanced();
extension
@@ -1895,7 +1846,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Scene variable where to store the Y position of the intersection. "
"If no intersection is found, the variable won't be changed."))
.AddCodeOnlyParameter("conditionInverted", "")
.SetHelpPath("/all-features/collisions/")
.MarkAsAdvanced();
extension

View File

@@ -92,16 +92,14 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
extension
.AddCondition("Once",
_("Trigger once while true"),
_("Run actions only once, for each time the conditions "
"have been met."),
_("Trigger once"),
"",
"res/conditions/once24.png",
"res/conditions/once.png")
.SetHelpPath("/all-features/advanced-conditions/trigger-once");
extension.AddCondition(
"Once",
_("Trigger once while true"),
_("Run actions only once, for each time the conditions have been met."),
_("Trigger once"),
"",
"res/conditions/once24.png",
"res/conditions/once.png");
extension
.AddCondition("CompareNumbers",

View File

@@ -116,7 +116,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.AddParameter("variable", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -130,7 +129,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/conditions/var.png")
.AddParameter("variable", _("Variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -144,7 +142,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("variable", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -157,7 +154,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Structure or array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -174,7 +170,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -188,7 +183,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -201,7 +195,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -214,7 +207,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -229,7 +221,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
@@ -240,8 +231,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"it is a text (string)."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("variable", _("Array variable"));
extension
.AddExpression(
@@ -251,8 +241,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"it is a number."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("variable", _("Array variable"));
extension
.AddStrExpression(
@@ -262,8 +251,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"it is a text (string)."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("variable", _("Array variable"));
extension
.AddExpression(
@@ -273,8 +261,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"it is a number."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("variable", _("Array variable"));
// Legacy instructions
@@ -329,7 +316,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -344,7 +330,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -532,7 +517,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("scenevar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly();
@@ -547,7 +531,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("globalvar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly();
@@ -561,7 +544,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Structure or array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -575,7 +557,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Structure or array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -593,7 +574,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -608,7 +588,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -622,7 +601,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -636,7 +614,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -652,7 +629,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -668,7 +644,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.AddParameter("scenevar", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -681,7 +656,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly();
extension
@@ -693,7 +667,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly();
extension
@@ -705,7 +678,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly();
extension
@@ -717,7 +689,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("External variables/Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly();
extension
@@ -734,7 +705,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -750,7 +720,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -765,7 +734,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -779,7 +747,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -793,7 +760,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -809,7 +775,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.AddParameter("globalvar", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -821,7 +786,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("External variables/Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly();
extension
@@ -832,7 +796,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("External variables/Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly();
extension
@@ -844,7 +807,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("External variables/Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly();
extension
@@ -866,7 +828,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("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();
extension
@@ -876,8 +837,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"structure variable"),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array or structure variable"), "AllowUndeclaredVariable")
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("variable", _("Array or structure variable"), "AllowUndeclaredVariable");
extension
.AddExpression("Variable",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -26,8 +26,7 @@ PanelSpriteObject::PanelSpriteObject()
leftMargin(0),
topMargin(0),
rightMargin(0),
bottomMargin(0),
tiled(false) {}
bottomMargin(0) {}
PanelSpriteObject::~PanelSpriteObject() {}

View File

@@ -341,7 +341,7 @@ namespace gdjs {
*/
_currentContacts: Array<Physics3DRuntimeBehavior> = [];
private _destroyedDuringFrameLogic: boolean = false;
private _destroyedDuringFrameLogic: boolean;
_body: Jolt.Body | null = null;
/**
* When set to `true` the body will be recreated before the next physics step.
@@ -402,6 +402,7 @@ namespace gdjs {
this.gravityScale = behaviorData.gravityScale;
this.layers = behaviorData.layers;
this.masks = behaviorData.masks;
this._destroyedDuringFrameLogic = false;
this._sharedData = Physics3DSharedData.getSharedData(
instanceContainer.getScene(),
behaviorData.name
@@ -613,7 +614,11 @@ namespace gdjs {
onDeActivate() {
this._sharedData.removeFromBehaviorsList(this);
this.bodyUpdater.destroyBody();
if (this._body !== null) {
this._sharedData.bodyInterface.RemoveBody(this._body.GetID());
this._sharedData.bodyInterface.DestroyBody(this._body.GetID());
this._body = null;
}
this._contactsEndedThisFrame.length = 0;
this._contactsStartedThisFrame.length = 0;
this._currentContacts.length = 0;
@@ -789,10 +794,6 @@ namespace gdjs {
if (!this.activated() || this._destroyedDuringFrameLogic) return false;
this._body = this.bodyUpdater.createAndAddBody();
if (!this._body) {
// It can only happen when the character behavior is destroyed.
return false;
}
this._body.gdjsAssociatedBehavior = this;
this._objectOldWidth = this.owner3D.getWidth();
@@ -1761,11 +1762,10 @@ namespace gdjs {
}
export interface BodyUpdater {
createAndAddBody(): Jolt.Body | null;
createAndAddBody(): Jolt.Body;
updateObjectFromBody(): void;
updateBodyFromObject(): void;
recreateShape(): void;
destroyBody(): void;
}
export class DefaultBodyUpdater {
@@ -1775,7 +1775,7 @@ namespace gdjs {
this.behavior = behavior;
}
createAndAddBody(): Jolt.Body | null {
createAndAddBody(): Jolt.Body {
const { behavior } = this;
const { _sharedData } = behavior;
@@ -1868,16 +1868,6 @@ namespace gdjs {
Jolt.EActivation_Activate
);
}
destroyBody() {
const { behavior } = this;
const { _sharedData } = behavior;
if (behavior._body !== null) {
_sharedData.bodyInterface.RemoveBody(behavior._body.GetID());
_sharedData.bodyInterface.DestroyBody(behavior._body.GetID());
behavior._body = null;
}
}
}
export interface CollisionChecker {

View File

@@ -54,7 +54,6 @@ namespace gdjs {
*/
_sharedData: gdjs.Physics3DSharedData;
collisionChecker: gdjs.PhysicsCharacter3DRuntimeBehavior.CharacterCollisionChecker;
private _destroyedDuringFrameLogic: boolean = false;
// TODO Should there be angle were the character can climb but will slip?
_slopeMaxAngle: float;
@@ -113,9 +112,6 @@ namespace gdjs {
*/
private static readonly epsilon = 2 ** -20;
/** Handle collisions between characters that can push each other. */
charactersManager: gdjs.PhysicsCharacter3DRuntimeBehavior.CharactersManager;
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
behaviorData,
@@ -131,9 +127,6 @@ namespace gdjs {
this.collisionChecker = new gdjs.PhysicsCharacter3DRuntimeBehavior.CharacterCollisionChecker(
this
);
this.charactersManager = gdjs.PhysicsCharacter3DRuntimeBehavior.CharactersManager.getManager(
instanceContainer
);
this._slopeMaxAngle = 0;
this.setSlopeMaxAngle(behaviorData.slopeMaxAngle);
@@ -165,10 +158,7 @@ namespace gdjs {
return tempVec3;
}
getPhysics3D(): Physics3D | null {
if (this._destroyedDuringFrameLogic) {
return null;
}
getPhysics3D(): Physics3D {
if (this._physics3D) {
return this._physics3D;
}
@@ -328,12 +318,7 @@ namespace gdjs {
}
getPhysicsPosition(result: Jolt.RVec3): Jolt.RVec3 {
const physics3D = this.getPhysics3D();
if (!physics3D) {
result.Set(0, 0, 0);
return result;
}
const { behavior } = physics3D;
const { behavior } = this.getPhysics3D();
// The character origin is at its feet:
// - the center is used for X and Y because Box3D origin is at the top-left corner
// - the origin is used for Z because, when the character is made smaller,
@@ -363,11 +348,7 @@ namespace gdjs {
}
moveObjectToPhysicsPosition(physicsPosition: Jolt.RVec3): void {
const physics3D = this.getPhysics3D();
if (!physics3D) {
return;
}
const { behavior } = physics3D;
const { behavior } = this.getPhysics3D();
this.owner3D.setCenterXInScene(
physicsPosition.GetX() * this._sharedData.worldScale
);
@@ -400,45 +381,7 @@ namespace gdjs {
onActivate() {}
onDestroy() {
this._destroyedDuringFrameLogic = true;
this.onDeActivate();
this._destroyCharacter();
}
/**
* Remove the character and its body from the physics engine.
* This method is called when:
* - The Physics3D behavior is deactivated
* - The object is destroyed
*
* Only deactivating the character behavior won't destroy the character.
* Indeed, deactivated characters don't move as characters but still have collisions.
*/
_destroyCharacter() {
if (this.character) {
if (this._canBePushed) {
this.charactersManager.removeCharacter(this.character);
}
// The body is destroyed with the character.
Jolt.destroy(this.character);
this.character = null;
if (this._physics3D) {
this._physics3D.behavior._body = null;
const {
extendedUpdateSettings,
broadPhaseLayerFilter,
objectLayerFilter,
bodyFilter,
shapeFilter,
} = this._physics3D;
Jolt.destroy(extendedUpdateSettings);
Jolt.destroy(broadPhaseLayerFilter);
Jolt.destroy(objectLayerFilter);
Jolt.destroy(bodyFilter);
Jolt.destroy(shapeFilter);
this._physics3D = null;
}
}
}
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
@@ -447,13 +390,6 @@ namespace gdjs {
}
doBeforePhysicsStep(timeDelta: float): void {
if (!this.activated()) {
return;
}
const physics3D = this.getPhysics3D();
if (!physics3D) {
return;
}
const {
behavior,
extendedUpdateSettings,
@@ -461,7 +397,7 @@ namespace gdjs {
objectLayerFilter,
bodyFilter,
shapeFilter,
} = physics3D;
} = this.getPhysics3D();
if (!this.character) {
return;
}
@@ -893,13 +829,8 @@ namespace gdjs {
}
setStairHeightMax(stairHeightMax: float): void {
const { extendedUpdateSettings } = this.getPhysics3D();
this._stairHeightMax = stairHeightMax;
const physics3D = this.getPhysics3D();
if (!physics3D) {
return;
}
const { extendedUpdateSettings } = physics3D;
const walkStairsStepUp = stairHeightMax * this._sharedData.worldInvScale;
extendedUpdateSettings.mWalkStairsStepUp = this.getVec3(
0,
@@ -1424,74 +1355,18 @@ namespace gdjs {
);
export namespace PhysicsCharacter3DRuntimeBehavior {
/**
* Handle collisions between characters that can push each other.
*/
export class CharactersManager {
/** Handle collisions between characters that can push each other. */
private characterVsCharacterCollision: Jolt.CharacterVsCharacterCollisionSimple;
constructor(instanceContainer: gdjs.RuntimeInstanceContainer) {
this.characterVsCharacterCollision = new Jolt.CharacterVsCharacterCollisionSimple();
}
/**
* Get the characters manager of an instance container.
*/
static getManager(instanceContainer: gdjs.RuntimeInstanceContainer) {
// @ts-ignore
if (!instanceContainer.charactersManager) {
//Create the shared manager if necessary.
// @ts-ignore
instanceContainer.charactersManager = new gdjs.PhysicsCharacter3DRuntimeBehavior.CharactersManager(
instanceContainer
);
}
// @ts-ignore
return instanceContainer.charactersManager;
}
/**
* Add a character to the list of characters that can push each other.
*/
addCharacter(character: Jolt.CharacterVirtual) {
this.characterVsCharacterCollision.Add(character);
character.SetCharacterVsCharacterCollision(
this.characterVsCharacterCollision
);
}
/**
* Remove a character from the list of characters that can push each other.
*/
removeCharacter(character: Jolt.CharacterVirtual) {
this.characterVsCharacterCollision.Remove(character);
}
destroy() {
Jolt.destroy(this.characterVsCharacterCollision);
}
}
gdjs.registerRuntimeSceneUnloadedCallback(function (runtimeScene) {
gdjs.PhysicsCharacter3DRuntimeBehavior.CharactersManager.getManager(
runtimeScene
).destroy();
});
export class CharacterBodyUpdater {
characterBehavior: gdjs.PhysicsCharacter3DRuntimeBehavior;
/** Handle collisions between characters that can push each other. */
static characterVsCharacterCollision: Jolt.CharacterVsCharacterCollisionSimple | null = null;
constructor(characterBehavior: gdjs.PhysicsCharacter3DRuntimeBehavior) {
this.characterBehavior = characterBehavior;
}
createAndAddBody(): Jolt.Body | null {
const physics3D = this.characterBehavior.getPhysics3D();
if (!physics3D) {
return null;
}
const { behavior } = physics3D;
createAndAddBody(): Jolt.Body {
const { _slopeMaxAngle, owner3D, _sharedData } = this.characterBehavior;
const { behavior } = this.characterBehavior.getPhysics3D();
const shape = behavior.createShape();
@@ -1545,7 +1420,16 @@ namespace gdjs {
if (this.characterBehavior._canBePushed) {
// CharacterVsCharacterCollisionSimple handle characters pushing each other.
this.characterBehavior.charactersManager.addCharacter(character);
let characterVsCharacterCollision =
CharacterBodyUpdater.characterVsCharacterCollision;
if (!characterVsCharacterCollision) {
characterVsCharacterCollision = new Jolt.CharacterVsCharacterCollisionSimple();
CharacterBodyUpdater.characterVsCharacterCollision = characterVsCharacterCollision;
}
characterVsCharacterCollision.Add(character);
character.SetCharacterVsCharacterCollision(
characterVsCharacterCollision
);
const characterContactListener = new Jolt.CharacterContactListenerJS();
characterContactListener.OnAdjustBodyVelocity = (
@@ -1653,11 +1537,7 @@ namespace gdjs {
}
updateBodyFromObject() {
const physics3D = this.characterBehavior.getPhysics3D();
if (!physics3D) {
return;
}
const { behavior } = physics3D;
const { behavior } = this.characterBehavior.getPhysics3D();
const { character, owner3D, _sharedData } = this.characterBehavior;
if (!character) {
return;
@@ -1695,17 +1575,13 @@ namespace gdjs {
}
recreateShape() {
const physics3D = this.characterBehavior.getPhysics3D();
if (!physics3D) {
return;
}
const {
behavior,
broadPhaseLayerFilter,
objectLayerFilter,
bodyFilter,
shapeFilter,
} = physics3D;
} = this.characterBehavior.getPhysics3D();
const { character, _sharedData } = this.characterBehavior;
if (!character) {
return;
@@ -1729,10 +1605,6 @@ namespace gdjs {
// shapeHalfDepth may have changed, update the character position accordingly.
this.updateCharacterPosition();
}
destroyBody() {
this.characterBehavior._destroyCharacter();
}
}
/**

View File

@@ -81,11 +81,8 @@ module.exports = {
} else if (propertyName === 'maxLength') {
objectContent.maxLength = newValue;
return true;
} else if (propertyName === 'paddingX') {
objectContent.paddingX = Math.max(0, parseFloat(newValue));
return true;
} else if (propertyName === 'paddingY') {
objectContent.paddingY = Math.max(0, parseFloat(newValue));
} else if (propertyName === 'padding') {
objectContent.padding = newValue;
return true;
} else if (propertyName === 'textAlign') {
objectContent.textAlign = newValue;
@@ -213,27 +210,11 @@ module.exports = {
.setGroup(_('Border appearance'));
objectProperties
.getOrCreate('paddingX')
.setValue(
(objectContent.paddingX !== undefined
? objectContent.paddingX
: 2
).toString()
)
.getOrCreate('padding')
.setValue((objectContent.padding || 0).toString())
.setType('number')
.setLabel(_('Padding (horizontal)'))
.setGroup(_('Field appearance'));
objectProperties
.getOrCreate('paddingY')
.setValue(
(objectContent.paddingY !== undefined
? objectContent.paddingY
: 1
).toString()
)
.setType('number')
.setLabel(_('Padding (vertical)'))
.setGroup(_('Field appearance'));
.setLabel(_('Padding'))
.setGroup(_('Font'));
objectProperties
.getOrCreate('maxLength')
.setValue((objectContent.maxLength || 0).toString())
@@ -254,7 +235,7 @@ module.exports = {
.addExtraInfo('center')
.addExtraInfo('right')
.setLabel(_('Text alignment'))
.setGroup(_('Field appearance'));
.setGroup(_('Font'));
return objectProperties;
};
@@ -272,8 +253,7 @@ module.exports = {
borderWidth: 1,
readOnly: false,
disabled: false,
paddingX: 2,
paddingY: 1,
padding: 0,
textAlign: 'left',
maxLength: 0,
};
@@ -641,8 +621,8 @@ module.exports = {
),
_('_PARAM0_ value was submitted'),
'',
'res/conditions/surObjet24.png',
'res/conditions/surObjet.png'
'res/conditions/surObject24.png',
'res/conditions/surObject.png'
)
.addParameter('object', _('Text input'), 'TextInputObject', false)
.getCodeExtraInformation()
@@ -703,6 +683,7 @@ module.exports = {
const DEFAULT_WIDTH = 300;
const DEFAULT_HEIGHT = 30;
const TEXT_MASK_PADDING = 2;
class RenderedTextInputObjectInstance extends RenderedInstance {
constructor(
@@ -816,32 +797,16 @@ module.exports = {
);
const borderWidth = object.content.borderWidth || 0;
const paddingX =
object.content.paddingX !== undefined
? Math.min(
parseFloat(object.content.paddingX),
width / 2 - borderWidth
)
: 2;
const paddingY =
object.content.paddingY !== undefined
? Math.min(
parseFloat(object.content.paddingY),
height / 2 - borderWidth
)
: 1;
// Draw the mask for the text.
const textOffsetX = borderWidth + paddingX;
// textOffsetY does not include the paddingY because browsers display the text, even if it is supposed to be cut off by vertical padding.
const textOffsetY = borderWidth;
const textOffset = borderWidth + TEXT_MASK_PADDING;
this._pixiTextMask.clear();
this._pixiTextMask.beginFill(0xdddddd, 1);
this._pixiTextMask.drawRect(
textOffsetX,
textOffsetY,
width - 2 * textOffsetX,
height - 2 * textOffsetY
textOffset,
textOffset,
width - 2 * textOffset,
height - 2 * textOffset
);
this._pixiTextMask.endFill();
@@ -849,18 +814,22 @@ module.exports = {
const textAlign = object.content.textAlign
? object.content.textAlign
: 'left';
const padding = object.content.padding
? parseFloat(object.content.padding)
: 0;
if (textAlign === 'left') this._pixiText.position.x = textOffsetX;
if (textAlign === 'left')
this._pixiText.position.x = textOffset + padding;
else if (textAlign === 'right')
this._pixiText.position.x =
0 + width - this._pixiText.width - textOffsetX;
0 + width - this._pixiText.width - textOffset - padding;
else if (textAlign === 'center') {
this._pixiText.align = 'center';
this._pixiText.position.x = 0 + width / 2 - this._pixiText.width / 2;
}
this._pixiText.position.y = isTextArea
? textOffsetY + paddingY
? textOffset
: height / 2 - this._pixiText.height / 2;
// Draw the background and border.

View File

@@ -25,8 +25,7 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
borderWidth: 2,
disabled: false,
readOnly: false,
paddingX: 2,
paddingY: 1,
padding: 0,
textAlign: 'left',
maxLength: 20,
},

View File

@@ -57,6 +57,8 @@ namespace gdjs {
this._form.style.borderRadius = '0px';
this._form.style.backgroundColor = 'transparent';
this._form.style.position = 'absolute';
this._form.style.outline = 'none';
this._form.style.resize = 'none';
this._form.style.pointerEvents = 'auto'; // Element can be clicked/touched.
this._form.style.display = 'none'; // Hide while object is being set up.
this._form.style.boxSizing = 'border-box';
@@ -64,16 +66,12 @@ namespace gdjs {
this._input.autocomplete = 'off';
this._input.style.backgroundColor = 'white';
this._input.style.outline = 'none'; // Remove any style added by the browser to highlight the focused field in a form (:focus & :focus-visible modifiers).
this._input.style.resize = 'none'; // Prevent user from resizing the input when it's a text area.
this._input.style.border = '1px solid black';
this._input.style.boxSizing = 'border-box';
this._input.style.width = '100%';
this._input.style.height = '100%';
this._input.maxLength = this._object.getMaxLength();
this._input.style.padding = `${this._object
.getPaddingY()
.toFixed(2)}px ${this._object.getPaddingX().toFixed(2)}px`;
this._input.style.padding = this._object.getPadding() + 'px';
this._form.appendChild(this._input);
@@ -116,14 +114,9 @@ namespace gdjs {
}
_destroyElement() {
if (this._form) {
this._form.remove();
this._form = null;
}
if (this._input) {
this._input.remove();
this._input = null;
}
if (!this._input) return;
this._input.remove();
this._input = null;
}
onScenePaused() {
@@ -247,9 +240,7 @@ namespace gdjs {
'rotate3d(0,0,1,' + (this._object.getAngle() % 360) + 'deg)';
this._form.style.textAlign = this._object.getTextAlign();
this._input.style.padding = `${this._object
.getPaddingY()
.toFixed(2)}px ${this._object.getPaddingX().toFixed(2)}px`;
this._input.style.padding = this._object.getPadding() + 'px';
// Automatically adjust the font size to follow the game scale.
this._input.style.fontSize =
@@ -331,14 +322,14 @@ namespace gdjs {
this._input.style.borderWidth = this._object.getBorderWidth() + 'px';
}
updateDisabled() {
if (!this._input) return;
if (!this._form) return;
this._input.disabled = this._object.isDisabled();
this._form.disabled = this._object.isDisabled();
}
updateReadOnly() {
if (!this._input) return;
if (!this._form) return;
this._input.readOnly = this._object.isReadOnly();
this._form.readOnly = this._object.isReadOnly();
}
updateMaxLength() {
@@ -354,9 +345,7 @@ namespace gdjs {
updatePadding() {
if (!this._input) return;
this._input.style.padding = `${this._object
.getPaddingY()
.toFixed(2)}px ${this._object.getPaddingX().toFixed(2)}px`;
this._input.style.padding = this._object.getPadding() + 'px';
}
updateTextAlign() {

View File

@@ -48,17 +48,14 @@ namespace gdjs {
textColor: string;
fillColor: string;
fillOpacity: float;
padding?: float;
textAlign?: SupportedTextAlign;
maxLength?: integer;
borderColor: string;
borderOpacity: float;
borderWidth: float;
disabled: boolean;
readOnly: boolean;
// ---- Values can be undefined because of support for these feature was added in v5.5.222.
paddingX?: float;
paddingY?: float;
textAlign?: SupportedTextAlign;
maxLength?: integer;
// ----
};
}
@@ -87,10 +84,6 @@ namespace gdjs {
const DEFAULT_WIDTH = 300;
const DEFAULT_HEIGHT = 30;
const clampPadding = (value: float, dimension: float, borderWidth: float) => {
return Math.max(0, Math.min(dimension / 2 - borderWidth, value));
};
/**
* Shows a text input on the screen the player can type text into.
*/
@@ -108,8 +101,7 @@ namespace gdjs {
private _textColor: [float, float, float];
private _fillColor: [float, float, float];
private _fillOpacity: float;
private _paddingX: integer;
private _paddingY: integer;
private _padding: integer;
private _textAlign: SupportedTextAlign;
private _maxLength: integer;
private _borderColor: [float, float, float];
@@ -141,16 +133,9 @@ namespace gdjs {
this._borderWidth = objectData.content.borderWidth;
this._disabled = objectData.content.disabled;
this._readOnly = objectData.content.readOnly;
this._textAlign = parseTextAlign(objectData.content.textAlign);
this._maxLength = objectData.content.maxLength || 0;
this._paddingX =
objectData.content.paddingX !== undefined
? objectData.content.paddingX
: 2;
this._paddingY =
objectData.content.paddingY !== undefined
? objectData.content.paddingY
: 1;
this._textAlign = parseTextAlign(objectData.content.textAlign); //textAlign is defaulted to 'left' by the parser if undefined.
this._maxLength = objectData.content.maxLength || 0; //maxlength and padding require a default value as they can be undefined in older projects.
this._padding = objectData.content.padding || 0;
this._isSubmitted = false;
this._renderer = new gdjs.TextInputRuntimeObjectRenderer(
this,
@@ -228,7 +213,7 @@ namespace gdjs {
this.setReadOnly(newObjectData.content.readOnly);
}
if (
newObjectData.content.maxLength !== undefined &&
newObjectData.content.maxLength &&
oldObjectData.content.maxLength !== newObjectData.content.maxLength
) {
this.setMaxLength(newObjectData.content.maxLength);
@@ -240,16 +225,10 @@ namespace gdjs {
this._textAlign = newObjectData.content.textAlign;
}
if (
newObjectData.content.paddingX !== undefined &&
oldObjectData.content.paddingX !== newObjectData.content.paddingX
newObjectData.content.padding &&
oldObjectData.content.padding !== newObjectData.content.padding
) {
this.setPaddingX(newObjectData.content.paddingX);
}
if (
newObjectData.content.paddingY !== undefined &&
oldObjectData.content.paddingY !== newObjectData.content.paddingY
) {
this.setPaddingY(newObjectData.content.paddingY);
this.setPadding(newObjectData.content.padding);
}
return true;
@@ -317,7 +296,6 @@ namespace gdjs {
if (initialInstanceData.customSize) {
this.setWidth(initialInstanceData.width);
this.setHeight(initialInstanceData.height);
this._renderer.updatePadding();
}
if (initialInstanceData.opacity !== undefined) {
this.setOpacity(initialInstanceData.opacity);
@@ -353,12 +331,10 @@ namespace gdjs {
setWidth(width: float): void {
this._width = width;
this._renderer.updatePadding();
}
setHeight(height: float): void {
this._height = height;
this._renderer.updatePadding();
}
/**
@@ -584,31 +560,17 @@ namespace gdjs {
this._maxLength = value;
this._renderer.updateMaxLength();
}
getPaddingX(): integer {
return clampPadding(this._paddingX, this._width, this._borderWidth);
getPadding(): integer {
return this._padding;
}
setPaddingX(value: integer) {
if (this._paddingX === value) return;
setPadding(value: integer) {
if (this._padding === value) return;
if (value < 0) {
this._paddingX = 0;
this._padding = 0;
return;
}
this._paddingX = value;
this._renderer.updatePadding();
}
getPaddingY(): integer {
return clampPadding(this._paddingY, this._height, this._borderWidth);
}
setPaddingY(value: integer) {
if (this._paddingY === value) return;
if (value < 0) {
this._paddingY = 0;
return;
}
this._paddingY = value;
this._padding = value;
this._renderer.updatePadding();
}

View File

@@ -2786,13 +2786,6 @@ interface WholeProjectRefactorer {
[Value] SetString STATIC_FindAllLeaderboardIds([Ref] Project project);
};
interface ObjectTools {
boolean STATIC_IsBehaviorCompatibleWithObject(
[Const, Ref] Platform platform,
[Const] DOMString objectType,
[Const] DOMString behaviorType);
};
interface EventsBasedObjectDependencyFinder {
boolean STATIC_IsDependentFromEventsBasedObject(
[Const, Ref] Project project,
@@ -2816,10 +2809,6 @@ interface UsedExtensionsFinder {
[Value] UsedExtensionsResult STATIC_ScanProject([Ref] Project project);
};
interface ExampleExtensionUsagesFinder {
[Value] SetString STATIC_GetUsedExtensions([Ref] Project project);
};
interface InstructionsCountEvaluator {
long STATIC_ScanProject([Ref] Project project);
};

View File

@@ -44,7 +44,6 @@
#include <GDCore/IDE/Events/InstructionsTypeRenamer.h>
#include <GDCore/IDE/Events/TextFormatting.h>
#include <GDCore/IDE/Events/UsedExtensionsFinder.h>
#include <GDCore/IDE/Events/ExampleExtensionUsagesFinder.h>
#include <GDCore/IDE/EventsFunctionTools.h>
#include <GDCore/IDE/GroupVariableHelper.h>
#include <GDCore/IDE/Project/ArbitraryResourceWorker.h>
@@ -78,7 +77,6 @@
#include <GDCore/Project/MeasurementUnitElement.h>
#include <GDCore/Project/NamedPropertyDescriptor.h>
#include <GDCore/Project/Object.h>
#include <GDCore/Project/ObjectTools.h>
#include <GDCore/Project/ObjectFolderOrObject.h>
#include <GDCore/Project/ObjectConfiguration.h>
#include <GDCore/Project/Project.h>
@@ -660,7 +658,6 @@ typedef ExtensionAndMetadata<ExpressionMetadata> ExtensionAndExpressionMetadata;
#define STATIC_FindInvalidRequiredBehaviorProperties \
FindInvalidRequiredBehaviorProperties
#define STATIC_GetBehaviorsWithType GetBehaviorsWithType
#define STATIC_IsBehaviorCompatibleWithObject IsBehaviorCompatibleWithObject
#define STATIC_FixInvalidRequiredBehaviorProperties \
FixInvalidRequiredBehaviorProperties
#define STATIC_RemoveLayerInScene RemoveLayerInScene
@@ -813,7 +810,6 @@ typedef ExtensionAndMetadata<ExpressionMetadata> ExtensionAndExpressionMetadata;
#define STATIC_GetNodeAtPosition GetNodeAtPosition
#define STATIC_ScanProject ScanProject
#define STATIC_GetUsedExtensions GetUsedExtensions
#define STATIC_ApplyTranslation ApplyTranslation
#define STATIC_GetUndefined GetUndefined

View File

@@ -342,6 +342,12 @@ type CustomObjectConfiguration_EdgeAnchor = 0 | 1 | 2 | 3 | 4`
// Add inheritance not expressed in Bindings.idl.
// TODO: these should be expressed in Bindings.idl using "implements".
shell.sed(
'-i',
'declare class gdEventsFunctionsExtension {',
'declare class gdEventsFunctionsExtension extends gdEventsFunctionsContainer {',
'types/gdeventsfunctionsextension.js'
);
shell.sed(
'-i',
'declare class gdObjectJsImplementation {',

View File

@@ -4,11 +4,13 @@ const path = require('path');
const { makeSimplePromisePool } = require('./utils/SimplePromisePool');
const gdevelopRootPath = path.resolve(__dirname, '../../');
const sourcesRootPath = path.join(gdevelopRootPath, 'Core/GDCore');
const coreSourcesRootPath = path.join(gdevelopRootPath, 'Core/GDCore');
const extensionSourcesRootPath = path.join(gdevelopRootPath, 'Extensions');
const excludedPaths = [
'Tools/Localization.cpp', // emscripten code which can't be linted
'Serialization/Serializer.cpp', // Diagnostic that can't be ignored in rapidjson.
'Core/GDCore/Tools/Localization.cpp', // emscripten code which can't be linted
'Core/GDCore/Serialization/Serializer.cpp', // Diagnostic that can't be ignored in rapidjson.
];
const supportedExtensions = ['.cpp', '.h', '.hpp'];
async function findClangTidy() {
const tryClangTidy = (clangTidyCommandName) =>
@@ -78,18 +80,18 @@ function findFiles(directoryPath) {
list.forEach((file) => {
const filePath = path.resolve(directoryPath, file);
const relativePath = path.relative(sourcesRootPath, filePath);
const relativePath = path.relative(gdevelopRootPath, filePath);
const stat = fs.statSync(filePath);
if (stat && stat.isDirectory() && !excludedPaths.includes(relativePath)) {
results = results.concat(findFiles(filePath));
} else {
if (
path.extname(filePath) === '.inl' ||
(!supportedExtensions.includes(path.extname(filePath))) ||
path.basename(filePath) === '.gitignore' ||
excludedPaths.includes(relativePath)
) {
// Ignore .inl files
// Ignore the file.
} else {
results.push(filePath);
}
@@ -108,7 +110,9 @@ async function main() {
process.exit(1);
}
const filesToCheck = findFiles(sourcesRootPath);
const coreFilesToCheck = findFiles(coreSourcesRootPath);
const extensionFilesToCheck = findFiles(extensionSourcesRootPath);
const filesToCheck = [...coreFilesToCheck, ...extensionFilesToCheck];
// Run clang-tidy on each file.
const filesWithErrors = [];

View File

@@ -1985,10 +1985,6 @@ export class WholeProjectRefactorer extends EmscriptenObject {
static findAllLeaderboardIds(project: Project): SetString;
}
export class ObjectTools extends EmscriptenObject {
static isBehaviorCompatibleWithObject(platform: Platform, objectType: string, behaviorType: string): boolean;
}
export class EventsBasedObjectDependencyFinder extends EmscriptenObject {
static isDependentFromEventsBasedObject(project: Project, eventsBasedObject: EventsBasedObject, dependency: EventsBasedObject): boolean;
}
@@ -2008,10 +2004,6 @@ export class UsedExtensionsFinder extends EmscriptenObject {
static scanProject(project: Project): UsedExtensionsResult;
}
export class ExampleExtensionUsagesFinder extends EmscriptenObject {
static getUsedExtensions(project: Project): SetString;
}
export class InstructionsCountEvaluator extends EmscriptenObject {
static scanProject(project: Project): number;
}

View File

@@ -1,5 +1,5 @@
// Automatically generated by GDevelop.js/scripts/generate-types.js
declare class gdEventsFunctionsExtension {
declare class gdEventsFunctionsExtension extends gdEventsFunctionsContainer {
constructor(): void;
setNamespace(namespace_: string): gdEventsFunctionsExtension;
getNamespace(): string;

View File

@@ -1,6 +0,0 @@
// Automatically generated by GDevelop.js/scripts/generate-types.js
declare class gdExampleExtensionUsagesFinder {
static getUsedExtensions(project: gdProject): gdSetString;
delete(): void;
ptr: number;
};

View File

@@ -1,6 +0,0 @@
// Automatically generated by GDevelop.js/scripts/generate-types.js
declare class gdObjectTools {
static isBehaviorCompatibleWithObject(platform: gdPlatform, objectType: string, behaviorType: string): boolean;
delete(): void;
ptr: number;
};

View File

@@ -184,12 +184,10 @@ declare class libGDevelop {
ResourceExposer: Class<gdResourceExposer>;
VariablesChangeset: Class<gdVariablesChangeset>;
WholeProjectRefactorer: Class<gdWholeProjectRefactorer>;
ObjectTools: Class<gdObjectTools>;
EventsBasedObjectDependencyFinder: Class<gdEventsBasedObjectDependencyFinder>;
PropertyFunctionGenerator: Class<gdPropertyFunctionGenerator>;
UsedExtensionsResult: Class<gdUsedExtensionsResult>;
UsedExtensionsFinder: Class<gdUsedExtensionsFinder>;
ExampleExtensionUsagesFinder: Class<gdExampleExtensionUsagesFinder>;
InstructionsCountEvaluator: Class<gdInstructionsCountEvaluator>;
ExtensionAndBehaviorMetadata: Class<gdExtensionAndBehaviorMetadata>;
ExtensionAndObjectMetadata: Class<gdExtensionAndObjectMetadata>;

View File

@@ -262,16 +262,7 @@ export class ColorAssetStoreSearchFilter
}
const toAssetStoreType = (type: string) => {
switch (type) {
case 'Sprite':
return 'sprite';
case 'TiledSpriteObject::TiledSprite':
return 'tiled';
case 'PanelSpriteObject::PanelSprite':
return '9patch';
default:
return type;
}
return type === 'Sprite' ? 'sprite' : type;
};
// Thematic tags are noise for asset swapping as changing the theme may be what

View File

@@ -81,18 +81,10 @@ type SpriteObjectDataType = {
animations: Array<SpriteAnimationData>,
};
const unswappableObjectTypes = [
'BBText::BBText',
'TextObject::Text',
'Lighting::LightObject',
'PrimitiveDrawing::Drawer',
'TileMap::TileMap',
'TileMap::CollisionMask',
'TileMap::SimpleTileMap',
'Video::VideoObject',
];
export const canSwapAssetOfObject = (object: gdObject) =>
!unswappableObjectTypes.includes(object.getType());
export const canSwapAssetOfObject = (object: gdObject) => {
const type = object.getType();
return type === 'Scene3D::Model3DObject' || type === 'Sprite';
};
const mergeAnimations = function<A: { name: string }>(
project: gdProject,
@@ -320,7 +312,7 @@ export const swapAsset = (
assetObject: gdObject,
assetShortHeader?: ?AssetShortHeader
) => {
let serializedObject = serializeToJSObject(object);
const serializedObject = serializeToJSObject(object);
const serializedAssetObject = serializeToJSObject(assetObject);
if (object.getType() === 'Sprite') {
@@ -346,7 +338,6 @@ export const swapAsset = (
scaleX,
scaleY
);
serializedObject.assetStoreId = serializedAssetObject.assetStoreId;
} else if (object.getType() === 'Scene3D::Model3DObject') {
const objectVolume =
serializedObject.content.width *
@@ -374,15 +365,6 @@ export const swapAsset = (
centerLocation: serializedObject.content.centerLocation,
};
serializedObject.assetStoreId = serializedAssetObject.assetStoreId;
} else {
serializedObject = {
...serializedAssetObject,
name: serializedObject.name,
type: serializedObject.type,
variables: serializedObject.variables,
behaviors: serializedObject.behaviors,
effects: serializedObject.effects,
};
}
unserializeFromJSObject(object, serializedObject, 'unserializeFrom', project);
};

View File

@@ -90,22 +90,22 @@ const sortedContentType: PrivateAssetPackAssetType[] = [
'TileMap::SimpleTileMap',
'ParticleSystem::ParticleEmitter',
'font',
'bitmapFont',
'audio',
'partial',
];
const contentTypeToMessageDescriptor: {
[PrivateAssetPackAssetType]: MessageDescriptor,
} = {
sprite: t`sprites`,
'9patch': t`panel sprites`,
tiled: t`tiled sprites`,
sprite: t`Sprites`,
'9patch': t`Panel sprites`,
tiled: t`Tiled sprites`,
'Scene3D::Model3DObject': t`3D models`,
'TileMap::SimpleTileMap': t`tile maps`,
'ParticleSystem::ParticleEmitter': t`particle emitters`,
font: t`fonts`,
bitmapFont: t`bitmap fonts`,
audio: t`audios`,
'TileMap::SimpleTileMap': t`Tilemaps`,
'ParticleSystem::ParticleEmitter': t`Particle emitters`,
font: t`Fonts`,
audio: t`Audios`,
partial: t`Other`,
};
const styles = {
@@ -521,23 +521,6 @@ const PrivateAssetPackInformationPage = ({
{ subscription, privateAssetPackListingData, isAlreadyReceived }
);
const smartObjectsCount = React.useMemo(
() => {
if (!assetPack) {
return 0;
}
let smartObjectsCount = 0;
for (const type in assetPack.content) {
const assetCount = assetPack.content[type];
if (!sortedContentType.includes(type)) {
smartObjectsCount += assetCount;
}
}
return smartObjectsCount;
},
[assetPack]
);
return (
<I18n>
{({ i18n }) => (
@@ -731,13 +714,6 @@ const PrivateAssetPackInformationPage = ({
}
return null;
})}
{smartObjectsCount > 0 ? (
<li>
<Text displayInlineAsSpan noMargin>
<Trans>{smartObjectsCount} smart objects</Trans>
</Text>
</li>
) : null}
</Column>
{bundlesContainingPackTiles &&
bundlesContainingPackTiles.length ? (

View File

@@ -477,15 +477,6 @@ export const useManageObjectBehaviors = ({
if (!name || !type || !serializedBehavior) {
return;
}
if (
!gd.ObjectTools.isBehaviorCompatibleWithObject(
project.getCurrentPlatform(),
object.getType(),
type
)
) {
return;
}
const behaviorMetadata = gd.MetadataProvider.getBehaviorMetadata(
project.getCurrentPlatform(),

View File

@@ -18,7 +18,7 @@ import GDevelopThemeContext from '../UI/Theme/GDevelopThemeContext';
import Divider from '@material-ui/core/Divider';
import FlatButton from '../UI/FlatButton';
import ChevronArrowBottom from '../UI/CustomSvgIcons/ChevronArrowBottom';
import ChevronArrowRight from '../UI/CustomSvgIcons/ChevronArrowRight';
import ChevronArrowTop from '../UI/CustomSvgIcons/ChevronArrowTop';
import Cloud from '../UI/CustomSvgIcons/Cloud';
import CourseChapterTaskItem from './CourseChapterTaskItem';
import { useResponsiveWindowSize } from '../UI/Responsive/ResponsiveWindowMeasurer';
@@ -51,9 +51,6 @@ const getYoutubeVideoIdFromUrl = (youtubeUrl: ?string): ?string => {
};
const styles = {
icon: {
fontSize: 18,
},
stickyTitle: {
position: 'sticky',
top: -1, // If 0, it somehow lets a 1px gap between the parent, letting the user see the text scroll behind.
@@ -386,9 +383,9 @@ const CourseChapterView = React.forwardRef<Props, HTMLDivElement>(
}
leftIcon={
openTasks ? (
<ChevronArrowBottom style={styles.icon} />
<ChevronArrowTop size="small" />
) : (
<ChevronArrowRight style={styles.icon} />
<ChevronArrowBottom size="small" />
)
}
onClick={() => setOpenTasks(!openTasks)}

View File

@@ -5,7 +5,7 @@ import { I18n } from '@lingui/react';
import { Trans } from '@lingui/macro';
import Avatar from '@material-ui/core/Avatar';
import Divider from '@material-ui/core/Divider';
import ButtonBase from '@material-ui/core/ButtonBase';
import type { Course, CourseChapter } from '../Utils/GDevelopServices/Asset';
import {
ColumnStackLayout,
@@ -29,14 +29,12 @@ import CheckCircle from '../UI/CustomSvgIcons/CheckCircle';
import type { GDevelopTheme } from '../UI/Theme';
import GDevelopThemeContext from '../UI/Theme/GDevelopThemeContext';
import Lock from '../UI/CustomSvgIcons/Lock';
import LockOpen from '../UI/CustomSvgIcons/LockOpen';
import EmptyBadge from '../UI/CustomSvgIcons/EmptyBadge';
const styles = {
container: { padding: 16, display: 'flex', borderRadius: 8 },
mobileContainer: { padding: 8, display: 'flex', borderRadius: 8 },
paper: { padding: 16 },
mobilePaper: { padding: 8 },
badgePaper: { padding: '8px 16px' },
mobileBadgePaper: { padding: 8 },
badgeImage: { width: 25 },
leftColumn: {
display: 'flex',
@@ -46,16 +44,6 @@ const styles = {
},
progress: { borderRadius: 4, height: 5 },
chip: { height: 24 },
freeChip: {
height: 20,
borderRadius: 32,
paddingTop: 2,
paddingBottom: 2,
paddingLeft: 8,
paddingRight: 8,
backgroundColor: '#8BE7C4',
color: '#1D1D26',
},
gdevelopAvatar: { width: 20, height: 20 },
thumbnail: { borderRadius: 4, aspectRatio: '16 / 9' },
statusContainer: {
@@ -63,9 +51,6 @@ const styles = {
alignItems: 'center',
fontSize: 20,
},
statusIconOnly: {
fontSize: 22,
},
emptyBadgeContainer: {
display: 'flex',
opacity: 0.5,
@@ -85,42 +70,29 @@ const ChapterTile = ({
|}) => {
return (
<Column expand>
<Spacer />
{chapter && chapter.isLocked ? (
<Paper background="light" style={{ padding: 4 }}>
<LineStackLayout noMargin alignItems="center" justifyContent="center">
<div style={styles.statusContainer}>
<Lock fontSize="inherit" color="secondary" />
</div>
<Text color="secondary" noMargin>
<Trans>Unlock with {chapter.priceInCredits} credits</Trans>
</Text>
</LineStackLayout>
</Paper>
) : isComplete ? (
<div
style={{
...styles.statusIconOnly,
color: gdevelopTheme.statusIndicator.success,
}}
>
<CheckCircle fontSize="inherit" />
</div>
) : chapter && chapter.isFree ? (
<Line noMargin>
<div style={styles.freeChip}>
<Text noMargin color="inherit" size="body-small">
<Trans>Free</Trans>
</Text>
</div>
</Line>
<>
<Spacer />
<Paper background="light" style={{ padding: 4 }}>
<LineStackLayout
noMargin
alignItems="center"
justifyContent="center"
>
<div style={styles.statusContainer}>
<Lock fontSize="inherit" color="secondary" />
</div>
<Text color="secondary" noMargin>
<Trans>Unlock with {chapter.priceInCredits} credits</Trans>
</Text>
</LineStackLayout>
</Paper>
<Spacer />
</>
) : (
<div style={styles.statusIconOnly}>
<LockOpen fontSize="inherit" color="secondary" />
</div>
<LargeSpacer />
)}
<Spacer />
<Line noMargin>
<Text color="secondary" noMargin>
{rankLabel[chapterIndex + 1]}
@@ -129,6 +101,17 @@ const ChapterTile = ({
<Text color="secondary" noMargin>
<Trans>Chapter</Trans>
</Text>
{isComplete && (
<div
style={{
...styles.statusContainer,
color: gdevelopTheme.statusIndicator.success,
}}
>
<Spacer />
<CheckCircle fontSize="inherit" />
</div>
)}
</Line>
{chapter ? (
<Text
@@ -273,119 +256,110 @@ const CoursePreviewBanner = ({
return (
<I18n>
{({ i18n }) => (
<Paper background="medium">
<ButtonBase
onClick={() => onDisplayCourse(true)}
component="div"
style={
isMobile && !isLandscape
? styles.mobileContainer
: styles.container
}
<Paper
background="medium"
style={isMobile && !isLandscape ? styles.mobilePaper : styles.paper}
>
<ResponsiveLineStackLayout
noResponsiveLandscape
noMargin
noColumnMargin
>
<ResponsiveLineStackLayout
noResponsiveLandscape
noMargin
noColumnMargin
noOverflowParent
<div
style={{
...styles.leftColumn,
width: isMobile && !isLandscape ? '100%' : 220,
}}
>
<div
style={{
...styles.leftColumn,
width: isMobile && !isLandscape ? '100%' : 220,
}}
>
<Line noMargin>
<Chip
label={<Trans>Recommended for you</Trans>}
style={styles.chip}
/>
</Line>
<Text noMargin size="block-title">
{selectMessageByLocale(i18n, course.titleByLocale)}
</Text>
<LineStackLayout noMargin alignItems="center">
<Avatar
src="./res/gdevelop-logo-b-w.png"
style={styles.gdevelopAvatar}
/>
<Text noMargin>GDevelop</Text>
</LineStackLayout>
<img
src="https://public-resources.gdevelop.io/course/gdevelop-premium-course.jpeg"
alt="Red hero buffed by knowledge"
style={styles.thumbnail}
onClick={() => onDisplayCourse(true)}
<Line noMargin>
<Chip
label={<Trans>Recommended for you</Trans>}
style={styles.chip}
/>
</div>
<ColumnStackLayout expand noMargin>
{isMobile && !isLandscape ? (
<Column noMargin>
<Text color="secondary" noMargin>
{selectMessageByLocale(i18n, course.levelByLocale)}
&nbsp;&nbsp;
<Trans>{course.durationInWeeks} weeks</Trans>
</Text>
{renderProgress()}
</Column>
) : (
<LineStackLayout noMargin alignItems="center" expand>
{renderProgress()}
<Text color="secondary" noMargin>
{selectMessageByLocale(i18n, course.levelByLocale)}
&nbsp;&nbsp;
<Trans>{course.durationInWeeks} weeks</Trans>
</Line>
<Text noMargin size="block-title">
{selectMessageByLocale(i18n, course.titleByLocale)}
</Text>
<LineStackLayout noMargin alignItems="center">
<Avatar
src="./res/gdevelop-logo-b-w.png"
style={styles.gdevelopAvatar}
/>
<Text noMargin>GDevelop</Text>
</LineStackLayout>
<img
src="https://public-resources.gdevelop.io/course/gdevelop-premium-course.jpeg"
alt="Red hero buffed by knowledge"
style={styles.thumbnail}
onClick={() => onDisplayCourse(true)}
/>
</div>
<ColumnStackLayout expand noMargin>
{isMobile && !isLandscape ? (
<Column noMargin>
<Text color="secondary" noMargin>
{selectMessageByLocale(i18n, course.levelByLocale)}
&nbsp;&nbsp;
<Trans>{course.durationInWeeks} weeks</Trans>
</Text>
{renderProgress()}
</Column>
) : (
<LineStackLayout noMargin alignItems="center" expand>
{renderProgress()}
<Text color="secondary" noMargin>
{selectMessageByLocale(i18n, course.levelByLocale)}
&nbsp;&nbsp;
<Trans>{course.durationInWeeks} weeks</Trans>
</Text>
</LineStackLayout>
)}
<ResponsiveLineStackLayout noResponsiveLandscape>
{chapterTiles}
</ResponsiveLineStackLayout>
<Paper
style={
isMobile && !isLandscape
? styles.mobilePaper
: styles.badgePaper
}
background="light"
>
<ResponsiveLineStackLayout
noResponsiveLandscape
noColumnMargin
alignItems="center"
noMargin
justifyContent="space-between"
>
<LineStackLayout alignItems="center" noMargin>
<div
style={{
...styles.emptyBadgeContainer,
color: gdevelopTheme.text.color.secondary,
}}
>
<EmptyBadge />
</div>
<Text noMargin>
<Trans>Earn an exclusive badge</Trans>
</Text>
</LineStackLayout>
)}
<ResponsiveLineStackLayout noResponsiveLandscape>
{chapterTiles}
<RaisedButton
primary
label={
!courseCompletion || courseCompletion.percentage === 0 ? (
<Trans>Start learning</Trans>
) : (
<Trans>Keep learning</Trans>
)
}
onClick={() => onDisplayCourse(true)}
/>
</ResponsiveLineStackLayout>
<Paper
style={
isMobile && !isLandscape
? styles.mobileBadgePaper
: styles.badgePaper
}
background="light"
>
<ResponsiveLineStackLayout
noResponsiveLandscape
noColumnMargin
alignItems="center"
noMargin
justifyContent="space-between"
>
<LineStackLayout alignItems="center" noMargin>
<div
style={{
...styles.emptyBadgeContainer,
color: gdevelopTheme.text.color.secondary,
}}
>
<EmptyBadge />
</div>
<Text noMargin>
<Trans>Earn an exclusive badge</Trans>
</Text>
</LineStackLayout>
<RaisedButton
primary
label={
!courseCompletion ||
courseCompletion.percentage === 0 ? (
<Trans>Start learning</Trans>
) : (
<Trans>Keep learning</Trans>
)
}
onClick={() => onDisplayCourse(true)}
/>
</ResponsiveLineStackLayout>
</Paper>
</ColumnStackLayout>
</ResponsiveLineStackLayout>
</ButtonBase>
</Paper>
</ColumnStackLayout>
</ResponsiveLineStackLayout>
</Paper>
)}
</I18n>

View File

@@ -22,7 +22,7 @@ import VisibilityOff from '../UI/CustomSvgIcons/VisibilityOff';
const gd: libGDevelop = global.gd;
type Props = {|
eventsFunctionsContainer: gdEventsFunctionsContainer,
eventsFunctionsExtension: gdEventsFunctionsExtension,
onCancel: () => void,
onChoose: (parameters: EventsFunctionCreationParameters) => void,
|};
@@ -58,8 +58,8 @@ const FunctionListItem = ({
);
};
export default function ExtensionFunctionSelectorDialog({
eventsFunctionsContainer,
export default function BehaviorMethodSelectorDialog({
eventsFunctionsExtension,
onChoose,
onCancel,
}: Props) {
@@ -139,7 +139,7 @@ export default function ExtensionFunctionSelectorDialog({
<FunctionListItem
icon={<Create style={styles.icon} />}
name={'onFirstSceneLoaded'}
disabled={eventsFunctionsContainer.hasEventsFunctionNamed(
disabled={eventsFunctionsExtension.hasEventsFunctionNamed(
'onFirstSceneLoaded'
)}
onChoose={() =>
@@ -158,7 +158,7 @@ export default function ExtensionFunctionSelectorDialog({
<FunctionListItem
icon={<Create style={styles.icon} />}
name={'onSceneLoaded'}
disabled={eventsFunctionsContainer.hasEventsFunctionNamed(
disabled={eventsFunctionsExtension.hasEventsFunctionNamed(
'onSceneLoaded'
)}
onChoose={() =>
@@ -177,7 +177,7 @@ export default function ExtensionFunctionSelectorDialog({
<FunctionListItem
icon={<Step style={styles.icon} />}
name={'onScenePreEvents'}
disabled={eventsFunctionsContainer.hasEventsFunctionNamed(
disabled={eventsFunctionsExtension.hasEventsFunctionNamed(
'onScenePreEvents'
)}
onChoose={() =>
@@ -196,7 +196,7 @@ export default function ExtensionFunctionSelectorDialog({
<FunctionListItem
icon={<Step style={styles.icon} />}
name={'onScenePostEvents'}
disabled={eventsFunctionsContainer.hasEventsFunctionNamed(
disabled={eventsFunctionsExtension.hasEventsFunctionNamed(
'onScenePostEvents'
)}
onChoose={() =>
@@ -215,7 +215,7 @@ export default function ExtensionFunctionSelectorDialog({
<FunctionListItem
icon={<Deactivate style={styles.icon} />}
name={'onScenePaused'}
disabled={eventsFunctionsContainer.hasEventsFunctionNamed(
disabled={eventsFunctionsExtension.hasEventsFunctionNamed(
'onScenePaused'
)}
onChoose={() =>
@@ -234,7 +234,7 @@ export default function ExtensionFunctionSelectorDialog({
<FunctionListItem
icon={<Activate style={styles.icon} />}
name={'onSceneResumed'}
disabled={eventsFunctionsContainer.hasEventsFunctionNamed(
disabled={eventsFunctionsExtension.hasEventsFunctionNamed(
'onSceneResumed'
)}
onChoose={() =>
@@ -253,7 +253,7 @@ export default function ExtensionFunctionSelectorDialog({
<FunctionListItem
icon={<Destroy style={styles.icon} />}
name={'onSceneUnloading'}
disabled={eventsFunctionsContainer.hasEventsFunctionNamed(
disabled={eventsFunctionsExtension.hasEventsFunctionNamed(
'onSceneUnloading'
)}
onChoose={() =>

View File

@@ -280,10 +280,9 @@ export default class EventsFunctionsExtensionEditor extends React.Component<
}
} else {
// Free function
const eventsFunctions = eventsFunctionsExtension.getEventsFunctions();
if (eventsFunctions.hasEventsFunctionNamed(functionName)) {
if (eventsFunctionsExtension.hasEventsFunctionNamed(functionName)) {
this._selectEventsFunction(
eventsFunctions.getEventsFunction(functionName),
eventsFunctionsExtension.getEventsFunction(functionName),
null,
null
);
@@ -390,9 +389,7 @@ export default class EventsFunctionsExtensionEditor extends React.Component<
gd.MetadataDeclarationHelper.isExtensionLifecycleEventsFunction(
tentativeNewName
) ||
eventsFunctionsExtension
.getEventsFunctions()
.hasEventsFunctionNamed(tentativeNewName)
eventsFunctionsExtension.hasEventsFunctionNamed(tentativeNewName)
) {
return true;
}
@@ -1359,7 +1356,7 @@ export default class EventsFunctionsExtensionEditor extends React.Component<
eventsFunctionsContainer={
(selectedEventsBasedEntity &&
selectedEventsBasedEntity.getEventsFunctions()) ||
eventsFunctionsExtension.getEventsFunctions()
eventsFunctionsExtension
}
eventsFunctionsExtension={eventsFunctionsExtension}
globalObjectsContainer={
@@ -1722,7 +1719,7 @@ export default class EventsFunctionsExtensionEditor extends React.Component<
)}
{extensionFunctionSelectorDialogOpen && eventsFunctionsExtension && (
<ExtensionFunctionSelectorDialog
eventsFunctionsContainer={eventsFunctionsExtension.getEventsFunctions()}
eventsFunctionsExtension={eventsFunctionsExtension}
onCancel={() => this._onCloseExtensionFunctionSelectorDialog(null)}
onChoose={parameters =>
this._onCloseExtensionFunctionSelectorDialog(parameters)

View File

@@ -619,7 +619,7 @@ const EventsFunctionsList = React.forwardRef<
const eventBasedEntity = eventsBasedBehavior || eventsBasedObject;
const eventsFunctionsContainer = eventBasedEntity
? eventBasedEntity.getEventsFunctions()
: eventsFunctionsExtension.getEventsFunctions();
: eventsFunctionsExtension;
// Let EventsFunctionsExtensionEditor know if the function is:
// a free function, a behavior one or an object one.
@@ -1288,7 +1288,7 @@ const EventsFunctionsList = React.forwardRef<
selectedEventsBasedBehavior || selectedEventsBasedObject;
const eventsFunctionsContainer = eventsBasedEntity
? eventsBasedEntity.getEventsFunctions()
: eventsFunctionsExtension.getEventsFunctions();
: eventsFunctionsExtension;
const eventFunctionProps = {
eventsBasedBehavior: selectedEventsBasedBehavior,
eventsBasedObject: selectedEventsBasedObject,

View File

@@ -198,9 +198,9 @@ export const validateEventsFunctionNameUniqueness = (
extensionName
);
return !eventsFunctionsExtension
.getEventsFunctions()
.hasEventsFunctionNamed(eventsFunction.getName());
return !eventsFunctionsExtension.hasEventsFunctionNamed(
eventsFunction.getName()
);
}
return true;

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="2 2 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.49303 6.80028C5.69538 6.61238 6.01175 6.62409 6.19965 6.82645L7.99992 8.7652L9.80019 6.82645C9.98809 6.62409 10.3045 6.61238 10.5068 6.80028C10.7092 6.98818 10.7209 7.30454 10.533 7.5069L8.36632 9.84023C8.27171 9.94212 8.13896 10 7.99992 10C7.86089 10 7.72813 9.94212 7.63352 9.84023L5.46686 7.5069C5.27896 7.30454 5.29067 6.98818 5.49303 6.80028Z" fill="#F5F5F7"/>
</svg>

Before

Width:  |  Height:  |  Size: 521 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="2 2 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.49303 6.80028C5.69538 6.61238 6.01175 6.62409 6.19965 6.82645L7.99992 8.7652L9.80019 6.82645C9.98809 6.62409 10.3045 6.61238 10.5068 6.80028C10.7092 6.98818 10.7209 7.30454 10.533 7.5069L8.36632 9.84023C8.27171 9.94212 8.13896 10 7.99992 10C7.86089 10 7.72813 9.94212 7.63352 9.84023L5.46686 7.5069C5.27896 7.30454 5.29067 6.98818 5.49303 6.80028Z" fill="#1D1D26"/>
</svg>

Before

Width:  |  Height:  |  Size: 521 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="2 2 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.80035 5.49311C6.98825 5.29075 7.30462 5.27904 7.50698 5.46694L9.84031 7.6336C9.94219 7.72821 10.0001 7.86097 10.0001 8C10.0001 8.13904 9.94219 8.27179 9.84031 8.3664L7.50698 10.5331C7.30462 10.721 6.98825 10.7092 6.80035 10.5069C6.61245 10.3045 6.62417 9.98817 6.82652 9.80027L8.76528 8L6.82652 6.19973C6.62417 6.01183 6.61245 5.69546 6.80035 5.49311Z" fill="#F5F5F7"/>
</svg>

Before

Width:  |  Height:  |  Size: 525 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="2 2 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.80035 5.49311C6.98825 5.29075 7.30462 5.27904 7.50698 5.46694L9.84031 7.6336C9.94219 7.72821 10.0001 7.86097 10.0001 8C10.0001 8.13904 9.94219 8.27179 9.84031 8.3664L7.50698 10.5331C7.30462 10.721 6.98825 10.7092 6.80035 10.5069C6.61245 10.3045 6.62417 9.98817 6.82652 9.80027L8.76528 8L6.82652 6.19973C6.62417 6.01183 6.61245 5.69546 6.80035 5.49311Z" fill="#1D1D26"/>
</svg>

Before

Width:  |  Height:  |  Size: 525 B

View File

@@ -373,9 +373,7 @@ const Instruction = (props: Props) => {
props.scope.eventsBasedObject;
const functionsContainer = eventsBasedEntity
? eventsBasedEntity.getEventsFunctions()
: props.scope.eventsFunctionsExtension
? props.scope.eventsFunctionsExtension.getEventsFunctions()
: null;
: props.scope.eventsFunctionsExtension;
if (functionsContainer) {
const allowedParameterTypes = parameterMetadata

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 B

View File

@@ -117,37 +117,36 @@
/**
* Expand/collapse buttons
*/
.gd-events-sheet .rst__collapseButton,
.gd-events-sheet .rst__expandButton {
.gd-events-sheet .rst__collapseButton, .rst__expandButton {
border-radius: 0;
border: none;
box-shadow: none;
background-repeat: no-repeat;
background-color: transparent;
height: var(--icon-size); /*Keep the height of a single-line event, more-or-less*/
width: 16px; /*Leave space for the line to be visible between the button and the handle*/
background-color: var(--event-sheet-event-tree-background-color);
border-radius: 4px;
height: 12px;
width: 22px;
}
.gd-events-sheet .rst__collapseButton:hover:not(:active), .rst__expandButton:hover:not(:active) {
background-size: initial !important; /*Avoid buttons size to change*/
height: var(--icon-size) !important; /*Avoid buttons size to change*/
width: 16px !important; /*Avoid buttons size to change*/
height: 12px !important; /*Avoid buttons size to change*/
width: 22px !important; /*Avoid buttons size to change*/
}
.gd-events-sheet .rst__expandButton {
background-image: url('./Chevron-right.svg');
.gd-events-sheet .rst__expandButton {
background-image: url('./unfold.png');
background-position: 11px 3px !important;
}
.gd-events-sheet .light-theme .rst__expandButton {
background-image: url('./Chevron-right_black.svg');
background-image: url('./unfoldDark.png');
}
.gd-events-sheet .rst__collapseButton {
background-image: url('./Chevron-down.svg');
.gd-events-sheet .rst__collapseButton {
background-image: url('./fold.png');
background-position: center 7px !important;
}
.gd-events-sheet .light-theme .rst__collapseButton {
background-image: url('./Chevron-down_black.svg');
background-image: url('./foldDark.png');
}
/**

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

View File

@@ -30,9 +30,7 @@ export default React.forwardRef<ParameterFieldProps, ParameterFieldInterface>(
props.scope.eventsBasedBehavior || props.scope.eventsBasedObject;
const functionsContainer = eventsBasedEntity
? eventsBasedEntity.getEventsFunctions()
: props.scope.eventsFunctionsExtension
? props.scope.eventsFunctionsExtension.getEventsFunctions()
: null;
: props.scope.eventsFunctionsExtension;
const parameters: Array<gdParameterMetadata> =
props.scope.eventsFunction && functionsContainer
? enumerateParametersUsableInExpressions(

View File

@@ -372,9 +372,7 @@ const getAutocompletionsForText = function(
scope.eventsBasedBehavior || scope.eventsBasedObject;
const functionsContainer = eventsBasedEntity
? eventsBasedEntity.getEventsFunctions()
: scope.eventsFunctionsExtension
? scope.eventsFunctionsExtension.getEventsFunctions()
: null;
: scope.eventsFunctionsExtension;
const eventsFunction = scope.eventsFunction;
if (eventsFunction && functionsContainer) {
const allowedParameterTypes = completionDescription

View File

@@ -146,7 +146,13 @@ const getDashboardItemsToDisplay = ({
orderBy: GamesDashboardOrderBy,
|}): ?Array<DashboardItem> => {
if (!allDashboardItems) return null;
let itemsToDisplay: DashboardItem[] = [...allDashboardItems];
let itemsToDisplay: DashboardItem[] = allDashboardItems.filter(
item =>
// First, filter out unsaved games, unless they are the opened project.
!item.game ||
item.game.savedStatus !== 'draft' ||
(project && item.game.id === project.getProjectUuid())
);
if (searchText) {
// If there is a search, just return those items, ordered by the search relevance.
@@ -159,15 +165,14 @@ const getDashboardItemsToDisplay = ({
itemsToDisplay = searchResults.map(result => result.item);
} else {
// If there is no search, sort the items by the selected order.
if (orderBy) {
itemsToDisplay.sort(
orderBy === 'totalSessions'
? totalSessionsSort
: orderBy === 'weeklySessions'
? lastWeekSessionsSort
: lastModifiedAtSort
);
}
itemsToDisplay =
orderBy === 'totalSessions'
? itemsToDisplay.sort(totalSessionsSort)
: orderBy === 'weeklySessions'
? itemsToDisplay.sort(lastWeekSessionsSort)
: orderBy === 'lastModifiedAt'
? itemsToDisplay.sort(lastModifiedAtSort)
: itemsToDisplay;
// If a project is opened, no search is done, and sorted by last modified date,
// then the opened project should be displayed first.
@@ -320,21 +325,9 @@ const GamesList = ({
file => !games.find(game => game.id === file.fileMetadata.gameId)
)
.map(file => ({ projectFiles: [file] }));
const allItems = [...projectFilesWithGame, ...projectFilesWithoutGame];
return allItems.filter(
item =>
// Filter out draft games which don't have a project file linked to it (local or cloud)
// and which are not the current opened project.
!(
item.game &&
item.game.savedStatus === 'draft' &&
(!item.projectFiles || !item.projectFiles.length) &&
(!project || item.game.id !== project.getProjectUuid())
)
);
return [...projectFilesWithGame, ...projectFilesWithoutGame];
},
[games, allRecentProjectFiles, project]
[games, allRecentProjectFiles]
);
const totalNumberOfPages = allDashboardItems

View File

@@ -1,6 +1,5 @@
// @flow
import * as React from 'react';
import { Trans } from '@lingui/macro';
import Rectangle from '../Utils/Rectangle';
import useOnResize from '../Utils/UseOnResize';
import useForceUpdate from '../Utils/UseForceUpdate';
@@ -14,7 +13,6 @@ import Mouse from '../UI/CustomSvgIcons/Mouse';
import useIsElementVisibleInScroll from '../Utils/UseIsElementVisibleInScroll';
import { aboveMaterialUiMaxZIndex } from '../UI/MaterialUISpecificUtil';
import { useResponsiveWindowSize } from '../UI/Responsive/ResponsiveWindowMeasurer';
import Text from '../UI/Text';
type Props = {|
element: HTMLElement,
@@ -42,7 +40,6 @@ const styles = {
boxShadow: `0 0 12px 2px ${highlighterPrimaryColor}`,
padding: '2px 5px 2px 2px',
borderRadius: 3,
gap: 1,
},
};
@@ -165,7 +162,7 @@ function InAppTutorialElementHighlighter({ element }: Props) {
? scrollParentRectangle.left + 15
: scrollDirection === 'right'
? scrollParentRectangle.right - 50
: elementRectangle.centerX() - 35,
: elementRectangle.centerX() - 15,
}}
>
<div style={styles.scrollDirectionArrow}>
@@ -173,9 +170,6 @@ function InAppTutorialElementHighlighter({ element }: Props) {
<>
<Icon fontSize="large" />
{isMobile ? <PointerFinger /> : <Mouse />}
<Text noMargin color="inherit">
<Trans>Scroll</Trans>
</Text>
</>
)}
</div>

View File

@@ -90,7 +90,7 @@ const ProjectFileList = ({
onDeleteCloudProject,
disabled,
}: Props) => {
const projectFiles = useProjectsListFor(game.id);
const projectFiles = useProjectsListFor(game);
const contextMenu = React.useRef<?ContextMenuInterface>(null);
const [loadingProjectId, setLoadingProjectId] = React.useState<?string>(null);
const { removeRecentProjectFile } = React.useContext(PreferencesContext);

View File

@@ -166,9 +166,8 @@ const CreateSection = ({
authenticatedUser
);
const allRecentProjectFiles = useProjectsListFor(null);
const savedGames = (games || []).filter(game => game.savedStatus !== 'draft');
const hasAProjectOpenedNowOrRecentlyOrGameSaved =
!!project || savedGames.length || !!allRecentProjectFiles.length;
const hasAProjectOpenedOrSavedOrGameRegistered =
!!project || (!!games && games.length) || !!allRecentProjectFiles.length;
const hidePerformanceDashboard =
!!limits &&
!!limits.capabilities.classrooms &&
@@ -461,7 +460,7 @@ const CreateSection = ({
<SectionRow expand>
{!!profile || loginState === 'done' ? (
<ColumnStackLayout noMargin>
{hidePerformanceDashboard ? null : hasAProjectOpenedNowOrRecentlyOrGameSaved ? (
{hidePerformanceDashboard ? null : hasAProjectOpenedOrSavedOrGameRegistered ? (
<ColumnStackLayout noMargin>
<Grid container spacing={2}>
<UserEarningsWidget
@@ -560,7 +559,7 @@ const CreateSection = ({
/>
</ColumnStackLayout>
)}
{!hasAProjectOpenedNowOrRecentlyOrGameSaved && (
{!hasAProjectOpenedOrSavedOrGameRegistered && (
<ColumnStackLayout noMargin>
<Line noMargin justifyContent="space-between">
<Text size="block-title" noMargin>

View File

@@ -15,6 +15,7 @@ import { type PrivateGameTemplateListingData } from '../../../../Utils/GDevelopS
import { type ExampleShortHeader } from '../../../../Utils/GDevelopServices/Example';
import { type PrivateGameTemplate } from '../../../../Utils/GDevelopServices/Asset';
import { type CarouselThumbnail } from '../../../../UI/Carousel';
import { type Game } from '../../../../Utils/GDevelopServices/Game';
import {
ExampleTile,
PrivateGameTemplateTile,
@@ -100,22 +101,21 @@ export const getStorageProviderByInternalName = (
);
};
export const useProjectsListFor = (gameId: string | null) => {
export const useProjectsListFor = (game: ?Game) => {
const { getRecentProjectFiles } = React.useContext(PreferencesContext);
const authenticatedUser = React.useContext(AuthenticatedUserContext);
const { cloudProjects } = authenticatedUser;
let projectFiles: Array<FileMetadataAndStorageProviderName> = getRecentProjectFiles().filter(
file =>
!gameId || (file.fileMetadata && file.fileMetadata.gameId === gameId)
file => !game || (file.fileMetadata && file.fileMetadata.gameId === game.id)
);
if (cloudProjects) {
projectFiles = projectFiles.concat(
transformCloudProjectsIntoFileMetadataWithStorageProviderName(
cloudProjects.filter(
cloudProject => !gameId || cloudProject.gameId === gameId
cloudProject => !game || cloudProject.gameId === game.id
)
)
);

View File

@@ -33,7 +33,8 @@ export const SurveyCard = ({
</Text>
<Text noMargin size="body">
<Trans>
Answer a 1-minute survey to personalize your suggested content.
Answer a 1-minute survey to personalize your Get started
content.
</Trans>
</Text>
<Spacer />

View File

@@ -6,9 +6,9 @@ import Drawer from '@material-ui/core/Drawer';
import IconButton from '../../../UI/IconButton';
import VerticalTabButton from '../../../UI/VerticalTabButton';
import DoubleChevronArrowLeft from '../../../UI/CustomSvgIcons/DoubleChevronArrowLeft';
import HammerIcon from '../../../UI/CustomSvgIcons/Hammer';
import PickAxeIcon from '../../../UI/CustomSvgIcons/PickAxe';
import SchoolIcon from '../../../UI/CustomSvgIcons/School';
import ControllerIcon from '../../../UI/CustomSvgIcons/Controller';
import GoogleControllerIcon from '../../../UI/CustomSvgIcons/GoogleController';
import BookLeafIcon from '../../../UI/CustomSvgIcons/BookLeaf';
import SunIcon from '../../../UI/CustomSvgIcons/Sun';
import StoreIcon from '../../../UI/CustomSvgIcons/Store';
@@ -63,7 +63,7 @@ export type HomePageMenuTab = {|
const homePageMenuTabs: { [tab: HomeTab]: HomePageMenuTab } = {
'get-started': {
label: <Trans>Start</Trans>,
label: <Trans>Get Started</Trans>,
tab: 'get-started',
id: 'home-get-started-tab',
getIcon: ({ color, fontSize }) => (
@@ -75,7 +75,7 @@ const homePageMenuTabs: { [tab: HomeTab]: HomePageMenuTab } = {
tab: 'create',
id: 'home-create-tab',
getIcon: ({ color, fontSize }) => (
<HammerIcon fontSize={fontSize} color={color} />
<PickAxeIcon fontSize={fontSize} color={color} />
),
},
shop: {
@@ -99,7 +99,7 @@ const homePageMenuTabs: { [tab: HomeTab]: HomePageMenuTab } = {
tab: 'play',
id: 'home-play-tab',
getIcon: ({ color, fontSize }) => (
<ControllerIcon fontSize={fontSize} color={color} />
<GoogleControllerIcon fontSize={fontSize} color={color} />
),
},
'team-view': {

View File

@@ -20,19 +20,18 @@ import {
import { Toolbar, ToolbarGroup } from '../../../UI/Toolbar';
import AuthenticatedUserContext from '../../../Profile/AuthenticatedUserContext';
import { SECTION_DESKTOP_SPACING } from './SectionContainer';
import Text from '../../../UI/Text';
const iconSize = 24;
const iconButtonPadding = 4;
const iconSize = 20;
const iconButtonPadding = 8;
/**
* Padding bottom is bigger than padding top to leave space for the Android/iOS
* bottom navigation bar.
*/
const iconButtonMarginBottom = 12;
const iconButtonLabelSize = 20;
const iconButtonLabelPadding = 4;
const toolbarHeight =
iconSize +
iconButtonLabelSize +
2 * iconButtonLabelPadding +
2 * iconButtonPadding +
iconButtonMarginBottom;
export const homepageDesktopMenuBarWidth = 230;
@@ -58,12 +57,6 @@ export const styles = {
fontSize: iconSize,
height: toolbarHeight,
},
buttonContainer: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flex: 1,
},
bottomButtonsContainer: {
marginBottom: 'env(safe-area-inset-bottom)',
},
@@ -72,11 +65,7 @@ export const styles = {
marginBottom: iconButtonMarginBottom,
fontSize: 'inherit',
},
icon: {
display: 'flex',
justifyContent: 'center',
marginBottom: 2,
},
buttonLabel: { padding: iconButtonLabelPadding, display: 'flex' },
};
type Props = {|
@@ -96,7 +85,7 @@ const HomePageMenuBar = ({
}: Props) => {
const { isMobile, isMediumScreen } = useResponsiveWindowSize();
const isMobileOrSmallScreen = isMobile || isMediumScreen;
const gdevelopTheme = React.useContext(GDevelopThemeContext);
const theme = React.useContext(GDevelopThemeContext);
const { limits } = React.useContext(AuthenticatedUserContext);
const tabsToDisplay = getTabsToDisplay({ limits });
const largeScreenOnlyButtons: {
@@ -130,54 +119,33 @@ const HomePageMenuBar = ({
square
style={{
...styles.mobileContainer,
borderTop: `1px solid ${gdevelopTheme.home.separator.color}`,
borderTop: `1px solid ${theme.home.separator.color}`,
}}
>
<Toolbar height={toolbarHeight}>
<ToolbarGroup spaceOut>
<ToolbarGroup>
{tabsToDisplay.map(({ label, tab, getIcon, id }) => {
const isActive = activeTab === tab;
return (
<div
style={{
...styles.buttonContainer,
borderTop: `3px solid ${
isActive
? gdevelopTheme.iconButton.selectedBackgroundColor
: // Always keep the border so there's no layout shift.
'transparent'
}`,
...(!isActive
? { color: gdevelopTheme.text.color.secondary }
: {}),
<IconButton
color="default"
key={id}
disableRipple
disableFocusRipple
style={styles.mobileButton}
onClick={() => {
setActiveTab(tab);
}}
selected={isActive}
id={id}
>
<IconButton
color="inherit"
key={id}
disableRipple
disableFocusRipple
disableHover
style={styles.mobileButton}
onClick={() => {
setActiveTab(tab);
}}
selected={false}
id={id}
>
<Column noMargin>
<span style={styles.icon}>
{getIcon({
color: 'inherit',
fontSize: 'inherit',
})}
</span>
<Text size="body-small" color="inherit" noMargin>
{label}
</Text>
</Column>
</IconButton>
</div>
<span style={styles.buttonLabel}>
{getIcon({
color: isActive ? 'inherit' : 'secondary',
fontSize: 'inherit',
})}
</span>
</IconButton>
);
})}
</ToolbarGroup>
@@ -190,7 +158,7 @@ const HomePageMenuBar = ({
<Paper
style={{
...(isMobileOrSmallScreen ? styles.mobileMenu : styles.desktopMenu),
borderRight: `1px solid ${gdevelopTheme.home.separator.color}`,
borderRight: `1px solid ${theme.home.separator.color}`,
}}
square
background="dark"

View File

@@ -134,20 +134,6 @@ const GuidedLessons = ({ selectInAppTutorial, lessonsIds }: Props) => {
durationInMinutes: 1,
renderImage: props => <Platformer {...props} />,
},
{
id: OBJECT_3D_IN_APP_TUTORIAL_ID,
title: t`3D platforms`,
description: t`Place 3D platforms in this 2D platformer, creating a path to the end.`,
durationInMinutes: 2,
renderImage: props => <Object3D {...props} />,
},
{
id: CAMERA_PARALLAX_IN_APP_TUTORIAL_ID,
title: t`Background and cameras`,
description: t`Follow this Castlevania-type chraracter with the camera, while the background scrolls.`,
durationInMinutes: 2,
renderImage: props => <Parallax {...props} />,
},
{
id: TOP_DOWN_RPG_MOVEMENT_ID,
title: t`Top-Down RPG Pixel Perfect`,
@@ -155,6 +141,13 @@ const GuidedLessons = ({ selectInAppTutorial, lessonsIds }: Props) => {
durationInMinutes: 2,
renderImage: props => <TopDownRPGMovement {...props} />,
},
{
id: FIRE_A_BULLET_ID,
title: t`Fire a Bullet`,
description: t`Fire bullets in this Asteroids game. Get ready for a Star Wars show.`,
durationInMinutes: 3,
renderImage: props => <FireABullet {...props} />,
},
{
id: JOYSTICK_IN_APP_TUTORIAL_ID,
title: t`Joystick controls`,
@@ -162,6 +155,13 @@ const GuidedLessons = ({ selectInAppTutorial, lessonsIds }: Props) => {
durationInMinutes: 1,
renderImage: props => <Joystick {...props} />,
},
{
id: OBJECT_3D_IN_APP_TUTORIAL_ID,
title: t`3D platforms`,
description: t`Place 3D platforms in this 2D platformer, creating a path to the end.`,
durationInMinutes: 2,
renderImage: props => <Object3D {...props} />,
},
{
id: COOP_PLATFORMER_ID,
title: t`Co-op Multiplayer`,
@@ -177,11 +177,11 @@ const GuidedLessons = ({ selectInAppTutorial, lessonsIds }: Props) => {
renderImage: props => <HealthBar {...props} />,
},
{
id: FIRE_A_BULLET_ID,
title: t`Fire a Bullet`,
description: t`Fire bullets in this Asteroids game. Get ready for a Star Wars show.`,
durationInMinutes: 3,
renderImage: props => <FireABullet {...props} />,
id: CAMERA_PARALLAX_IN_APP_TUTORIAL_ID,
title: t`Background and cameras`,
description: t`Follow this Castlevania-type chraracter with the camera, while the background scrolls.`,
durationInMinutes: 2,
renderImage: props => <Parallax {...props} />,
},
{
id: TIMER_IN_APP_TUTORIAL_ID,

View File

@@ -173,7 +173,7 @@ const CourseSection = ({
style={textEllipsisStyle}
color={chapter.isLocked ? 'secondary' : 'primary'}
>
{chapter.shortTitle || chapter.title}
{chapter.title}
</Text>
</Line>
{chapter.isLocked ? (

View File

@@ -29,7 +29,7 @@ import GridListTile from '@material-ui/core/GridListTile';
import ImageTileRow from '../../../../UI/ImageTileRow';
import { formatTutorialToImageTileComponent, TUTORIAL_CATEGORY_TEXTS } from '.';
import GuidedLessons from '../InAppTutorials/GuidedLessons';
import ArrowRight from '../../../../UI/CustomSvgIcons/ArrowRight';
import ChevronArrowRight from '../../../../UI/CustomSvgIcons/ChevronArrowRight';
import Upload from '../../../../UI/CustomSvgIcons/Upload';
import FlingGame from '../InAppTutorials/FlingGame';
import AuthenticatedUserContext from '../../../../Profile/AuthenticatedUserContext';
@@ -129,7 +129,7 @@ export const TutorialsRow = ({
})
)}
onShowAll={() => onSelectCategory(category)}
showAllIcon={<ArrowRight fontSize="small" />}
showAllIcon={<ChevronArrowRight fontSize="small" />}
getColumnsFromWindowSize={getTutorialsColumnsFromWidth}
getLimitFromWindowSize={getTutorialsColumnsFromWidth}
/>

View File

@@ -31,7 +31,7 @@ import AlertMessage from '../../../../../UI/AlertMessage';
import Link from '../../../../../UI/Link';
import TeamAvailableSeats from '../TeamAvailableSeats';
import { copyTextToClipboard } from '../../../../../Utils/Clipboard';
import ChevronArrowRight from '../../../../../UI/CustomSvgIcons/ChevronArrowRight';
import ChevronArrowTop from '../../../../../UI/CustomSvgIcons/ChevronArrowTop';
import ChevronArrowBottom from '../../../../../UI/CustomSvgIcons/ChevronArrowBottom';
import Paper from '../../../../../UI/Paper';
import Checkbox from '../../../../../UI/Checkbox';
@@ -930,7 +930,7 @@ const ManageEducationAccountDialog = ({ onClose }: Props) => {
setIsArchivedAccountsSectionOpen(false)
}
>
<ChevronArrowBottom />
<ChevronArrowTop />
</IconButton>
) : (
<IconButton
@@ -941,7 +941,7 @@ const ManageEducationAccountDialog = ({ onClose }: Props) => {
setIsArchivedAccountsSectionOpen(true)
}
>
<ChevronArrowRight />
<ChevronArrowBottom />
</IconButton>
)}
<Text size="sub-title">

View File

@@ -179,15 +179,6 @@ export const buildMainMenuDeclarativeTemplate = ({
onClickSendEvent: 'main-menu-close',
enabled: !!project,
},
...(!isMacLike() || !isApplicationTopLevelMenu
? [
{ type: 'separator' },
{
label: i18n._(t`Preferences`),
onClickSendEvent: 'main-menu-open-preferences',
},
]
: []),
],
};

View File

@@ -2,15 +2,14 @@
import { Trans } from '@lingui/macro';
import React, { useContext } from 'react';
import SelectField from '../../UI/SelectField';
import SelectOption from '../../UI/SelectOption';
import { Column } from '../../UI/Grid';
import { Column, Line } from '../../UI/Grid';
import Window from '../../Utils/Window';
import PreferencesContext from './PreferencesContext';
import LocalesMetadata from '../../locales/LocalesMetadata';
import Text from '../../UI/Text';
import Link from '../../UI/Link';
import { LineStackLayout } from '../../UI/Layout';
import CompactSelectField from '../../UI/CompactSelectField';
type Props = {|
onLanguageChanged: (language: string) => void,
@@ -53,31 +52,26 @@ const LanguageSelector = ({ onLanguageChanged }: Props) => {
return (
<Column noMargin>
<LineStackLayout noMargin alignItems="center">
<Column noMargin expand>
<Text noMargin>
<Trans>Choose GDevelop language</Trans>
</Text>
</Column>
<Column noMargin expand>
<CompactSelectField
value={values.language}
onChange={(value: string) => {
setLanguage(value);
onLanguageChanged(value);
}}
>
<SelectOption value="en" label="English (default)" />
{goodProgressLocales.map(localeMetadata =>
renderLanguageSelectOption(localeMetadata)
)}
{startedLocales.map(localeMetadata =>
renderLanguageSelectOption(localeMetadata)
)}
</CompactSelectField>
</Column>
</LineStackLayout>
<Text color="secondary">
<Line noMargin expand>
<SelectField
floatingLabelText={<Trans>Choose GDevelop language</Trans>}
value={values.language}
onChange={(e, i, value: string) => {
setLanguage(value);
onLanguageChanged(value);
}}
fullWidth
>
<SelectOption value="en" label="English (default)" />
{goodProgressLocales.map(localeMetadata =>
renderLanguageSelectOption(localeMetadata)
)}
{startedLocales.map(localeMetadata =>
renderLanguageSelectOption(localeMetadata)
)}
</SelectField>
</Line>
<Text>
<Trans>
You can{' '}
<Link

View File

@@ -49,6 +49,7 @@ export type AlertMessageIdentifier =
export type EditorMosaicName =
| 'scene-editor'
| 'scene-editor-small'
| 'debugger'
| 'resources-editor'
| 'events-functions-extension-editor';
@@ -274,9 +275,7 @@ export type Preferences = {|
name: EditorMosaicName,
node: ?EditorMosaicNode
) => void,
getRecentProjectFiles: (
options: ?{| limit: number |}
) => Array<FileMetadataAndStorageProviderName>,
getRecentProjectFiles: () => Array<FileMetadataAndStorageProviderName>,
insertRecentProjectFile: (
fileMetadata: FileMetadataAndStorageProviderName
) => void,
@@ -425,7 +424,7 @@ export const initialPreferences = {
name: EditorMosaicName,
node: ?EditorMosaicNode
) => {},
getRecentProjectFiles: options => [],
getRecentProjectFiles: () => [],
insertRecentProjectFile: () => {},
removeRecentProjectFile: () => {},
getAutoOpenMostRecentProject: () => true,

View File

@@ -3,20 +3,22 @@ import { t, Trans } from '@lingui/macro';
import { type I18n } from '@lingui/core';
import React from 'react';
import SelectField from '../../UI/SelectField';
import FlatButton from '../../UI/FlatButton';
import LocalFolderPicker from '../../UI/LocalFolderPicker';
import SelectOption from '../../UI/SelectOption';
import { CompactToggleField } from '../../UI/CompactToggleField';
import Toggle from '../../UI/Toggle';
import Dialog from '../../UI/Dialog';
import { Column, Line } from '../../UI/Grid';
import { Column, Line, Spacer } from '../../UI/Grid';
import { themes } from '../../UI/Theme/ThemeRegistry';
import { getAllThemes } from '../../CodeEditor/Theme';
import Window from '../../Utils/Window';
import optionalRequire from '../../Utils/OptionalRequire';
import PreferencesContext from './PreferencesContext';
import Text from '../../UI/Text';
import { ColumnStackLayout, LineStackLayout } from '../../UI/Layout';
import { ColumnStackLayout, ResponsiveLineStackLayout } from '../../UI/Layout';
import { Tabs } from '../../UI/Tabs';
import RaisedButton from '../../UI/RaisedButton';
import ShortcutsList from '../../KeyboardShortcuts/ShortcutsList';
import LanguageSelector from './LanguageSelector';
import Link from '../../UI/Link';
@@ -26,7 +28,6 @@ import { getElectronAccelerator } from '../../KeyboardShortcuts';
import defaultShortcuts from '../../KeyboardShortcuts/DefaultShortcuts';
import AlertMessage from '../../UI/AlertMessage';
import ErrorBoundary from '../../UI/ErrorBoundary';
import CompactSelectField from '../../UI/CompactSelectField';
const electron = optionalRequire('electron');
type Props = {|
@@ -121,102 +122,97 @@ const PreferencesDialog = ({
<Text size="block-title">
<Trans>Language</Trans>
</Text>
<Column>
<LanguageSelector
onLanguageChanged={() => {
setLanguageDidChange(true);
}}
/>
</Column>
<LanguageSelector
onLanguageChanged={() => {
setLanguageDidChange(true);
}}
/>
<Text size="block-title">
<Trans>Appearance</Trans>
</Text>
<ColumnStackLayout>
<LineStackLayout noMargin alignItems="center">
<Column noMargin expand>
<Text noMargin>
<Trans>UI Theme</Trans>
</Text>
</Column>
<Column noMargin expand>
<CompactSelectField
value={values.themeName}
onChange={(value: string) => setThemeName(value)}
>
{Object.keys(themes).map(themeName => (
<SelectOption
value={themeName}
label={themeName}
key={themeName}
/>
))}
</CompactSelectField>
</Column>
</LineStackLayout>
<LineStackLayout noMargin alignItems="center">
<Column noMargin expand>
<Text noMargin>
<Trans>Code editor Theme</Trans>
</Text>
</Column>
<Column noMargin expand>
<CompactSelectField
value={values.codeEditorThemeName}
onChange={(value: string) => setCodeEditorThemeName(value)}
>
{getAllThemes().map(codeEditorTheme => (
<SelectOption
value={codeEditorTheme.themeName}
label={codeEditorTheme.name}
key={codeEditorTheme.themeName}
/>
))}
</CompactSelectField>
</Column>
</LineStackLayout>
<Line noMargin>
<Text color="secondary">
<Trans>
You can contribute and{' '}
<Link
href={
<ResponsiveLineStackLayout noMargin>
<SelectField
floatingLabelText={<Trans>UI Theme</Trans>}
value={values.themeName}
onChange={(e, i, value: string) => setThemeName(value)}
fullWidth
>
{Object.keys(themes).map(themeName => (
<SelectOption
value={themeName}
label={themeName}
key={themeName}
/>
))}
</SelectField>
<SelectField
floatingLabelText={<Trans>Code editor Theme</Trans>}
value={values.codeEditorThemeName}
onChange={(e, i, value: string) => setCodeEditorThemeName(value)}
fullWidth
>
{getAllThemes().map(codeEditorTheme => (
<SelectOption
value={codeEditorTheme.themeName}
label={codeEditorTheme.name}
key={codeEditorTheme.themeName}
/>
))}
</SelectField>
</ResponsiveLineStackLayout>
<Line noMargin>
<Text>
<Trans>
You can contribute and{' '}
<Link
href={
'https://github.com/4ian/GDevelop/blob/master/newIDE/README-themes.md'
}
onClick={() =>
Window.openExternalURL(
'https://github.com/4ian/GDevelop/blob/master/newIDE/README-themes.md'
}
onClick={() =>
Window.openExternalURL(
'https://github.com/4ian/GDevelop/blob/master/newIDE/README-themes.md'
)
}
>
create your own themes
</Link>
.
</Trans>
</Text>
</Line>
</ColumnStackLayout>
)
}
>
create your own themes
</Link>
.
</Trans>
</Text>
</Line>
<Text size="block-title">
<Trans>Layouts</Trans>
</Text>
<ColumnStackLayout expand>
<FlatButton
<Column noMargin>
<RaisedButton
label={<Trans>Reset Scene Editor layout</Trans>}
onClick={() => setDefaultEditorMosaicNode('scene-editor', null)}
disabled={!getDefaultEditorMosaicNode('scene-editor')}
/>
<FlatButton
<Spacer />
<RaisedButton
label={<Trans>Reset Scene Editor (small window) layout</Trans>}
onClick={() =>
setDefaultEditorMosaicNode('scene-editor-small', null)
}
disabled={!getDefaultEditorMosaicNode('scene-editor-small')}
/>
<Spacer />
<RaisedButton
label={<Trans>Reset Debugger layout</Trans>}
onClick={() => setDefaultEditorMosaicNode('debugger', null)}
disabled={!getDefaultEditorMosaicNode('debugger')}
/>
<FlatButton
<Spacer />
<RaisedButton
label={<Trans>Reset Resource Editor layout</Trans>}
onClick={() =>
setDefaultEditorMosaicNode('resources-editor', null)
}
disabled={!getDefaultEditorMosaicNode('resources-editor')}
/>
<FlatButton
<Spacer />
<RaisedButton
label={<Trans>Reset Extension Editor layout</Trans>}
onClick={() =>
setDefaultEditorMosaicNode(
@@ -228,383 +224,335 @@ const PreferencesDialog = ({
!getDefaultEditorMosaicNode('events-functions-extension-editor')
}
/>
</ColumnStackLayout>
</Column>
<Text size="block-title">
<Trans>Dialogs</Trans>
</Text>
<ColumnStackLayout>
<LineStackLayout noMargin alignItems="center">
<Column noMargin expand>
<Text noMargin>
<Trans>Dialog backdrop click behavior</Trans>
</Text>
</Column>
<Column noMargin expand>
<CompactSelectField
value={values.backdropClickBehavior}
onChange={(value: string) => setBackdropClickBehavior(value)}
>
<SelectOption value="cancel" label={t`Cancel changes`} />
<SelectOption value="apply" label={t`Apply changes`} />
<SelectOption value="nothing" label={t`Do nothing`} />
</CompactSelectField>
</Column>
</LineStackLayout>
{!!electron && (
<LineStackLayout noMargin alignItems="center">
<Column noMargin expand>
<Text noMargin>
<Trans>
Importing resources outside from the project folder
</Trans>
</Text>
</Column>
<Column noMargin expand>
<CompactSelectField
value={values.resourcesImporationBehavior}
onChange={(value: string) =>
setResourcesImporationBehavior(value)
}
>
<SelectOption
value="import"
label={t`Copy them into the project folder`}
/>
<SelectOption
value="relative"
label={t`Keep their original location`}
/>
<SelectOption value="ask" label={t`Ask every time`} />
</CompactSelectField>
</Column>
</LineStackLayout>
)}
</ColumnStackLayout>
<SelectField
floatingLabelText={<Trans>Dialog backdrop click behavior</Trans>}
value={values.backdropClickBehavior}
onChange={(e, i, value: string) => setBackdropClickBehavior(value)}
fullWidth
>
<SelectOption value="cancel" label={t`Cancel changes`} />
<SelectOption value="apply" label={t`Apply changes`} />
<SelectOption value="nothing" label={t`Do nothing`} />
</SelectField>
{!!electron && (
<SelectField
floatingLabelText={
<Trans>
Importing resources outside from the project folder
</Trans>
}
value={values.resourcesImporationBehavior}
onChange={(e, i, value: string) =>
setResourcesImporationBehavior(value)
}
fullWidth
>
<SelectOption
value="import"
label={t`Copy them into the project folder`}
/>
<SelectOption
value="relative"
label={t`Keep their original location`}
/>
<SelectOption value="ask" label={t`Ask every time`} />
</SelectField>
)}
<Text size="block-title">
<Trans>Updates</Trans>
</Text>
<ColumnStackLayout expand>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setAutoDownloadUpdates}
checked={values.autoDownloadUpdates}
label={i18n._(t`Auto download and install updates (recommended)`)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setAutoDisplayChangelog}
checked={values.autoDisplayChangelog}
label={i18n._(
t`Display What's New when a new version is launched (recommended)`
)}
/>
</ColumnStackLayout>
<Toggle
onToggle={(e, check) => setAutoDownloadUpdates(check)}
toggled={values.autoDownloadUpdates}
labelPosition="right"
label={
<Trans>Auto download and install updates (recommended)</Trans>
}
/>
<Toggle
onToggle={(e, check) => setAutoDisplayChangelog(check)}
toggled={values.autoDisplayChangelog}
labelPosition="right"
label={
<Trans>
Display What's New when a new version is launched (recommended)
</Trans>
}
/>
<Text size="block-title">
<Trans>Events Sheet</Trans>
</Text>
<ColumnStackLayout expand>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setEventsSheetShowObjectThumbnails}
checked={values.eventsSheetShowObjectThumbnails}
label={i18n._(t`Display object thumbnails in Events Sheets`)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setEventsSheetUseAssignmentOperators}
checked={values.eventsSheetUseAssignmentOperators}
label={i18n._(t`Display assignment operators in Events Sheets`)}
/>
<LineStackLayout noMargin alignItems="center">
<Column noMargin expand>
<Text noMargin>
<Trans>Indent Scale in Events Sheet</Trans>
</Text>
</Column>
<Column noMargin expand>
<CompactSelectField
value={values.eventsSheetIndentScale.toString()}
onChange={(value: string) =>
setEventsSheetIndentScale(parseInt(value, 10))
}
>
<SelectOption value="1" label={t`100% (Default)`} />
<SelectOption value="2" label={t`200%`} />
<SelectOption value="3" label={t`300%`} />
<SelectOption value="4" label={t`400%`} />
<SelectOption value="5" label={t`500%`} />
<SelectOption value="6" label={t`600%`} />
<SelectOption value="7" label={t`700%`} />
<SelectOption value="8" label={t`800%`} />
</CompactSelectField>
</Column>
</LineStackLayout>
<LineStackLayout noMargin alignItems="center">
<Column noMargin expand>
<Text noMargin>
<Trans>
Escape key behavior when editing an parameter inline
</Trans>
</Text>
</Column>
<Column noMargin expand>
<CompactSelectField
value={values.eventsSheetCancelInlineParameter}
onChange={(value: string) =>
setEventsSheetCancelInlineParameter(value)
}
>
<SelectOption value="cancel" label={t`Cancel changes`} />
<SelectOption value="apply" label={t`Apply changes`} />
</CompactSelectField>
</Column>
</LineStackLayout>
</ColumnStackLayout>
<Toggle
onToggle={(e, check) => setEventsSheetShowObjectThumbnails(check)}
toggled={values.eventsSheetShowObjectThumbnails}
labelPosition="right"
label={<Trans>Display object thumbnails in Events Sheets</Trans>}
/>
<Toggle
onToggle={(e, check) => setEventsSheetUseAssignmentOperators(check)}
toggled={values.eventsSheetUseAssignmentOperators}
labelPosition="right"
label={<Trans>Display assignment operators in Events Sheets</Trans>}
/>
<SelectField
floatingLabelText={<Trans>Indent Scale in Events Sheet</Trans>}
fullWidth
value={values.eventsSheetIndentScale.toString()}
onChange={(e, i, value) => {
setEventsSheetIndentScale(parseInt(value, 10));
}}
>
<SelectOption value="1" label={t`100% (Default)`} />
<SelectOption value="2" label={t`200%`} />
<SelectOption value="3" label={t`300%`} />
<SelectOption value="4" label={t`400%`} />
<SelectOption value="5" label={t`500%`} />
<SelectOption value="6" label={t`600%`} />
<SelectOption value="7" label={t`700%`} />
<SelectOption value="8" label={t`800%`} />
</SelectField>
<SelectField
floatingLabelText={
<Trans>
Escape key behavior when editing an parameter inline
</Trans>
}
value={values.eventsSheetCancelInlineParameter}
onChange={(e, i, value: string) => {
setEventsSheetCancelInlineParameter(value);
}}
fullWidth
>
<SelectOption value="cancel" label={t`Cancel changes`} />
<SelectOption value="apply" label={t`Apply changes`} />
</SelectField>
<Text size="block-title">
<Trans>Embedded help and tutorials</Trans>
</Text>
<ColumnStackLayout expand>
<FlatButton
label={<Trans>Reset hidden embedded explanations</Trans>}
onClick={() => showAllAlertMessages()}
disabled={!Object.keys(values.hiddenAlertMessages).length}
/>
<FlatButton
label={<Trans>Reset hidden embedded tutorials</Trans>}
onClick={() => showAllTutorialHints()}
disabled={!Object.keys(values.hiddenTutorialHints).length}
/>
<FlatButton
label={<Trans>Reset hidden announcements</Trans>}
onClick={() => showAllAnnouncements()}
disabled={!Object.keys(values.hiddenAnnouncements).length}
/>
</ColumnStackLayout>
<Column noMargin>
<Text size="block-title">
<Trans>Advanced</Trans>
</Text>
<ColumnStackLayout>
<Text size="sub-title">
<Trans>Previews</Trans>
</Text>
<ColumnStackLayout>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setAutosaveOnPreview}
checked={values.autosaveOnPreview}
label={i18n._(t`Auto-save project on preview`)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setFetchPlayerTokenForPreviewAutomatically}
checked={values.fetchPlayerTokenForPreviewAutomatically}
label={i18n._(t`Automatically log in as a player in preview`)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setOpenDiagnosticReportAutomatically}
checked={values.openDiagnosticReportAutomatically}
label={i18n._(
t`Automatically open the diagnostic report at preview`
)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={check =>
setPreviewCrashReportUploadLevel(
check ? 'exclude-javascript-code-events' : 'none'
)
}
checked={values.previewCrashReportUploadLevel !== 'none'}
label={i18n._(
t`Send crash reports during previews to GDevelop`
)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setTakeScreenshotOnPreview}
checked={values.takeScreenshotOnPreview}
label={i18n._(
t`Automatically take a screenshot in game previews`
)}
/>
{electron && (
<>
<ColumnStackLayout expand noMargin>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setIsMenuBarHiddenInPreview}
checked={values.isMenuBarHiddenInPreview}
label={i18n._(
t`Hide the menu bar in the preview window`
)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setIsAlwaysOnTopInPreview}
checked={values.isAlwaysOnTopInPreview}
label={i18n._(
t`Always display the preview window on top of the editor`
)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setUseShortcutToClosePreviewWindow}
checked={values.useShortcutToClosePreviewWindow}
label={i18n._(
t`Enable "Close project" shortcut (${adaptAcceleratorString(
getElectronAccelerator(
values.userShortcutMap['CLOSE_PROJECT'] ||
defaultShortcuts['CLOSE_PROJECT']
)
)}) to close preview window`
)}
/>
</ColumnStackLayout>
</>
)}
</ColumnStackLayout>
<Text size="sub-title">
<Trans>Scene editor</Trans>
</Text>
<ColumnStackLayout>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setShowBasicProfilingCounters}
checked={values.showBasicProfilingCounters}
label={i18n._(
t`Display profiling information in scene editor`
)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setUse3DEditor}
checked={values.use3DEditor}
label={i18n._(t`Show objects in 3D in the scene editor`)}
/>
{initialUse3DEditor.current !== values.use3DEditor && (
<AlertMessage kind="info">
<Trans>
For the 3D change to take effect, close and reopen all
currently opened scenes.
</Trans>
</AlertMessage>
)}
</ColumnStackLayout>
<Text size="sub-title">
<Trans>Other</Trans>
</Text>
<ColumnStackLayout>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={check =>
setDisplaySaveReminder({ activated: check })
}
checked={values.displaySaveReminder.activated}
label={i18n._(
t`Display save reminder after significant changes in project`
)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setAutoOpenMostRecentProject}
checked={values.autoOpenMostRecentProject}
label={i18n._(
t`Automatically re-open the project edited during last session`
)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setShowCommunityExtensions}
checked={values.showCommunityExtensions}
label={i18n._(
t`Show community (non reviewed) extensions in the list of extensions`
)}
/>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setShowDeprecatedInstructionWarning}
checked={values.showDeprecatedInstructionWarning}
label={i18n._(
t`Show a warning on deprecated actions and conditions`
)}
/>
{!!electron && (
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={check =>
setWatchProjectFolderFilesForLocalProjects(check)
}
checked={values.watchProjectFolderFilesForLocalProjects}
label={i18n._(
t`Watch the project folder for file changes in order to refresh the resources used in the editor (images, 3D models, fonts, etc.)`
)}
/>
)}
</ColumnStackLayout>
</ColumnStackLayout>
<Line>
<RaisedButton
label={<Trans>Reset hidden embedded explanations</Trans>}
onClick={() => showAllAlertMessages()}
disabled={!Object.keys(values.hiddenAlertMessages).length}
/>
</Line>
<Line>
<RaisedButton
label={<Trans>Reset hidden embedded tutorials</Trans>}
onClick={() => showAllTutorialHints()}
disabled={!Object.keys(values.hiddenTutorialHints).length}
/>
</Line>
<Line>
<RaisedButton
label={<Trans>Reset hidden announcements</Trans>}
onClick={() => showAllAnnouncements()}
disabled={!Object.keys(values.hiddenAnnouncements).length}
/>
</Line>
</Column>
<Text size="block-title">
<Trans>Advanced</Trans>
</Text>
<Toggle
onToggle={(e, check) => setAutosaveOnPreview(check)}
toggled={values.autosaveOnPreview}
labelPosition="right"
label={<Trans>Auto-save project on preview</Trans>}
/>
<Toggle
onToggle={(e, check) =>
setFetchPlayerTokenForPreviewAutomatically(check)
}
toggled={values.fetchPlayerTokenForPreviewAutomatically}
labelPosition="right"
label={<Trans>Automatically log in as a player in preview</Trans>}
/>
<Toggle
onToggle={(e, check) =>
setDisplaySaveReminder({ activated: check })
}
toggled={values.displaySaveReminder.activated}
labelPosition="right"
label={
<Trans>
Display save reminder after significant changes in project
</Trans>
}
/>
<Toggle
onToggle={(e, check) => setAutoOpenMostRecentProject(check)}
toggled={values.autoOpenMostRecentProject}
labelPosition="right"
label={
<Trans>
Automatically re-open the project edited during last session
</Trans>
}
/>
<Toggle
onToggle={(e, check) => setShowCommunityExtensions(check)}
toggled={values.showCommunityExtensions}
labelPosition="right"
label={
<Trans>
Show community (non reviewed) extensions in the list of
extensions
</Trans>
}
/>
{!!electron && (
<Toggle
onToggle={(e, check) =>
setWatchProjectFolderFilesForLocalProjects(check)
}
toggled={values.watchProjectFolderFilesForLocalProjects}
labelPosition="right"
label={
<Trans>
Watch the project folder for file changes in order to refresh
the resources used in the editor (images, 3D models, fonts,
etc.)
</Trans>
}
/>
)}
<Toggle
onToggle={(e, check) => setOpenDiagnosticReportAutomatically(check)}
toggled={values.openDiagnosticReportAutomatically}
labelPosition="right"
label={
<Trans>Automatically open the diagnostic report at preview</Trans>
}
/>
<Toggle
onToggle={(e, check) =>
setPreviewCrashReportUploadLevel(
check ? 'exclude-javascript-code-events' : 'none'
)
}
toggled={values.previewCrashReportUploadLevel !== 'none'}
labelPosition="right"
label={
<Trans>Send crash reports during previews to GDevelop</Trans>
}
/>
<Toggle
onToggle={(e, check) => setTakeScreenshotOnPreview(check)}
toggled={values.takeScreenshotOnPreview}
labelPosition="right"
label={
<Trans>Automatically take a screenshot in game previews</Trans>
}
/>
<Toggle
onToggle={(e, check) => setShowDeprecatedInstructionWarning(check)}
toggled={values.showDeprecatedInstructionWarning}
labelPosition="right"
label={
<Trans>Show a warning on deprecated actions and conditions</Trans>
}
/>
<Toggle
onToggle={(e, check) => setShowBasicProfilingCounters(check)}
toggled={values.showBasicProfilingCounters}
labelPosition="right"
label={<Trans>Display profiling information in scene editor</Trans>}
/>
<Toggle
onToggle={(e, check) => setUse3DEditor(check)}
toggled={values.use3DEditor}
labelPosition="right"
label={<Trans>Show objects in 3D in the scene editor</Trans>}
/>
{initialUse3DEditor.current !== values.use3DEditor && (
<AlertMessage kind="info">
<Trans>
For the 3D change to take effect, close and reopen all currently
opened scenes.
</Trans>
</AlertMessage>
)}
{electron && (
<>
<ColumnStackLayout expand noMargin>
<Toggle
onToggle={(e, check) => setIsMenuBarHiddenInPreview(check)}
toggled={values.isMenuBarHiddenInPreview}
labelPosition="right"
label={<Trans>Hide the menu bar in the preview window</Trans>}
/>
<Toggle
onToggle={(e, check) => setIsAlwaysOnTopInPreview(check)}
toggled={values.isAlwaysOnTopInPreview}
labelPosition="right"
label={
<Trans>
Always display the preview window on top of the editor
</Trans>
}
/>
<Toggle
onToggle={(e, check) =>
setUseShortcutToClosePreviewWindow(check)
}
toggled={values.useShortcutToClosePreviewWindow}
labelPosition="right"
label={
<Trans>
Enable "Close project" shortcut (
{adaptAcceleratorString(
getElectronAccelerator(
values.userShortcutMap['CLOSE_PROJECT'] ||
defaultShortcuts['CLOSE_PROJECT']
)
)}
) to close preview window
</Trans>
}
/>
</ColumnStackLayout>
</>
)}
<Text size="block-title">
<Trans>Contributor options</Trans>
</Text>
<ColumnStackLayout>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setShowInAppTutorialDeveloperMode}
checked={values.showInAppTutorialDeveloperMode}
label={i18n._(
t`Show button to load guided lesson from file and test it`
)}
/>
</ColumnStackLayout>
<Toggle
onToggle={(e, check) => setShowInAppTutorialDeveloperMode(check)}
toggled={values.showInAppTutorialDeveloperMode}
labelPosition="right"
label={
<Trans>
Show button to load guided lesson from file and test it.
</Trans>
}
/>
{Window.isDev() && (
<>
<ColumnStackLayout expand noMargin>
<Text size="block-title">
<Trans>Developer options</Trans>
</Text>
<ColumnStackLayout>
<CompactToggleField
labelColor="primary"
hideTooltip
onCheck={setUseGDJSDevelopmentWatcher}
checked={values.useGDJSDevelopmentWatcher}
label={i18n._(
t`Watch changes in game engine (GDJS) sources and auto import them (dev only)`
)}
/>
<FlatButton
fullWidth
onClick={onOpenQuickCustomizationDialog}
label={<Trans>Open quick customization</Trans>}
/>
</ColumnStackLayout>
</ColumnStackLayout>
<Text size="block-title">
<Trans>Developer options</Trans>
</Text>
<Toggle
onToggle={(e, check) => setUseGDJSDevelopmentWatcher(check)}
toggled={values.useGDJSDevelopmentWatcher}
labelPosition="right"
label={
<Trans>
Watch changes in game engine (GDJS) sources and auto import
them (dev only)
</Trans>
}
/>
<FlatButton
fullWidth
onClick={onOpenQuickCustomizationDialog}
label={<Trans>Open quick customization</Trans>}
/>
</>
)}
</ColumnStackLayout>

View File

@@ -39,6 +39,7 @@ type Props = {|
type State = Preferences;
const localStorageItem = 'gd-preferences';
const MAX_RECENT_FILES_COUNT = 20;
export const loadPreferencesFromLocalStorage = (): ?PreferencesValues => {
try {
@@ -84,7 +85,7 @@ export const getInitialPreferences = () => {
return { ...initialPreferences.values, language: languageOrLocale };
};
const getPreferences = (): PreferencesValues => {
const getPreferences = () => {
const preferences =
loadPreferencesFromLocalStorage() || getInitialPreferences();
setLanguageInDOM(preferences.language);
@@ -717,12 +718,8 @@ export default class PreferencesProvider extends React.Component<Props, State> {
);
}
_getRecentProjectFiles(
options: ?{| limit: number |}
): Array<FileMetadataAndStorageProviderName> {
const limit = options ? options.limit : undefined;
const recentProjectFiles = this.state.values.recentProjectFiles;
return limit ? recentProjectFiles.slice(0, limit) : recentProjectFiles;
_getRecentProjectFiles() {
return this.state.values.recentProjectFiles;
}
_setRecentProjectFiles(recents: Array<FileMetadataAndStorageProviderName>) {
@@ -745,19 +742,24 @@ export default class PreferencesProvider extends React.Component<Props, State> {
const isNotNewRecentFile = recentFile =>
recentFile.fileMetadata.fileIdentifier !==
newRecentFile.fileMetadata.fileIdentifier;
this._setRecentProjectFiles([
newRecentFile,
...recentProjectFiles.filter(isNotNewRecentFile),
]);
this._setRecentProjectFiles(
[newRecentFile, ...recentProjectFiles.filter(isNotNewRecentFile)].slice(
0,
MAX_RECENT_FILES_COUNT
)
);
}
_removeRecentProjectFile(recentFile: FileMetadataAndStorageProviderName) {
const isNotRemovedRecentFile = recentFileItem =>
recentFileItem.fileMetadata.fileIdentifier !==
recentFile.fileMetadata.fileIdentifier;
this._setRecentProjectFiles([
...this._getRecentProjectFiles().filter(isNotRemovedRecentFile),
]);
this._setRecentProjectFiles(
[...this._getRecentProjectFiles().filter(isNotRemovedRecentFile)].slice(
0,
MAX_RECENT_FILES_COUNT
)
);
}
_getAutoOpenMostRecentProject() {

View File

@@ -2224,7 +2224,7 @@ const MainFrame = (props: Props) => {
);
}
extension.getEventsFunctions().insertEventsFunction(eventsFunction, 0);
extension.insertEventsFunction(eventsFunction, 0);
eventsFunctionsExtensionsState.loadProjectEventsFunctionsExtensions(
currentProject
);
@@ -3523,7 +3523,7 @@ const MainFrame = (props: Props) => {
i18n: i18n,
project: state.currentProject,
canSaveProjectAs,
recentProjectFiles: preferences.getRecentProjectFiles({ limit: 20 }),
recentProjectFiles: preferences.getRecentProjectFiles(),
shortcutMap,
isApplicationTopLevelMenu: false,
};

View File

@@ -14,12 +14,6 @@ import { useForceRecompute } from '../../Utils/UseForceUpdate';
import { type Schema, type ActionButton } from '../../CompactPropertiesEditor';
import ShareExternal from '../../UI/CustomSvgIcons/ShareExternal';
export const styles = {
icon: {
fontSize: 18,
},
};
export const getSchemaWithOpenFullEditorButton = ({
schema,
fullEditorLabel,
@@ -155,7 +149,7 @@ export const CompactBehaviorPropertiesEditor = ({
<FlatButton
fullWidth
primary
leftIcon={<ChevronArrowRight style={styles.icon} />}
leftIcon={<ChevronArrowRight />}
label={<Trans>Show more</Trans>}
onClick={() => {
setShowAdvancedOptions(true);
@@ -176,7 +170,7 @@ export const CompactBehaviorPropertiesEditor = ({
<FlatButton
fullWidth
primary
leftIcon={<ChevronArrowTop style={styles.icon} />}
leftIcon={<ChevronArrowTop />}
label={<Trans>Show less</Trans>}
onClick={() => {
setShowAdvancedOptions(false);

View File

@@ -27,11 +27,8 @@ import { ColumnStackLayout, LineStackLayout } from '../../UI/Layout';
import { IconContainer } from '../../UI/IconContainer';
import Remove from '../../UI/CustomSvgIcons/Remove';
import useForceUpdate, { useForceRecompute } from '../../Utils/UseForceUpdate';
import ChevronArrowTop from '../../UI/CustomSvgIcons/ChevronArrowTop';
import ChevronArrowRight from '../../UI/CustomSvgIcons/ChevronArrowRight';
import ChevronArrowBottom from '../../UI/CustomSvgIcons/ChevronArrowBottom';
import ChevronArrowDownWithRoundedBorder from '../../UI/CustomSvgIcons/ChevronArrowDownWithRoundedBorder';
import ChevronArrowRightWithRoundedBorder from '../../UI/CustomSvgIcons/ChevronArrowRightWithRoundedBorder';
import Add from '../../UI/CustomSvgIcons/Add';
import { useManageObjectBehaviors } from '../../BehaviorsEditor';
import Object3d from '../../UI/CustomSvgIcons/Object3d';
@@ -47,10 +44,13 @@ import SelectOption from '../../UI/SelectOption';
import { ChildObjectPropertiesEditor } from './ChildObjectPropertiesEditor';
import { getSchemaWithOpenFullEditorButton } from './CompactObjectPropertiesSchema';
import FlatButton from '../../UI/FlatButton';
import ChevronArrowTop from '../../UI/CustomSvgIcons/ChevronArrowTop';
import Help from '../../UI/CustomSvgIcons/Help';
import { getHelpLink } from '../../Utils/HelpLink';
import Window from '../../Utils/Window';
import CompactTextField from '../../UI/CompactTextField';
import SquaredDoubleChevronArrowDown from '../../UI/CustomSvgIcons/SquaredDoubleChevronArrowDown';
import SquaredDoubleChevronArrowUp from '../../UI/CustomSvgIcons/SquaredDoubleChevronArrowUp';
import { textEllipsisStyle } from '../../UI/TextEllipsis';
import Link from '../../UI/Link';
@@ -166,9 +166,9 @@ const TopLevelCollapsibleSection = ({
<LineStackLayout noMargin alignItems="center">
<IconButton size="small" onClick={toggleFolded}>
{isFolded ? (
<ChevronArrowRightWithRoundedBorder style={styles.icon} />
<SquaredDoubleChevronArrowUp style={styles.icon} />
) : (
<ChevronArrowDownWithRoundedBorder style={styles.icon} />
<SquaredDoubleChevronArrowDown style={styles.icon} />
)}
</IconButton>
<Text size="sub-title" noMargin style={textEllipsisStyle}>
@@ -456,7 +456,7 @@ export const CompactObjectPropertiesEditor = ({
<FlatButton
fullWidth
primary
leftIcon={<ChevronArrowRight style={styles.icon} />}
leftIcon={<ChevronArrowRight />}
label={<Trans>Show more</Trans>}
onClick={() => {
setShowObjectAdvancedOptions(true);
@@ -482,7 +482,7 @@ export const CompactObjectPropertiesEditor = ({
<FlatButton
fullWidth
primary
leftIcon={<ChevronArrowTop style={styles.icon} />}
leftIcon={<ChevronArrowTop />}
label={<Trans>Show less</Trans>}
onClick={() => {
setShowObjectAdvancedOptions(false);

View File

@@ -66,7 +66,7 @@ const BottomToolbar = React.memo<Props>((props: Props) => {
return (
<Paper background="medium" square style={styles.container}>
<Toolbar height={toolbarHeight} paddingBottom={toolbarPaddingBottom}>
<ToolbarGroup spaceOut>
<ToolbarGroup>
{Object.keys(editors).map(editorId => {
const { icon, buttonId } = editors[editorId];
const isSelected = props.selectedEditorId === editorId;

View File

@@ -1,6 +1,5 @@
// @flow
import * as React from 'react';
import { makeStyles } from '@material-ui/styles';
import MUIAccordion from '@material-ui/core/Accordion';
import MUIAccordionSummary from '@material-ui/core/AccordionSummary';
import MUIAccordionDetails from '@material-ui/core/AccordionDetails';
@@ -8,16 +7,7 @@ import MUIAccordionActions from '@material-ui/core/AccordionActions';
import IconButton from './IconButton';
import GDevelopThemeContext from './Theme/GDevelopThemeContext';
import { Column, Line } from '../UI/Grid';
import ChevronArrowRight from './CustomSvgIcons/ChevronArrowRight';
const useStylesForExpandIcon = () =>
makeStyles(theme => ({
root: {
'& .MuiAccordionSummary-expandIcon.Mui-expanded': {
transform: 'rotate(90deg)',
},
},
}))();
import ChevronArrowBottom from './CustomSvgIcons/ChevronArrowBottom';
const styles = {
bodyRoot: {
@@ -51,19 +41,16 @@ type AccordionHeadProps = {|
* Based on Material-UI AccordionSummary (but we could almost remove it).
*/
export const AccordionHeader = (props: AccordionHeadProps) => {
const classes = useStylesForExpandIcon();
return (
<Column noMargin={props.noMargin} expand>
<Line noMargin expand alignItems="center">
<Column noMargin expand>
<MUIAccordionSummary
classes={classes}
style={styles.accordionSummaryWithExpandOnLeft}
expandIcon={
props.expandIcon || (
<IconButton size="small">
<ChevronArrowRight />
<ChevronArrowBottom />
</IconButton>
)
}

View File

@@ -13,6 +13,7 @@ const styles = {
textOverflow: 'ellipsis',
lineHeight: '17px',
maxHeight: 34, // 2 * lineHeight to limit to 2 lines.
opacity: 0.7,
},
};
type Props = {|
@@ -23,27 +24,12 @@ type Props = {|
onCheck: (newValue: boolean) => void,
disabled?: boolean,
fullWidth?: boolean,
hideTooltip?: boolean,
labelColor?: 'primary',
|};
export const CompactToggleField = (props: Props) => {
const title = props.hideTooltip
? null
: !props.markdownDescription
const title = !props.markdownDescription
? props.label
: [props.label, ' - ', <MarkdownText source={props.markdownDescription} />];
const label = (
<Text
noMargin
style={styles.label}
color={props.labelColor === 'primary' ? 'primary' : 'secondary'}
>
{props.label}
</Text>
);
return (
<label
className={classNames({
@@ -83,29 +69,27 @@ export const CompactToggleField = (props: Props) => {
</span>
</span>
</div>
{props.hideTooltip ? (
label
) : (
<Tooltip
title={title}
enterDelay={tooltipEnterDelay}
placement="bottom"
PopperProps={{
modifiers: {
offset: {
enabled: true,
/**
* It does not seem possible to get the tooltip closer to the anchor
* when positioned on top. So it is positioned on bottom with a negative offset.
*/
offset: '0,-20',
},
<Tooltip
title={title}
enterDelay={tooltipEnterDelay}
placement="bottom"
PopperProps={{
modifiers: {
offset: {
enabled: true,
/**
* It does not seem possible to get the tooltip closer to the anchor
* when positioned on top. So it is positioned on bottom with a negative offset.
*/
offset: '0,-20',
},
}}
>
{label}
</Tooltip>
)}
},
}}
>
<Text noMargin style={styles.label}>
{props.label}
</Text>
</Tooltip>
</label>
);
};

View File

@@ -2,7 +2,7 @@ import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
export default React.memo(props => (
<SvgIcon width="16" height="16" viewBox="0 0 16 16" {...props} fill="none">
<SvgIcon {...props} width="16" height="16" viewBox="0 0 16 16">
<path
fillRule="evenodd"
clipRule="evenodd"

View File

@@ -1,22 +0,0 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
export default React.memo(props => (
<SvgIcon {...props} width="16" height="16" viewBox="0 0 16 16" fill="none">
<rect
x="0.5"
y="0.5"
width="15"
height="15"
rx="3.5"
stroke="currentColor"
fill="none"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.49303 6.80026C5.69538 6.61236 6.01175 6.62408 6.19965 6.82643L7.99992 8.76519L9.80019 6.82643C9.98809 6.62408 10.3045 6.61236 10.5068 6.80026C10.7092 6.98816 10.7209 7.30453 10.533 7.50688L8.36632 9.84022C8.27171 9.9421 8.13896 9.99999 7.99992 9.99999C7.86089 9.99999 7.72813 9.9421 7.63352 9.84022L5.46686 7.50688C5.27896 7.30453 5.29067 6.98816 5.49303 6.80026Z"
fill="currentColor"
/>
</SvgIcon>
));

View File

@@ -2,7 +2,7 @@ import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
export default React.memo(props => (
<SvgIcon width="16" height="16" viewBox="0 0 16 16" {...props} fill="none">
<SvgIcon {...props} width="16" height="16" viewBox="0 0 16 16">
<path
fillRule="evenodd"
clipRule="evenodd"

View File

@@ -1,22 +0,0 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
export default React.memo(props => (
<SvgIcon {...props} width="16" height="16" viewBox="0 0 16 16" fill="none">
<rect
x="0.5"
y="0.5"
width="15"
height="15"
rx="3.5"
stroke="currentColor"
fill="none"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.80035 5.49309C6.98825 5.29073 7.30462 5.27902 7.50698 5.46692L9.84031 7.63359C9.94219 7.72819 10.0001 7.86095 10.0001 7.99998C10.0001 8.13902 9.94219 8.27177 9.84031 8.36638L7.50698 10.533C7.30462 10.7209 6.98825 10.7092 6.80035 10.5069C6.61245 10.3045 6.62417 9.98815 6.82652 9.80025L8.76528 7.99998L6.82652 6.19971C6.62417 6.01181 6.61245 5.69544 6.80035 5.49309Z"
fill="currentColor"
/>
</SvgIcon>
));

View File

@@ -1,38 +0,0 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
export default React.memo(props => (
<SvgIcon
{...props}
width="25"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.2079 4.25C6.08921 4.25 5.15646 5.04939 4.90073 6.12513C4.21877 8.99403 3.61173 11.5052 2.89195 14.2377C2.42794 15.9991 3.14788 17.6469 4.43117 18.3752C5.07736 18.7419 5.85387 18.8626 6.63456 18.6338C7.41151 18.4061 8.12572 17.8531 8.70885 16.9922C8.94115 16.6493 8.85145 16.1829 8.50851 15.9506C8.16556 15.7183 7.69924 15.808 7.46694 16.151C7.034 16.7901 6.58495 17.0852 6.21265 17.1943C5.84409 17.3024 5.48536 17.2487 5.1715 17.0706C4.5347 16.7092 4.03537 15.7856 4.34247 14.6198C5.06704 11.8691 5.67749 9.3435 6.36006 6.47205C6.46711 6.02173 6.83463 5.75 7.2079 5.75H17.6749C18.0509 5.75 18.4247 6.02298 18.5399 6.47691C18.8684 7.77218 19.4991 10.2222 20.6575 14.6198C20.9646 15.7856 20.4653 16.7092 19.8285 17.0706C19.5146 17.2487 19.1559 17.3024 18.7873 17.1943C18.415 17.0852 17.966 16.7901 17.533 16.151C17.3007 15.808 16.8344 15.7183 16.4915 15.9506C16.1485 16.1829 16.0588 16.6493 16.2911 16.9922C16.8743 17.8531 17.5885 18.4061 18.3654 18.6338C19.1461 18.8626 19.9226 18.7419 20.5688 18.3752C21.8521 17.6469 22.572 15.9991 22.108 14.2377C20.9503 9.84271 20.3208 7.39736 19.9938 6.10808C19.7234 5.04219 18.7908 4.25 17.6749 4.25H7.2079Z"
fill="currentColor"
/>
<path
d="M9.24999 8C9.24999 7.58579 8.9142 7.25 8.49999 7.25C8.08577 7.25 7.74999 7.58579 7.74999 8V8.25H7.49999C7.08577 8.25 6.74999 8.58579 6.74999 9C6.74999 9.41421 7.08577 9.75 7.49999 9.75H7.74999V10C7.74999 10.4142 8.08577 10.75 8.49999 10.75C8.9142 10.75 9.24999 10.4142 9.24999 10V9.75H9.49999C9.9142 9.75 10.25 9.41421 10.25 9C10.25 8.58579 9.9142 8.25 9.49999 8.25H9.24999V8Z"
fill="currentColor"
/>
<path
d="M14.75 9C14.75 8.58579 15.0858 8.25 15.5 8.25H16.5C16.9142 8.25 17.25 8.58579 17.25 9C17.25 9.41421 16.9142 9.75 16.5 9.75H15.5C15.0858 9.75 14.75 9.41421 14.75 9Z"
fill="currentColor"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.74999 13.5C6.74999 12.2573 7.75735 11.25 8.99999 11.25C10.2426 11.25 11.25 12.2573 11.25 13.5C11.25 14.7427 10.2426 15.75 8.99999 15.75C7.75735 15.75 6.74999 14.7427 6.74999 13.5ZM8.99999 12.75C8.58577 12.75 8.24999 13.0858 8.24999 13.5C8.24999 13.9142 8.58577 14.25 8.99999 14.25C9.41421 14.25 9.74999 13.9142 9.74999 13.5C9.74999 13.0858 9.41421 12.75 8.99999 12.75Z"
fill="currentColor"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M16 11.25C14.7573 11.25 13.75 12.2573 13.75 13.5C13.75 14.7427 14.7573 15.75 16 15.75C17.2427 15.75 18.25 14.7427 18.25 13.5C18.25 12.2573 17.2427 11.25 16 11.25ZM15.25 13.5C15.25 13.0858 15.5858 12.75 16 12.75C16.4142 12.75 16.75 13.0858 16.75 13.5C16.75 13.9142 16.4142 14.25 16 14.25C15.5858 14.25 15.25 13.9142 15.25 13.5Z"
fill="currentColor"
/>
</SvgIcon>
));

View File

@@ -0,0 +1,11 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
export default React.memo(props => (
<SvgIcon {...props} width="16" height="16" viewBox="0 0 16 16" fill="none">
<path
fill="currentColor"
d="M5.31331 10.6667L3.33331 12.6667C3.11331 12.8667 2.81998 13 2.49998 13C2.19056 13 1.89381 12.8771 1.67502 12.6583C1.45623 12.4395 1.33331 12.1428 1.33331 11.8333V11.6667L1.99998 6.74667C2.06719 5.99709 2.41221 5.29972 2.96729 4.79151C3.52237 4.2833 4.24739 4.00099 4.99998 4H11C12.5733 4 13.86 5.20667 14 6.74667L14.6666 11.6667V11.8333C14.6666 12.1428 14.5437 12.4395 14.3249 12.6583C14.1061 12.8771 13.8094 13 13.5 13C13.18 13 12.8866 12.8667 12.6666 12.6667L10.6866 10.6667H5.31331ZM4.66665 5.33333V6.66667H3.33331V7.33333H4.66665V8.66667H5.33331V7.33333H6.66665V6.66667H5.33331V5.33333H4.66665ZM11 5.33333C10.8674 5.33333 10.7402 5.38601 10.6464 5.47978C10.5527 5.57355 10.5 5.70073 10.5 5.83333C10.5 5.96594 10.5527 6.09312 10.6464 6.18689C10.7402 6.28065 10.8674 6.33333 11 6.33333C11.1326 6.33333 11.2598 6.28065 11.3535 6.18689C11.4473 6.09312 11.5 5.96594 11.5 5.83333C11.5 5.70073 11.4473 5.57355 11.3535 5.47978C11.2598 5.38601 11.1326 5.33333 11 5.33333ZM9.83331 6.5C9.7007 6.5 9.57353 6.55268 9.47976 6.64645C9.38599 6.74022 9.33331 6.86739 9.33331 7C9.33331 7.13261 9.38599 7.25978 9.47976 7.35355C9.57353 7.44732 9.7007 7.5 9.83331 7.5C9.96592 7.5 10.0931 7.44732 10.1869 7.35355C10.2806 7.25978 10.3333 7.13261 10.3333 7C10.3333 6.86739 10.2806 6.74022 10.1869 6.64645C10.0931 6.55268 9.96592 6.5 9.83331 6.5ZM12.1666 6.5C12.034 6.5 11.9069 6.55268 11.8131 6.64645C11.7193 6.74022 11.6666 6.86739 11.6666 7C11.6666 7.13261 11.7193 7.25978 11.8131 7.35355C11.9069 7.44732 12.034 7.5 12.1666 7.5C12.2993 7.5 12.4264 7.44732 12.5202 7.35355C12.614 7.25978 12.6666 7.13261 12.6666 7C12.6666 6.86739 12.614 6.74022 12.5202 6.64645C12.4264 6.55268 12.2993 6.5 12.1666 6.5ZM11 7.66667C10.8674 7.66667 10.7402 7.71935 10.6464 7.81311C10.5527 7.90688 10.5 8.03406 10.5 8.16667C10.5 8.29927 10.5527 8.42645 10.6464 8.52022C10.7402 8.61399 10.8674 8.66667 11 8.66667C11.1326 8.66667 11.2598 8.61399 11.3535 8.52022C11.4473 8.42645 11.5 8.29927 11.5 8.16667C11.5 8.03406 11.4473 7.90688 11.3535 7.81311C11.2598 7.71935 11.1326 7.66667 11 7.66667Z"
/>
</SvgIcon>
));

View File

@@ -1,20 +0,0 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
export default React.memo(props => (
<SvgIcon
{...props}
width="25"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10.8427 1.23901C10.5452 1.0407 10.1491 1.07992 9.89633 1.33272L8.83567 2.39338C8.69501 2.53403 8.616 2.7248 8.616 2.92371C8.616 3.12262 8.69502 3.31339 8.83567 3.45404C10.5106 5.12894 11.2421 6.69567 11.5617 7.81432C11.7222 8.37618 11.7804 8.83058 11.7994 9.13557C11.8038 9.20557 11.8061 9.26768 11.8071 9.3214L2.11811 19.0103C1.82522 19.3032 1.82521 19.7781 2.1181 20.071L4.23942 22.1924C4.38007 22.3331 4.57084 22.4121 4.76975 22.4121C4.96867 22.4121 5.15943 22.3331 5.30009 22.1924L15.0228 12.4696L15.3764 12.8232L14.8461 13.3536C14.5532 13.6465 14.5532 14.1213 14.8461 14.4142L17.3209 16.8891C17.4616 17.0298 17.6523 17.1088 17.8512 17.1088C18.0502 17.1088 18.2409 17.0298 18.3816 16.8891L23.3314 11.9393C23.472 11.7987 23.551 11.6079 23.551 11.409C23.551 11.2101 23.472 11.0193 23.3314 10.8786L20.8565 8.40378C20.5636 8.11089 20.0887 8.11089 19.7958 8.40377L19.2655 8.93412L18.9119 8.58057L19.4423 8.05024C19.6012 7.89136 19.6804 7.66961 19.6583 7.446C19.6362 7.2224 19.5149 7.0205 19.328 6.89586L10.8427 1.23901ZM12.1944 13.1768L11.1337 12.1161L3.70909 19.5407L4.76977 20.6014L12.1944 13.1768ZM13.0783 10.1715C13.1987 10.0511 13.2746 9.89331 13.2934 9.72405L13.2936 9.72213L13.2938 9.71991L13.2944 9.71457L13.2957 9.70037C13.2967 9.68934 13.2979 9.67521 13.2991 9.65807C13.3016 9.62378 13.3042 9.5774 13.3059 9.51965C13.3093 9.40416 13.3091 9.24305 13.2965 9.04202C13.2714 8.6399 13.197 8.07783 13.0039 7.40225C12.6543 6.1786 11.9205 4.60016 10.4137 2.93665L10.5222 2.82815L17.7347 7.63646L17.3209 8.05022C17.1803 8.19087 17.1012 8.38164 17.1012 8.58055C17.1012 8.77947 17.1803 8.97023 17.3209 9.11089L18.7351 10.5251C19.028 10.818 19.5029 10.818 19.7958 10.5251L20.3261 9.99476L21.7404 11.409L17.8513 15.2981L16.4371 13.8839L16.9674 13.3535C17.2603 13.0606 17.2603 12.5857 16.9674 12.2929L15.5532 10.8787C15.2603 10.5858 14.7854 10.5858 14.4925 10.8786L13.255 12.1161L12.1944 11.0555L13.0783 10.1715Z"
fill="currentColor"
/>
</SvgIcon>
));

View File

@@ -0,0 +1,11 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
export default React.memo(props => (
<SvgIcon {...props} width="16" height="16" viewBox="0 0 16 16" fill="none">
<path
fill="currentColor"
d="M9.86003 7.08L2.33336 14.6L1.40002 13.6667L8.92002 6.14L9.86003 7.08ZM12.8467 5.15333L13.24 4.76L12.7134 4.23333L13.14 3.80666L12.1934 2.86L11.7667 3.28666L11.24 2.76L10.8467 3.15333C9.68669 2.20666 8.38002 1.44666 6.98003 0.91333L6.42669 2.10666C7.59336 2.72 8.66669 3.46 9.66669 4.33333L9.33336 4.66666L11.3334 6.66666L11.6667 6.33333C12.54 7.33333 13.28 8.40666 13.8934 9.57333L15.0867 9.02C14.5534 7.62 13.7934 6.31333 12.8467 5.15333Z"
/>
</SvgIcon>
));

View File

@@ -0,0 +1,28 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
export default React.memo(props => (
<SvgIcon {...props} width="16" height="16" viewBox="0 0 16 16" fill="none">
<rect
x="0.5"
y="0.5"
width="15"
height="15"
rx="3.5"
stroke="currentColor"
fill="none"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.93304 5.03353C5.09872 4.81261 5.41212 4.76784 5.63304 4.93353L7.9997 6.70853L10.3664 4.93353C10.5873 4.76784 10.9007 4.81261 11.0664 5.03353C11.2321 5.25444 11.1873 5.56784 10.9664 5.73353L8.2997 7.73353C8.12193 7.86686 7.87748 7.86686 7.6997 7.73353L5.03304 5.73353C4.81212 5.56784 4.76735 5.25444 4.93304 5.03353Z"
fill="currentColor"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.93304 8.36686C5.09872 8.14595 5.41212 8.10117 5.63304 8.26686L7.9997 10.0419L10.3664 8.26686C10.5873 8.10117 10.9007 8.14595 11.0664 8.36686C11.2321 8.58777 11.1873 8.90117 10.9664 9.06686L8.2997 11.0669C8.12193 11.2002 7.87748 11.2002 7.6997 11.0669L5.03304 9.06686C4.81212 8.90117 4.76735 8.58777 4.93304 8.36686Z"
fill="currentColor"
/>
</SvgIcon>
));

View File

@@ -0,0 +1,28 @@
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
export default React.memo(props => (
<SvgIcon {...props} width="16" height="16" viewBox="0 0 16 16" fill="none">
<rect
x="0.5"
y="0.5"
width="15"
height="15"
rx="3.5"
stroke="currentColor"
fill="none"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.93304 7.6335C5.09872 7.85441 5.41212 7.89918 5.63304 7.7335L7.9997 5.9585L10.3664 7.7335C10.5873 7.89918 10.9007 7.85441 11.0664 7.6335C11.2321 7.41258 11.1873 7.09918 10.9664 6.9335L8.2997 4.9335C8.12193 4.80016 7.87748 4.80016 7.6997 4.9335L5.03304 6.9335C4.81212 7.09918 4.76735 7.41258 4.93304 7.6335Z"
fill="currentColor"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.93304 10.9668C5.09872 11.1877 5.41212 11.2325 5.63304 11.0668L7.9997 9.29183L10.3664 11.0668C10.5873 11.2325 10.9007 11.1877 11.0664 10.9668C11.2321 10.7459 11.1873 10.4325 10.9664 10.2668L8.2997 8.26683C8.12193 8.1335 7.87748 8.1335 7.6997 8.26683L5.03304 10.2668C4.81212 10.4325 4.76735 10.7459 4.93304 10.9668Z"
fill="currentColor"
/>
</SvgIcon>
));

View File

@@ -4,7 +4,7 @@ exports[`HelpIcon renders nothing if the helpPagePath is empty 1`] = `null`;
exports[`HelpIcon renders the icon linking to a help page 1`] = `
<button
className="MuiButtonBase-root MuiIconButton-root makeStyles-root-1 MuiIconButton-colorSecondary"
className="MuiButtonBase-root MuiIconButton-root makeStyles-root-1 makeStyles-root-3 MuiIconButton-colorSecondary"
disabled={false}
onBlur={[Function]}
onClick={[Function]}
@@ -22,7 +22,7 @@ exports[`HelpIcon renders the icon linking to a help page 1`] = `
type="button"
>
<span
className="MuiIconButton-label makeStyles-label-2"
className="MuiIconButton-label makeStyles-label-2 makeStyles-label-4"
>
<svg
aria-hidden={true}

View File

@@ -7,7 +7,6 @@ import { type MessageDescriptor } from '../Utils/i18n/MessageDescriptor.flow';
import { adaptAcceleratorString } from '../UI/AcceleratorString';
import { tooltipEnterDelay } from './Tooltip';
import GDevelopThemeContext from './Theme/GDevelopThemeContext';
import { type GDevelopTheme } from './Theme';
import { makeStyles } from '@material-ui/core/styles';
type IconProps =
@@ -61,32 +60,25 @@ type Props = {|
disableRipple?: boolean,
disableFocusRipple?: boolean,
disableHover?: boolean,
color?: 'default' | 'inherit',
color?: 'default',
|};
const useStylesForIconButton = ({
theme,
selected,
disableHover,
}: {|
theme: GDevelopTheme,
selected?: boolean,
disableHover?: boolean,
|}) =>
makeStyles({
root: {
color: selected ? theme.iconButton.selectedColor : undefined,
'&:hover': disableHover ? { backgroundColor: 'transparent' } : {},
},
label: {
backgroundColor: selected
? theme.iconButton.selectedBackgroundColor
: undefined,
borderRadius: selected ? 4 : undefined,
},
})();
const useStyles = makeStyles({
root: props =>
props.color
? {
color: props.color,
}
: undefined,
label: props =>
props.backgroundColor
? {
backgroundColor: props.backgroundColor,
borderRadius: 4,
}
: undefined,
});
/**
* A button showing just an icon, based on Material-UI icon button.
@@ -100,15 +92,16 @@ const IconButton = React.forwardRef<Props, {||}>((props: Props, ref) => {
acceleratorString,
color,
style,
disableHover,
...otherProps
} = props;
const gdevelopTheme = React.useContext(GDevelopThemeContext);
const classes = useStylesForIconButton({
theme: gdevelopTheme,
selected,
disableHover,
const classes = useStyles({
// Override Material-UI colors only when the button is selected.
color: selected ? gdevelopTheme.iconButton.selectedColor : undefined,
backgroundColor: selected
? gdevelopTheme.iconButton.selectedBackgroundColor
: undefined,
});
const iconButton = (

View File

@@ -144,7 +144,6 @@ type ResponsiveLineStackLayoutProps = {|
noColumnMargin?: boolean,
/** Do not measure window width in case parent component is in smaller component */
forceMobileLayout?: boolean,
noOverflowParent?: boolean,
noResponsiveLandscape?: boolean,
useLargeSpacer?: boolean,
children: React.Node,
@@ -158,7 +157,6 @@ export const ResponsiveLineStackLayout = ({
noMargin,
noColumnMargin,
forceMobileLayout,
noOverflowParent,
noResponsiveLandscape,
useLargeSpacer,
children,
@@ -175,7 +173,6 @@ export const ResponsiveLineStackLayout = ({
noMargin={noMargin || noColumnMargin}
expand
useLargeSpacer={useLargeSpacer}
noOverflowParent={noOverflowParent}
>
{children}
</ColumnStackLayout>

View File

@@ -241,24 +241,6 @@ export const sortResultsUsingExactMatches = (orderedKeys: string[]) => {
for (const key of orderedKeys) {
const matchA = resultA.matches.find(match => match.key === key);
const matchB = resultB.matches.find(match => match.key === key);
// If a result has an exact math at the start of the word in the key but
// the other doesn't even has a match in the key, give priority.
if (
matchA &&
matchA.closestExactMatchAtStartOfWordIndex !== null &&
!matchB
) {
return -1;
}
if (
!matchA &&
matchB &&
matchB.closestExactMatchAtStartOfWordIndex !== null
) {
return 1;
}
// If both result have exact matches in the key, give priority to the one where
// the match is closer to the start of the sentence.
if (matchA && matchB) {
if (
matchA.closestExactMatchAtStartOfWordIndex !== null &&

View File

@@ -1,125 +0,0 @@
// @flow
import Fuse from 'fuse.js';
import {
getFuseSearchQueryForMultipleKeys,
nullifySingleCharacterMatches,
sortResultsUsingExactMatches,
sharedFuseConfiguration,
augmentSearchResult,
} from './UseSearchStructuredItem';
const facebookInstantGameSavePlayerDataAction = {
displayedName: 'Save player data',
description:
'Save the content of the given scene variable in the player data, stored on Facebook Instant Games servers',
fullGroupName: 'Third-party/Facebook Instant Games/Player data',
};
const changeVariableValueAction = {
displayedName: 'Change variable value',
description: 'Modify the number value of an object variable.',
fullGroupName: 'General/Objects/Variables',
};
const triggerOnceCondition = {
displayedName: 'Trigger once while true',
description:
'Run actions only once, for each time the conditions have been met.',
fullGroupName: 'Advanced/Events and control flow',
};
const p2pOnEventCondition = {
displayedName: 'Event triggered by peer',
description: 'Triggers once when a connected client sends the event',
fullGroupName: 'Network/P2P',
};
const textCondition = {
displayedName: 'Text',
description: 'Compare the text.',
fullGroupName: 'General/Text capability',
};
const sceneTweenExistsCondition = {
displayedName: 'Scene tween exists',
description: 'Check if the scene tween exists.',
fullGroupName: 'Visual effect/Tweening/Scene Tweens',
};
const applySearch = (lowerCaseSearchText: string, instructions) => {
const searchApi = new Fuse(instructions, {
...sharedFuseConfiguration,
includeScore: true, // Use Fuse.js score to sort results that don't contain exact matches.
keys: [
{ name: 'displayedName', weight: 5 },
{ name: 'fullGroupName', weight: 1 },
{ name: 'description', weight: 3 },
],
});
const results = searchApi
.search(
getFuseSearchQueryForMultipleKeys(lowerCaseSearchText, [
'displayedName',
'fullGroupName',
'description',
])
)
.map(nullifySingleCharacterMatches)
.filter(Boolean)
.map(result => augmentSearchResult(result, lowerCaseSearchText))
.sort(
sortResultsUsingExactMatches([
'displayedName',
'description',
'fullGroupName',
])
);
return results;
};
describe('UseSearchStructuredItem', () => {
it('should give priority to exact matches at start of word in the first ordered key', () => {
// In the second key `description`, facebookInstantGameSavePlayerDataAction has an exact match at start of word closer than
// changeVariableValueAction, so it could be sorted first. But changeVariableValueAction has an exact match at start of word
// in the first key `displayedName`, so it should be sorted first.
const results = applySearch('var', [
facebookInstantGameSavePlayerDataAction,
changeVariableValueAction,
]);
expect(results[0].item.displayedName).toEqual(
changeVariableValueAction.displayedName
);
});
it('should give priority to exact matches at start of word that are closer to the start of the sentence', () => {
const results = applySearch('tri', [
p2pOnEventCondition,
triggerOnceCondition,
]);
expect(results[0].item.displayedName).toEqual(
triggerOnceCondition.displayedName
);
});
it('should give priority to the result with at least one exact match over one that has none', () => {
const results = applySearch('rigger', [
changeVariableValueAction,
triggerOnceCondition,
]);
expect(results[0].item.displayedName).toEqual(
triggerOnceCondition.displayedName
);
});
it('should give priority to the result with at least one exact match at start of word over one that has a match not at start of word', () => {
const results = applySearch('ex', [
textCondition,
sceneTweenExistsCondition,
]);
expect(results[0].item.displayedName).toEqual(
sceneTweenExistsCondition.displayedName
);
});
});

View File

@@ -6,7 +6,6 @@ import TextField from '@material-ui/core/TextField';
import { type MessageDescriptor } from '../Utils/i18n/MessageDescriptor.flow';
import { makeStyles } from '@material-ui/core';
import Paper from './Paper';
import ChevronArrowBottom from './CustomSvgIcons/ChevronArrowBottom';
const INVALID_VALUE = '';
const stopPropagation = event => event.stopPropagation();
@@ -144,7 +143,6 @@ const SearchBarSelectField = React.forwardRef<
SelectProps={{
native: true,
classes: selectStyles,
IconComponent: ChevronArrowBottom,
}}
margin="none"
style={styles.input}

View File

@@ -8,7 +8,6 @@ import { computeTextFieldStyleProps } from './TextField';
import { type FieldFocusFunction } from '../EventsSheet/ParameterFields/ParameterFieldCommons';
import { MarkdownText } from './MarkdownText';
import { makeStyles } from '@material-ui/core';
import ChevronArrowBottom from './CustomSvgIcons/ChevronArrowBottom';
const INVALID_VALUE = '';
const stopPropagation = event => event.stopPropagation();
@@ -138,7 +137,6 @@ const SelectField = React.forwardRef<Props, SelectFieldInterface>(
SelectProps={{
native: true,
classes: selectStyles,
IconComponent: ChevronArrowBottom,
}}
style={props.style}
inputRef={inputRef}

View File

@@ -14,7 +14,6 @@ import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import { textEllipsisStyle } from './TextEllipsis';
import Text from './Text';
import ChevronArrowBottom from './CustomSvgIcons/ChevronArrowBottom';
const renderItem = (option: AutocompleteOption, state: Object): React.Node => (
<ListItem dense component={'div'} style={autocompleteStyles.listItem}>
@@ -100,7 +99,6 @@ const SemiControlledMultiAutoComplete = React.forwardRef<
inputValue={props.inputValue}
onInputChange={props.onInputChange}
options={props.dataSource}
popupIcon={<ChevronArrowBottom />}
PaperComponent={AutocompletePaperComponent}
renderOption={renderItem}
getOptionLabel={(option: AutocompleteOption) => option.text}

View File

@@ -51,9 +51,7 @@ const toolbarGroupStyle = props => ({
flex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: props.spaceOut
? 'space-around'
: props.firstChild
justifyContent: props.firstChild
? 'flex-start'
: props.lastChild
? 'flex-end'
@@ -64,7 +62,6 @@ type ToolbarGroupProps = {|
children?: React.Node,
firstChild?: boolean,
lastChild?: boolean,
spaceOut?: boolean,
|};
export const ToolbarGroup = React.memo<ToolbarGroupProps>(

View File

@@ -1,18 +1,18 @@
// @flow
import * as React from 'react';
import classNames from 'classnames';
import { areEqual } from 'react-window';
import IconButton from '../IconButton';
import ArrowHeadBottom from '../CustomSvgIcons/ArrowHeadBottom';
import ArrowHeadRight from '../CustomSvgIcons/ArrowHeadRight';
import Folder from '../CustomSvgIcons/Folder';
import ListIcon from '../ListIcon';
import classes from './TreeView.module.css';
import { type ItemBaseAttributes } from './ReadOnlyTreeView';
import { type ItemData } from './ReadOnlyTreeView';
import { dataObjectToProps } from '../../Utils/HTMLDataset';
import classNames from 'classnames';
import RaisedButton from '../RaisedButton';
import ChevronArrowRight from '../CustomSvgIcons/ChevronArrowRight';
import ChevronArrowBottom from '../CustomSvgIcons/ChevronArrowBottom';
const iconSize = 24;
@@ -112,15 +112,9 @@ const TreeViewRow = <Item: ItemBaseAttributes>(props: Props<Item>) => {
disabled={node.disableCollapse}
>
{node.collapsed ? (
<ChevronArrowRight
viewBox="2 2 12 12"
fontSize="small"
/>
<ArrowHeadRight fontSize="small" />
) : (
<ChevronArrowBottom
viewBox="2 2 12 12"
fontSize="small"
/>
<ArrowHeadBottom fontSize="small" />
)}
</IconButton>
{!node.thumbnailSrc ||

View File

@@ -5,8 +5,8 @@ import DropIndicator from '../SortableVirtualizedItemList/DropIndicator';
import memoizeOne from 'memoize-one';
import { areEqual } from 'react-window';
import IconButton from '../IconButton';
import ChevronArrowBottom from '../CustomSvgIcons/ChevronArrowBottom';
import ChevronArrowRight from '../CustomSvgIcons/ChevronArrowRight';
import ArrowHeadBottom from '../CustomSvgIcons/ArrowHeadBottom';
import ArrowHeadRight from '../CustomSvgIcons/ArrowHeadRight';
import Folder from '../CustomSvgIcons/Folder';
import ListIcon from '../ListIcon';
import useForceUpdate from '../../Utils/UseForceUpdate';
@@ -358,12 +358,9 @@ const TreeViewRow = <Item: ItemBaseAttributes>(props: Props<Item>) => {
disabled={node.disableCollapse}
>
{node.collapsed ? (
<ChevronArrowRight viewBox="2 2 12 12" fontSize="small" />
<ArrowHeadRight fontSize="small" />
) : (
<ChevronArrowBottom
viewBox="2 2 12 12"
fontSize="small"
/>
<ArrowHeadBottom fontSize="small" />
)}
</IconButton>
{node.thumbnailSrc && node.thumbnailSrc !== 'FOLDER' ? (

View File

@@ -102,10 +102,10 @@ export type PrivateAssetPackAssetType =
| 'sprite'
| '9patch'
| 'tiled'
| 'partial'
| 'Scene3D::Model3DObject'
| 'TileMap::SimpleTileMap'
| 'ParticleSystem::ParticleEmitter'
| string;
| 'ParticleSystem::ParticleEmitter';
export type PrivateAssetPackContent = { [PrivateAssetPackAssetType]: number };
@@ -189,20 +189,16 @@ export type CourseChapterTask = {|
export type UnlockedCourseChapter = {|
id: string,
title: string,
shortTitle?: string,
videoUrl: string,
isLocked?: false,
isFree?: boolean,
templateUrl: string,
tasks: Array<CourseChapterTask>,
|};
export type LockedCourseChapter = {|
id: string,
title: string,
shortTitle?: string,
videoUrl: string,
isLocked: true,
isFree?: boolean,
priceInCredits?: number,
productId: string,
|};

View File

@@ -19,7 +19,6 @@ import {
findLeaderboardsToReplaceInProject,
replaceLeaderboardsInProject,
} from '../Leaderboard/UseLeaderboardReplacer';
import { useProjectsListFor } from '../MainFrame/EditorContainers/HomePage/CreateSection/utils';
export const getDefaultRegisterGameProperties = ({
projectId,
@@ -70,8 +69,6 @@ export const useGameManager = ({
} = useMultiplayerLobbyConfigurator();
const [game, setGame] = React.useState<?Game>(null);
const projectId = project ? project.getProjectUuid() : null;
const projectFiles = useProjectsListFor(projectId);
const [
gameAvailabilityError,
setGameAvailabilityError,
@@ -157,7 +154,6 @@ export const useGameManager = ({
error
);
if (extractedStatusAndCode && extractedStatusAndCode.status === 404) {
const hasProjectFiles = projectFiles.length > 0;
// If the game is not registered, register it before launching the export.
await registerGame(
getAuthorizationHeader,
@@ -166,7 +162,9 @@ export const useGameManager = ({
projectId: gameId,
projectName: project.getName(),
projectAuthor: project.getAuthor(),
savedStatus: hasProjectFiles ? 'saved' : 'draft',
// Assume a project going through the export process is not saved yet.
// It will be marked as saved when the user saves it next anyway.
savedStatus: 'draft',
})
);
@@ -211,7 +209,6 @@ export const useGameManager = ({
configureMultiplayerLobbiesIfNeeded,
authenticatedUser,
onGameRegistered,
projectFiles,
]
);

View File

@@ -9,8 +9,8 @@ import { ClickAwayListener } from '@material-ui/core';
import Add from '../UI/CustomSvgIcons/Add';
import Edit from '../UI/CustomSvgIcons/Edit';
import Undo from '../UI/CustomSvgIcons/Undo';
import ChevronArrowRight from '../UI/CustomSvgIcons/ChevronArrowRight';
import ChevronArrowBottom from '../UI/CustomSvgIcons/ChevronArrowBottom';
import ChevronRight from '../UI/CustomSvgIcons/ChevronArrowRight';
import ChevronBottom from '../UI/CustomSvgIcons/ChevronArrowBottom';
import ButtonBase from '@material-ui/core/ButtonBase';
import { Column, Line, Spacer } from '../UI/Grid';
@@ -316,11 +316,7 @@ const VariableRow = React.memo<VariableRowProps>(
focusRipple
style={variableRowStyles.chevron}
>
{isExpanded ? (
<ChevronArrowBottom />
) : (
<ChevronArrowRight />
)}
{isExpanded ? <ChevronBottom /> : <ChevronRight />}
</ButtonBase>
) : (
<div style={variableRowStyles.chevron} />

View File

@@ -5,354 +5,354 @@ module.exports = [
"languageCode": "af_ZA",
"languageName": "Afrikaans",
"languageNativeName": "Afrikaans",
"translationRatio": 0.04971383683088315
"translationRatio": 0.04973616256876612
},
{
"languageCode": "ar_SA",
"languageName": "Arabic",
"languageNativeName": "اَلْعَرَبِيَّةُ",
"translationRatio": 0.948378408708338
"translationRatio": 0.9435275625912204
},
{
"languageCode": "az_AZ",
"languageName": "Azerbaijani",
"languageNativeName": "azərbaycan dili",
"translationRatio": 0.04051172707889128
"translationRatio": 0.04052992028741442
},
{
"languageCode": "bg_BG",
"languageName": "Bulgarian",
"languageNativeName": "български език",
"translationRatio": 0.08394119627426777
"translationRatio": 0.08397889300550132
},
{
"languageCode": "bn_BD",
"languageName": "Bengali",
"languageNativeName": "বাংলা",
"translationRatio": 0.05510043766131745
"translationRatio": 0.05512518244077691
},
{
"languageCode": "br_FR",
"languageName": "Breton",
"languageNativeName": "brezhoneg",
"translationRatio": 0.028167433509145967
"translationRatio": 0.028180083080723062
},
{
"languageCode": "ca_ES",
"languageName": "Catalan",
"languageNativeName": "Català",
"translationRatio": 0.23723487824037703
"translationRatio": 0.23734141686314136
},
{
"languageCode": "cs_CZ",
"languageName": "Czech",
"languageNativeName": "čeština",
"translationRatio": 0.2649534283469869
"translationRatio": 0.26540922869653083
},
{
"languageCode": "da_DK",
"languageName": "Danish",
"languageNativeName": "Dansk",
"translationRatio": 0.1278195488721805
"translationRatio": 0.12798922196025597
},
{
"languageCode": "de_DE",
"languageName": "German",
"languageNativeName": "Deutsch",
"translationRatio": 0.741667601840422
"translationRatio": 0.743011114853486
},
{
"languageCode": "el_GR",
"languageName": "Greek",
"languageNativeName": "Ελληνικά",
"translationRatio": 0.23454157782515994
"translationRatio": 0.23475917817446956
},
{
"languageCode": "en",
"languageName": "English",
"languageNativeName": "English",
"translationRatio": 0.07290755322251385
"translationRatio": 0.07295010213014297
},
{
"languageCode": "eo_UY",
"languageName": "Esperanto",
"languageNativeName": "Esperanto",
"translationRatio": 0.20570081921220962
"translationRatio": 0.20601773885707875
},
{
"languageCode": "es_ES",
"languageName": "Spanish",
"languageNativeName": "Español",
"translationRatio": 0.938951857255078
"translationRatio": 0.939822611429213
},
{
"languageCode": "fa_IR",
"languageName": "Persian",
"languageNativeName": "فارسی",
"translationRatio": 0.2219728425541465
"translationRatio": 0.2222970697204446
},
{
"languageCode": "fi_FI",
"languageName": "Finnish",
"languageNativeName": "suomi",
"translationRatio": 0.2149029289642016
"translationRatio": 0.21511170989109685
},
{
"languageCode": "fil_PH",
"languageName": "Filipino",
"languageNativeName": "Mga Filipino",
"translationRatio": 0.2678711704634721
"translationRatio": 0.26799146738520263
},
{
"languageCode": "fr_FR",
"languageName": "French",
"languageNativeName": "Français",
"translationRatio": 0.9012456514420379
"translationRatio": 0.9020994723251375
},
{
"languageCode": "ha_HG",
"languageName": "Hausa",
"languageNativeName": "هَوُسَ",
"translationRatio": 0.03321737178767814
"translationRatio": 0.03323228921073318
},
{
"languageCode": "he_IL",
"languageName": "Hebrew",
"languageNativeName": "עברית",
"translationRatio": 0.17472786443721244
"translationRatio": 0.17480633209834961
},
{
"languageCode": "hi_IN",
"languageName": "Hindi",
"languageNativeName": "हिन्दी",
"translationRatio": 0.14599932667489623
"translationRatio": 0.1461771640282924
},
{
"languageCode": "hu_HU",
"languageName": "Hungarian",
"languageNativeName": "magyar",
"translationRatio": 0.3729098866569409
"translationRatio": 0.3700460312114068
},
{
"languageCode": "id_ID",
"languageName": "Indonesian",
"languageNativeName": "Bahasa Indonesia",
"translationRatio": 0.47985635731118836
"translationRatio": 0.4763669024362861
},
{
"languageCode": "ig_NG",
"languageName": "Igbo",
"languageNativeName": "Asụsụ Igbo",
"translationRatio": 0.03187072158006954
"translationRatio": 0.03188503424273048
},
{
"languageCode": "it_IT",
"languageName": "Italian",
"languageNativeName": "Italiano",
"translationRatio": 0.9817080013466503
"translationRatio": 0.9754125968339509
},
{
"languageCode": "ja_JP",
"languageName": "Japanese",
"languageNativeName": "日本語",
"translationRatio": 0.9864212770732802
"translationRatio": 0.9850679241046368
},
{
"languageCode": "ka_GE",
"languageName": "Georgian",
"languageNativeName": "ქართული",
"translationRatio": 0.058467063180338896
"translationRatio": 0.058493319860783655
},
{
"languageCode": "km_KH",
"languageName": "Khmer",
"languageNativeName": "ខេមរភាសា",
"translationRatio": 0.03243182583323978
"translationRatio": 0.032446390479398235
},
{
"languageCode": "ko_KR",
"languageName": "Korean",
"languageNativeName": "한국어",
"translationRatio": 0.8447985635731119
"translationRatio": 0.8455147636690243
},
{
"languageCode": "lt_LT",
"languageName": "Lithuanian",
"languageNativeName": "lietuvių kalba",
"translationRatio": 0.46223768376164287
"translationRatio": 0.46255753901425845
},
{
"languageCode": "lv_LV",
"languageName": "Latvian",
"languageNativeName": "latviešu valoda",
"translationRatio": 0.028167433509145967
"translationRatio": 0.028180083080723062
},
{
"languageCode": "mr_IN",
"languageName": "Marathi",
"languageNativeName": "मराठी",
"translationRatio": 0.03983840197508692
"translationRatio": 0.039856292803413074
},
{
"languageCode": "ms_MY",
"languageName": "Malay",
"languageNativeName": "Bahasa Melayu",
"translationRatio": 0.05667152957019417
"translationRatio": 0.05669697990344669
},
{
"languageCode": "my_MM",
"languageName": "Burmese",
"languageNativeName": "ဗမာစာ",
"translationRatio": 0.030524071372461048
"translationRatio": 0.030537779274727783
},
{
"languageCode": "nl_NL",
"languageName": "Dutch",
"languageNativeName": "Nederlands",
"translationRatio": 0.4583099539894513
"translationRatio": 0.45862804535758395
},
{
"languageCode": "no_NO",
"languageName": "Norwegian",
"languageNativeName": "Norsk",
"translationRatio": 0.3615755807429021
"translationRatio": 0.36218704389805767
},
{
"languageCode": "pl_PL",
"languageName": "Polish",
"languageNativeName": "Polski",
"translationRatio": 0.976321400516216
"translationRatio": 0.9760862243179522
},
{
"languageCode": "pseudo_LOCALE",
"languageName": "for development only",
"languageNativeName": "Pseudolocalization",
"translationRatio": 0.9959171770195392
"translationRatio": 0.995914794280712
},
{
"languageCode": "pt_BR",
"languageName": "Brazilian Portuguese",
"languageNativeName": "Português brasileiro",
"translationRatio": 0.8634272247783639
"translationRatio": 0.8630290782530594
},
{
"languageCode": "pt_PT",
"languageName": "Portuguese",
"languageNativeName": "Português",
"translationRatio": 0.3279093255526877
"translationRatio": 0.32816885595598966
},
{
"languageCode": "ro_RO",
"languageName": "Romanian",
"languageNativeName": "Română",
"translationRatio": 0.0994276736617663
"translationRatio": 0.09756371393286178
},
{
"languageCode": "ru_RU",
"languageName": "Russian",
"languageNativeName": "Русский",
"translationRatio": 0.9925934238581529
"translationRatio": 0.9821488716739643
},
{
"languageCode": "si_LK",
"languageName": "Sinhala",
"languageNativeName": "සිංහල",
"translationRatio": 0.5933116373022107
"translationRatio": 0.5938026271471877
},
{
"languageCode": "sk_SK",
"languageName": "Slovak",
"languageNativeName": "slovenčina",
"translationRatio": 0.16956570530804627
"translationRatio": 0.1698663972156731
},
{
"languageCode": "sl_SI",
"languageName": "Slovenian",
"languageNativeName": "slovenščina",
"translationRatio": 0.6474020873078218
"translationRatio": 0.6479173683619626
},
{
"languageCode": "sq_AL",
"languageName": "Albanian",
"languageNativeName": "Shqip",
"translationRatio": 0.15452811132308386
"translationRatio": 0.15470977882564274
},
{
"languageCode": "sr_CS",
"languageName": "Serbian (Latin)",
"languageNativeName": "srpski",
"translationRatio": 0.1358994501178319
"translationRatio": 0.13596048052093856
},
{
"languageCode": "sr_SP",
"languageName": "Serbian",
"languageNativeName": "српски језик",
"translationRatio": 0.28077656828638764
"translationRatio": 0.28090266082856186
},
{
"languageCode": "sv_SE",
"languageName": "Swedish",
"languageNativeName": "Svenska",
"translationRatio": 0.18022668611828074
"translationRatio": 0.180307623217694
},
{
"languageCode": "sw_KE",
"languageName": "Swahili",
"languageNativeName": "Kiswahili",
"translationRatio": 0.028279654359780082
"translationRatio": 0.028292354328056546
},
{
"languageCode": "th_TH",
"languageName": "Thai",
"languageNativeName": "ไทย",
"translationRatio": 0.2692178206710807
"translationRatio": 0.2695632648478724
},
{
"languageCode": "tr_TR",
"languageName": "Turkish",
"languageNativeName": "Türkçe",
"translationRatio": 0.9850746268656716
"translationRatio": 0.9859660940833053
},
{
"languageCode": "uk_UA",
"languageName": "Ukrainian",
"languageNativeName": "Українська",
"translationRatio": 0.9903490068454719
"translationRatio": 0.990344672729314
},
{
"languageCode": "ur_PK",
"languageName": "Urdu",
"languageNativeName": "اردو",
"translationRatio": 0.037481764111771954
"translationRatio": 0.03749859660940835
},
{
"languageCode": "uz_UZ",
"languageName": "Uzbek",
"languageNativeName": "Ўзбек",
"translationRatio": 0.031982942430703654
"translationRatio": 0.031997305490063965
},
{
"languageCode": "vi_VN",
"languageName": "Vietnamese",
"languageNativeName": "Tiếng Việt",
"translationRatio": 0.2968241499270564
"translationRatio": 0.2972942629392612
},
{
"languageCode": "yo_NG",
"languageName": "Yoruba",
"languageNativeName": "Yorùbá",
"translationRatio": 0.2625967904836719
"translationRatio": 0.26271471876052543
},
{
"languageCode": "zh_CN",
"languageName": "Chinese Simplified",
"languageNativeName": "简化字",
"translationRatio": 0.9922567613062507
"translationRatio": 0.9922532839339845
},
{
"languageCode": "zh_TW",
"languageName": "Chinese Traditional",
"languageNativeName": "正體字",
"translationRatio": 0.8832903153405903
"translationRatio": 0.8840238015044347
}
];

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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