Compare commits

..

1 Commits

Author SHA1 Message Date
Cursor Agent
1ec6ea68fe Add line height support for Text and BBText objects
Co-authored-by: florian <florian@gdevelop.io>
2025-08-07 14:17:51 +00:00
492 changed files with 7514 additions and 24407 deletions

View File

@@ -329,6 +329,7 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
condition.SetParameters(parameters); condition.SetParameters(parameters);
} }
gd::EventsCodeGenerator::CheckBehaviorParameters(condition, instrInfos);
// Verify that there are no mismatches between object type in parameters. // Verify that there are no mismatches between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) { for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) { if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) {
@@ -356,11 +357,6 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
} }
} }
} }
bool isAnyBehaviorMissing =
gd::EventsCodeGenerator::CheckBehaviorParameters(condition, instrInfos);
if (isAnyBehaviorMissing) {
return "/* Missing behavior - skipped. */";
}
if (instrInfos.IsObjectInstruction()) { if (instrInfos.IsObjectInstruction()) {
gd::String objectName = condition.GetParameter(0).GetPlainString(); gd::String objectName = condition.GetParameter(0).GetPlainString();
@@ -492,16 +488,14 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
return outputCode; return outputCode;
} }
bool EventsCodeGenerator::CheckBehaviorParameters( void EventsCodeGenerator::CheckBehaviorParameters(
const gd::Instruction &instruction, const gd::Instruction &instruction,
const gd::InstructionMetadata &instrInfos) { const gd::InstructionMetadata &instrInfos) {
bool isAnyBehaviorMissing = false; gd::ParameterMetadataTools::IterateOverParameters(
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(), instrInfos.parameters, instruction.GetParameters(), instrInfos.parameters,
[this, &isAnyBehaviorMissing, [this](const gd::ParameterMetadata &parameterMetadata,
&instrInfos](const gd::ParameterMetadata &parameterMetadata, const gd::Expression &parameterValue,
const gd::Expression &parameterValue, size_t parameterIndex, const gd::String &lastObjectName) {
const gd::String &lastObjectName, size_t lastObjectIndex) {
if (ParameterMetadata::IsBehavior(parameterMetadata.GetType())) { if (ParameterMetadata::IsBehavior(parameterMetadata.GetType())) {
const gd::String &behaviorName = parameterValue.GetPlainString(); const gd::String &behaviorName = parameterValue.GetPlainString();
const gd::String &actualBehaviorType = const gd::String &actualBehaviorType =
@@ -512,25 +506,13 @@ bool EventsCodeGenerator::CheckBehaviorParameters(
if (!expectedBehaviorType.empty() && if (!expectedBehaviorType.empty() &&
actualBehaviorType != expectedBehaviorType) { actualBehaviorType != expectedBehaviorType) {
const auto &objectParameterMetadata =
instrInfos.GetParameter(lastObjectIndex);
// Event functions crash if some objects in a group are missing
// the required behaviors, since they lose reference to the original
// objects. Missing behaviors are considered "fatal" only for
// ObjectList parameters, in order to minimize side effects on
// built-in functions.
if (objectParameterMetadata.GetType() == "objectList") {
isAnyBehaviorMissing = true;
}
gd::ProjectDiagnostic projectDiagnostic( gd::ProjectDiagnostic projectDiagnostic(
gd::ProjectDiagnostic::ErrorType::MissingBehavior, "", gd::ProjectDiagnostic::ErrorType::MissingBehavior, "",
actualBehaviorType, expectedBehaviorType, lastObjectName); actualBehaviorType, expectedBehaviorType, lastObjectName);
if (diagnosticReport) if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
diagnosticReport->Add(projectDiagnostic);
} }
} }
}); });
return isAnyBehaviorMissing;
} }
/** /**
@@ -570,6 +552,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
action.SetParameters(parameters); action.SetParameters(parameters);
} }
gd::EventsCodeGenerator::CheckBehaviorParameters(action, instrInfos);
// Verify that there are no mismatches between object type in parameters. // Verify that there are no mismatches between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) { for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) { if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) {
@@ -596,11 +579,6 @@ gd::String EventsCodeGenerator::GenerateActionCode(
} }
} }
} }
bool isAnyBehaviorMissing =
gd::EventsCodeGenerator::CheckBehaviorParameters(action, instrInfos);
if (isAnyBehaviorMissing) {
return "/* Missing behavior - skipped. */";
}
// Call free function first if available // Call free function first if available
if (instrInfos.IsObjectInstruction()) { if (instrInfos.IsObjectInstruction()) {
@@ -791,7 +769,7 @@ gd::String EventsCodeGenerator::GenerateActionsListCode(
} else { } else {
outputCode += actionCode; outputCode += actionCode;
} }
outputCode += "}\n"; outputCode += "}";
} }
return outputCode; return outputCode;

View File

@@ -837,7 +837,7 @@ protected:
virtual gd::String GenerateGetBehaviorNameCode( virtual gd::String GenerateGetBehaviorNameCode(
const gd::String& behaviorName); const gd::String& behaviorName);
bool CheckBehaviorParameters( void CheckBehaviorParameters(
const gd::Instruction &instruction, const gd::Instruction &instruction,
const gd::InstructionMetadata &instrInfos); const gd::InstructionMetadata &instrInfos);

View File

@@ -18,19 +18,19 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAnimatableExtension(
gd::PlatformExtension& extension) { gd::PlatformExtension& extension) {
extension extension
.SetExtensionInformation("AnimatableCapability", .SetExtensionInformation("AnimatableCapability",
_("Objects with animations"),
_("Actions and conditions for objects having animations (sprite, 3D models...)."), _("Actions and conditions for objects having animations (sprite, 3D models...)."),
_("Animate objects."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/objects"); .SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Objects with animations")) extension.AddInstructionOrExpressionGroupMetadata(_("Animatable capability"))
.SetIcon("res/actions/animation24.png"); .SetIcon("res/actions/animation24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Animations and images")) extension.AddInstructionOrExpressionGroupMetadata(_("Animations and images"))
.SetIcon("res/actions/animation24.png"); .SetIcon("res/actions/animation24.png");
gd::BehaviorMetadata& aut = extension.AddBehavior( gd::BehaviorMetadata& aut = extension.AddBehavior(
"AnimatableBehavior", "AnimatableBehavior",
_("Objects with animations"), _("Animatable capability"),
"Animation", "Animation",
_("Actions and conditions for objects having animations (sprite, 3D models...).."), _("Actions and conditions for objects having animations (sprite, 3D models...).."),
"", "",

View File

@@ -18,7 +18,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsEffectExtension(
gd::PlatformExtension& extension) { gd::PlatformExtension& extension) {
extension extension
.SetExtensionInformation("EffectCapability", .SetExtensionInformation("EffectCapability",
_("Objects with effects"), _("Effect capability"),
_("Actions/conditions to enable/disable and change parameters of visual effects applied on objects."), _("Actions/conditions to enable/disable and change parameters of visual effects applied on objects."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
@@ -28,7 +28,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsEffectExtension(
gd::BehaviorMetadata& aut = extension.AddBehavior( gd::BehaviorMetadata& aut = extension.AddBehavior(
"EffectBehavior", "EffectBehavior",
_("Objects with effects"), _("Effect capability"),
"Effect", "Effect",
_("Actions/conditions to enable/disable and change parameters of visual effects applied on objects."), _("Actions/conditions to enable/disable and change parameters of visual effects applied on objects."),
"", "",

View File

@@ -18,7 +18,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFlippableExtension(
gd::PlatformExtension& extension) { gd::PlatformExtension& extension) {
extension extension
.SetExtensionInformation("FlippableCapability", .SetExtensionInformation("FlippableCapability",
_("Flippable objects"), _("Flippable capability"),
_("Actions/conditions for objects which can be flipped horizontally or vertically."), _("Actions/conditions for objects which can be flipped horizontally or vertically."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
@@ -28,7 +28,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFlippableExtension(
gd::BehaviorMetadata& aut = extension.AddBehavior( gd::BehaviorMetadata& aut = extension.AddBehavior(
"FlippableBehavior", "FlippableBehavior",
_("Flippable objects"), _("Flippable capability"),
"Flippable", "Flippable",
_("Actions/conditions for objects which can be flipped horizontally or vertically."), _("Actions/conditions for objects which can be flipped horizontally or vertically."),
"", "",

View File

@@ -18,13 +18,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsOpacityExtension(
gd::PlatformExtension& extension) { gd::PlatformExtension& extension) {
extension extension
.SetExtensionInformation("OpacityCapability", .SetExtensionInformation("OpacityCapability",
_("Objects with opacity"), _("Opacity capability"),
_("Action/condition/expression to change or " _("Action/condition/expression to change or "
"check the opacity of an object (0-255)."), "check the opacity of an object (0-255)."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/objects"); .SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Objects with opacity")) extension.AddInstructionOrExpressionGroupMetadata(_("Opacity capability"))
.SetIcon("res/actions/opacity24.png"); .SetIcon("res/actions/opacity24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Visibility")) extension.AddInstructionOrExpressionGroupMetadata(_("Visibility"))
.SetIcon("res/actions/opacity24.png"); .SetIcon("res/actions/opacity24.png");
@@ -32,7 +32,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsOpacityExtension(
gd::BehaviorMetadata& aut = gd::BehaviorMetadata& aut =
extension extension
.AddBehavior("OpacityBehavior", .AddBehavior("OpacityBehavior",
_("Objects with opacity"), _("Opacity capability"),
"Opacity", "Opacity",
_("Action/condition/expression to change or check the " _("Action/condition/expression to change or check the "
"opacity of an object (0-255)."), "opacity of an object (0-255)."),

View File

@@ -18,7 +18,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsResizableExtension(
extension extension
.SetExtensionInformation( .SetExtensionInformation(
"ResizableCapability", "ResizableCapability",
_("Resizable objects"), _("Resizable capability"),
_("Change or compare the size (width/height) of an object which can " _("Change or compare the size (width/height) of an object which can "
"be resized (i.e: most objects)."), "be resized (i.e: most objects)."),
"Florian Rival", "Florian Rival",
@@ -30,7 +30,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsResizableExtension(
gd::BehaviorMetadata &aut = gd::BehaviorMetadata &aut =
extension extension
.AddBehavior("ResizableBehavior", .AddBehavior("ResizableBehavior",
_("Resizable objects"), _("Resizable capability"),
"Resizable", "Resizable",
_("Change or compare the size (width/height) of an " _("Change or compare the size (width/height) of an "
"object which can be resized (i.e: most objects)."), "object which can be resized (i.e: most objects)."),

View File

@@ -18,13 +18,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsScalableExtension(
gd::PlatformExtension& extension) { gd::PlatformExtension& extension) {
extension extension
.SetExtensionInformation("ScalableCapability", .SetExtensionInformation("ScalableCapability",
_("Scalable objects"), _("Scalable capability"),
_("Actions/conditions/expression to change or " _("Actions/conditions/expression to change or "
"check the scale of an object (default: 1)."), "check the scale of an object (default: 1)."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/objects"); .SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Scalable objects")) extension.AddInstructionOrExpressionGroupMetadata(_("Scalable capability"))
.SetIcon("res/actions/scale24_black.png"); .SetIcon("res/actions/scale24_black.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon( extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon(
"res/actions/scale24_black.png"); "res/actions/scale24_black.png");
@@ -32,7 +32,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsScalableExtension(
gd::BehaviorMetadata& aut = gd::BehaviorMetadata& aut =
extension extension
.AddBehavior("ScalableBehavior", .AddBehavior("ScalableBehavior",
_("Scalable objects"), _("Scalable capability"),
"Scale", "Scale",
_("Actions/conditions/expression to change or check the " _("Actions/conditions/expression to change or check the "
"scale of an object (default: 1)."), "scale of an object (default: 1)."),

View File

@@ -18,17 +18,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTextContainerExtension(
gd::PlatformExtension& extension) { gd::PlatformExtension& extension) {
extension extension
.SetExtensionInformation("TextContainerCapability", .SetExtensionInformation("TextContainerCapability",
_("Objects containing a text"), _("Text capability"),
_("Allows an object to contain a text, usually shown on screen, that can be modified."), _("Allows an object to contain a text, usually shown on screen, that can be modified."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/objects"); .SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Objects containing a text")) extension.AddInstructionOrExpressionGroupMetadata(_("Text capability"))
.SetIcon("res/conditions/text24_black.png"); .SetIcon("res/conditions/text24_black.png");
gd::BehaviorMetadata& aut = extension.AddBehavior( gd::BehaviorMetadata& aut = extension.AddBehavior(
"TextContainerBehavior", "TextContainerBehavior",
_("Objects containing a text"), _("Text capability"),
"Text", "Text",
_("Allows an object to contain a text, usually shown on screen, that can be modified."), _("Allows an object to contain a text, usually shown on screen, that can be modified."),
"", "",

View File

@@ -52,25 +52,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
.SetHidden(); .SetHidden();
extension extension
.AddCondition( .AddCondition("KeyFromTextPressed",
"KeyFromTextPressed", _("Key pressed"),
_("Key pressed"), _("Check if a key is pressed"),
_("Check if a key is pressed. This stays true as long as " _("_PARAM1_ key is pressed"),
"the key is held down. To check if a key was pressed during "
"the frame, use \"Key just pressed\" instead."),
_("_PARAM1_ key is pressed"),
"",
"res/conditions/keyboard24.png",
"res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("keyboardKey", _("Key to check"))
.MarkAsSimple();
extension
.AddCondition("KeyFromTextJustPressed",
_("Key just pressed"),
_("Check if a key was just pressed."),
_("_PARAM1_ key was just pressed"),
"", "",
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
@@ -81,7 +66,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
extension extension
.AddCondition("KeyFromTextReleased", .AddCondition("KeyFromTextReleased",
_("Key released"), _("Key released"),
_("Check if a key was just released."), _("Check if a key was just released"),
_("_PARAM1_ key is released"), _("_PARAM1_ key is released"),
"", "",
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",

View File

@@ -298,19 +298,6 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
return *this; return *this;
} }
/**
* Check if the behavior can be used on objects from event-based objects.
*/
bool IsRelevantForChildObjects() const { return isRelevantForChildObjects; }
/**
* Set that behavior can't be used on objects from event-based objects.
*/
BehaviorMetadata &MarkAsIrrelevantForChildObjects() {
isRelevantForChildObjects = false;
return *this;
}
QuickCustomization::Visibility GetQuickCustomizationVisibility() const { QuickCustomization::Visibility GetQuickCustomizationVisibility() const {
return quickCustomizationVisibility; return quickCustomizationVisibility;
} }
@@ -406,7 +393,6 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
mutable std::vector<gd::String> requiredBehaviors; mutable std::vector<gd::String> requiredBehaviors;
bool isPrivate = false; bool isPrivate = false;
bool isHidden = false; bool isHidden = false;
bool isRelevantForChildObjects = true;
gd::String openFullEditorLabel; gd::String openFullEditorLabel;
QuickCustomization::Visibility quickCustomizationVisibility = QuickCustomization::Visibility::Default; QuickCustomization::Visibility quickCustomizationVisibility = QuickCustomization::Visibility::Default;

View File

@@ -277,10 +277,6 @@ class GD_CORE_API MetadataProvider {
return &metadata == &badObjectInfo; return &metadata == &badObjectInfo;
} }
static bool IsBadEffectMetadata(const gd::EffectMetadata& metadata) {
return &metadata == &badEffectMetadata;
}
virtual ~MetadataProvider(); virtual ~MetadataProvider();
private: private:

View File

@@ -194,8 +194,7 @@ void ParameterMetadataTools::IterateOverParameters(
[&fn](const gd::ParameterMetadata& parameterMetadata, [&fn](const gd::ParameterMetadata& parameterMetadata,
const gd::Expression& parameterValue, const gd::Expression& parameterValue,
size_t parameterIndex, size_t parameterIndex,
const gd::String& lastObjectName, const gd::String& lastObjectName) {
size_t lastObjectIndex) {
fn(parameterMetadata, parameterValue, lastObjectName); fn(parameterMetadata, parameterValue, lastObjectName);
}); });
} }
@@ -206,10 +205,8 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
std::function<void(const gd::ParameterMetadata& parameterMetadata, std::function<void(const gd::ParameterMetadata& parameterMetadata,
const gd::Expression& parameterValue, const gd::Expression& parameterValue,
size_t parameterIndex, size_t parameterIndex,
const gd::String& lastObjectName, const gd::String& lastObjectName)> fn) {
size_t lastObjectIndex)> fn) {
gd::String lastObjectName = ""; gd::String lastObjectName = "";
size_t lastObjectIndex = 0;
for (std::size_t pNb = 0; pNb < parametersMetadata.GetParametersCount(); for (std::size_t pNb = 0; pNb < parametersMetadata.GetParametersCount();
++pNb) { ++pNb) {
const gd::ParameterMetadata &parameterMetadata = const gd::ParameterMetadata &parameterMetadata =
@@ -221,17 +218,15 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
? Expression(parameterMetadata.GetDefaultValue()) ? Expression(parameterMetadata.GetDefaultValue())
: parameterValue; : parameterValue;
fn(parameterMetadata, parameterValueOrDefault, pNb, lastObjectName, lastObjectIndex); fn(parameterMetadata, parameterValueOrDefault, pNb, lastObjectName);
// Memorize the last object name. By convention, parameters that require // Memorize the last object name. By convention, parameters that require
// an object (mainly, "objectvar" and "behavior") should be placed after // an object (mainly, "objectvar" and "behavior") should be placed after
// the object in the list of parameters (if possible, just after). // the object in the list of parameters (if possible, just after).
// Search "lastObjectName" in the codebase for other place where this // Search "lastObjectName" in the codebase for other place where this
// convention is enforced. // convention is enforced.
if (gd::ParameterMetadata::IsObject(parameterMetadata.GetType())) { if (gd::ParameterMetadata::IsObject(parameterMetadata.GetType()))
lastObjectName = parameterValueOrDefault.GetPlainString(); lastObjectName = parameterValueOrDefault.GetPlainString();
lastObjectIndex = pNb;
}
} }
} }

View File

@@ -64,8 +64,7 @@ class GD_CORE_API ParameterMetadataTools {
std::function<void(const gd::ParameterMetadata& parameterMetadata, std::function<void(const gd::ParameterMetadata& parameterMetadata,
const gd::Expression& parameterValue, const gd::Expression& parameterValue,
size_t parameterIndex, size_t parameterIndex,
const gd::String& lastObjectName, const gd::String& lastObjectName)> fn);
size_t lastObjectIndex)> fn);
/** /**
* Iterate over the parameters of a FunctionCallNode. * Iterate over the parameters of a FunctionCallNode.

View File

@@ -813,13 +813,6 @@ gd::String PlatformExtension::GetObjectFullType(const gd::String& extensionName,
return extensionName + separator + objectName; return extensionName + separator + objectName;
} }
gd::String PlatformExtension::GetVariantFullType(const gd::String& extensionName,
const gd::String& objectName,
const gd::String& variantName) {
const auto& separator = GetNamespaceSeparator();
return extensionName + separator + objectName + separator + variantName;
}
gd::String PlatformExtension::GetExtensionFromFullObjectType( gd::String PlatformExtension::GetExtensionFromFullObjectType(
const gd::String& type) { const gd::String& type) {
const auto separatorIndex = const auto separatorIndex =

View File

@@ -663,10 +663,6 @@ class GD_CORE_API PlatformExtension {
static gd::String GetObjectFullType(const gd::String& extensionName, static gd::String GetObjectFullType(const gd::String& extensionName,
const gd::String& objectName); const gd::String& objectName);
static gd::String GetVariantFullType(const gd::String& extensionName,
const gd::String& objectName,
const gd::String& variantName);
static gd::String GetExtensionFromFullObjectType(const gd::String& type); static gd::String GetExtensionFromFullObjectType(const gd::String& type);
static gd::String GetObjectNameFromFullObjectType(const gd::String& type); static gd::String GetObjectNameFromFullObjectType(const gd::String& type);

View File

@@ -29,7 +29,7 @@ bool BehaviorParametersFiller::DoVisitInstruction(gd::Instruction &instruction,
instruction.GetParameters(), metadata.GetParameters(), instruction.GetParameters(), metadata.GetParameters(),
[&](const gd::ParameterMetadata &parameterMetadata, [&](const gd::ParameterMetadata &parameterMetadata,
const gd::Expression &parameterValue, size_t parameterIndex, const gd::Expression &parameterValue, size_t parameterIndex,
const gd::String &lastObjectName, size_t lastObjectIndex) { const gd::String &lastObjectName) {
if (parameterMetadata.GetValueTypeMetadata().IsBehavior() && if (parameterMetadata.GetValueTypeMetadata().IsBehavior() &&
parameterValue.GetPlainString().length() == 0) { parameterValue.GetPlainString().length() == 0) {

View File

@@ -108,10 +108,12 @@ bool EventsBehaviorRenamer::DoVisitInstruction(gd::Instruction& instruction,
platform, instruction.GetType()); platform, instruction.GetType());
gd::ParameterMetadataTools::IterateOverParametersWithIndex( gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(), metadata.GetParameters(), instruction.GetParameters(),
[&](const gd::ParameterMetadata &parameterMetadata, metadata.GetParameters(),
const gd::Expression &parameterValue, size_t parameterIndex, [&](const gd::ParameterMetadata& parameterMetadata,
const gd::String &lastObjectName, size_t lastObjectIndex) { const gd::Expression& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
const gd::String& type = parameterMetadata.GetType(); const gd::String& type = parameterMetadata.GetType();
if (gd::ParameterMetadata::IsBehavior(type)) { if (gd::ParameterMetadata::IsBehavior(type)) {

View File

@@ -183,10 +183,12 @@ bool EventsParameterReplacer::DoVisitInstruction(gd::Instruction& instruction,
platform, instruction.GetType()); platform, instruction.GetType());
gd::ParameterMetadataTools::IterateOverParametersWithIndex( gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(), metadata.GetParameters(), instruction.GetParameters(),
[&](const gd::ParameterMetadata &parameterMetadata, metadata.GetParameters(),
const gd::Expression &parameterValue, size_t parameterIndex, [&](const gd::ParameterMetadata& parameterMetadata,
const gd::String &lastObjectName, size_t lastObjectIndex) { const gd::Expression& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
if (!gd::EventsParameterReplacer::CanContainParameter( if (!gd::EventsParameterReplacer::CanContainParameter(
parameterMetadata.GetValueTypeMetadata())) { parameterMetadata.GetValueTypeMetadata())) {
return; return;

View File

@@ -217,10 +217,12 @@ bool EventsPropertyReplacer::DoVisitInstruction(gd::Instruction& instruction,
bool shouldDeleteInstruction = false; bool shouldDeleteInstruction = false;
gd::ParameterMetadataTools::IterateOverParametersWithIndex( gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(), metadata.GetParameters(), instruction.GetParameters(),
[&](const gd::ParameterMetadata &parameterMetadata, metadata.GetParameters(),
const gd::Expression &parameterValue, size_t parameterIndex, [&](const gd::ParameterMetadata& parameterMetadata,
const gd::String &lastObjectName, size_t lastObjectIndex) { const gd::Expression& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
if (!gd::EventsPropertyReplacer::CanContainProperty( if (!gd::EventsPropertyReplacer::CanContainProperty(
parameterMetadata.GetValueTypeMetadata())) { parameterMetadata.GetValueTypeMetadata())) {
return; return;

View File

@@ -334,7 +334,7 @@ private:
instruction.GetParameters(), metadata.GetParameters(), instruction.GetParameters(), metadata.GetParameters(),
[&](const gd::ParameterMetadata &parameterMetadata, [&](const gd::ParameterMetadata &parameterMetadata,
const gd::Expression &parameterValue, size_t parameterIndex, const gd::Expression &parameterValue, size_t parameterIndex,
const gd::String &lastObjectName, size_t lastObjectIndex) { const gd::String &lastObjectName) {
if (!gd::EventsObjectReplacer::CanContainObject( if (!gd::EventsObjectReplacer::CanContainObject(
parameterMetadata.GetValueTypeMetadata())) { parameterMetadata.GetValueTypeMetadata())) {
return; return;

View File

@@ -42,16 +42,18 @@ bool EventsVariableInstructionTypeSwitcher::DoVisitInstruction(gd::Instruction&
platform, instruction.GetType()); platform, instruction.GetType());
gd::ParameterMetadataTools::IterateOverParametersWithIndex( gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(), metadata.GetParameters(), instruction.GetParameters(),
[&](const gd::ParameterMetadata &parameterMetadata, metadata.GetParameters(),
const gd::Expression &parameterValue, size_t parameterIndex, [&](const gd::ParameterMetadata& parameterMetadata,
const gd::String &lastObjectName, size_t lastObjectIndex) { const gd::Expression& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
const gd::String& type = parameterMetadata.GetType(); const gd::String& type = parameterMetadata.GetType();
if (!gd::ParameterMetadata::IsExpression("variable", type) || if (!gd::ParameterMetadata::IsExpression("variable", type) ||
!gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction( !gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction(
instruction.GetType())) { instruction.GetType())) {
return; return;
} }
const auto variableName = const auto variableName =
gd::ExpressionVariableNameFinder::GetVariableName( gd::ExpressionVariableNameFinder::GetVariableName(
@@ -70,11 +72,10 @@ bool EventsVariableInstructionTypeSwitcher::DoVisitInstruction(gd::Instruction&
.GetObjectOrGroupVariablesContainer(lastObjectName); .GetObjectOrGroupVariablesContainer(lastObjectName);
} }
} else if (type == "variableOrProperty") { } else if (type == "variableOrProperty") {
variablesContainer = variablesContainer =
&GetProjectScopedContainers() &GetProjectScopedContainers()
.GetVariablesContainersList() .GetVariablesContainersList()
.GetVariablesContainerFromVariableOrPropertyName( .GetVariablesContainerFromVariableOrPropertyName(variableName);
variableName);
} else { } else {
if (GetProjectScopedContainers().GetVariablesContainersList().Has( if (GetProjectScopedContainers().GetVariablesContainersList().Has(
variableName)) { variableName)) {

View File

@@ -448,10 +448,12 @@ bool EventsVariableReplacer::DoVisitInstruction(gd::Instruction& instruction,
bool shouldDeleteInstruction = false; bool shouldDeleteInstruction = false;
gd::ParameterMetadataTools::IterateOverParametersWithIndex( gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(), metadata.GetParameters(), instruction.GetParameters(),
[&](const gd::ParameterMetadata &parameterMetadata, metadata.GetParameters(),
const gd::Expression &parameterValue, size_t parameterIndex, [&](const gd::ParameterMetadata& parameterMetadata,
const gd::String &lastObjectName, size_t lastObjectIndex) { const gd::Expression& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
const gd::String& type = parameterMetadata.GetType(); const gd::String& type = parameterMetadata.GetType();
if (!gd::ParameterMetadata::IsExpression("variable", type) && if (!gd::ParameterMetadata::IsExpression("variable", type) &&

View File

@@ -150,7 +150,7 @@ bool ProjectElementRenamer::DoVisitInstruction(gd::Instruction &instruction,
instruction.GetParameters(), metadata.GetParameters(), instruction.GetParameters(), metadata.GetParameters(),
[&](const gd::ParameterMetadata &parameterMetadata, [&](const gd::ParameterMetadata &parameterMetadata,
const gd::Expression &parameterValue, size_t parameterIndex, const gd::Expression &parameterValue, size_t parameterIndex,
const gd::String &lastObjectName, size_t lastObjectIndex) { const gd::String &lastObjectName) {
if (parameterMetadata.GetType() == "layer") { if (parameterMetadata.GetType() == "layer") {
if (parameterValue.GetPlainString().length() < 2) { if (parameterValue.GetPlainString().length() < 2) {
// This is either the base layer or an invalid layer name. // This is either the base layer or an invalid layer name.

View File

@@ -1,23 +0,0 @@
#include "UsedObjectTypeFinder.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/IDE/ProjectBrowserHelper.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
namespace gd {
bool UsedObjectTypeFinder::ScanProject(gd::Project &project,
const gd::String &objectType) {
UsedObjectTypeFinder worker(project, objectType);
gd::ProjectBrowserHelper::ExposeProjectObjects(project, worker);
return worker.hasFoundObjectType;
};
void UsedObjectTypeFinder::DoVisitObject(gd::Object &object) {
if (!hasFoundObjectType && object.GetType() == objectType) {
hasFoundObjectType = true;
}
};
} // namespace gd

View File

@@ -1,39 +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;
} // namespace gd
namespace gd {
class GD_CORE_API UsedObjectTypeFinder : public ArbitraryObjectsWorker {
public:
static bool ScanProject(gd::Project &project, const gd::String &objectType);
private:
UsedObjectTypeFinder(gd::Project &project_, const gd::String &objectType_)
: project(project_), objectType(objectType_){};
gd::Project &project;
const gd::String &objectType;
bool hasFoundObjectType = false;
// Object Visitor
void DoVisitObject(gd::Object &object) override;
};
}; // namespace gd

View File

@@ -76,7 +76,6 @@ void ObjectAssetSerializer::SerializeTo(
double width = 0; double width = 0;
double height = 0; double height = 0;
std::unordered_set<gd::String> alreadyUsedVariantIdentifiers;
if (project.HasEventsBasedObject(object.GetType())) { if (project.HasEventsBasedObject(object.GetType())) {
SerializerElement &variantsElement = SerializerElement &variantsElement =
objectAssetElement.AddChild("variants"); objectAssetElement.AddChild("variants");
@@ -88,6 +87,7 @@ void ObjectAssetSerializer::SerializeTo(
height = variant->GetAreaMaxY() - variant->GetAreaMinY(); height = variant->GetAreaMaxY() - variant->GetAreaMinY();
} }
std::unordered_set<gd::String> alreadyUsedVariantIdentifiers;
gd::ObjectAssetSerializer::SerializeUsedVariantsTo( gd::ObjectAssetSerializer::SerializeUsedVariantsTo(
project, object, variantsElement, alreadyUsedVariantIdentifiers); project, object, variantsElement, alreadyUsedVariantIdentifiers);
} }
@@ -114,24 +114,14 @@ void ObjectAssetSerializer::SerializeTo(
resourceElement.SetAttribute("name", resource.GetName()); resourceElement.SetAttribute("name", resource.GetName());
} }
std::unordered_set<gd::String> usedExtensionNames;
usedExtensionNames.insert(extensionName);
for (auto &usedVariantIdentifier : alreadyUsedVariantIdentifiers) {
usedExtensionNames.insert(PlatformExtension::GetExtensionFromFullObjectType(
usedVariantIdentifier));
}
SerializerElement &requiredExtensionsElement = SerializerElement &requiredExtensionsElement =
objectAssetElement.AddChild("requiredExtensions"); objectAssetElement.AddChild("requiredExtensions");
requiredExtensionsElement.ConsiderAsArrayOf("requiredExtension"); requiredExtensionsElement.ConsiderAsArrayOf("requiredExtension");
for (auto &usedExtensionName : usedExtensionNames) { if (project.HasEventsFunctionsExtensionNamed(extensionName)) {
if (project.HasEventsFunctionsExtensionNamed(usedExtensionName)) { SerializerElement &requiredExtensionElement =
auto &extension = project.GetEventsFunctionsExtension(usedExtensionName); requiredExtensionsElement.AddChild("requiredExtension");
SerializerElement &requiredExtensionElement = requiredExtensionElement.SetAttribute("extensionName", extensionName);
requiredExtensionsElement.AddChild("requiredExtension"); requiredExtensionElement.SetAttribute("extensionVersion", "1.0.0");
requiredExtensionElement.SetAttribute("extensionName", usedExtensionName);
requiredExtensionElement.SetAttribute("extensionVersion",
extension.GetVersion());
}
} }
// TODO This can be removed when the asset script no longer require it. // TODO This can be removed when the asset script no longer require it.

View File

@@ -227,11 +227,12 @@ bool ResourceWorkerInEventsWorker::DoVisitInstruction(gd::Instruction& instructi
platform, instruction.GetType()); platform, instruction.GetType());
gd::ParameterMetadataTools::IterateOverParametersWithIndex( gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(), metadata.GetParameters(), instruction.GetParameters(),
[this, &instruction]( metadata.GetParameters(),
const gd::ParameterMetadata &parameterMetadata, [this, &instruction](const gd::ParameterMetadata& parameterMetadata,
const gd::Expression &parameterExpression, size_t parameterIndex, const gd::Expression& parameterExpression,
const gd::String &lastObjectName, size_t lastObjectIndex) { size_t parameterIndex,
const gd::String& lastObjectName) {
const String& parameterValue = parameterExpression.GetPlainString(); const String& parameterValue = parameterExpression.GetPlainString();
if (parameterMetadata.GetType() == "fontResource") { if (parameterMetadata.GetType() == "fontResource") {
gd::String updatedParameterValue = parameterValue; gd::String updatedParameterValue = parameterValue;

View File

@@ -7,6 +7,7 @@
#include <map> #include <map>
#include "GDCore/CommonTools.h" #include "GDCore/CommonTools.h"
#include "GDCore/IDE/AbstractFileSystem.h" #include "GDCore/IDE/AbstractFileSystem.h"
#include "GDCore/IDE/Project/ResourcesAbsolutePathChecker.h"
#include "GDCore/IDE/Project/ResourcesMergingHelper.h" #include "GDCore/IDE/Project/ResourcesMergingHelper.h"
#include "GDCore/Project/Project.h" #include "GDCore/Project/Project.h"
#include "GDCore/Tools/Localization.h" #include "GDCore/Tools/Localization.h"
@@ -25,37 +26,42 @@ bool ProjectResourcesCopier::CopyAllResourcesTo(
bool preserveAbsoluteFilenames, bool preserveAbsoluteFilenames,
bool preserveDirectoryStructure) { bool preserveDirectoryStructure) {
if (updateOriginalProject) { if (updateOriginalProject) {
gd::ProjectResourcesCopier::AdaptFilePathsAndCopyAllResourcesTo( gd::ProjectResourcesCopier::CopyAllResourcesTo(
originalProject, fs, destinationDirectory, preserveAbsoluteFilenames, originalProject, originalProject, fs, destinationDirectory,
preserveDirectoryStructure); preserveAbsoluteFilenames, preserveDirectoryStructure);
} else { } else {
gd::Project clonedProject = originalProject; gd::Project clonedProject = originalProject;
gd::ProjectResourcesCopier::AdaptFilePathsAndCopyAllResourcesTo( gd::ProjectResourcesCopier::CopyAllResourcesTo(
clonedProject, fs, destinationDirectory, preserveAbsoluteFilenames, originalProject, clonedProject, fs, destinationDirectory,
preserveDirectoryStructure); preserveAbsoluteFilenames, preserveDirectoryStructure);
} }
return true; return true;
} }
bool ProjectResourcesCopier::AdaptFilePathsAndCopyAllResourcesTo( bool ProjectResourcesCopier::CopyAllResourcesTo(
gd::Project& project, gd::Project& originalProject,
gd::Project& clonedProject,
AbstractFileSystem& fs, AbstractFileSystem& fs,
gd::String destinationDirectory, gd::String destinationDirectory,
bool preserveAbsoluteFilenames, bool preserveAbsoluteFilenames,
bool preserveDirectoryStructure) { bool preserveDirectoryStructure) {
auto projectDirectory = fs.DirNameFrom(project.GetProjectFile()); // Check if there are some resources with absolute filenames
gd::ResourcesAbsolutePathChecker absolutePathChecker(originalProject.GetResourcesManager(), fs);
gd::ResourceExposer::ExposeWholeProjectResources(originalProject, absolutePathChecker);
auto projectDirectory = fs.DirNameFrom(originalProject.GetProjectFile());
std::cout << "Copying all resources from " << projectDirectory << " to " std::cout << "Copying all resources from " << projectDirectory << " to "
<< destinationDirectory << "..." << std::endl; << destinationDirectory << "..." << std::endl;
// Get the resources to be copied // Get the resources to be copied
gd::ResourcesMergingHelper resourcesMergingHelper( gd::ResourcesMergingHelper resourcesMergingHelper(
project.GetResourcesManager(), fs); clonedProject.GetResourcesManager(), fs);
resourcesMergingHelper.SetBaseDirectory(projectDirectory); resourcesMergingHelper.SetBaseDirectory(projectDirectory);
resourcesMergingHelper.PreserveDirectoriesStructure( resourcesMergingHelper.PreserveDirectoriesStructure(
preserveDirectoryStructure); preserveDirectoryStructure);
resourcesMergingHelper.PreserveAbsoluteFilenames(preserveAbsoluteFilenames); resourcesMergingHelper.PreserveAbsoluteFilenames(preserveAbsoluteFilenames);
gd::ResourceExposer::ExposeWholeProjectResources(project, gd::ResourceExposer::ExposeWholeProjectResources(clonedProject,
resourcesMergingHelper); resourcesMergingHelper);
// Copy resources // Copy resources

View File

@@ -50,10 +50,12 @@ class GD_CORE_API ProjectResourcesCopier {
bool preserveDirectoryStructure = true); bool preserveDirectoryStructure = true);
private: private:
static bool AdaptFilePathsAndCopyAllResourcesTo( static bool CopyAllResourcesTo(gd::Project& originalProject,
gd::Project &project, gd::AbstractFileSystem &fs, gd::Project& clonedProject,
gd::String destinationDirectory, bool preserveAbsoluteFilenames = true, gd::AbstractFileSystem& fs,
bool preserveDirectoryStructure = true); gd::String destinationDirectory,
bool preserveAbsoluteFilenames = true,
bool preserveDirectoryStructure = true);
}; };
} // namespace gd } // namespace gd

View File

@@ -0,0 +1,17 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ResourcesAbsolutePathChecker.h"
#include "GDCore/IDE/AbstractFileSystem.h"
#include "GDCore/String.h"
namespace gd {
void ResourcesAbsolutePathChecker::ExposeFile(gd::String& resourceFilename) {
if (fs.IsAbsolute(resourceFilename)) hasAbsoluteFilenames = true;
}
} // namespace gd

View File

@@ -0,0 +1,48 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/IDE/AbstractFileSystem.h"
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
#include "GDCore/String.h"
namespace gd {
/**
* \brief Helper used to check if a project has at least a resource with an
* absolute filename.
*
* \see ArbitraryResourceWorker
*
* \ingroup IDE
*/
class GD_CORE_API ResourcesAbsolutePathChecker
: public ArbitraryResourceWorker {
public:
ResourcesAbsolutePathChecker(gd::ResourcesManager &resourcesManager,
AbstractFileSystem &fileSystem)
: ArbitraryResourceWorker(resourcesManager), hasAbsoluteFilenames(false),
fs(fileSystem){};
virtual ~ResourcesAbsolutePathChecker(){};
/**
* Return true if there is at least a resource with an absolute filename.
*/
bool HasResourceWithAbsoluteFilenames() const {
return hasAbsoluteFilenames;
};
/**
* Check if there is a resource with an absolute path
*/
virtual void ExposeFile(gd::String& resource);
private:
bool hasAbsoluteFilenames;
AbstractFileSystem& fs;
};
} // namespace gd

View File

@@ -22,14 +22,6 @@ void ResourcesMergingHelper::ExposeFile(gd::String& resourceFilename) {
resourceFullFilename = gd::AbstractFileSystem::NormalizeSeparator( resourceFullFilename = gd::AbstractFileSystem::NormalizeSeparator(
resourceFullFilename); // Protect against \ on Linux. resourceFullFilename); // Protect against \ on Linux.
if (shouldUseOriginalAbsoluteFilenames) {
// There is no need to fill `newFilenames` and `oldFilenames` since the file
// location stays the same.
fs.MakeAbsolute(resourceFullFilename, baseDirectory);
resourceFilename = resourceFullFilename;
return;
}
// In the case of absolute filenames that we don't want to preserve, or // In the case of absolute filenames that we don't want to preserve, or
// in the case of copying files without preserving relative folders, the new // in the case of copying files without preserving relative folders, the new
// names will be generated from the filename alone (with collision protection). // names will be generated from the filename alone (with collision protection).

View File

@@ -3,7 +3,8 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License. * reserved. This project is released under the MIT License.
*/ */
#pragma once #ifndef RESOURCESMERGINGHELPER_H
#define RESOURCESMERGINGHELPER_H
#include <map> #include <map>
#include <memory> #include <memory>
@@ -57,15 +58,6 @@ public:
preserveAbsoluteFilenames = preserveAbsoluteFilenames_; preserveAbsoluteFilenames = preserveAbsoluteFilenames_;
}; };
/**
* \brief Set if the absolute filenames of original files must be used for
* any resource.
*/
void SetShouldUseOriginalAbsoluteFilenames(
bool shouldUseOriginalAbsoluteFilenames_ = true) {
shouldUseOriginalAbsoluteFilenames = shouldUseOriginalAbsoluteFilenames_;
};
/** /**
* \brief Return a map containing the resources old absolute filename as key, * \brief Return a map containing the resources old absolute filename as key,
* and the resources new filenames as value. The new filenames are relative to * and the resources new filenames as value. The new filenames are relative to
@@ -101,13 +93,10 @@ public:
///< absolute (C:\MyFile.png will not be ///< absolute (C:\MyFile.png will not be
///< transformed into a relative filename ///< transformed into a relative filename
///< (MyFile.png). ///< (MyFile.png).
/**
* Set to true if the absolute filenames of original files must be used for
* any resource.
*/
bool shouldUseOriginalAbsoluteFilenames = false;
gd::AbstractFileSystem& gd::AbstractFileSystem&
fs; ///< The gd::AbstractFileSystem used to manipulate files. fs; ///< The gd::AbstractFileSystem used to manipulate files.
}; };
} // namespace gd } // namespace gd
#endif // RESOURCESMERGINGHELPER_H

View File

@@ -6,7 +6,6 @@
#include "SceneResourcesFinder.h" #include "SceneResourcesFinder.h"
#include "GDCore/IDE/ResourceExposer.h" #include "GDCore/IDE/ResourceExposer.h"
#include "GDCore/Project/EventsBasedObjectVariant.h"
#include "GDCore/Project/Layout.h" #include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h" #include "GDCore/Project/Project.h"
#include "GDCore/Serialization/SerializerElement.h" #include "GDCore/Serialization/SerializerElement.h"
@@ -28,14 +27,6 @@ std::set<gd::String> SceneResourcesFinder::FindSceneResources(gd::Project &proje
return resourceWorker.resourceNames; return resourceWorker.resourceNames;
} }
std::set<gd::String> SceneResourcesFinder::FindEventsBasedObjectVariantResources(gd::Project &project,
gd::EventsBasedObjectVariant &variant) {
gd::SceneResourcesFinder resourceWorker(project.GetResourcesManager());
gd::ResourceExposer::ExposeEventsBasedObjectVariantResources(project, variant, resourceWorker);
return resourceWorker.resourceNames;
}
void SceneResourcesFinder::AddUsedResource(gd::String &resourceName) { void SceneResourcesFinder::AddUsedResource(gd::String &resourceName) {
if (resourceName.empty()) { if (resourceName.empty()) {
return; return;

View File

@@ -15,7 +15,6 @@ namespace gd {
class Project; class Project;
class Layout; class Layout;
class SerializerElement; class SerializerElement;
class EventsBasedObjectVariant;
} // namespace gd } // namespace gd
namespace gd { namespace gd {
@@ -28,7 +27,7 @@ namespace gd {
class SceneResourcesFinder : private gd::ArbitraryResourceWorker { class SceneResourcesFinder : private gd::ArbitraryResourceWorker {
public: public:
/** /**
* @brief Find resource usages in a given scene. * @brief Find resource usages in a given scenes.
* *
* It doesn't include resources used globally. * It doesn't include resources used globally.
*/ */
@@ -42,13 +41,6 @@ public:
*/ */
static std::set<gd::String> FindProjectResources(gd::Project &project); static std::set<gd::String> FindProjectResources(gd::Project &project);
/**
* @brief Find resource usages in a given events-based object variant.
*/
static std::set<gd::String>
FindEventsBasedObjectVariantResources(gd::Project &project,
gd::EventsBasedObjectVariant &variant);
virtual ~SceneResourcesFinder(){}; virtual ~SceneResourcesFinder(){};
private: private:

View File

@@ -332,12 +332,6 @@ void ProjectBrowserHelper::ExposeLayoutObjects(gd::Layout &layout,
worker.Launch(layout.GetObjects()); worker.Launch(layout.GetObjects());
} }
void ProjectBrowserHelper::ExposeEventsBasedObjectVariantObjects(
gd::EventsBasedObjectVariant &eventsBasedObjectVariant,
gd::ArbitraryObjectsWorker &worker) {
worker.Launch(eventsBasedObjectVariant.GetObjects());
}
void ProjectBrowserHelper::ExposeProjectFunctions( void ProjectBrowserHelper::ExposeProjectFunctions(
gd::Project &project, gd::ArbitraryEventsFunctionsWorker &worker) { gd::Project &project, gd::ArbitraryEventsFunctionsWorker &worker) {

View File

@@ -13,7 +13,6 @@ class EventsFunctionsExtension;
class EventsFunction; class EventsFunction;
class EventsBasedBehavior; class EventsBasedBehavior;
class EventsBasedObject; class EventsBasedObject;
class EventsBasedObjectVariant;
class ArbitraryEventsWorker; class ArbitraryEventsWorker;
class ArbitraryEventsWorkerWithContext; class ArbitraryEventsWorkerWithContext;
class ArbitraryEventsFunctionsWorker; class ArbitraryEventsFunctionsWorker;
@@ -208,17 +207,6 @@ public:
static void ExposeLayoutObjects(gd::Layout &layout, static void ExposeLayoutObjects(gd::Layout &layout,
gd::ArbitraryObjectsWorker &worker); gd::ArbitraryObjectsWorker &worker);
/**
* \brief Call the specified worker on all ObjectContainers of the
* events-based object variant.
*
* This should be the preferred way to traverse all the objects of an
* events-based object variant.
*/
static void ExposeEventsBasedObjectVariantObjects(
gd::EventsBasedObjectVariant &eventsBasedObjectVariant,
gd::ArbitraryObjectsWorker &worker);
/** /**
* \brief Call the specified worker on all FunctionsContainers of the project * \brief Call the specified worker on all FunctionsContainers of the project
* (global, layouts...) * (global, layouts...)

View File

@@ -248,13 +248,12 @@ gd::String PropertyFunctionGenerator::GetStringifiedExtraInfo(
gd::String arrayString; gd::String arrayString;
arrayString += "["; arrayString += "[";
bool isFirst = true; bool isFirst = true;
for (const auto &choice : property.GetChoices()) { for (const gd::String &choice : property.GetExtraInfo()) {
if (!isFirst) { if (!isFirst) {
arrayString += ","; arrayString += ",";
} }
isFirst = false; isFirst = false;
// TODO Handle labels (and search "choice label") arrayString += "\"" + choice + "\"";
arrayString += "\"" + choice.GetValue() + "\"";
} }
arrayString += "]"; arrayString += "]";
return arrayString; return arrayString;

View File

@@ -75,17 +75,6 @@ void ResourceExposer::ExposeProjectResources(
// Expose global objects configuration resources // Expose global objects configuration resources
auto objectWorker = gd::GetResourceWorkerOnObjects(project, worker); auto objectWorker = gd::GetResourceWorkerOnObjects(project, worker);
objectWorker.Launch(project.GetObjects()); objectWorker.Launch(project.GetObjects());
// Exposed extension event resources
// Note that using resources in extensions is very unlikely and probably not
// worth the effort of something smart.
auto eventWorker = gd::GetResourceWorkerOnEvents(project, worker);
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
gd::ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
project, eventsFunctionsExtension, eventWorker);
}
} }
void ResourceExposer::ExposeLayoutResources( void ResourceExposer::ExposeLayoutResources(
@@ -114,34 +103,16 @@ void ResourceExposer::ExposeLayoutResources(
auto eventWorker = gd::GetResourceWorkerOnEvents(project, worker); auto eventWorker = gd::GetResourceWorkerOnEvents(project, worker);
gd::ProjectBrowserHelper::ExposeLayoutEventsAndDependencies( gd::ProjectBrowserHelper::ExposeLayoutEventsAndDependencies(
project, layout, eventWorker); project, layout, eventWorker);
}
void ResourceExposer::ExposeEventsBasedObjectVariantResources( // Exposed extension event resources
gd::Project &project, // Note that using resources in extensions is very unlikely and probably not
gd::EventsBasedObjectVariant &eventsBasedObjectVariant, // worth the effort of something smart.
gd::ArbitraryResourceWorker &worker) { for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
// Expose object configuration resources e++) {
auto objectWorker = gd::GetResourceWorkerOnObjects(project, worker); auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
gd::ProjectBrowserHelper::ExposeEventsBasedObjectVariantObjects( gd::ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
eventsBasedObjectVariant, objectWorker); project, eventsFunctionsExtension, eventWorker);
// Expose layer effect resources
auto &layers = eventsBasedObjectVariant.GetLayers();
for (std::size_t layerIndex = 0; layerIndex < layers.GetLayersCount();
layerIndex++) {
auto &layer = layers.GetLayer(layerIndex);
auto &effects = layer.GetEffects();
for (size_t effectIndex = 0; effectIndex < effects.GetEffectsCount();
effectIndex++) {
auto &effect = effects.GetEffect(effectIndex);
gd::ResourceExposer::ExposeEffectResources(project.GetCurrentPlatform(),
effect, worker);
}
} }
// We don't check the events because it would cost too much to do it for every
// variant. Resource usage in events-based object events and their
// dependencies should be rare.
} }
void ResourceExposer::ExposeEffectResources( void ResourceExposer::ExposeEffectResources(

View File

@@ -9,11 +9,10 @@ namespace gd {
class Platform; class Platform;
class Project; class Project;
class ArbitraryResourceWorker; class ArbitraryResourceWorker;
class EventsBasedObjectVariant;
class EventsFunctionsExtension; class EventsFunctionsExtension;
class Effect; class Effect;
class Layout; class Layout;
} // namespace gd } // namespace gd
namespace gd { namespace gd {
@@ -21,7 +20,7 @@ namespace gd {
* \brief * \brief
*/ */
class GD_CORE_API ResourceExposer { class GD_CORE_API ResourceExposer {
public: public:
/** /**
* \brief Called ( e.g. during compilation ) so as to inventory internal * \brief Called ( e.g. during compilation ) so as to inventory internal
* resources, sometimes update their filename or any other work or resources. * resources, sometimes update their filename or any other work or resources.
@@ -51,14 +50,6 @@ public:
gd::Layout &layout, gd::Layout &layout,
gd::ArbitraryResourceWorker &worker); gd::ArbitraryResourceWorker &worker);
/**
* @brief Expose the resources used in a given events-based object variant.
*/
static void ExposeEventsBasedObjectVariantResources(
gd::Project &project,
gd::EventsBasedObjectVariant &eventsBasedObjectVariant,
gd::ArbitraryResourceWorker &worker);
/** /**
* @brief Expose the resources used in a given effect. * @brief Expose the resources used in a given effect.
*/ */

View File

@@ -37,7 +37,6 @@ void EventsBasedObjectVariant::SerializeTo(SerializerElement &element) const {
layers.SerializeLayersTo(element.AddChild("layers")); layers.SerializeLayersTo(element.AddChild("layers"));
initialInstances.SerializeTo(element.AddChild("instances")); initialInstances.SerializeTo(element.AddChild("instances"));
editorSettings.SerializeTo(element.AddChild("editionSettings"));
} }
void EventsBasedObjectVariant::UnserializeFrom( void EventsBasedObjectVariant::UnserializeFrom(
@@ -67,7 +66,6 @@ void EventsBasedObjectVariant::UnserializeFrom(
layers.Reset(); layers.Reset();
} }
initialInstances.UnserializeFrom(element.GetChild("instances")); initialInstances.UnserializeFrom(element.GetChild("instances"));
editorSettings.UnserializeFrom(element.GetChild("editionSettings"));
} }
} // namespace gd } // namespace gd

View File

@@ -5,7 +5,6 @@
*/ */
#pragma once #pragma once
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
#include "GDCore/Project/InitialInstancesContainer.h" #include "GDCore/Project/InitialInstancesContainer.h"
#include "GDCore/Project/LayersContainer.h" #include "GDCore/Project/LayersContainer.h"
#include "GDCore/Project/ObjectsContainer.h" #include "GDCore/Project/ObjectsContainer.h"
@@ -200,19 +199,6 @@ public:
const gd::String &GetAssetStoreOriginalName() const { const gd::String &GetAssetStoreOriginalName() const {
return assetStoreOriginalName; return assetStoreOriginalName;
}; };
/**
*
* \brief Get the user settings for the IDE.
*/
const gd::EditorSettings& GetAssociatedEditorSettings() const {
return editorSettings;
}
/**
* \brief Get the user settings for the IDE.
*/
gd::EditorSettings& GetAssociatedEditorSettings() { return editorSettings; }
void SerializeTo(SerializerElement &element) const; void SerializeTo(SerializerElement &element) const;
@@ -238,7 +224,6 @@ private:
* store. * store.
*/ */
gd::String assetStoreOriginalName; gd::String assetStoreOriginalName;
gd::EditorSettings editorSettings;
}; };
} // namespace gd } // namespace gd

View File

@@ -60,18 +60,6 @@ void InitialInstance::UnserializeFrom(const SerializerElement& element) {
} else { } else {
SetHasCustomDepth(false); SetHasCustomDepth(false);
} }
if (element.HasChild("defaultWidth") ||
element.HasAttribute("defaultWidth")) {
defaultWidth = element.GetDoubleAttribute("defaultWidth");
}
if (element.HasChild("defaultHeight") ||
element.HasAttribute("defaultHeight")) {
defaultHeight = element.GetDoubleAttribute("defaultHeight");
}
if (element.HasChild("defaultDepth") ||
element.HasAttribute("defaultDepth")) {
defaultDepth = element.GetDoubleAttribute("defaultDepth");
}
SetZOrder(element.GetIntAttribute("zOrder", 0, "plan")); SetZOrder(element.GetIntAttribute("zOrder", 0, "plan"));
SetOpacity(element.GetIntAttribute("opacity", 255)); SetOpacity(element.GetIntAttribute("opacity", 255));
SetLayer(element.GetStringAttribute("layer")); SetLayer(element.GetStringAttribute("layer"));
@@ -86,51 +74,45 @@ void InitialInstance::UnserializeFrom(const SerializerElement& element) {
if (persistentUuid.empty()) ResetPersistentUuid(); if (persistentUuid.empty()) ResetPersistentUuid();
numberProperties.clear(); numberProperties.clear();
if (element.HasChild("numberProperties", "floatInfos")) { const SerializerElement& numberPropertiesElement =
const SerializerElement& numberPropertiesElement = element.GetChild("numberProperties", 0, "floatInfos");
element.GetChild("numberProperties", 0, "floatInfos"); numberPropertiesElement.ConsiderAsArrayOf("property", "Info");
numberPropertiesElement.ConsiderAsArrayOf("property", "Info"); for (std::size_t j = 0; j < numberPropertiesElement.GetChildrenCount(); ++j) {
for (std::size_t j = 0; j < numberPropertiesElement.GetChildrenCount(); ++j) { gd::String name =
gd::String name = numberPropertiesElement.GetChild(j).GetStringAttribute("name");
numberPropertiesElement.GetChild(j).GetStringAttribute("name"); double value =
double value = numberPropertiesElement.GetChild(j).GetDoubleAttribute("value");
numberPropertiesElement.GetChild(j).GetDoubleAttribute("value");
// Compatibility with GD <= 5.1.164 // Compatibility with GD <= 5.1.164
if (name == "z") { if (name == "z") {
SetZ(value); SetZ(value);
} else if (name == "rotationX") { } else if (name == "rotationX") {
SetRotationX(value); SetRotationX(value);
} else if (name == "rotationY") { } else if (name == "rotationY") {
SetRotationY(value); SetRotationY(value);
} else if (name == "depth") { } else if (name == "depth") {
SetHasCustomDepth(true); SetHasCustomDepth(true);
SetCustomDepth(value); SetCustomDepth(value);
} }
// end of compatibility code // end of compatibility code
else { else {
numberProperties[name] = value; numberProperties[name] = value;
}
} }
} }
stringProperties.clear(); stringProperties.clear();
if (element.HasChild("stringProperties", "stringInfos")) { const SerializerElement& stringPropElement =
const SerializerElement& stringPropElement = element.GetChild("stringProperties", 0, "stringInfos");
element.GetChild("stringProperties", 0, "stringInfos"); stringPropElement.ConsiderAsArrayOf("property", "Info");
stringPropElement.ConsiderAsArrayOf("property", "Info"); for (std::size_t j = 0; j < stringPropElement.GetChildrenCount(); ++j) {
for (std::size_t j = 0; j < stringPropElement.GetChildrenCount(); ++j) { gd::String name = stringPropElement.GetChild(j).GetStringAttribute("name");
gd::String name = stringPropElement.GetChild(j).GetStringAttribute("name"); gd::String value =
gd::String value = stringPropElement.GetChild(j).GetStringAttribute("value");
stringPropElement.GetChild(j).GetStringAttribute("value"); stringProperties[name] = value;
stringProperties[name] = value;
}
} }
if (element.HasChild("initialVariables", "InitialVariables")) { GetVariables().UnserializeFrom(
GetVariables().UnserializeFrom( element.GetChild("initialVariables", 0, "InitialVariables"));
element.GetChild("initialVariables", 0, "InitialVariables"));
}
} }
void InitialInstance::SerializeTo(SerializerElement& element) const { void InitialInstance::SerializeTo(SerializerElement& element) const {
@@ -151,8 +133,6 @@ void InitialInstance::SerializeTo(SerializerElement& element) const {
element.SetAttribute("width", GetCustomWidth()); element.SetAttribute("width", GetCustomWidth());
element.SetAttribute("height", GetCustomHeight()); element.SetAttribute("height", GetCustomHeight());
if (HasCustomDepth()) element.SetAttribute("depth", GetCustomDepth()); if (HasCustomDepth()) element.SetAttribute("depth", GetCustomDepth());
// defaultWidth, defaultHeight and defaultDepth are not serialized
// because they are evaluated by InGameEditor.
if (IsLocked()) element.SetAttribute("locked", IsLocked()); if (IsLocked()) element.SetAttribute("locked", IsLocked());
if (IsSealed()) element.SetAttribute("sealed", IsSealed()); if (IsSealed()) element.SetAttribute("sealed", IsSealed());
if (ShouldKeepRatio()) element.SetAttribute("keepRatio", ShouldKeepRatio()); if (ShouldKeepRatio()) element.SetAttribute("keepRatio", ShouldKeepRatio());

View File

@@ -219,13 +219,6 @@ class GD_CORE_API InitialInstance {
double GetCustomDepth() const { return depth; } double GetCustomDepth() const { return depth; }
void SetCustomDepth(double depth_) { depth = depth_; } void SetCustomDepth(double depth_) { depth = depth_; }
double GetDefaultWidth() const { return defaultWidth; }
double GetDefaultHeight() const { return defaultHeight; }
double GetDefaultDepth() const { return defaultDepth; }
void SetDefaultWidth(double width_) { defaultWidth = width_; }
void SetDefaultHeight(double height_) { defaultHeight = height_; }
void SetDefaultDepth(double depth_) { defaultDepth = depth_; }
/** /**
* \brief Return true if the instance is locked and cannot be moved in the * \brief Return true if the instance is locked and cannot be moved in the
* IDE. * IDE.
@@ -373,11 +366,7 @@ class GD_CORE_API InitialInstance {
*/ */
InitialInstance& ResetPersistentUuid(); InitialInstance& ResetPersistentUuid();
/** const gd::String& GetPersistentUuid() const { return persistentUuid; }
* \brief Reset the persistent UUID used to recognize
* the same initial instance between serialization.
*/
const gd::String& GetPersistentUuid() const { return persistentUuid; }
///@} ///@}
private: private:
@@ -406,9 +395,6 @@ class GD_CORE_API InitialInstance {
double width; ///< Instance custom width double width; ///< Instance custom width
double height; ///< Instance custom height double height; ///< Instance custom height
double depth; ///< Instance custom depth double depth; ///< Instance custom depth
double defaultWidth = 0; ///< Instance default width as reported by InGameEditor
double defaultHeight = 0; ///< Instance default height as reported by InGameEditor
double defaultDepth = 0; ///< Instance default depth as reported by InGameEditor
gd::VariablesContainer initialVariables; ///< Instance specific variables gd::VariablesContainer initialVariables; ///< Instance specific variables
bool locked; ///< True if the instance is locked bool locked; ///< True if the instance is locked
bool sealed; ///< True if the instance is sealed bool sealed; ///< True if the instance is sealed

View File

@@ -23,7 +23,6 @@ Layer::Layer()
camera3DNearPlaneDistance(3), camera3DNearPlaneDistance(3),
camera3DFarPlaneDistance(10000), camera3DFarPlaneDistance(10000),
camera3DFieldOfView(45), camera3DFieldOfView(45),
camera2DPlaneMaxDrawingDistance(5000),
ambientLightColorR(200), ambientLightColorR(200),
ambientLightColorG(200), ambientLightColorG(200),
ambientLightColorB(200) {} ambientLightColorB(200) {}
@@ -57,8 +56,6 @@ void Layer::SerializeTo(SerializerElement& element) const {
element.SetAttribute("camera3DFarPlaneDistance", element.SetAttribute("camera3DFarPlaneDistance",
GetCamera3DFarPlaneDistance()); GetCamera3DFarPlaneDistance());
element.SetAttribute("camera3DFieldOfView", GetCamera3DFieldOfView()); element.SetAttribute("camera3DFieldOfView", GetCamera3DFieldOfView());
element.SetAttribute("camera2DPlaneMaxDrawingDistance",
GetCamera2DPlaneMaxDrawingDistance());
SerializerElement& camerasElement = element.AddChild("cameras"); SerializerElement& camerasElement = element.AddChild("cameras");
camerasElement.ConsiderAsArrayOf("camera"); camerasElement.ConsiderAsArrayOf("camera");
@@ -102,8 +99,6 @@ void Layer::UnserializeFrom(const SerializerElement& element) {
"camera3DFarPlaneDistance", 10000, "threeDFarPlaneDistance")); "camera3DFarPlaneDistance", 10000, "threeDFarPlaneDistance"));
SetCamera3DFieldOfView(element.GetDoubleAttribute( SetCamera3DFieldOfView(element.GetDoubleAttribute(
"camera3DFieldOfView", 45, "threeDFieldOfView")); "camera3DFieldOfView", 45, "threeDFieldOfView"));
SetCamera2DPlaneMaxDrawingDistance(element.GetDoubleAttribute(
"camera2DPlaneMaxDrawingDistance", 5000));
cameras.clear(); cameras.clear();
SerializerElement& camerasElement = element.GetChild("cameras"); SerializerElement& camerasElement = element.GetChild("cameras");

View File

@@ -182,8 +182,6 @@ class GD_CORE_API Layer {
} }
double GetCamera3DFieldOfView() const { return camera3DFieldOfView; } double GetCamera3DFieldOfView() const { return camera3DFieldOfView; }
void SetCamera3DFieldOfView(double angle) { camera3DFieldOfView = angle; } void SetCamera3DFieldOfView(double angle) { camera3DFieldOfView = angle; }
double GetCamera2DPlaneMaxDrawingDistance() const { return camera2DPlaneMaxDrawingDistance; }
void SetCamera2DPlaneMaxDrawingDistance(double distance) { camera2DPlaneMaxDrawingDistance = distance; }
///@} ///@}
/** \name Cameras /** \name Cameras
@@ -294,7 +292,6 @@ class GD_CORE_API Layer {
double camera3DNearPlaneDistance; ///< 3D camera frustum near plan distance double camera3DNearPlaneDistance; ///< 3D camera frustum near plan distance
double camera3DFarPlaneDistance; ///< 3D camera frustum far plan distance double camera3DFarPlaneDistance; ///< 3D camera frustum far plan distance
double camera3DFieldOfView; ///< 3D camera field of view (fov) in degrees double camera3DFieldOfView; ///< 3D camera field of view (fov) in degrees
double camera2DPlaneMaxDrawingDistance; ///< Max drawing distance of the 2D plane when in the 3D world
unsigned int ambientLightColorR; ///< Ambient light color Red component unsigned int ambientLightColorR; ///< Ambient light color Red component
unsigned int ambientLightColorG; ///< Ambient light color Green component unsigned int ambientLightColorG; ///< Ambient light color Green component
unsigned int ambientLightColorB; ///< Ambient light color Blue component unsigned int ambientLightColorB; ///< Ambient light color Blue component

View File

@@ -730,8 +730,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
SetPackageName(propElement.GetStringAttribute("packageName")); SetPackageName(propElement.GetStringAttribute("packageName"));
SetTemplateSlug(propElement.GetStringAttribute("templateSlug")); SetTemplateSlug(propElement.GetStringAttribute("templateSlug"));
SetOrientation(propElement.GetStringAttribute("orientation", "default")); SetOrientation(propElement.GetStringAttribute("orientation", "default"));
SetEffectsHiddenInEditor(
propElement.GetBoolAttribute("areEffectsHiddenInEditor", false));
SetFolderProject(propElement.GetBoolAttribute("folderProject")); SetFolderProject(propElement.GetBoolAttribute("folderProject"));
SetLastCompilationDirectory(propElement SetLastCompilationDirectory(propElement
.GetChild("latestCompilationDirectory", .GetChild("latestCompilationDirectory",
@@ -1111,10 +1109,6 @@ void Project::SerializeTo(SerializerElement& element) const {
propElement.SetAttribute("packageName", packageName); propElement.SetAttribute("packageName", packageName);
propElement.SetAttribute("templateSlug", templateSlug); propElement.SetAttribute("templateSlug", templateSlug);
propElement.SetAttribute("orientation", orientation); propElement.SetAttribute("orientation", orientation);
if (areEffectsHiddenInEditor) {
propElement.SetBoolAttribute("areEffectsHiddenInEditor",
areEffectsHiddenInEditor);
}
platformSpecificAssets.SerializeTo( platformSpecificAssets.SerializeTo(
propElement.AddChild("platformSpecificAssets")); propElement.AddChild("platformSpecificAssets"));
loadingScreen.SerializeTo(propElement.AddChild("loadingScreen")); loadingScreen.SerializeTo(propElement.AddChild("loadingScreen"));
@@ -1156,8 +1150,6 @@ void Project::SerializeTo(SerializerElement& element) const {
// end of compatibility code // end of compatibility code
extensionProperties.SerializeTo(propElement.AddChild("extensionProperties")); extensionProperties.SerializeTo(propElement.AddChild("extensionProperties"));
playableDevicesElement.AddChild("").SetStringValue("mobile");
SerializerElement& platformsElement = propElement.AddChild("platforms"); SerializerElement& platformsElement = propElement.AddChild("platforms");
platformsElement.ConsiderAsArrayOf("platform"); platformsElement.ConsiderAsArrayOf("platform");
@@ -1327,8 +1319,6 @@ void Project::Init(const gd::Project& game) {
sceneResourcesPreloading = game.sceneResourcesPreloading; sceneResourcesPreloading = game.sceneResourcesPreloading;
sceneResourcesUnloading = game.sceneResourcesUnloading; sceneResourcesUnloading = game.sceneResourcesUnloading;
areEffectsHiddenInEditor = game.areEffectsHiddenInEditor;
} }
} // namespace gd } // namespace gd

View File

@@ -506,20 +506,6 @@ class GD_CORE_API Project {
*/ */
void SetCurrentPlatform(const gd::String& platformName); void SetCurrentPlatform(const gd::String& platformName);
/**
* Check if the effects are shown.
*/
bool AreEffectsHiddenInEditor() const { return areEffectsHiddenInEditor; }
/**
* Define the project as playable on a mobile.
* \param enable True When false effects are not shown and a default light is
* used for 3D layers.
*/
void SetEffectsHiddenInEditor(bool enable = true) {
areEffectsHiddenInEditor = enable;
}
///@} ///@}
/** \name Factory method /** \name Factory method
@@ -1179,9 +1165,6 @@ class GD_CORE_API Project {
mutable unsigned int gdBuildVersion = mutable unsigned int gdBuildVersion =
0; ///< The GD build version used the last 0; ///< The GD build version used the last
///< time the project was saved. ///< time the project was saved.
bool areEffectsHiddenInEditor =
false; ///< When false effects are not shown and a default light is used
///< for 3D layers.
}; };
} // namespace gd } // namespace gd

View File

@@ -34,20 +34,6 @@ void PropertyDescriptor::SerializeTo(SerializerElement& element) const {
} }
} }
if (!choices.empty()
// Compatibility with GD <= 5.5.239
|| !extraInformation.empty()
// end of compatibility code
) {
SerializerElement &choicesElement = element.AddChild("choices");
choicesElement.ConsiderAsArrayOf("choice");
for (const auto &choice : choices) {
auto &choiceElement = choicesElement.AddChild("Choice");
choiceElement.SetStringAttribute("value", choice.GetValue());
choiceElement.SetStringAttribute("label", choice.GetLabel());
}
}
if (hidden) { if (hidden) {
element.AddChild("hidden").SetBoolValue(hidden); element.AddChild("hidden").SetBoolValue(hidden);
} }
@@ -70,9 +56,7 @@ void PropertyDescriptor::UnserializeFrom(const SerializerElement& element) {
currentValue = element.GetChild("value").GetStringValue(); currentValue = element.GetChild("value").GetStringValue();
type = element.GetChild("type").GetStringValue(); type = element.GetChild("type").GetStringValue();
if (type == "Number") { if (type == "Number") {
gd::String unitName = element.HasChild("unit") gd::String unitName = element.GetChild("unit").GetStringValue();
? element.GetChild("unit").GetStringValue()
: "";
measurementUnit = measurementUnit =
gd::MeasurementUnit::HasDefaultMeasurementUnitNamed(unitName) gd::MeasurementUnit::HasDefaultMeasurementUnitNamed(unitName)
? measurementUnit = ? measurementUnit =
@@ -96,26 +80,6 @@ void PropertyDescriptor::UnserializeFrom(const SerializerElement& element) {
extraInformationElement.GetChild(i).GetStringValue()); extraInformationElement.GetChild(i).GetStringValue());
} }
if (element.HasChild("choices")) {
choices.clear();
const SerializerElement &choicesElement = element.GetChild("choices");
choicesElement.ConsiderAsArrayOf("choice");
for (std::size_t i = 0; i < choicesElement.GetChildrenCount(); ++i) {
auto &choiceElement = choicesElement.GetChild(i);
AddChoice(choiceElement.GetStringAttribute("value"),
choiceElement.GetStringAttribute("label"));
}
}
// Compatibility with GD <= 5.5.239
else if (type == "Choice") {
choices.clear();
for (auto &choiceValue : extraInformation) {
AddChoice(choiceValue, choiceValue);
}
extraInformation.clear();
}
// end of compatibility code
hidden = element.HasChild("hidden") hidden = element.HasChild("hidden")
? element.GetChild("hidden").GetBoolValue() ? element.GetChild("hidden").GetBoolValue()
: false; : false;

View File

@@ -116,11 +116,6 @@ class GD_CORE_API PropertyDescriptor {
return *this; return *this;
} }
PropertyDescriptor& ClearChoices() {
choices.clear();
return *this;
}
PropertyDescriptor& AddChoice(const gd::String& value, PropertyDescriptor& AddChoice(const gd::String& value,
const gd::String& label) { const gd::String& label) {
choices.push_back(PropertyDescriptorChoice(value, label)); choices.push_back(PropertyDescriptorChoice(value, label));

View File

@@ -764,6 +764,129 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
REQUIRE(worker.audios[0] == "res4"); REQUIRE(worker.audios[0] == "res4");
} }
SECTION("Can find resource usages in event-based functions") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
project.GetResourcesManager().AddResource(
"res1", "path/to/file1.png", "image");
project.GetResourcesManager().AddResource(
"res2", "path/to/file2.png", "image");
project.GetResourcesManager().AddResource(
"res3", "path/to/file3.png", "image");
ArbitraryResourceWorkerTest worker(project.GetResourcesManager());
auto& extension = project.InsertNewEventsFunctionsExtension("MyEventExtension", 0);
auto &function = extension.GetEventsFunctions().InsertNewEventsFunction(
"MyFreeFunction", 0);
gd::StandardEvent standardEvent;
gd::Instruction instruction;
instruction.SetType("MyExtension::DoSomethingWithResources");
instruction.SetParametersCount(3);
instruction.SetParameter(0, "res3");
instruction.SetParameter(1, "res1");
instruction.SetParameter(2, "res4");
standardEvent.GetActions().Insert(instruction);
function.GetEvents().InsertEvent(standardEvent);
auto& layout = project.InsertNewLayout("MyScene", 0);
// MyEventExtension::MyFreeFunction doesn't need to be actually used in
// events because the implementation is naive.
gd::ResourceExposer::ExposeLayoutResources(project, layout, worker);
REQUIRE(worker.bitmapFonts.size() == 1);
REQUIRE(worker.bitmapFonts[0] == "res3");
REQUIRE(worker.images.size() == 1);
REQUIRE(worker.images[0] == "res1");
REQUIRE(worker.audios.size() == 1);
REQUIRE(worker.audios[0] == "res4");
}
SECTION("Can find resource usages in event-based behavior functions") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
project.GetResourcesManager().AddResource(
"res1", "path/to/file1.png", "image");
project.GetResourcesManager().AddResource(
"res2", "path/to/file2.png", "image");
project.GetResourcesManager().AddResource(
"res3", "path/to/file3.png", "image");
ArbitraryResourceWorkerTest worker(project.GetResourcesManager());
auto& extension = project.InsertNewEventsFunctionsExtension("MyEventExtension", 0);
auto& behavior = extension.GetEventsBasedBehaviors().InsertNew("MyBehavior", 0);
auto& function = behavior.GetEventsFunctions().InsertNewEventsFunction("MyFunction", 0);
gd::StandardEvent standardEvent;
gd::Instruction instruction;
instruction.SetType("MyExtension::DoSomethingWithResources");
instruction.SetParametersCount(3);
instruction.SetParameter(0, "res3");
instruction.SetParameter(1, "res1");
instruction.SetParameter(2, "res4");
standardEvent.GetActions().Insert(instruction);
function.GetEvents().InsertEvent(standardEvent);
auto& layout = project.InsertNewLayout("MyScene", 0);
// MyEventExtension::MyBehavior::MyFunction doesn't need to be actually used in
// events because the implementation is naive.
gd::ResourceExposer::ExposeLayoutResources(project, layout, worker);
REQUIRE(worker.bitmapFonts.size() == 1);
REQUIRE(worker.bitmapFonts[0] == "res3");
REQUIRE(worker.images.size() == 1);
REQUIRE(worker.images[0] == "res1");
REQUIRE(worker.audios.size() == 1);
REQUIRE(worker.audios[0] == "res4");
}
SECTION("Can find resource usages in event-based object functions") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
project.GetResourcesManager().AddResource(
"res1", "path/to/file1.png", "image");
project.GetResourcesManager().AddResource(
"res2", "path/to/file2.png", "image");
project.GetResourcesManager().AddResource(
"res3", "path/to/file3.png", "image");
ArbitraryResourceWorkerTest worker(project.GetResourcesManager());
auto& extension = project.InsertNewEventsFunctionsExtension("MyEventExtension", 0);
auto& object = extension.GetEventsBasedObjects().InsertNew("MyObject", 0);
auto& function = object.GetEventsFunctions().InsertNewEventsFunction("MyFunction", 0);
gd::StandardEvent standardEvent;
gd::Instruction instruction;
instruction.SetType("MyExtension::DoSomethingWithResources");
instruction.SetParametersCount(3);
instruction.SetParameter(0, "res3");
instruction.SetParameter(1, "res1");
instruction.SetParameter(2, "res4");
standardEvent.GetActions().Insert(instruction);
function.GetEvents().InsertEvent(standardEvent);
auto& layout = project.InsertNewLayout("MyScene", 0);
// MyEventExtension::MyObject::MyFunction doesn't need to be actually used in
// events because the implementation is naive.
gd::ResourceExposer::ExposeLayoutResources(project, layout, worker);
REQUIRE(worker.bitmapFonts.size() == 1);
REQUIRE(worker.bitmapFonts[0] == "res3");
REQUIRE(worker.images.size() == 1);
REQUIRE(worker.images[0] == "res1");
REQUIRE(worker.audios.size() == 1);
REQUIRE(worker.audios[0] == "res4");
}
SECTION("Can find resource usages in layer effects") { SECTION("Can find resource usages in layer effects") {
gd::Project project; gd::Project project;
gd::Platform platform; gd::Platform platform;

View File

@@ -139,8 +139,8 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
.SetLabel("Dot shape") .SetLabel("Dot shape")
.SetDescription("The shape is used for collision.") .SetDescription("The shape is used for collision.")
.SetGroup("Movement"); .SetGroup("Movement");
property.AddChoice("DotShape", "Dot shape"); property.GetExtraInfo().push_back("Dot shape");
property.AddChoice("BoundingDisk", "Bounding disk"); property.GetExtraInfo().push_back("Bounding disk");
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter( gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
project, extension, behavior, property, false); project, extension, behavior, property, false);
@@ -157,7 +157,7 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
gd::EventsFunction::ExpressionAndCondition); gd::EventsFunction::ExpressionAndCondition);
REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector"); REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector");
REQUIRE(getter.GetExpressionType().GetExtraInfo() == REQUIRE(getter.GetExpressionType().GetExtraInfo() ==
"[\"DotShape\",\"BoundingDisk\"]"); "[\"Dot shape\",\"Bounding disk\"]");
} }
SECTION("Can generate functions for a boolean property in a behavior") { SECTION("Can generate functions for a boolean property in a behavior") {
@@ -386,8 +386,8 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
.SetLabel("Dot shape") .SetLabel("Dot shape")
.SetDescription("The shape is used for collision.") .SetDescription("The shape is used for collision.")
.SetGroup("Movement"); .SetGroup("Movement");
property.AddChoice("DotShape", "Dot shape"); property.GetExtraInfo().push_back("Dot shape");
property.AddChoice("BoundingDisk", "Bounding disk"); property.GetExtraInfo().push_back("Bounding disk");
gd::PropertyFunctionGenerator::GenerateObjectGetterAndSetter( gd::PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
project, extension, object, property); project, extension, object, property);
@@ -404,7 +404,7 @@ TEST_CASE("PropertyFunctionGenerator", "[common]") {
gd::EventsFunction::ExpressionAndCondition); gd::EventsFunction::ExpressionAndCondition);
REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector"); REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector");
REQUIRE(getter.GetExpressionType().GetExtraInfo() == REQUIRE(getter.GetExpressionType().GetExtraInfo() ==
"[\"DotShape\",\"BoundingDisk\"]"); "[\"Dot shape\",\"Bounding disk\"]");
} }
SECTION("Can generate functions for a boolean property in an object") { SECTION("Can generate functions for a boolean property in an object") {

View File

@@ -147,9 +147,15 @@ namespace gdjs {
if (initialInstanceData.depth !== undefined) { if (initialInstanceData.depth !== undefined) {
this.setDepth(initialInstanceData.depth); this.setDepth(initialInstanceData.depth);
} }
this.flipX(!!initialInstanceData.flippedX); if (initialInstanceData.flippedX) {
this.flipY(!!initialInstanceData.flippedY); this.flipX(initialInstanceData.flippedX);
this.flipZ(!!initialInstanceData.flippedZ); }
if (initialInstanceData.flippedY) {
this.flipY(initialInstanceData.flippedY);
}
if (initialInstanceData.flippedZ) {
this.flipZ(initialInstanceData.flippedZ);
}
} }
setX(x: float): void { setX(x: float): void {
@@ -316,18 +322,6 @@ namespace gdjs {
this.setAngle(gdjs.toDegrees(mesh.rotation.z)); this.setAngle(gdjs.toDegrees(mesh.rotation.z));
} }
override getOriginalWidth(): float {
return this._originalWidth;
}
override getOriginalHeight(): float {
return this._originalHeight;
}
getOriginalDepth(): float {
return this._originalDepth;
}
getWidth(): float { getWidth(): float {
return this._width; return this._width;
} }
@@ -374,6 +368,31 @@ namespace gdjs {
this.getRenderer().updateSize(); this.getRenderer().updateSize();
} }
/**
* Return the width of the object for a scale of 1.
*
* It can't be 0.
*/
_getOriginalWidth(): float {
return this._originalWidth;
}
/**
* Return the height of the object for a scale of 1.
*
* It can't be 0.
*/
_getOriginalHeight(): float {
return this._originalHeight;
}
/**
* Return the object size on the Z axis (called "depth") when the scale equals 1.
*/
_getOriginalDepth(): float {
return this._originalDepth;
}
/** /**
* Set the width of the object for a scale of 1. * Set the width of the object for a scale of 1.
*/ */

View File

@@ -11,8 +11,6 @@ namespace gdjs {
this._object = runtimeObject; this._object = runtimeObject;
this._threeObject3D = threeObject3D; this._threeObject3D = threeObject3D;
this._threeObject3D.rotation.order = 'ZYX'; this._threeObject3D.rotation.order = 'ZYX';
//@ts-ignore
this._threeObject3D.gdjsRuntimeObject = runtimeObject;
instanceContainer instanceContainer
.getLayer('') .getLayer('')

View File

@@ -115,12 +115,6 @@ namespace gdjs {
* Rotations around X and Y are not taken into account. * Rotations around X and Y are not taken into account.
*/ */
getUnrotatedAABBMaxZ(): number; getUnrotatedAABBMaxZ(): number;
/**
* Return the depth of the object before any custom size is applied.
* @return The depth of the object
*/
getOriginalDepth(): float;
} }
export interface Object3DDataContent { export interface Object3DDataContent {
@@ -137,11 +131,7 @@ namespace gdjs {
export namespace Base3DHandler { export namespace Base3DHandler {
export const is3D = ( export const is3D = (
object: gdjs.RuntimeObject object: gdjs.RuntimeObject
): object is gdjs.RuntimeObject & ): object is gdjs.RuntimeObject & gdjs.Base3DHandler => {
gdjs.Base3DHandler &
gdjs.Resizable &
gdjs.Scalable &
gdjs.Flippable => {
//@ts-ignore We are checking if the methods are present. //@ts-ignore We are checking if the methods are present.
return object.getZ && object.setZ; return object.getZ && object.setZ;
}; };
@@ -253,10 +243,6 @@ namespace gdjs {
getUnrotatedAABBMaxZ(): number { getUnrotatedAABBMaxZ(): number {
return this.object.getUnrotatedAABBMaxZ(); return this.object.getUnrotatedAABBMaxZ();
} }
getOriginalDepth(): float {
return this.object.getOriginalDepth();
}
} }
gdjs.registerBehavior('Scene3D::Base3DBehavior', gdjs.Base3DBehavior); gdjs.registerBehavior('Scene3D::Base3DBehavior', gdjs.Base3DBehavior);

View File

@@ -74,9 +74,15 @@ namespace gdjs {
if (initialInstanceData.depth !== undefined) { if (initialInstanceData.depth !== undefined) {
this.setDepth(initialInstanceData.depth); this.setDepth(initialInstanceData.depth);
} }
this.flipX(!!initialInstanceData.flippedX); if (initialInstanceData.flippedX) {
this.flipY(!!initialInstanceData.flippedY); this.flipX(initialInstanceData.flippedX);
this.flipZ(!!initialInstanceData.flippedZ); }
if (initialInstanceData.flippedY) {
this.flipY(initialInstanceData.flippedY);
}
if (initialInstanceData.flippedZ) {
this.flipZ(initialInstanceData.flippedZ);
}
} }
getNetworkSyncData(): CustomObject3DNetworkSyncDataType { getNetworkSyncData(): CustomObject3DNetworkSyncDataType {
@@ -309,10 +315,6 @@ namespace gdjs {
return this._maxZ - this._minZ; return this._maxZ - this._minZ;
} }
getOriginalDepth(): float {
return this._instanceContainer._getInitialInnerAreaDepth();
}
override _updateUntransformedHitBoxes(): void { override _updateUntransformedHitBoxes(): void {
super._updateUntransformedHitBoxes(); super._updateUntransformedHitBoxes();

View File

@@ -162,12 +162,7 @@ module.exports = {
) )
.addParameter('object', _('3D object'), '', false) .addParameter('object', _('3D object'), '', false)
.addParameter('behavior', _('Behavior'), 'Base3DBehavior') .addParameter('behavior', _('Behavior'), 'Base3DBehavior')
.useStandardParameters( .useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Angle (in degrees)')
)
)
.setFunctionName('setRotationX') .setFunctionName('setRotationX')
.setGetter('getRotationX'); .setGetter('getRotationX');
@@ -183,12 +178,7 @@ module.exports = {
) )
.addParameter('object', _('3D object'), '', false) .addParameter('object', _('3D object'), '', false)
.addParameter('behavior', _('Behavior'), 'Base3DBehavior') .addParameter('behavior', _('Behavior'), 'Base3DBehavior')
.useStandardParameters( .useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Angle (in degrees)')
)
)
.setFunctionName('setRotationY') .setFunctionName('setRotationY')
.setGetter('getRotationY'); .setGetter('getRotationY');
@@ -206,7 +196,7 @@ module.exports = {
) )
.addParameter('object', _('3D object'), '', false) .addParameter('object', _('3D object'), '', false)
.addParameter('behavior', _('Behavior'), 'Base3DBehavior') .addParameter('behavior', _('Behavior'), 'Base3DBehavior')
.addParameter('number', _('Angle to add (in degrees)'), '', false) .addParameter('number', _('Rotation angle'), '', false)
.markAsAdvanced() .markAsAdvanced()
.setFunctionName('turnAroundX'); .setFunctionName('turnAroundX');
@@ -224,7 +214,7 @@ module.exports = {
) )
.addParameter('object', _('3D object'), '', false) .addParameter('object', _('3D object'), '', false)
.addParameter('behavior', _('Behavior'), 'Base3DBehavior') .addParameter('behavior', _('Behavior'), 'Base3DBehavior')
.addParameter('number', _('Angle to add (in degrees)'), '', false) .addParameter('number', _('Rotation angle'), '', false)
.markAsAdvanced() .markAsAdvanced()
.setFunctionName('turnAroundY'); .setFunctionName('turnAroundY');
@@ -242,7 +232,7 @@ module.exports = {
) )
.addParameter('object', _('3D object'), '', false) .addParameter('object', _('3D object'), '', false)
.addParameter('behavior', _('Behavior'), 'Base3DBehavior') .addParameter('behavior', _('Behavior'), 'Base3DBehavior')
.addParameter('number', _('Angle to add (in degrees)'), '', false) .addParameter('number', _('Rotation angle'), '', false)
.markAsAdvanced() .markAsAdvanced()
.setFunctionName('turnAroundZ'); .setFunctionName('turnAroundZ');
} }
@@ -604,12 +594,7 @@ module.exports = {
'res/conditions/3d_box.svg' 'res/conditions/3d_box.svg'
) )
.addParameter('object', _('3D model'), 'Model3DObject', false) .addParameter('object', _('3D model'), 'Model3DObject', false)
.useStandardParameters( .useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Angle (in degrees)')
)
)
.setHidden() .setHidden()
.setFunctionName('setRotationX') .setFunctionName('setRotationX')
.setGetter('getRotationX'); .setGetter('getRotationX');
@@ -626,12 +611,7 @@ module.exports = {
'res/conditions/3d_box.svg' 'res/conditions/3d_box.svg'
) )
.addParameter('object', _('3D model'), 'Model3DObject', false) .addParameter('object', _('3D model'), 'Model3DObject', false)
.useStandardParameters( .useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Angle (in degrees)')
)
)
.setHidden() .setHidden()
.setFunctionName('setRotationY') .setFunctionName('setRotationY')
.setGetter('getRotationY'); .setGetter('getRotationY');
@@ -650,7 +630,7 @@ module.exports = {
'res/conditions/3d_box.svg' 'res/conditions/3d_box.svg'
) )
.addParameter('object', _('3D model'), 'Model3DObject', false) .addParameter('object', _('3D model'), 'Model3DObject', false)
.addParameter('number', _('Angle to add (in degrees)'), '', false) .addParameter('number', _('Rotation angle'), '', false)
.markAsAdvanced() .markAsAdvanced()
.setHidden() .setHidden()
.setFunctionName('turnAroundX'); .setFunctionName('turnAroundX');
@@ -669,7 +649,7 @@ module.exports = {
'res/conditions/3d_box.svg' 'res/conditions/3d_box.svg'
) )
.addParameter('object', _('3D model'), 'Model3DObject', false) .addParameter('object', _('3D model'), 'Model3DObject', false)
.addParameter('number', _('Angle to add (in degrees)'), '', false) .addParameter('number', _('Rotation angle'), '', false)
.markAsAdvanced() .markAsAdvanced()
.setHidden() .setHidden()
.setFunctionName('turnAroundY'); .setFunctionName('turnAroundY');
@@ -688,7 +668,7 @@ module.exports = {
'res/conditions/3d_box.svg' 'res/conditions/3d_box.svg'
) )
.addParameter('object', _('3D model'), 'Model3DObject', false) .addParameter('object', _('3D model'), 'Model3DObject', false)
.addParameter('number', _('Angle to add (in degrees)'), '', false) .addParameter('number', _('Rotation angle'), '', false)
.markAsAdvanced() .markAsAdvanced()
.setHidden() .setHidden()
.setFunctionName('turnAroundZ'); .setFunctionName('turnAroundZ');
@@ -1513,12 +1493,7 @@ module.exports = {
'res/conditions/3d_box.svg' 'res/conditions/3d_box.svg'
) )
.addParameter('object', _('3D cube'), 'Cube3DObject', false) .addParameter('object', _('3D cube'), 'Cube3DObject', false)
.useStandardParameters( .useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Angle (in degrees)')
)
)
.setFunctionName('setRotationX') .setFunctionName('setRotationX')
.setHidden() .setHidden()
.setGetter('getRotationX'); .setGetter('getRotationX');
@@ -1535,12 +1510,7 @@ module.exports = {
'res/conditions/3d_box.svg' 'res/conditions/3d_box.svg'
) )
.addParameter('object', _('3D cube'), 'Cube3DObject', false) .addParameter('object', _('3D cube'), 'Cube3DObject', false)
.useStandardParameters( .useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Angle (in degrees)')
)
)
.setFunctionName('setRotationY') .setFunctionName('setRotationY')
.setHidden() .setHidden()
.setGetter('getRotationY'); .setGetter('getRotationY');
@@ -1908,9 +1878,7 @@ module.exports = {
.addEffect('AmbientLight') .addEffect('AmbientLight')
.setFullName(_('Ambient light')) .setFullName(_('Ambient light'))
.setDescription( .setDescription(
_( _('A light that illuminates all objects from every direction.')
'A light that illuminates all objects from every direction. Often used along with a Directional light (though a Hemisphere light can be used instead of an Ambient light).'
)
) )
.markAsNotWorkingForObjects() .markAsNotWorkingForObjects()
.markAsOnlyWorkingFor3D() .markAsOnlyWorkingFor3D()
@@ -1931,11 +1899,7 @@ module.exports = {
const effect = extension const effect = extension
.addEffect('DirectionalLight') .addEffect('DirectionalLight')
.setFullName(_('Directional light')) .setFullName(_('Directional light'))
.setDescription( .setDescription(_('A very far light source like the sun.'))
_(
"A very far light source like the sun. This is the light to use for casting shadows for 3D objects (other lights won't emit shadows). Often used along with a Hemisphere light."
)
)
.markAsNotWorkingForObjects() .markAsNotWorkingForObjects()
.markAsOnlyWorkingFor3D() .markAsOnlyWorkingFor3D()
.addIncludeFile('Extensions/3D/DirectionalLight.js'); .addIncludeFile('Extensions/3D/DirectionalLight.js');
@@ -2019,7 +1983,7 @@ module.exports = {
.setFullName(_('Hemisphere light')) .setFullName(_('Hemisphere light'))
.setDescription( .setDescription(
_( _(
'A light that illuminates objects from every direction with a gradient. Often used along with a Directional light.' 'A light that illuminates objects from every direction with a gradient.'
) )
) )
.markAsNotWorkingForObjects() .markAsNotWorkingForObjects()
@@ -2063,48 +2027,6 @@ module.exports = {
.setType('number') .setType('number')
.setGroup(_('Orientation')); .setGroup(_('Orientation'));
} }
{
const effect = extension
.addEffect('Skybox')
.setFullName(_('Skybox'))
.setDescription(
_('Display a background on a cube surrounding the scene.')
)
.markAsNotWorkingForObjects()
.markAsOnlyWorkingFor3D()
.addIncludeFile('Extensions/3D/Skybox.js');
const properties = effect.getProperties();
properties
.getOrCreate('rightFaceResourceName')
.setType('resource')
.addExtraInfo('image')
.setLabel(_('Right face (X+)'));
properties
.getOrCreate('leftFaceResourceName')
.setType('resource')
.addExtraInfo('image')
.setLabel(_('Left face (X-)'));
properties
.getOrCreate('bottomFaceResourceName')
.setType('resource')
.addExtraInfo('image')
.setLabel(_('Bottom face (Y+)'));
properties
.getOrCreate('topFaceResourceName')
.setType('resource')
.addExtraInfo('image')
.setLabel(_('Top face (Y-)'));
properties
.getOrCreate('frontFaceResourceName')
.setType('resource')
.addExtraInfo('image')
.setLabel(_('Front face (Z+)'));
properties
.getOrCreate('backFaceResourceName')
.setType('resource')
.addExtraInfo('image')
.setLabel(_('Back face (Z-)'));
}
{ {
const effect = extension const effect = extension
.addEffect('HueAndSaturation') .addEffect('HueAndSaturation')

View File

@@ -278,9 +278,9 @@ namespace gdjs {
rotationX, rotationX,
rotationY, rotationY,
rotationZ, rotationZ,
this.getOriginalWidth(), this._getOriginalWidth(),
this.getOriginalHeight(), this._getOriginalHeight(),
this.getOriginalDepth(), this._getOriginalDepth(),
keepAspectRatio keepAspectRatio
); );
} }

View File

@@ -1,102 +0,0 @@
namespace gdjs {
interface SkyboxFilterNetworkSyncData {}
gdjs.PixiFiltersTools.registerFilterCreator(
'Scene3D::Skybox',
new (class implements gdjs.PixiFiltersTools.FilterCreator {
makeFilter(
target: EffectsTarget,
effectData: EffectData
): gdjs.PixiFiltersTools.Filter {
if (typeof THREE === 'undefined') {
return new gdjs.PixiFiltersTools.EmptyFilter();
}
return new (class implements gdjs.PixiFiltersTools.Filter {
_cubeTexture: THREE.CubeTexture;
_oldBackground:
| THREE.CubeTexture
| THREE.Texture
| THREE.Color
| null = null;
_isEnabled: boolean = false;
constructor() {
this._cubeTexture = target
.getRuntimeScene()
.getGame()
.getImageManager()
.getThreeCubeTexture(
effectData.stringParameters.rightFaceResourceName,
effectData.stringParameters.leftFaceResourceName,
effectData.stringParameters.topFaceResourceName,
effectData.stringParameters.bottomFaceResourceName,
effectData.stringParameters.frontFaceResourceName,
effectData.stringParameters.backFaceResourceName
);
}
isEnabled(target: EffectsTarget): boolean {
return this._isEnabled;
}
setEnabled(target: EffectsTarget, enabled: boolean): boolean {
if (this._isEnabled === enabled) {
return true;
}
if (enabled) {
return this.applyEffect(target);
} else {
return this.removeEffect(target);
}
}
applyEffect(target: EffectsTarget): boolean {
const scene = target.get3DRendererObject() as
| THREE.Scene
| null
| undefined;
if (!scene) {
return false;
}
// TODO Add a background stack in LayerPixiRenderer to allow
// filters to stack them.
this._oldBackground = scene.background;
scene.background = this._cubeTexture;
if (!scene.environment) {
scene.environment = this._cubeTexture;
}
this._isEnabled = true;
return true;
}
removeEffect(target: EffectsTarget): boolean {
const scene = target.get3DRendererObject() as
| THREE.Scene
| null
| undefined;
if (!scene) {
return false;
}
scene.background = this._oldBackground;
scene.environment = null;
this._isEnabled = false;
return true;
}
updatePreRender(target: gdjs.EffectsTarget): any {}
updateDoubleParameter(parameterName: string, value: number): void {}
getDoubleParameter(parameterName: string): number {
return 0;
}
updateStringParameter(parameterName: string, value: string): void {}
updateColorParameter(parameterName: string, value: number): void {}
getColorParameter(parameterName: string): number {
return 0;
}
updateBooleanParameter(parameterName: string, value: boolean): void {}
getNetworkSyncData(): SkyboxFilterNetworkSyncData {
return {};
}
updateFromNetworkSyncData(
syncData: SkyboxFilterNetworkSyncData
): void {}
})();
}
})()
);
}

View File

@@ -473,14 +473,7 @@ namespace gdjs {
this._parentOldMaxY = instanceContainer.getUnrotatedViewportMaxY(); this._parentOldMaxY = instanceContainer.getUnrotatedViewportMaxY();
} }
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) { doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {}
// Custom objects can be resized during the events step.
// The anchor constraints must be applied on child-objects after the parent events.
const isChildObject = instanceContainer !== instanceContainer.getScene();
if (isChildObject) {
this.doStepPreEvents(instanceContainer);
}
}
private _convertCoords( private _convertCoords(
instanceContainer: gdjs.RuntimeInstanceContainer, instanceContainer: gdjs.RuntimeInstanceContainer,

View File

@@ -94,6 +94,16 @@ module.exports = {
.setLabel(_('Vertical alignment')) .setLabel(_('Vertical alignment'))
.setGroup(_('Appearance')); .setGroup(_('Appearance'));
if (!objectContent.lineHeight) {
objectContent.lineHeight = 0;
}
objectProperties
.getOrCreate('lineHeight')
.setValue(objectContent.lineHeight.toString())
.setType('number')
.setLabel(_('Line height (0 = default)'))
.setGroup(_('Font'));
objectProperties objectProperties
.getOrCreate('fontFamily') .getOrCreate('fontFamily')
.setValue(objectContent.fontFamily) .setValue(objectContent.fontFamily)
@@ -394,6 +404,19 @@ module.exports = {
expressionLabel: _('Get the wrapping width'), expressionLabel: _('Get the wrapping width'),
expressionDescription: _('Get the wrapping width'), expressionDescription: _('Get the wrapping width'),
}, },
{
functionName: 'LineHeight',
iconPath: 'res/actions/characterSize24.png',
type: 'number',
instructionLabel: _('Line height'),
paramLabel: _('Line height (0 = default)'),
conditionDescription: _('Compare the base line height of the text.'),
conditionSentence: _('the base line height'),
actionDescription: _('Set base line height'),
actionSentence: _('the base line height'),
expressionLabel: _('Get the base line height'),
expressionDescription: _('Get the base line height'),
},
]; ];
addSettersAndGettersToObject(object, setterAndGetterProperties, 'BBText'); addSettersAndGettersToObject(object, setterAndGetterProperties, 'BBText');

View File

@@ -32,6 +32,7 @@ namespace gdjs {
wordWrap: runtimeObject._wrapping, wordWrap: runtimeObject._wrapping,
wordWrapWidth: runtimeObject._wrappingWidth, wordWrapWidth: runtimeObject._wrappingWidth,
align: runtimeObject._textAlign as PIXI.TextStyleAlign | undefined, align: runtimeObject._textAlign as PIXI.TextStyleAlign | undefined,
lineHeight: runtimeObject._lineHeight > 0 ? runtimeObject._lineHeight : undefined,
}, },
}); });
instanceContainer instanceContainer
@@ -102,6 +103,13 @@ namespace gdjs {
this._pixiObject.dirty = true; this._pixiObject.dirty = true;
} }
updateLineHeight(): void {
//@ts-ignore Private member usage.
this._pixiObject.textStyles.default.lineHeight =
this._object._lineHeight;
this._pixiObject.dirty = true;
}
updatePosition(): void { updatePosition(): void {
if (this._object.isWrapping() && this._pixiObject.width !== 0) { if (this._object.isWrapping() && this._pixiObject.width !== 0) {
const alignmentX = const alignmentX =

View File

@@ -20,6 +20,8 @@ namespace gdjs {
/** Alignment of the text: "left", "center" or "right" */ /** Alignment of the text: "left", "center" or "right" */
align: 'left' | 'center' | 'right'; align: 'left' | 'center' | 'right';
verticalTextAlignment: 'top' | 'center' | 'bottom'; verticalTextAlignment: 'top' | 'center' | 'bottom';
/** Line height for multiline text (0 = default) */
lineHeight: number;
}; };
}; };
export type BBTextObjectData = ObjectData & BBTextObjectDataType; export type BBTextObjectData = ObjectData & BBTextObjectDataType;
@@ -35,6 +37,7 @@ namespace gdjs {
align: string; align: string;
vta: string; vta: string;
hidden: boolean; hidden: boolean;
lh: number;
}; };
export type BBTextObjectNetworkSyncData = ObjectNetworkSyncData & export type BBTextObjectNetworkSyncData = ObjectNetworkSyncData &
@@ -61,6 +64,7 @@ namespace gdjs {
_textAlign: string; _textAlign: string;
_verticalTextAlignment: string; _verticalTextAlignment: string;
_lineHeight: float;
_renderer: gdjs.BBTextRuntimeObjectRenderer; _renderer: gdjs.BBTextRuntimeObjectRenderer;
@@ -87,6 +91,7 @@ namespace gdjs {
this._textAlign = objectData.content.align; this._textAlign = objectData.content.align;
this._verticalTextAlignment = this._verticalTextAlignment =
objectData.content.verticalTextAlignment || 'top'; objectData.content.verticalTextAlignment || 'top';
this._lineHeight = objectData.content.lineHeight || 0;
this.hidden = !objectData.content.visible; this.hidden = !objectData.content.visible;
this._renderer = new gdjs.BBTextRuntimeObjectRenderer( this._renderer = new gdjs.BBTextRuntimeObjectRenderer(
@@ -142,6 +147,11 @@ namespace gdjs {
newObjectData.content.verticalTextAlignment newObjectData.content.verticalTextAlignment
); );
} }
if (
oldObjectData.content.lineHeight !== newObjectData.content.lineHeight
) {
this.setLineHeight(newObjectData.content.lineHeight);
}
return true; return true;
} }
@@ -158,6 +168,7 @@ namespace gdjs {
align: this._textAlign, align: this._textAlign,
vta: this._verticalTextAlignment, vta: this._verticalTextAlignment,
hidden: this.hidden, hidden: this.hidden,
lh: this._lineHeight,
}; };
} }
@@ -196,6 +207,9 @@ namespace gdjs {
if (this.hidden !== undefined) { if (this.hidden !== undefined) {
this.hide(networkSyncData.hidden); this.hide(networkSyncData.hidden);
} }
if (networkSyncData.lh !== undefined) {
this.setLineHeight(networkSyncData.lh);
}
} }
override extraInitializationFromInitialInstance( override extraInitializationFromInitialInstance(
@@ -397,6 +411,23 @@ namespace gdjs {
: 0) : 0)
); );
} }
/**
* Get line height of the BBText object.
* @return line height (0 = default)
*/
getLineHeight(): number {
return this._lineHeight;
}
/**
* Set line height of the BBText object.
* @param value line height (0 = default)
*/
setLineHeight(value: float): void {
this._lineHeight = value;
this._renderer.updateLineHeight();
}
} }
// @ts-ignore // @ts-ignore
gdjs.registerObject('BBText::BBText', gdjs.BBTextRuntimeObject); gdjs.registerObject('BBText::BBText', gdjs.BBTextRuntimeObject);

View File

@@ -218,11 +218,9 @@ namespace gdjs {
this.setWrappingWidth(initialInstanceData.width); this.setWrappingWidth(initialInstanceData.width);
this.setWrapping(true); this.setWrapping(true);
} }
this.setOpacity( if (initialInstanceData.opacity !== undefined) {
initialInstanceData.opacity === undefined this.setOpacity(initialInstanceData.opacity);
? 255 }
: initialInstanceData.opacity
);
} }
override onDestroyed(): void { override onDestroyed(): void {

View File

@@ -388,9 +388,6 @@ namespace gdjs {
return new gdjs.PromiseTask( return new gdjs.PromiseTask(
(async () => { (async () => {
if (runtimeScene.getGame().isInGameEdition()) {
return;
}
const scoreSavingState = (_scoreSavingStateByLeaderboard[ const scoreSavingState = (_scoreSavingStateByLeaderboard[
leaderboardId leaderboardId
] = ] =
@@ -426,9 +423,6 @@ namespace gdjs {
) => ) =>
new gdjs.PromiseTask( new gdjs.PromiseTask(
(async () => { (async () => {
if (runtimeScene.getGame().isInGameEdition()) {
return;
}
const playerId = gdjs.playerAuthentication.getUserId(); const playerId = gdjs.playerAuthentication.getUserId();
const playerToken = gdjs.playerAuthentication.getUserToken(); const playerToken = gdjs.playerAuthentication.getUserToken();
if (!playerId || !playerToken) { if (!playerId || !playerToken) {
@@ -753,9 +747,6 @@ namespace gdjs {
leaderboardId: string, leaderboardId: string,
displayLoader: boolean displayLoader: boolean
) { ) {
if (runtimeScene.getGame().isInGameEdition()) {
return;
}
// First ensure we're not trying to display multiple times the same leaderboard (in which case // First ensure we're not trying to display multiple times the same leaderboard (in which case
// we "de-duplicate" the request to display it). // we "de-duplicate" the request to display it).
if (leaderboardId === _requestedLeaderboardId) { if (leaderboardId === _requestedLeaderboardId) {

View File

@@ -1841,9 +1841,6 @@ namespace gdjs {
displayLoader: boolean, displayLoader: boolean,
openLobbiesPageIfFailure: boolean openLobbiesPageIfFailure: boolean
) => { ) => {
if (runtimeScene.getGame().isInGameEdition()) {
return;
}
if (isQuickJoiningTooFast()) { if (isQuickJoiningTooFast()) {
return; return;
} }
@@ -1863,9 +1860,6 @@ namespace gdjs {
displayLoader: boolean, displayLoader: boolean,
openLobbiesPageIfFailure: boolean openLobbiesPageIfFailure: boolean
) => { ) => {
if (runtimeScene.getGame().isInGameEdition()) {
return;
}
if (isQuickJoiningTooFast()) { if (isQuickJoiningTooFast()) {
return; return;
} }
@@ -1899,9 +1893,6 @@ namespace gdjs {
export const openLobbiesWindow = async ( export const openLobbiesWindow = async (
runtimeScene: gdjs.RuntimeScene runtimeScene: gdjs.RuntimeScene
) => { ) => {
if (runtimeScene.getGame().isInGameEdition()) {
return;
}
if ( if (
isLobbiesWindowOpen(runtimeScene) || isLobbiesWindowOpen(runtimeScene) ||
gdjs.playerAuthentication.isAuthenticationWindowOpen() gdjs.playerAuthentication.isAuthenticationWindowOpen()

View File

@@ -389,15 +389,26 @@ namespace gdjs {
this.updatePosition(); this.updatePosition();
} }
setColor(rgbOrHexColor: string): void { setColor(rgbColor): void {
const tint = gdjs.rgbOrHexStringToNumber(rgbOrHexColor); const colors = rgbColor.split(';');
this._centerSprite.tint = tint; if (colors.length < 3) {
return;
}
this._centerSprite.tint = gdjs.rgbToHexNumber(
parseInt(colors[0], 10),
parseInt(colors[1], 10),
parseInt(colors[2], 10)
);
for ( for (
let borderCounter = 0; let borderCounter = 0;
borderCounter < this._borderSprites.length; borderCounter < this._borderSprites.length;
borderCounter++ borderCounter++
) { ) {
this._borderSprites[borderCounter].tint = tint; this._borderSprites[borderCounter].tint = gdjs.rgbToHexNumber(
parseInt(colors[0], 10),
parseInt(colors[1], 10),
parseInt(colors[2], 10)
);
} }
this._spritesContainer.cacheAsBitmap = false; this._spritesContainer.cacheAsBitmap = false;
} }
@@ -405,11 +416,11 @@ namespace gdjs {
getColor() { getColor() {
const rgb = new PIXI.Color(this._centerSprite.tint).toRgbArray(); const rgb = new PIXI.Color(this._centerSprite.tint).toRgbArray();
return ( return (
Math.round(rgb[0] * 255) + Math.floor(rgb[0] * 255) +
';' + ';' +
Math.round(rgb[1] * 255) + Math.floor(rgb[1] * 255) +
';' + ';' +
Math.round(rgb[2] * 255) Math.floor(rgb[2] * 255)
); );
} }

View File

@@ -53,8 +53,6 @@ namespace gdjs {
_renderer: gdjs.PanelSpriteRuntimeObjectRenderer; _renderer: gdjs.PanelSpriteRuntimeObjectRenderer;
_objectData: PanelSpriteObjectData;
/** /**
* @param instanceContainer The container the object belongs to. * @param instanceContainer The container the object belongs to.
* @param panelSpriteObjectData The initial properties of the object * @param panelSpriteObjectData The initial properties of the object
@@ -64,7 +62,6 @@ namespace gdjs {
panelSpriteObjectData: PanelSpriteObjectData panelSpriteObjectData: PanelSpriteObjectData
) { ) {
super(instanceContainer, panelSpriteObjectData); super(instanceContainer, panelSpriteObjectData);
this._objectData = panelSpriteObjectData;
this._rBorder = panelSpriteObjectData.rightMargin; this._rBorder = panelSpriteObjectData.rightMargin;
this._lBorder = panelSpriteObjectData.leftMargin; this._lBorder = panelSpriteObjectData.leftMargin;
this._tBorder = panelSpriteObjectData.topMargin; this._tBorder = panelSpriteObjectData.topMargin;
@@ -87,7 +84,6 @@ namespace gdjs {
oldObjectData: PanelSpriteObjectData, oldObjectData: PanelSpriteObjectData,
newObjectData: PanelSpriteObjectData newObjectData: PanelSpriteObjectData
): boolean { ): boolean {
this._objectData = newObjectData;
if (oldObjectData.width !== newObjectData.width) { if (oldObjectData.width !== newObjectData.width) {
this.setWidth(newObjectData.width); this.setWidth(newObjectData.width);
} }
@@ -167,11 +163,9 @@ namespace gdjs {
this.setWidth(initialInstanceData.width); this.setWidth(initialInstanceData.width);
this.setHeight(initialInstanceData.height); this.setHeight(initialInstanceData.height);
} }
this.setOpacity( if (initialInstanceData.opacity !== undefined) {
initialInstanceData.opacity === undefined this.setOpacity(initialInstanceData.opacity);
? 255 }
: initialInstanceData.opacity
);
} }
/** /**
@@ -250,14 +244,6 @@ namespace gdjs {
this.setHeight(newHeight); this.setHeight(newHeight);
} }
override getOriginalWidth(): float {
return this._objectData.width;
}
override getOriginalHeight(): float {
return this._objectData.height;
}
setOpacity(opacity: float): void { setOpacity(opacity: float): void {
if (opacity < 0) { if (opacity < 0) {
opacity = 0; opacity = 0;

View File

@@ -21,11 +21,7 @@ module.exports = {
.setExtensionInformation( .setExtensionInformation(
'Physics2', 'Physics2',
_('2D Physics Engine'), _('2D Physics Engine'),
"The 2D physics engine simulates realistic object physics, with gravity, forces, collisions, joints, etc. It's perfect for 2D games that need to have realistic behaving objects and a gameplay centered around it.\n" + "The 2D physics engine simulates realistic object physics, with gravity, forces, collisions, joints, etc. It's perfect for 2D games that need to have realistic behaving objects and a gameplay centered around it.",
'\n' +
'Objects like floors or wall objects should usually be set to "Static" as type. Objects that should be moveable are usually "Dynamic" (default). "Kinematic" objects (typically, players or controlled characters) are only moved by their "linear velocity" and "angular velocity" - they can interact with other objects but only these other objects will move.\n' +
'\n' +
'Forces (and impulses) are expressed in all conditions/expressions/actions of the 2D physics engine in Newtons (N). Typical values for a force are 10-200 N. One meter is 100 pixels by default in the game (check the world scale). Mass is expressed in kilograms (kg).',
'Florian Rival, Franco Maciel', 'Florian Rival, Franco Maciel',
'MIT' 'MIT'
) )
@@ -531,7 +527,6 @@ module.exports = {
physics2Behavior, physics2Behavior,
sharedData sharedData
) )
.markAsIrrelevantForChildObjects()
.setIncludeFile('Extensions/Physics2Behavior/physics2runtimebehavior.js') .setIncludeFile('Extensions/Physics2Behavior/physics2runtimebehavior.js')
.addIncludeFile('Extensions/Physics2Behavior/Box2D_v2.3.1_min.wasm.js') .addIncludeFile('Extensions/Physics2Behavior/Box2D_v2.3.1_min.wasm.js')
.addRequiredFile('Extensions/Physics2Behavior/Box2D_v2.3.1_min.wasm.wasm') .addRequiredFile('Extensions/Physics2Behavior/Box2D_v2.3.1_min.wasm.wasm')

View File

@@ -21,11 +21,7 @@ module.exports = {
.setExtensionInformation( .setExtensionInformation(
'Physics3D', 'Physics3D',
_('3D physics engine'), _('3D physics engine'),
"The 3D physics engine simulates realistic object physics, with gravity, forces, collisions, joints, etc. It's perfect for almost all 3D games.\n" + "The 3D physics engine simulates realistic object physics, with gravity, forces, collisions, joints, etc. It's perfect for almost all 3D games.",
'\n' +
'Objects like floors or wall objects should usually be set to "Static" as type. Objects that should be moveable are usually "Dynamic" (default). "Kinematic" objects (typically, players or controlled characters) are only moved by their "linear velocity" and "angular velocity" - they can interact with other objects but only these other objects will move.\n' +
'\n' +
'Forces (and impulses) are expressed in all conditions/expressions/actions of the 3D physics engine in Newtons (N). Typical values for a force are 10-200 N. One meter is 100 pixels by default in the game (check the world scale). Mass is expressed in kilograms (kg).',
'Florian Rival', 'Florian Rival',
'MIT' 'MIT'
) )
@@ -679,7 +675,6 @@ module.exports = {
behavior, behavior,
sharedData sharedData
) )
.markAsIrrelevantForChildObjects()
.addIncludeFile( .addIncludeFile(
'Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.js' 'Extensions/Physics3DBehavior/Physics3DRuntimeBehavior.js'
) )
@@ -2048,12 +2043,7 @@ module.exports = {
'PhysicsCharacter3D', 'PhysicsCharacter3D',
_('3D physics character'), _('3D physics character'),
'PhysicsCharacter3D', 'PhysicsCharacter3D',
_( _('Jump and run on platforms.'),
'Allow an object to jump and run on platforms that have the 3D physics behavior' +
'(and which are generally set to "Static" as type, unless the platform is animated/moved in events).\n' +
'\n' +
'This behavior is usually used with one or more "mapper" behavior to let the player move it.'
),
'', '',
'JsPlatform/Extensions/physics_character3d.svg', 'JsPlatform/Extensions/physics_character3d.svg',
'PhysicsCharacter3D', 'PhysicsCharacter3D',
@@ -2622,7 +2612,7 @@ module.exports = {
'JumpSustainTime', 'JumpSustainTime',
_('Jump sustain time'), _('Jump sustain time'),
_( _(
'the jump sustain time of an object. This is the time during which keeping the jump button held allow the initial jump speed to be maintained' 'the jump sustain time of an object. This is the time during which keeping the jump button held allow the initial jump speed to be maintained.'
), ),
_('the jump sustain time'), _('the jump sustain time'),
_('Character configuration'), _('Character configuration'),
@@ -3310,11 +3300,7 @@ module.exports = {
'PhysicsCar3D', 'PhysicsCar3D',
_('3D physics car'), _('3D physics car'),
'PhysicsCar3D', 'PhysicsCar3D',
_( _('Simulate a realistic car using the 3D physics engine.'),
"Simulate a realistic car using the 3D physics engine. This is mostly useful for the car controlled by the player (it's usually too complex for other cars in a game).\n" +
'\n' +
'This behavior is usually used with one or more "mapper" behavior to let the player move it.'
),
'', '',
'JsPlatform/Extensions/physics_car3d.svg', 'JsPlatform/Extensions/physics_car3d.svg',
'PhysicsCar3D', 'PhysicsCar3D',

View File

@@ -37,8 +37,7 @@ void DeclarePhysicsBehaviorExtension(gd::PlatformExtension& extension) {
"res/physics-deprecated32.png", "res/physics-deprecated32.png",
"PhysicsBehavior", "PhysicsBehavior",
std::make_shared<PhysicsBehavior>(), std::make_shared<PhysicsBehavior>(),
std::make_shared<ScenePhysicsDatas>()) std::make_shared<ScenePhysicsDatas>());
.MarkAsIrrelevantForChildObjects();
aut.AddAction("SetStatic", aut.AddAction("SetStatic",
("Make the object static"), ("Make the object static"),

View File

@@ -647,9 +647,6 @@ namespace gdjs {
export const displayAuthenticationBanner = function ( export const displayAuthenticationBanner = function (
runtimeScene: gdjs.RuntimeScene runtimeScene: gdjs.RuntimeScene
) { ) {
if (runtimeScene.getGame().isInGameEdition()) {
return;
}
if (_authenticationBanner) { if (_authenticationBanner) {
// Banner already displayed, ensure it's visible. // Banner already displayed, ensure it's visible.
_authenticationBanner.style.opacity = '1'; _authenticationBanner.style.opacity = '1';
@@ -1045,10 +1042,6 @@ namespace gdjs {
): gdjs.PromiseTask<{ status: 'logged' | 'errored' | 'dismissed' }> => ): gdjs.PromiseTask<{ status: 'logged' | 'errored' | 'dismissed' }> =>
new gdjs.PromiseTask( new gdjs.PromiseTask(
new Promise((resolve) => { new Promise((resolve) => {
if (runtimeScene.getGame().isInGameEdition()) {
resolve({ status: 'dismissed' });
}
// Create the authentication container for the player to wait. // Create the authentication container for the player to wait.
const domElementContainer = runtimeScene const domElementContainer = runtimeScene
.getGame() .getGame()

View File

@@ -196,8 +196,12 @@ namespace gdjs {
* @param initialInstanceData The extra parameters * @param initialInstanceData The extra parameters
*/ */
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) { extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
this.flipX(!!initialInstanceData.flippedX); if (initialInstanceData.flippedX) {
this.flipY(!!initialInstanceData.flippedY); this.flipX(initialInstanceData.flippedX);
}
if (initialInstanceData.flippedY) {
this.flipY(initialInstanceData.flippedY);
}
} }
stepBehaviorsPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) { stepBehaviorsPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {

View File

@@ -202,22 +202,28 @@ namespace gdjs {
this._loadingSpineAtlases.clear(); this._loadingSpineAtlases.clear();
} }
unloadResource(resourceData: ResourceData): void { /**
const loadedSpineAtlas = this._loadedSpineAtlases.getFromName( * Unload the specified list of resources:
resourceData.name * this clears the Spine atlases loaded in this manager.
); *
if (loadedSpineAtlas) { * Usually called when scene resoures are unloaded.
loadedSpineAtlas.dispose(); *
this._loadedSpineAtlases.delete(resourceData); * @param resourcesList The list of specific resources
} */
unloadResourcesList(resourcesList: ResourceData[]): void {
resourcesList.forEach((resourceData) => {
const loadedSpineAtlas = this._loadedSpineAtlases.get(resourceData);
if (loadedSpineAtlas) {
loadedSpineAtlas.dispose();
this._loadedSpineAtlases.delete(resourceData);
}
const loadingSpineAtlas = this._loadingSpineAtlases.getFromName( const loadingSpineAtlas = this._loadingSpineAtlases.get(resourceData);
resourceData.name if (loadingSpineAtlas) {
); loadingSpineAtlas.then((atl) => atl.dispose());
if (loadingSpineAtlas) { this._loadingSpineAtlases.delete(resourceData);
loadingSpineAtlas.then((atl) => atl.dispose()); }
this._loadingSpineAtlases.delete(resourceData); });
}
} }
} }
} }

View File

@@ -127,11 +127,21 @@ namespace gdjs {
this._loadedSpines.clear(); this._loadedSpines.clear();
} }
unloadResource(resourceData: ResourceData): void { /**
const loadedSpine = this._loadedSpines.get(resourceData); * Unload the specified list of resources:
if (loadedSpine) { * this clears the Spine skeleton data loaded in this manager.
this._loadedSpines.delete(resourceData); *
} * Usually called when scene resoures are unloaded.
*
* @param resourcesList The list of specific resources
*/
unloadResourcesList(resourcesList: ResourceData[]): void {
resourcesList.forEach((resourceData) => {
const loadedSpine = this._loadedSpines.get(resourceData);
if (loadedSpine) {
this._loadedSpines.delete(resourceData);
}
});
} }
} }
} }

View File

@@ -199,13 +199,15 @@ namespace gdjs {
this.setSize(initialInstanceData.width, initialInstanceData.height); this.setSize(initialInstanceData.width, initialInstanceData.height);
this.invalidateHitboxes(); this.invalidateHitboxes();
} }
this.setOpacity( if (initialInstanceData.opacity !== undefined) {
initialInstanceData.opacity === undefined this.setOpacity(initialInstanceData.opacity);
? 255 }
: initialInstanceData.opacity if (initialInstanceData.flippedX) {
); this.flipX(initialInstanceData.flippedX);
this.flipX(!!initialInstanceData.flippedX); }
this.flipY(!!initialInstanceData.flippedY); if (initialInstanceData.flippedY) {
this.flipY(initialInstanceData.flippedY);
}
} }
getDrawableX(): number { getDrawableX(): number {

View File

@@ -141,9 +141,7 @@ namespace gdjs {
); );
this._borderOpacity = objectData.content.borderOpacity; this._borderOpacity = objectData.content.borderOpacity;
this._borderWidth = objectData.content.borderWidth; this._borderWidth = objectData.content.borderWidth;
this._disabled = instanceContainer.getGame().isInGameEdition() this._disabled = objectData.content.disabled;
? true
: objectData.content.disabled;
this._readOnly = objectData.content.readOnly; this._readOnly = objectData.content.readOnly;
this._spellCheck = this._spellCheck =
objectData.content.spellCheck !== undefined objectData.content.spellCheck !== undefined
@@ -331,11 +329,9 @@ namespace gdjs {
this.setHeight(initialInstanceData.height); this.setHeight(initialInstanceData.height);
this._renderer.updatePadding(); this._renderer.updatePadding();
} }
this.setOpacity( if (initialInstanceData.opacity !== undefined) {
initialInstanceData.opacity === undefined this.setOpacity(initialInstanceData.opacity);
? 255 }
: initialInstanceData.opacity
);
} }
onScenePaused(runtimeScene: gdjs.RuntimeScene): void { onScenePaused(runtimeScene: gdjs.RuntimeScene): void {
@@ -565,9 +561,6 @@ namespace gdjs {
} }
setDisabled(value: boolean) { setDisabled(value: boolean) {
if (this.getInstanceContainer().getGame().isInGameEdition()) {
return;
}
this._disabled = value; this._disabled = value;
this._renderer.updateDisabled(); this._renderer.updateDisabled();
} }

View File

@@ -454,8 +454,8 @@ void DeclareTextObjectExtension(gd::PlatformExtension& extension) {
_("Line height"), _("Line height"),
_("the line height of a text object"), _("the line height of a text object"),
_("the line height"), _("the line height"),
"", _("Font"),
"res/actions/font24.png") "res/conditions/characterSize24.png")
.AddParameter("object", _("Object"), "Text") .AddParameter("object", _("Object"), "Text")
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions()); .UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions());

View File

@@ -38,6 +38,14 @@ class TextObjectJsExtension : public gd::PlatformExtension {
GetAllExpressionsForObject("TextObject::Text")["FontSize"] GetAllExpressionsForObject("TextObject::Text")["FontSize"]
.SetFunctionName("getCharacterSize"); .SetFunctionName("getCharacterSize");
GetAllActionsForObject("TextObject::Text")["TextObject::Text::SetLineHeight"]
.SetFunctionName("setLineHeight")
.SetGetter("getLineHeight");
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::LineHeight"]
.SetFunctionName("getLineHeight");
GetAllExpressionsForObject("TextObject::Text")["LineHeight"]
.SetFunctionName("getLineHeight");
GetAllActionsForObject("TextObject::Text")["TextObject::Font"] GetAllActionsForObject("TextObject::Text")["TextObject::Font"]
.SetFunctionName("setFontName"); .SetFunctionName("setFontName");
@@ -96,14 +104,6 @@ class TextObjectJsExtension : public gd::PlatformExtension {
.SetFunctionName("setOutlineThickness") .SetFunctionName("setOutlineThickness")
.SetGetter("getOutlineThickness"); .SetGetter("getOutlineThickness");
GetAllExpressionsForObject("TextObject::Text")["LineHeight"]
.SetFunctionName("getLineHeight");
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::LineHeight"]
.SetFunctionName("getLineHeight");
GetAllActionsForObject("TextObject::Text")["TextObject::Text::SetLineHeight"]
.SetFunctionName("setLineHeight")
.SetGetter("getLineHeight");
GetAllActionsForObject("TextObject::Text")["TextObject::ShowShadow"] GetAllActionsForObject("TextObject::Text")["TextObject::ShowShadow"]
.SetFunctionName("showShadow"); .SetFunctionName("showShadow");
GetAllConditionsForObject("TextObject::Text")["TextObject::Text::IsShadowEnabled"] GetAllConditionsForObject("TextObject::Text")["TextObject::Text::IsShadowEnabled"]

View File

@@ -20,7 +20,6 @@ using namespace std;
TextObject::TextObject() TextObject::TextObject()
: text("Text"), : text("Text"),
characterSize(20), characterSize(20),
lineHeight(0),
fontName(""), fontName(""),
smoothed(true), smoothed(true),
bold(false), bold(false),
@@ -37,7 +36,8 @@ TextObject::TextObject()
shadowOpacity(127), shadowOpacity(127),
shadowAngle(90), shadowAngle(90),
shadowDistance(4), shadowDistance(4),
shadowBlurRadius(2) {} shadowBlurRadius(2),
lineHeight(0) {}
TextObject::~TextObject() {}; TextObject::~TextObject() {};
@@ -51,10 +51,6 @@ bool TextObject::UpdateProperty(const gd::String& propertyName,
characterSize = newValue.To<double>(); characterSize = newValue.To<double>();
return true; return true;
} }
if (propertyName == "lineHeight") {
lineHeight = newValue.To<double>();
return true;
}
if (propertyName == "font") { if (propertyName == "font") {
fontName = newValue; fontName = newValue;
return true; return true;
@@ -115,6 +111,10 @@ bool TextObject::UpdateProperty(const gd::String& propertyName,
shadowBlurRadius = newValue.To<double>(); shadowBlurRadius = newValue.To<double>();
return true; return true;
} }
if (propertyName == "lineHeight") {
lineHeight = newValue.To<double>();
return true;
}
return false; return false;
} }
@@ -134,13 +134,6 @@ std::map<gd::String, gd::PropertyDescriptor> TextObject::GetProperties() const {
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel()) .SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetGroup(_("Font")); .SetGroup(_("Font"));
objectProperties["lineHeight"]
.SetValue(gd::String::From(lineHeight))
.SetType("number")
.SetLabel(_("Line height"))
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetGroup(_("Font"));
objectProperties["font"] objectProperties["font"]
.SetValue(fontName) .SetValue(fontName)
.SetType("resource") .SetType("resource")
@@ -267,6 +260,13 @@ std::map<gd::String, gd::PropertyDescriptor> TextObject::GetProperties() const {
.SetAdvanced() .SetAdvanced()
.SetQuickCustomizationVisibility(gd::QuickCustomization::Hidden); .SetQuickCustomizationVisibility(gd::QuickCustomization::Hidden);
objectProperties["lineHeight"]
.SetValue(gd::String::From(lineHeight))
.SetType("number")
.SetLabel(_("Line height"))
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetGroup(_("Font"));
return objectProperties; return objectProperties;
} }
@@ -283,7 +283,6 @@ void TextObject::DoUnserializeFrom(gd::Project& project,
SetCharacterSize(content.GetChild("characterSize", 0, "CharacterSize") SetCharacterSize(content.GetChild("characterSize", 0, "CharacterSize")
.GetValue() .GetValue()
.GetInt()); .GetInt());
SetLineHeight(content.GetDoubleAttribute("lineHeight", 0));
smoothed = content.GetBoolAttribute("smoothed"); smoothed = content.GetBoolAttribute("smoothed");
bold = content.GetBoolAttribute("bold"); bold = content.GetBoolAttribute("bold");
italic = content.GetBoolAttribute("italic"); italic = content.GetBoolAttribute("italic");
@@ -317,6 +316,8 @@ void TextObject::DoUnserializeFrom(gd::Project& project,
SetShadowAngle(content.GetIntAttribute("shadowAngle", 90)); SetShadowAngle(content.GetIntAttribute("shadowAngle", 90));
SetShadowDistance(content.GetIntAttribute("shadowDistance", 4)); SetShadowDistance(content.GetIntAttribute("shadowDistance", 4));
SetShadowBlurRadius(content.GetIntAttribute("shadowBlurRadius", 2)); SetShadowBlurRadius(content.GetIntAttribute("shadowBlurRadius", 2));
SetLineHeight(content.GetDoubleAttribute("lineHeight", 0));
} }
} }
@@ -352,7 +353,6 @@ void TextObject::DoSerializeTo(gd::SerializerElement& element) const {
content.AddChild("textAlignment").SetValue(GetTextAlignment()); content.AddChild("textAlignment").SetValue(GetTextAlignment());
content.AddChild("verticalTextAlignment").SetValue(GetVerticalTextAlignment()); content.AddChild("verticalTextAlignment").SetValue(GetVerticalTextAlignment());
content.AddChild("characterSize").SetValue(GetCharacterSize()); content.AddChild("characterSize").SetValue(GetCharacterSize());
content.AddChild("lineHeight").SetValue(GetLineHeight());
content.AddChild("color").SetValue(GetColor()); content.AddChild("color").SetValue(GetColor());
content.SetAttribute("smoothed", smoothed); content.SetAttribute("smoothed", smoothed);
@@ -370,6 +370,7 @@ void TextObject::DoSerializeTo(gd::SerializerElement& element) const {
content.SetAttribute("shadowAngle", shadowAngle); content.SetAttribute("shadowAngle", shadowAngle);
content.SetAttribute("shadowDistance", shadowDistance); content.SetAttribute("shadowDistance", shadowDistance);
content.SetAttribute("shadowBlurRadius", shadowBlurRadius); content.SetAttribute("shadowBlurRadius", shadowBlurRadius);
content.SetAttribute("lineHeight", lineHeight);
} }
void TextObject::ExposeResources(gd::ArbitraryResourceWorker& worker) { void TextObject::ExposeResources(gd::ArbitraryResourceWorker& worker) {

View File

@@ -49,12 +49,6 @@ class GD_EXTENSION_API TextObject : public gd::ObjectConfiguration {
*/ */
inline double GetCharacterSize() const { return characterSize; }; inline double GetCharacterSize() const { return characterSize; };
/** \brief Change the line height. */
inline void SetLineHeight(double value) { lineHeight = value; };
/** \brief Get the line height. */
inline double GetLineHeight() const { return lineHeight; };
/** \brief Return the name of the font resource used for the text. /** \brief Return the name of the font resource used for the text.
*/ */
inline const gd::String& GetFontName() const { return fontName; }; inline const gd::String& GetFontName() const { return fontName; };
@@ -119,6 +113,9 @@ class GD_EXTENSION_API TextObject : public gd::ObjectConfiguration {
void SetShadowBlurRadius(double value) { shadowBlurRadius = value; }; void SetShadowBlurRadius(double value) { shadowBlurRadius = value; };
double GetShadowBlurRadius() const { return shadowBlurRadius; }; double GetShadowBlurRadius() const { return shadowBlurRadius; };
void SetLineHeight(double value) { lineHeight = value; };
double GetLineHeight() const { return lineHeight; };
private: private:
virtual void DoUnserializeFrom(gd::Project& project, virtual void DoUnserializeFrom(gd::Project& project,
const gd::SerializerElement& element) override; const gd::SerializerElement& element) override;
@@ -126,7 +123,6 @@ class GD_EXTENSION_API TextObject : public gd::ObjectConfiguration {
gd::String text; gd::String text;
double characterSize; double characterSize;
double lineHeight;
gd::String fontName; gd::String fontName;
bool smoothed; bool smoothed;
bool bold, italic, underlined; bool bold, italic, underlined;
@@ -144,4 +140,5 @@ class GD_EXTENSION_API TextObject : public gd::ObjectConfiguration {
double shadowAngle; double shadowAngle;
double shadowDistance; double shadowDistance;
double shadowBlurRadius; double shadowBlurRadius;
double lineHeight;
}; };

View File

@@ -64,6 +64,7 @@ namespace gdjs {
style.wordWrap = this._object._wrapping; style.wordWrap = this._object._wrapping;
style.wordWrapWidth = this._object._wrappingWidth; style.wordWrapWidth = this._object._wrappingWidth;
style.breakWords = true; style.breakWords = true;
style.lineHeight = this._object._lineHeight > 0 ? this._object._lineHeight : undefined;
style.stroke = gdjs.rgbToHexNumber( style.stroke = gdjs.rgbToHexNumber(
this._object._outlineColor[0], this._object._outlineColor[0],
this._object._outlineColor[1], this._object._outlineColor[1],
@@ -86,7 +87,6 @@ namespace gdjs {
? style.dropShadowDistance + style.dropShadowBlur ? style.dropShadowDistance + style.dropShadowBlur
: 0; : 0;
style.padding = Math.ceil(this._object._padding + extraPaddingForShadow); style.padding = Math.ceil(this._object._padding + extraPaddingForShadow);
style.lineHeight = this._object._lineHeight;
// Prevent spikey outlines by adding a miter limit // Prevent spikey outlines by adding a miter limit
style.miterLimit = 3; style.miterLimit = 3;

View File

@@ -22,8 +22,7 @@ namespace gdjs {
text: string; text: string;
textAlignment: string; textAlignment: string;
verticalTextAlignment: string; verticalTextAlignment: string;
/** The line height */ lineHeight: number;
lineHeight: float;
isOutlineEnabled: boolean; isOutlineEnabled: boolean;
outlineThickness: float; outlineThickness: float;
@@ -36,6 +35,7 @@ namespace gdjs {
shadowDistance: float; shadowDistance: float;
shadowAngle: float; shadowAngle: float;
shadowBlurRadius: float; shadowBlurRadius: float;
lineHeight: float;
}; };
}; };
@@ -92,6 +92,7 @@ namespace gdjs {
_wrapping: boolean = false; _wrapping: boolean = false;
// A wrapping of 1 makes games crash on Firefox // A wrapping of 1 makes games crash on Firefox
_wrappingWidth: float = 100; _wrappingWidth: float = 100;
_lineHeight: float;
_isOutlineEnabled: boolean; _isOutlineEnabled: boolean;
_outlineThickness: float; _outlineThickness: float;
@@ -104,9 +105,8 @@ namespace gdjs {
_shadowAngle: float; _shadowAngle: float;
_shadowBlur: float; _shadowBlur: float;
_lineHeight: float;
_padding: integer = 5; _padding: integer = 5;
_lineHeight: float = 0;
_str: string; _str: string;
_renderer: gdjs.TextRuntimeObjectRenderer; _renderer: gdjs.TextRuntimeObjectRenderer;
@@ -133,6 +133,7 @@ namespace gdjs {
this._str = content.text; this._str = content.text;
this._textAlign = content.textAlignment || 'left'; this._textAlign = content.textAlignment || 'left';
this._verticalTextAlignment = content.verticalTextAlignment || 'top'; this._verticalTextAlignment = content.verticalTextAlignment || 'top';
this._lineHeight = content.lineHeight || 0;
this._isOutlineEnabled = content.isOutlineEnabled; this._isOutlineEnabled = content.isOutlineEnabled;
this._outlineThickness = content.outlineThickness; this._outlineThickness = content.outlineThickness;
@@ -144,7 +145,6 @@ namespace gdjs {
this._shadowDistance = content.shadowDistance; this._shadowDistance = content.shadowDistance;
this._shadowBlur = content.shadowBlurRadius; this._shadowBlur = content.shadowBlurRadius;
this._shadowAngle = content.shadowAngle; this._shadowAngle = content.shadowAngle;
this._lineHeight = content.lineHeight || 0;
this._renderer = new gdjs.TextRuntimeObjectRenderer( this._renderer = new gdjs.TextRuntimeObjectRenderer(
this, this,
@@ -217,8 +217,8 @@ namespace gdjs {
if (oldContent.shadowBlurRadius !== newContent.shadowBlurRadius) { if (oldContent.shadowBlurRadius !== newContent.shadowBlurRadius) {
this.setShadowBlurRadius(newContent.shadowBlurRadius); this.setShadowBlurRadius(newContent.shadowBlurRadius);
} }
if ((oldContent.lineHeight || 0) !== (newContent.lineHeight || 0)) { if (oldContent.lineHeight !== newContent.lineHeight) {
this.setLineHeight(newContent.lineHeight || 0); this.setLineHeight(newContent.lineHeight);
} }
return true; return true;
} }
@@ -247,8 +247,8 @@ namespace gdjs {
shd: this._shadowDistance, shd: this._shadowDistance,
sha: this._shadowAngle, sha: this._shadowAngle,
shb: this._shadowBlur, shb: this._shadowBlur,
lh: this._lineHeight,
pad: this._padding, pad: this._padding,
lh: this._lineHeight,
}; };
} }
@@ -322,21 +322,19 @@ namespace gdjs {
if (networkSyncData.shb !== undefined) { if (networkSyncData.shb !== undefined) {
this.setShadowBlurRadius(networkSyncData.shb); this.setShadowBlurRadius(networkSyncData.shb);
} }
if (networkSyncData.lh !== undefined) {
this.setLineHeight(networkSyncData.lh);
}
if (networkSyncData.pad !== undefined) { if (networkSyncData.pad !== undefined) {
this.setPadding(networkSyncData.pad); this.setPadding(networkSyncData.pad);
} }
if (networkSyncData.lh !== undefined) {
this.setLineHeight(networkSyncData.lh);
}
} }
override getRendererObject() { override getRendererObject() {
return this._renderer.getRendererObject(); return this._renderer.getRendererObject();
} }
override updatePreRender( override update(instanceContainer: gdjs.RuntimeInstanceContainer): void {
instanceContainer: gdjs.RuntimeInstanceContainer
): void {
this._renderer.ensureUpToDate(); this._renderer.ensureUpToDate();
} }
@@ -354,11 +352,9 @@ namespace gdjs {
} else { } else {
this.setWrapping(false); this.setWrapping(false);
} }
this.setOpacity( if (initialInstanceData.opacity !== undefined) {
initialInstanceData.opacity === undefined this.setOpacity(initialInstanceData.opacity);
? 255 }
: initialInstanceData.opacity
);
} }
/** /**
@@ -461,22 +457,6 @@ namespace gdjs {
this._renderer.updateStyle(); this._renderer.updateStyle();
} }
/**
* Get the line height of the text.
*/
getLineHeight(): float {
return this._lineHeight;
}
/**
* Set the line height of the text.
* @param value The new line height for the text.
*/
setLineHeight(value: float): void {
this._lineHeight = value;
this._renderer.updateStyle();
}
/** /**
* Set the name of the resource to use for the font. * Set the name of the resource to use for the font.
* @param fontResourceName The name of the font resource. * @param fontResourceName The name of the font resource.
@@ -606,10 +586,16 @@ namespace gdjs {
/** /**
* Change the text color. * Change the text color.
* @param rgbOrHexColor color as a "R;G;B" string, for example: "255;0;0" * @param colorString color as a "R;G;B" string, for example: "255;0;0"
*/ */
setColor(rgbOrHexColor: string): void { setColor(colorString: string): void {
this._color = gdjs.rgbOrHexToRGBColor(rgbOrHexColor); const color = colorString.split(';');
if (color.length < 3) {
return;
}
this._color[0] = parseInt(color[0], 10);
this._color[1] = parseInt(color[1], 10);
this._color[2] = parseInt(color[2], 10);
this._useGradient = false; this._useGradient = false;
this._renderer.updateStyle(); this._renderer.updateStyle();
} }
@@ -718,12 +704,18 @@ namespace gdjs {
/** /**
* Set the outline for the text object. * Set the outline for the text object.
* @param rgbOrHexColor color as a "R;G;B" string, for example: "255;0;0" * @param str color as a "R;G;B" string, for example: "255;0;0"
* @param thickness thickness of the outline (0 = disabled) * @param thickness thickness of the outline (0 = disabled)
* @deprecated Prefer independent setters. * @deprecated Prefer independent setters.
*/ */
setOutline(rgbOrHexColor: string, thickness: number): void { setOutline(str: string, thickness: number): void {
this._outlineColor = gdjs.rgbOrHexToRGBColor(rgbOrHexColor); const color = str.split(';');
if (color.length < 3) {
return;
}
this._outlineColor[0] = parseInt(color[0], 10);
this._outlineColor[1] = parseInt(color[1], 10);
this._outlineColor[2] = parseInt(color[2], 10);
this._outlineThickness = thickness; this._outlineThickness = thickness;
this._renderer.updateStyle(); this._renderer.updateStyle();
} }
@@ -765,19 +757,25 @@ namespace gdjs {
/** /**
* Set the shadow for the text object. * Set the shadow for the text object.
* @param rgbOrHexColor color as a "R;G;B" string, for example: "255;0;0" * @param str color as a "R;G;B" string, for example: "255;0;0"
* @param distance distance between the shadow and the text, in pixels. * @param distance distance between the shadow and the text, in pixels.
* @param blur amount of shadow blur, in pixels. * @param blur amount of shadow blur, in pixels.
* @param angle shadow offset direction, in degrees. * @param angle shadow offset direction, in degrees.
* @deprecated Prefer independent setters. * @deprecated Prefer independent setters.
*/ */
setShadow( setShadow(
rgbOrHexColor: string, str: string,
distance: number, distance: number,
blur: integer, blur: integer,
angle: float angle: float
): void { ): void {
this._shadowColor = gdjs.rgbOrHexToRGBColor(rgbOrHexColor); const color = str.split(';');
if (color.length < 3) {
return;
}
this._shadowColor[0] = parseInt(color[0], 10);
this._shadowColor[1] = parseInt(color[1], 10);
this._shadowColor[2] = parseInt(color[2], 10);
this._shadowDistance = distance; this._shadowDistance = distance;
this._shadowBlur = blur; this._shadowBlur = blur;
this._shadowAngle = angle; this._shadowAngle = angle;
@@ -890,18 +888,38 @@ namespace gdjs {
strThirdColor: string, strThirdColor: string,
strFourthColor: string strFourthColor: string
): void { ): void {
const colorFirst = strFirstColor.split(';');
const colorSecond = strSecondColor.split(';');
const colorThird = strThirdColor.split(';');
const colorFourth = strFourthColor.split(';');
this._gradient = []; this._gradient = [];
if (strFirstColor) { if (colorFirst.length == 3) {
this._gradient.push(gdjs.rgbOrHexToRGBColor(strFirstColor)); this._gradient.push([
parseInt(colorFirst[0], 10),
parseInt(colorFirst[1], 10),
parseInt(colorFirst[2], 10),
]);
} }
if (strSecondColor) { if (colorSecond.length == 3) {
this._gradient.push(gdjs.rgbOrHexToRGBColor(strSecondColor)); this._gradient.push([
parseInt(colorSecond[0], 10),
parseInt(colorSecond[1], 10),
parseInt(colorSecond[2], 10),
]);
} }
if (strThirdColor) { if (colorThird.length == 3) {
this._gradient.push(gdjs.rgbOrHexToRGBColor(strThirdColor)); this._gradient.push([
parseInt(colorThird[0], 10),
parseInt(colorThird[1], 10),
parseInt(colorThird[2], 10),
]);
} }
if (strFourthColor) { if (colorFourth.length == 3) {
this._gradient.push(gdjs.rgbOrHexToRGBColor(strFourthColor)); this._gradient.push([
parseInt(colorFourth[0], 10),
parseInt(colorFourth[1], 10),
parseInt(colorFourth[2], 10),
]);
} }
this._gradientType = strGradientType; this._gradientType = strGradientType;
this._useGradient = this._gradient.length > 1 ? true : false; this._useGradient = this._gradient.length > 1 ? true : false;
@@ -924,6 +942,23 @@ namespace gdjs {
this._padding = value; this._padding = value;
this._renderer.updateStyle(); this._renderer.updateStyle();
} }
/**
* Get the line height of the text object.
* @return the line height
*/
getLineHeight(): number {
return this._lineHeight;
}
/**
* Set the line height of the text object.
* @param value the line height
*/
setLineHeight(value: float): void {
this._lineHeight = value;
this._renderer.updateStyle();
}
} }
gdjs.registerObject('TextObject::Text', gdjs.TextRuntimeObject); gdjs.registerObject('TextObject::Text', gdjs.TextRuntimeObject);
} }

View File

@@ -205,11 +205,9 @@ namespace gdjs {
this.setWidth(initialInstanceData.width); this.setWidth(initialInstanceData.width);
this.setHeight(initialInstanceData.height); this.setHeight(initialInstanceData.height);
} }
this.setOpacity( if (initialInstanceData.opacity !== undefined) {
initialInstanceData.opacity === undefined this.setOpacity(initialInstanceData.opacity);
? 255 }
: initialInstanceData.opacity
);
// 4. Update position (calculations based on renderer's dimensions). // 4. Update position (calculations based on renderer's dimensions).
this._renderer.updatePosition(); this._renderer.updatePosition();
@@ -417,14 +415,6 @@ namespace gdjs {
return this._renderer.getHeight(); return this._renderer.getHeight();
} }
override getOriginalWidth(): float {
return this._renderer.getTileMapWidth();
}
override getOriginalHeight(): float {
return this._renderer.getTileMapHeight();
}
getScaleX(): float { getScaleX(): float {
return this._renderer.getScaleX(); return this._renderer.getScaleX();
} }

View File

@@ -193,11 +193,9 @@ namespace gdjs {
this.setWidth(initialInstanceData.width); this.setWidth(initialInstanceData.width);
this.setHeight(initialInstanceData.height); this.setHeight(initialInstanceData.height);
} }
this.setOpacity( if (initialInstanceData.opacity !== undefined) {
initialInstanceData.opacity === undefined this.setOpacity(initialInstanceData.opacity);
? 255 }
: initialInstanceData.opacity
);
} }
private _updateTileMap(): void { private _updateTileMap(): void {
@@ -339,14 +337,6 @@ namespace gdjs {
this.setHeight(newHeight); this.setHeight(newHeight);
} }
override getOriginalWidth(): float {
return this._renderer.getTileMapWidth();
}
override getOriginalHeight(): float {
return this._renderer.getTileMapHeight();
}
/** /**
* Get the scale of the object (or the geometric mean of the X and Y scale in case they are different). * Get the scale of the object (or the geometric mean of the X and Y scale in case they are different).
* *

View File

@@ -92,18 +92,28 @@ namespace gdjs {
-this._object._yOffset % this._tiledSprite.texture.height; -this._object._yOffset % this._tiledSprite.texture.height;
} }
setColor(rgbOrHexColor: string): void { setColor(rgbColor: string): void {
this._tiledSprite.tint = gdjs.rgbOrHexStringToNumber(rgbOrHexColor); const colors = rgbColor.split(';');
if (colors.length < 3) {
return;
}
this._tiledSprite.tint =
'0x' +
gdjs.rgbToHex(
parseInt(colors[0], 10),
parseInt(colors[1], 10),
parseInt(colors[2], 10)
);
} }
getColor() { getColor() {
const rgb = new PIXI.Color(this._tiledSprite.tint).toRgbArray(); const rgb = new PIXI.Color(this._tiledSprite.tint).toRgbArray();
return ( return (
Math.round(rgb[0] * 255) + Math.floor(rgb[0] * 255) +
';' + ';' +
Math.round(rgb[1] * 255) + Math.floor(rgb[1] * 255) +
';' + ';' +
Math.round(rgb[2] * 255) Math.floor(rgb[2] * 255)
); );
} }

View File

@@ -42,8 +42,6 @@ namespace gdjs {
_renderer: gdjs.TiledSpriteRuntimeObjectRenderer; _renderer: gdjs.TiledSpriteRuntimeObjectRenderer;
_objectData: TiledSpriteObjectData;
/** /**
* @param instanceContainer The container the object belongs to. * @param instanceContainer The container the object belongs to.
* @param tiledSpriteObjectData The initial properties of the object * @param tiledSpriteObjectData The initial properties of the object
@@ -53,7 +51,6 @@ namespace gdjs {
tiledSpriteObjectData: TiledSpriteObjectData tiledSpriteObjectData: TiledSpriteObjectData
) { ) {
super(instanceContainer, tiledSpriteObjectData); super(instanceContainer, tiledSpriteObjectData);
this._objectData = tiledSpriteObjectData;
this._renderer = new gdjs.TiledSpriteRuntimeObjectRenderer( this._renderer = new gdjs.TiledSpriteRuntimeObjectRenderer(
this, this,
instanceContainer, instanceContainer,
@@ -69,7 +66,6 @@ namespace gdjs {
} }
updateFromObjectData(oldObjectData, newObjectData): boolean { updateFromObjectData(oldObjectData, newObjectData): boolean {
this._objectData = newObjectData;
if (oldObjectData.texture !== newObjectData.texture) { if (oldObjectData.texture !== newObjectData.texture) {
this.setTexture(newObjectData.texture, this.getRuntimeScene()); this.setTexture(newObjectData.texture, this.getRuntimeScene());
} }
@@ -130,11 +126,9 @@ namespace gdjs {
this.setWidth(initialInstanceData.width); this.setWidth(initialInstanceData.width);
this.setHeight(initialInstanceData.height); this.setHeight(initialInstanceData.height);
} }
this.setOpacity( if (initialInstanceData.opacity !== undefined) {
initialInstanceData.opacity === undefined this.setOpacity(initialInstanceData.opacity);
? 255 }
: initialInstanceData.opacity
);
} }
/** /**
@@ -226,14 +220,6 @@ namespace gdjs {
this.setHeight(height); this.setHeight(height);
} }
override getOriginalWidth(): float {
return this._objectData.width;
}
override getOriginalHeight(): float {
return this._objectData.height;
}
/** /**
* Set the offset on the X-axis when displaying the image of the Tiled Sprite object. * Set the offset on the X-axis when displaying the image of the Tiled Sprite object.
* @param xOffset The new offset on the X-axis. * @param xOffset The new offset on the X-axis.

View File

@@ -347,21 +347,17 @@ describe('gdjs.TweenRuntimeBehavior', () => {
// Check that there is no NaN. // Check that there is no NaN.
for (let i = 0; i < 11; i++) { for (let i = 0; i < 11; i++) {
runtimeScene.renderAndStep(1000 / 60); runtimeScene.renderAndStep(1000 / 60);
// The tween tries to set the camera zoom to 0, but it has no effect expect(camera.getCameraZoom(runtimeScene, '', 0)).to.be(0);
// because it doesn't make sense.
expect(camera.getCameraZoom(runtimeScene, '', 0)).to.be(1);
} }
}); });
it('can tween a layer camera zoom from 0', () => { it('can tween a layer camera zoom from 0', () => {
// The zoom stays at 1 because 0 doesn't make sense.
camera.setCameraZoom(runtimeScene, 0, '', 0); camera.setCameraZoom(runtimeScene, 0, '', 0);
// Here, it actually tweens from 1 to 1.
tween.tweenCameraZoom2(runtimeScene, 'MyTween', 1, '', 'linear', 0.25); tween.tweenCameraZoom2(runtimeScene, 'MyTween', 1, '', 'linear', 0.25);
// A camera zoom of 0 doesn't make sense. // A camera zoom of 0 doesn't make sense.
// Check that there is no NaN. // Check that there is no NaN.
for (let i = 0; i < 11; i++) { for (let i = 0; i < 11; i++) {
expect(camera.getCameraZoom(runtimeScene, '', 0)).to.be(1); expect(camera.getCameraZoom(runtimeScene, '', 0)).to.be(0);
runtimeScene.renderAndStep(1000 / 60); runtimeScene.renderAndStep(1000 / 60);
} }
expect(camera.getCameraZoom(runtimeScene, '', 0)).to.be(1); expect(camera.getCameraZoom(runtimeScene, '', 0)).to.be(1);

View File

@@ -145,7 +145,6 @@ describe('gdjs.TweenRuntimeBehavior', () => {
shadowDistance: 4, shadowDistance: 4,
shadowAngle: 90, shadowAngle: 90,
shadowBlurRadius: 2, shadowBlurRadius: 2,
lineHeight: 0,
}, },
}); });
runtimeScene.addObject(object); runtimeScene.addObject(object);

View File

@@ -145,7 +145,6 @@ describe('gdjs.TweenRuntimeBehavior', () => {
shadowDistance: 4, shadowDistance: 4,
shadowAngle: 90, shadowAngle: 90,
shadowBlurRadius: 2, shadowBlurRadius: 2,
lineHeight: 0,
}, },
}); });
runtimeScene.addObject(object); runtimeScene.addObject(object);

View File

@@ -1326,11 +1326,11 @@ namespace gdjs {
lightness lightness
); );
owner.setColor( owner.setColor(
Math.round(rgbFromHslColor[0]) + Math.floor(rgbFromHslColor[0]) +
';' + ';' +
Math.round(rgbFromHslColor[1]) + Math.floor(rgbFromHslColor[1]) +
';' + ';' +
Math.round(rgbFromHslColor[2]) Math.floor(rgbFromHslColor[2])
); );
}; };
} else { } else {
@@ -1439,11 +1439,12 @@ namespace gdjs {
if (!isColorable(this.owner)) return; if (!isColorable(this.owner)) return;
const owner = this.owner; const owner = this.owner;
const rgbFromColor = gdjs.rgbOrHexToRGBColor(owner.getColor()); const rgbFromColor: string[] = owner.getColor().split(';');
if (rgbFromColor.length < 3) return;
const hslFromColor = gdjs.evtTools.tween.rgbToHsl( const hslFromColor = gdjs.evtTools.tween.rgbToHsl(
rgbFromColor[0], parseFloat(rgbFromColor[0]),
rgbFromColor[1], parseFloat(rgbFromColor[1]),
rgbFromColor[2] parseFloat(rgbFromColor[2])
); );
const toH = animateHue ? toHue : hslFromColor[0]; const toH = animateHue ? toHue : hslFromColor[0];
@@ -1473,11 +1474,11 @@ namespace gdjs {
); );
owner.setColor( owner.setColor(
Math.round(rgbFromHslColor[0]) + Math.floor(rgbFromHslColor[0]) +
';' + ';' +
Math.round(rgbFromHslColor[1]) + Math.floor(rgbFromHslColor[1]) +
';' + ';' +
Math.round(rgbFromHslColor[2]) Math.floor(rgbFromHslColor[2])
); );
}, },

View File

@@ -146,11 +146,9 @@ namespace gdjs {
this.setWidth(initialInstanceData.width); this.setWidth(initialInstanceData.width);
this.setHeight(initialInstanceData.height); this.setHeight(initialInstanceData.height);
} }
this.setOpacity( if (initialInstanceData.opacity !== undefined) {
initialInstanceData.opacity === undefined this.setOpacity(initialInstanceData.opacity);
? 255 }
: initialInstanceData.opacity
);
} }
onDestroyed(): void { onDestroyed(): void {

View File

@@ -145,19 +145,16 @@ gd::String EventsCodeGenerator::GenerateEventsFunctionCode(
gd::DiagnosticReport diagnosticReport; gd::DiagnosticReport diagnosticReport;
codeGenerator.SetDiagnosticReport(&diagnosticReport); codeGenerator.SetDiagnosticReport(&diagnosticReport);
// Generate the code setting up the context of the function.
gd::String fullPreludeCode = "let scopeInstanceContainer = null;\n" +
codeGenerator.GenerateFreeEventsFunctionContext(
eventsFunctionsExtension, eventsFunction,
"runtimeScene.getOnceTriggers()");
gd::String output = GenerateEventsListCompleteFunctionCode( gd::String output = GenerateEventsListCompleteFunctionCode(
codeGenerator, codeGenerator.GetCodeNamespaceAccessor() + "func", codeGenerator, codeGenerator.GetCodeNamespaceAccessor() + "func",
codeGenerator.GenerateEventsFunctionParameterDeclarationsList( codeGenerator.GenerateEventsFunctionParameterDeclarationsList(
eventsFunction.GetParametersForEvents( eventsFunction.GetParametersForEvents(
eventsFunctionsExtension.GetEventsFunctions()), eventsFunctionsExtension.GetEventsFunctions()),
0, true), 0, true),
fullPreludeCode, eventsFunction.GetEvents(), "", codeGenerator.GenerateFreeEventsFunctionContext(
eventsFunctionsExtension, eventsFunction,
"runtimeScene.getOnceTriggers()"),
eventsFunction.GetEvents(), "",
codeGenerator.GenerateEventsFunctionReturn(eventsFunction)); codeGenerator.GenerateEventsFunctionReturn(eventsFunction));
// TODO: the editor should pass the diagnostic report and display it to the // TODO: the editor should pass the diagnostic report and display it to the
@@ -212,7 +209,6 @@ gd::String EventsCodeGenerator::GenerateBehaviorEventsFunctionCode(
// TODO: this should be renamed to "instanceContainer" and have the code generation // TODO: this should be renamed to "instanceContainer" and have the code generation
// adapted for this (rely less on `gdjs.RuntimeScene`, and more on `RuntimeInstanceContainer`). // adapted for this (rely less on `gdjs.RuntimeScene`, and more on `RuntimeInstanceContainer`).
"var runtimeScene = this._runtimeScene;\n" + "var runtimeScene = this._runtimeScene;\n" +
"let scopeInstanceContainer = null;\n" +
// By convention of Behavior Events Function, the object is accessible // By convention of Behavior Events Function, the object is accessible
// as a parameter called "Object", and thisObjectList is an array // as a parameter called "Object", and thisObjectList is an array
// containing it (for faster access, without having to go through the // containing it (for faster access, without having to go through the
@@ -298,7 +294,6 @@ gd::String EventsCodeGenerator::GenerateObjectEventsFunctionCode(
// TODO: this should be renamed to "instanceContainer" and have the code generation // TODO: this should be renamed to "instanceContainer" and have the code generation
// adapted for this (rely less on `gdjs.RuntimeScene`, and more on `RuntimeInstanceContainer`). // adapted for this (rely less on `gdjs.RuntimeScene`, and more on `RuntimeInstanceContainer`).
"var runtimeScene = this._instanceContainer;\n" + "var runtimeScene = this._instanceContainer;\n" +
"let scopeInstanceContainer = this._instanceContainer;\n" +
// By convention of Object Events Function, the object is accessible // By convention of Object Events Function, the object is accessible
// as a parameter called "Object", and thisObjectList is an array // as a parameter called "Object", and thisObjectList is an array
// containing it (for faster access, without having to go through the // containing it (for faster access, without having to go through the
@@ -629,11 +624,7 @@ gd::String EventsCodeGenerator::GenerateEventsFunctionContext(
// the cost of creating/storing it for each events function might not // the cost of creating/storing it for each events function might not
// be worth it. // be worth it.
" if (objectsList) {\n" + " if (objectsList) {\n" +
" const object = parentEventsFunctionContext && " " const object = parentEventsFunctionContext ?\n" +
// Check if `objectName` is not a child object and is passed by
// parameter from a parent instance container.
"!(scopeInstanceContainer && "
"scopeInstanceContainer.isObjectRegistered(objectName)) ?\n" +
" " " "
"parentEventsFunctionContext.createObject(objectsList.firstKey()) " "parentEventsFunctionContext.createObject(objectsList.firstKey()) "
":\n" + ":\n" +
@@ -643,7 +634,7 @@ gd::String EventsCodeGenerator::GenerateEventsFunctionContext(
" objectsList.get(objectsList.firstKey()).push(object);\n" + " objectsList.get(objectsList.firstKey()).push(object);\n" +
" " " "
"eventsFunctionContext._objectArraysMap[objectName].push(object);\n" + "eventsFunctionContext._objectArraysMap[objectName].push(object);\n" +
" }\n" + " return object;\n" + " }\n" + " }\n" + " return object;" + " }\n" +
// Unknown object, don't create anything: // Unknown object, don't create anything:
" return null;\n" + " return null;\n" +
" },\n" " },\n"
@@ -655,11 +646,7 @@ gd::String EventsCodeGenerator::GenerateEventsFunctionContext(
"eventsFunctionContext._objectsMap[objectName];\n" + "eventsFunctionContext._objectsMap[objectName];\n" +
" let count = 0;\n" + " if (objectsList) {\n" + " let count = 0;\n" + " if (objectsList) {\n" +
" for(const objectName in objectsList.items)\n" + " for(const objectName in objectsList.items)\n" +
" count += parentEventsFunctionContext && " " count += parentEventsFunctionContext ?\n" +
// Check if `objectName` is not a child object and is passed by
// parameter from a parent instance container.
"!(scopeInstanceContainer && "
"scopeInstanceContainer.isObjectRegistered(objectName)) ?\n" +
"parentEventsFunctionContext.getInstancesCountOnScene(objectName) " "parentEventsFunctionContext.getInstancesCountOnScene(objectName) "
":\n" + ":\n" +
" runtimeScene.getInstancesCountOnScene(objectName);\n" + " runtimeScene.getInstancesCountOnScene(objectName);\n" +

View File

@@ -841,23 +841,13 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
event.GetParameterObjects(), event.GetParameterObjects(),
parentContext.GetCurrentObject()); parentContext.GetCurrentObject());
if (realObjects.size() == 1) { callingCode += "var objects = [];\n";
parentContext.ObjectsListNeeded(realObjects[0]); for (unsigned int i = 0; i < realObjects.size(); ++i) {
parentContext.ObjectsListNeeded(realObjects[i]);
callingCode += callingCode +=
"const objects = " + "objects.push.apply(objects," +
codeGenerator.GetObjectListName(realObjects[0], parentContext) + codeGenerator.GetObjectListName(realObjects[i], parentContext) +
";\n"; ");\n";
} else {
// Groups are rarely used in JS events so it's fine to make
// allocations.
callingCode += "const objects = [];\n";
for (unsigned int i = 0; i < realObjects.size(); ++i) {
parentContext.ObjectsListNeeded(realObjects[i]);
callingCode += "objects.push.apply(objects," +
codeGenerator.GetObjectListName(realObjects[i],
parentContext) +
");\n";
}
} }
} }

View File

@@ -18,8 +18,6 @@ KeyboardExtension::KeyboardExtension() {
"gdjs.evtTools.input.wasKeyReleased"); "gdjs.evtTools.input.wasKeyReleased");
GetAllConditions()["KeyFromTextPressed"].SetFunctionName( GetAllConditions()["KeyFromTextPressed"].SetFunctionName(
"gdjs.evtTools.input.isKeyPressed"); "gdjs.evtTools.input.isKeyPressed");
GetAllConditions()["KeyFromTextJustPressed"].SetFunctionName(
"gdjs.evtTools.input.wasKeyJustPressed");
GetAllConditions()["KeyFromTextReleased"].SetFunctionName( GetAllConditions()["KeyFromTextReleased"].SetFunctionName(
"gdjs.evtTools.input.wasKeyReleased"); "gdjs.evtTools.input.wasKeyReleased");
GetAllConditions()["AnyKeyPressed"].SetFunctionName( GetAllConditions()["AnyKeyPressed"].SetFunctionName(

View File

@@ -18,9 +18,6 @@
#include "GDCore/IDE/Project/ProjectResourcesCopier.h" #include "GDCore/IDE/Project/ProjectResourcesCopier.h"
#include "GDCore/IDE/Project/SceneResourcesFinder.h" #include "GDCore/IDE/Project/SceneResourcesFinder.h"
#include "GDCore/IDE/ProjectStripper.h" #include "GDCore/IDE/ProjectStripper.h"
#include "GDCore/Project/EventsBasedObject.h"
#include "GDCore/Project/EventsBasedObjectVariant.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/ExternalEvents.h" #include "GDCore/Project/ExternalEvents.h"
#include "GDCore/Project/ExternalLayout.h" #include "GDCore/Project/ExternalLayout.h"
#include "GDCore/Project/Layout.h" #include "GDCore/Project/Layout.h"
@@ -50,7 +47,7 @@ Exporter::~Exporter() {}
bool Exporter::ExportProjectForPixiPreview( bool Exporter::ExportProjectForPixiPreview(
const PreviewExportOptions &options) { const PreviewExportOptions &options) {
ExporterHelper helper(fs, gdjsRoot, codeOutputDir); ExporterHelper helper(fs, gdjsRoot, codeOutputDir);
return helper.ExportProjectForPixiPreview(options, includesFiles); return helper.ExportProjectForPixiPreview(options);
} }
bool Exporter::ExportWholePixiProject(const ExportOptions &options) { bool Exporter::ExportWholePixiProject(const ExportOptions &options) {
@@ -83,7 +80,7 @@ bool Exporter::ExportWholePixiProject(const ExportOptions &options) {
// Prepare the export directory // Prepare the export directory
fs.MkDir(exportDir); fs.MkDir(exportDir);
includesFiles.clear(); std::vector<gd::String> includesFiles;
std::vector<gd::String> resourcesFiles; std::vector<gd::String> resourcesFiles;
// Export the resources (before generating events as some resources // Export the resources (before generating events as some resources
@@ -101,7 +98,6 @@ bool Exporter::ExportWholePixiProject(const ExportOptions &options) {
helper.AddLibsInclude( helper.AddLibsInclude(
/*pixiRenderers=*/true, /*pixiRenderers=*/true,
usedExtensionsResult.Has3DObjects(), usedExtensionsResult.Has3DObjects(),
/*isInGameEditor=*/false,
/*includeWebsocketDebuggerClient=*/false, /*includeWebsocketDebuggerClient=*/false,
/*includeWindowMessageDebuggerClient=*/false, /*includeWindowMessageDebuggerClient=*/false,
/*includeMinimalDebuggerClient=*/false, /*includeMinimalDebuggerClient=*/false,
@@ -124,7 +120,7 @@ bool Exporter::ExportWholePixiProject(const ExportOptions &options) {
helper.ExportEffectIncludes(exportedProject, includesFiles); helper.ExportEffectIncludes(exportedProject, includesFiles);
// Export events // Export events
if (!helper.ExportScenesEventsCode(exportedProject, if (!helper.ExportEventsCode(exportedProject,
codeOutputDir, codeOutputDir,
includesFiles, includesFiles,
wholeProjectDiagnosticReport, wholeProjectDiagnosticReport,
@@ -134,10 +130,29 @@ bool Exporter::ExportWholePixiProject(const ExportOptions &options) {
return false; return false;
} }
auto projectUsedResources =
gd::SceneResourcesFinder::FindProjectResources(exportedProject);
std::unordered_map<gd::String, std::set<gd::String>> scenesUsedResources;
for (std::size_t layoutIndex = 0;
layoutIndex < exportedProject.GetLayoutsCount();
layoutIndex++) {
auto &layout = exportedProject.GetLayout(layoutIndex);
scenesUsedResources[layout.GetName()] =
gd::SceneResourcesFinder::FindSceneResources(exportedProject, layout);
}
// Strip the project (*after* generating events as the events may use
// stripped things like objects groups...)...
gd::ProjectStripper::StripProjectForExport(exportedProject);
//...and export it //...and export it
gd::SerializerElement noRuntimeGameOptions; gd::SerializerElement noRuntimeGameOptions;
helper.ExportProjectData(fs, exportedProject, codeOutputDir + "/data.js", helper.ExportProjectData(fs,
noRuntimeGameOptions); exportedProject,
codeOutputDir + "/data.js",
noRuntimeGameOptions,
projectUsedResources,
scenesUsedResources);
includesFiles.push_back(codeOutputDir + "/data.js"); includesFiles.push_back(codeOutputDir + "/data.js");
helper.ExportIncludesAndLibs(includesFiles, exportDir, false); helper.ExportIncludesAndLibs(includesFiles, exportDir, false);
@@ -200,18 +215,4 @@ bool Exporter::ExportWholePixiProject(const ExportOptions &options) {
return true; return true;
} }
void Exporter::SerializeProjectData(const gd::Project &project,
const PreviewExportOptions &options,
gd::SerializerElement &projectDataElement) {
ExporterHelper::SerializeProjectData(fs, project, options,
projectDataElement);
}
void Exporter::SerializeRuntimeGameOptions(
const PreviewExportOptions &options,
gd::SerializerElement &runtimeGameOptionsElement) {
ExporterHelper::SerializeRuntimeGameOptions(
fs, gdjsRoot, options, includesFiles, runtimeGameOptionsElement);
}
} // namespace gdjs } // namespace gdjs

View File

@@ -16,7 +16,6 @@ class Project;
class Layout; class Layout;
class ExternalLayout; class ExternalLayout;
class AbstractFileSystem; class AbstractFileSystem;
class SerializerElement;
} // namespace gd } // namespace gd
namespace gdjs { namespace gdjs {
struct PreviewExportOptions; struct PreviewExportOptions;
@@ -65,33 +64,7 @@ class Exporter {
codeOutputDir = codeOutputDir_; codeOutputDir = codeOutputDir_;
} }
/** private:
* \brief Serialize a project without its events to JSON
*
* \param project The project to be exported
* \param options The content of the extra configuration
* \param projectDataElement The element where the project data is serialized
*/
void SerializeProjectData(const gd::Project &project,
const PreviewExportOptions &options,
gd::SerializerElement &projectDataElement);
/**
* \brief Serialize the content of the extra configuration to store
* in gdjs.runtimeGameOptions to JSON
*
* \warning `ExportProjectForPixiPreview` must be called first to serialize
* the list of scripts files.
*
* \param options The content of the extra configuration
* \param runtimeGameOptionsElement The element where the game options are
* serialized
*/
void
SerializeRuntimeGameOptions(const PreviewExportOptions &options,
gd::SerializerElement &runtimeGameOptionsElement);
private:
gd::AbstractFileSystem& gd::AbstractFileSystem&
fs; ///< The abstract file system to be used for exportation. fs; ///< The abstract file system to be used for exportation.
gd::String lastError; ///< The last error that occurred. gd::String lastError; ///< The last error that occurred.
@@ -99,8 +72,6 @@ private:
gdjsRoot; ///< The root directory of GDJS, used to copy runtime files. gdjsRoot; ///< The root directory of GDJS, used to copy runtime files.
gd::String codeOutputDir; ///< The directory where JS code is outputted. Will gd::String codeOutputDir; ///< The directory where JS code is outputted. Will
///< be then copied to the final output directory. ///< be then copied to the final output directory.
std::vector<gd::String>
includesFiles; ///< The list of scripts files - useful for hot-reloading
}; };
} // namespace gdjs } // namespace gdjs

View File

@@ -28,13 +28,10 @@
#include "GDCore/IDE/Events/UsedExtensionsFinder.h" #include "GDCore/IDE/Events/UsedExtensionsFinder.h"
#include "GDCore/IDE/ExportedDependencyResolver.h" #include "GDCore/IDE/ExportedDependencyResolver.h"
#include "GDCore/IDE/Project/ProjectResourcesCopier.h" #include "GDCore/IDE/Project/ProjectResourcesCopier.h"
#include "GDCore/IDE/Project/ResourcesMergingHelper.h"
#include "GDCore/IDE/Project/SceneResourcesFinder.h" #include "GDCore/IDE/Project/SceneResourcesFinder.h"
#include "GDCore/IDE/ProjectStripper.h" #include "GDCore/IDE/ProjectStripper.h"
#include "GDCore/IDE/ResourceExposer.h"
#include "GDCore/IDE/SceneNameMangler.h" #include "GDCore/IDE/SceneNameMangler.h"
#include "GDCore/Project/EventsBasedObject.h" #include "GDCore/Project/EventsBasedObject.h"
#include "GDCore/Project/EventsBasedObjectVariant.h"
#include "GDCore/Project/EventsFunctionsExtension.h" #include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/ExternalEvents.h" #include "GDCore/Project/ExternalEvents.h"
#include "GDCore/Project/ExternalLayout.h" #include "GDCore/Project/ExternalLayout.h"
@@ -61,6 +58,7 @@ double GetTimeSpent(double previousTime) { return GetTimeNow() - previousTime; }
double LogTimeSpent(const gd::String &name, double previousTime) { double LogTimeSpent(const gd::String &name, double previousTime) {
gd::LogStatus(name + " took " + gd::String::From(GetTimeSpent(previousTime)) + gd::LogStatus(name + " took " + gd::String::From(GetTimeSpent(previousTime)) +
"ms"); "ms");
std::cout << std::endl;
return GetTimeNow(); return GetTimeNow();
} }
} // namespace } // namespace
@@ -106,297 +104,128 @@ ExporterHelper::ExporterHelper(gd::AbstractFileSystem &fileSystem,
: fs(fileSystem), gdjsRoot(gdjsRoot_), codeOutputDir(codeOutputDir_) {}; : fs(fileSystem), gdjsRoot(gdjsRoot_), codeOutputDir(codeOutputDir_) {};
bool ExporterHelper::ExportProjectForPixiPreview( bool ExporterHelper::ExportProjectForPixiPreview(
const PreviewExportOptions &options, const PreviewExportOptions &options) {
std::vector<gd::String> &includesFiles) {
if (options.isInGameEdition && !options.shouldReloadProjectData &&
!options.shouldReloadLibraries && !options.shouldGenerateScenesEventsCode) {
gd::LogStatus("Skip project export entirely");
return "";
}
double previousTime = GetTimeNow(); double previousTime = GetTimeNow();
fs.MkDir(options.exportPath); fs.MkDir(options.exportPath);
if (options.shouldClearExportFolder) { fs.ClearDir(options.exportPath);
fs.ClearDir(options.exportPath); std::vector<gd::String> includesFiles;
}
includesFiles.clear();
std::vector<gd::String> resourcesFiles; std::vector<gd::String> resourcesFiles;
// TODO Try to remove side effects to avoid the copy // TODO Try to remove side effects to avoid the copy
// that destroys the AST in cache. // that destroys the AST in cache.
gd::Project exportedProject = options.project; gd::Project exportedProject = options.project;
const gd::Project &immutableProject = options.project; const gd::Project &immutableProject = exportedProject;
previousTime = LogTimeSpent("Project cloning", previousTime);
if (options.isInGameEdition) { if (options.fullLoadingScreen) {
if (options.shouldReloadProjectData || options.shouldGenerateScenesEventsCode) { // Use project properties fallback to set empty properties
auto projectDirectory = fs.DirNameFrom(exportedProject.GetProjectFile()); if (exportedProject.GetAuthorIds().empty() &&
gd::ResourcesMergingHelper resourcesMergingHelper( !options.fallbackAuthorId.empty()) {
exportedProject.GetResourcesManager(), fs); exportedProject.GetAuthorIds().push_back(options.fallbackAuthorId);
resourcesMergingHelper.SetBaseDirectory(projectDirectory); }
resourcesMergingHelper.SetShouldUseOriginalAbsoluteFilenames(); if (exportedProject.GetAuthorUsernames().empty() &&
gd::ResourceExposer::ExposeWholeProjectResources(exportedProject, !options.fallbackAuthorUsername.empty()) {
resourcesMergingHelper); exportedProject.GetAuthorUsernames().push_back(
options.fallbackAuthorUsername);
previousTime = LogTimeSpent("Resource path resolving", previousTime);
} }
gd::LogStatus("Resource export is skipped");
} else { } else {
// Export resources (*before* generating events as some resources filenames // Most of the time, we skip the logo and minimum duration so that
// may be updated) // the preview start as soon as possible.
ExportResources(fs, exportedProject, options.exportPath); exportedProject.GetLoadingScreen()
.ShowGDevelopLogoDuringLoadingScreen(false)
previousTime = LogTimeSpent("Resource export", previousTime); .SetMinDuration(0);
exportedProject.GetWatermark().ShowGDevelopWatermark(false);
} }
if (options.shouldReloadProjectData || options.shouldGenerateScenesEventsCode) { // Export resources (*before* generating events as some resources filenames
// Compatibility with GD <= 5.0-beta56 // may be updated)
// Stay compatible with text objects declaring their font as just a filename ExportResources(fs, exportedProject, options.exportPath);
// without a font resource - by manually adding these resources.
AddDeprecatedFontFilesToFontResources( previousTime = LogTimeSpent("Resource export", previousTime);
fs, exportedProject.GetResourcesManager(), options.exportPath);
// end of compatibility code // Compatibility with GD <= 5.0-beta56
// Stay compatible with text objects declaring their font as just a filename
// without a font resource - by manually adding these resources.
AddDeprecatedFontFilesToFontResources(
fs, exportedProject.GetResourcesManager(), options.exportPath);
// end of compatibility code
auto usedExtensionsResult =
gd::UsedExtensionsFinder::ScanProject(exportedProject);
// Export engine libraries
AddLibsInclude(/*pixiRenderers=*/true,
usedExtensionsResult.Has3DObjects(),
/*includeWebsocketDebuggerClient=*/
!options.websocketDebuggerServerAddress.empty(),
/*includeWindowMessageDebuggerClient=*/
options.useWindowMessageDebuggerClient,
/*includeMinimalDebuggerClient=*/
options.useMinimalDebuggerClient,
/*includeCaptureManager=*/
!options.captureOptions.IsEmpty(),
/*includeInAppTutorialMessage*/
!options.inAppTutorialMessageInPreview.empty(),
immutableProject.GetLoadingScreen().GetGDevelopLogoStyle(),
includesFiles);
// Export files for free function, object and behaviors
for (const auto &includeFile : usedExtensionsResult.GetUsedIncludeFiles()) {
InsertUnique(includesFiles, includeFile);
}
for (const auto &requiredFile : usedExtensionsResult.GetUsedRequiredFiles()) {
InsertUnique(resourcesFiles, requiredFile);
} }
std::vector<gd::SourceFileMetadata> noUsedSourceFiles; // Export effects (after engine libraries as they auto-register themselves to
std::vector<gd::SourceFileMetadata> &usedSourceFiles = noUsedSourceFiles; // the engine)
if (options.shouldReloadLibraries) { ExportEffectIncludes(exportedProject, includesFiles);
auto usedExtensionsResult =
gd::UsedExtensionsFinder::ScanProject(exportedProject);
usedSourceFiles = usedExtensionsResult.GetUsedSourceFiles();
// Export engine libraries previousTime = LogTimeSpent("Include files export", previousTime);
AddLibsInclude(/*pixiRenderers=*/true,
/*pixiInThreeRenderers=*/
usedExtensionsResult.Has3DObjects(),
/*isInGameEdition=*/
options.isInGameEdition,
/*includeWebsocketDebuggerClient=*/
!options.websocketDebuggerServerAddress.empty(),
/*includeWindowMessageDebuggerClient=*/
options.useWindowMessageDebuggerClient,
/*includeMinimalDebuggerClient=*/
options.useMinimalDebuggerClient,
/*includeCaptureManager=*/
!options.captureOptions.IsEmpty(),
/*includeInAppTutorialMessage*/
!options.inAppTutorialMessageInPreview.empty(),
immutableProject.GetLoadingScreen().GetGDevelopLogoStyle(),
includesFiles);
// Export files for free function, object and behaviors if (!options.projectDataOnlyExport) {
for (const auto &includeFile : usedExtensionsResult.GetUsedIncludeFiles()) {
InsertUnique(includesFiles, includeFile);
}
for (const auto &requiredFile : usedExtensionsResult.GetUsedRequiredFiles()) {
InsertUnique(resourcesFiles, requiredFile);
}
if (options.isInGameEdition) {
// TODO Scan the objects and events of event-based objects
// (it could be an alternative method ScanProjectAndEventsBasedObjects in
// UsedExtensionsFinder).
// This is already done by UsedExtensionsFinder, but maybe it shouldn't.
// Export all event-based objects because they can be edited even if they
// are not used yet.
for (std::size_t e = 0;
e < exportedProject.GetEventsFunctionsExtensionsCount(); e++) {
auto &eventsFunctionsExtension =
exportedProject.GetEventsFunctionsExtension(e);
for (auto &&eventsBasedObjectUniquePtr :
eventsFunctionsExtension.GetEventsBasedObjects()
.GetInternalVector()) {
auto eventsBasedObject = eventsBasedObjectUniquePtr.get();
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
exportedProject.GetCurrentPlatform(),
gd::PlatformExtension::GetObjectFullType(
eventsFunctionsExtension.GetName(),
eventsBasedObject->GetName()));
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
InsertUnique(includesFiles, includeFile);
}
for (auto &behaviorType :
metadata.GetMetadata().GetDefaultBehaviors()) {
auto behaviorMetadata =
gd::MetadataProvider::GetExtensionAndBehaviorMetadata(
exportedProject.GetCurrentPlatform(), behaviorType);
for (auto &&includeFile :
behaviorMetadata.GetMetadata().includeFiles) {
InsertUnique(includesFiles, includeFile);
}
}
}
}
}
// Export effects (after engine libraries as they auto-register themselves to
// the engine)
ExportEffectIncludes(exportedProject, includesFiles);
previousTime = LogTimeSpent("Include files export", previousTime);
}
else {
gd::LogStatus("Include files export is skipped");
}
if (options.shouldGenerateScenesEventsCode) {
gd::WholeProjectDiagnosticReport &wholeProjectDiagnosticReport = gd::WholeProjectDiagnosticReport &wholeProjectDiagnosticReport =
options.project.GetWholeProjectDiagnosticReport(); options.project.GetWholeProjectDiagnosticReport();
wholeProjectDiagnosticReport.Clear(); wholeProjectDiagnosticReport.Clear();
// Generate events code // Generate events code
if (!ExportScenesEventsCode(immutableProject, if (!ExportEventsCode(immutableProject,
codeOutputDir, codeOutputDir,
includesFiles, includesFiles,
wholeProjectDiagnosticReport, wholeProjectDiagnosticReport,
true)) { true)) {
return false; return false;
} }
previousTime = LogTimeSpent("Events code export", previousTime); previousTime = LogTimeSpent("Events code export", previousTime);
} }
else {
gd::LogStatus("Events code export is skipped"); auto projectUsedResources =
gd::SceneResourcesFinder::FindProjectResources(exportedProject);
std::unordered_map<gd::String, std::set<gd::String>> scenesUsedResources;
for (std::size_t layoutIndex = 0;
layoutIndex < exportedProject.GetLayoutsCount();
layoutIndex++) {
auto &layout = exportedProject.GetLayout(layoutIndex);
scenesUsedResources[layout.GetName()] =
gd::SceneResourcesFinder::FindSceneResources(exportedProject, layout);
} }
if (options.shouldReloadProjectData) { // Strip the project (*after* generating events as the events may use stripped
// things (objects groups...))
if (options.fullLoadingScreen) { gd::ProjectStripper::StripProjectForExport(exportedProject);
// Use project properties fallback to set empty properties exportedProject.SetFirstLayout(options.layoutName);
if (exportedProject.GetAuthorIds().empty() &&
!options.fallbackAuthorId.empty()) {
exportedProject.GetAuthorIds().push_back(options.fallbackAuthorId);
}
if (exportedProject.GetAuthorUsernames().empty() &&
!options.fallbackAuthorUsername.empty()) {
exportedProject.GetAuthorUsernames().push_back(
options.fallbackAuthorUsername);
}
} else {
// Most of the time, we skip the logo and minimum duration so that
// the preview start as soon as possible.
exportedProject.GetLoadingScreen()
.ShowGDevelopLogoDuringLoadingScreen(false)
.SetMinDuration(0);
exportedProject.GetWatermark().ShowGDevelopWatermark(false);
}
gd::SerializerElement runtimeGameOptions; previousTime = LogTimeSpent("Data stripping", previousTime);
ExporterHelper::SerializeRuntimeGameOptions(fs, gdjsRoot, options,
includesFiles, runtimeGameOptions);
ExportProjectData(fs,
exportedProject,
codeOutputDir + "/data.js",
runtimeGameOptions);
includesFiles.push_back(codeOutputDir + "/data.js");
previousTime = LogTimeSpent("Project data export", previousTime);
}
else {
gd::LogStatus("Project data export is skipped");
}
if (options.shouldReloadLibraries) {
// Copy all the dependencies and their source maps
ExportIncludesAndLibs(includesFiles, options.exportPath, true);
ExportIncludesAndLibs(resourcesFiles, options.exportPath, true);
// TODO Build a full includesFiles list without actually doing export or
// generation.
if (options.shouldGenerateScenesEventsCode) {
// Create the index file
if (!ExportIndexFile(exportedProject, gdjsRoot + "/Runtime/index.html",
options.exportPath, includesFiles, usedSourceFiles,
options.nonRuntimeScriptsCacheBurst,
"gdjs.runtimeGameOptions")) {
return false;
}
}
previousTime = LogTimeSpent("Include and libs export", previousTime);
} else {
gd::LogStatus("Include and libs export is skipped");
}
return true;
}
gd::String ExporterHelper::ExportProjectData(
gd::AbstractFileSystem &fs, gd::Project &project, gd::String filename,
const gd::SerializerElement &runtimeGameOptions) {
fs.MkDir(fs.DirNameFrom(filename));
gd::SerializerElement projectDataElement;
ExporterHelper::StriptAndSerializeProjectData(project, projectDataElement);
// Save the project to JSON
gd::String output =
"gdjs.projectData = " + gd::Serializer::ToJSON(projectDataElement) +
";\ngdjs.runtimeGameOptions = " + gd::Serializer::ToJSON(runtimeGameOptions) +
";\n";
if (!fs.WriteToFile(filename, output))
return "Unable to write " + filename;
return "";
}
void ExporterHelper::SerializeRuntimeGameOptions(
gd::AbstractFileSystem &fs, const gd::String &gdjsRoot,
const PreviewExportOptions &options,
std::vector<gd::String> &includesFiles,
gd::SerializerElement &runtimeGameOptions) {
// Create the setup options passed to the gdjs.RuntimeGame // Create the setup options passed to the gdjs.RuntimeGame
gd::SerializerElement runtimeGameOptions;
runtimeGameOptions.AddChild("isPreview").SetBoolValue(true); runtimeGameOptions.AddChild("isPreview").SetBoolValue(true);
auto &initialRuntimeGameStatus =
runtimeGameOptions.AddChild("initialRuntimeGameStatus");
initialRuntimeGameStatus.AddChild("sceneName")
.SetStringValue(options.layoutName);
if (options.isInGameEdition) {
initialRuntimeGameStatus.AddChild("isInGameEdition").SetBoolValue(true);
initialRuntimeGameStatus.AddChild("editorId").SetValue(options.editorId);
if (!options.editorCamera3DCameraMode.empty()) {
auto &editorCamera3D =
initialRuntimeGameStatus.AddChild("editorCamera3D");
editorCamera3D.AddChild("cameraMode").SetStringValue(
options.editorCamera3DCameraMode);
editorCamera3D.AddChild("positionX")
.SetDoubleValue(options.editorCamera3DPositionX);
editorCamera3D.AddChild("positionY")
.SetDoubleValue(options.editorCamera3DPositionY);
editorCamera3D.AddChild("positionZ")
.SetDoubleValue(options.editorCamera3DPositionZ);
editorCamera3D.AddChild("rotationAngle")
.SetDoubleValue(options.editorCamera3DRotationAngle);
editorCamera3D.AddChild("elevationAngle")
.SetDoubleValue(options.editorCamera3DElevationAngle);
editorCamera3D.AddChild("distance")
.SetDoubleValue(options.editorCamera3DDistance);
}
}
if (!options.externalLayoutName.empty()) { if (!options.externalLayoutName.empty()) {
initialRuntimeGameStatus.AddChild("injectedExternalLayoutName") runtimeGameOptions.AddChild("injectExternalLayout")
.SetValue(options.externalLayoutName); .SetValue(options.externalLayoutName);
if (options.isInGameEdition) {
initialRuntimeGameStatus.AddChild("skipCreatingInstancesFromScene")
.SetBoolValue(true);
}
} }
if (!options.eventsBasedObjectType.empty()) { runtimeGameOptions.AddChild("projectDataOnlyExport")
initialRuntimeGameStatus.AddChild("eventsBasedObjectType") .SetBoolValue(options.projectDataOnlyExport);
.SetValue(options.eventsBasedObjectType);
initialRuntimeGameStatus.AddChild("eventsBasedObjectVariantName")
.SetValue(options.eventsBasedObjectVariantName);
}
runtimeGameOptions.AddChild("shouldReloadLibraries")
.SetBoolValue(options.shouldReloadLibraries);
runtimeGameOptions.AddChild("shouldGenerateScenesEventsCode")
.SetBoolValue(options.shouldGenerateScenesEventsCode);
runtimeGameOptions.AddChild("nativeMobileApp") runtimeGameOptions.AddChild("nativeMobileApp")
.SetBoolValue(options.nativeMobileApp); .SetBoolValue(options.nativeMobileApp);
runtimeGameOptions.AddChild("websocketDebuggerServerAddress") runtimeGameOptions.AddChild("websocketDebuggerServerAddress")
@@ -468,93 +297,71 @@ void ExporterHelper::SerializeRuntimeGameOptions(
for (const auto &includeFile : includesFiles) { for (const auto &includeFile : includesFiles) {
auto hashIt = options.includeFileHashes.find(includeFile); auto hashIt = options.includeFileHashes.find(includeFile);
gd::String scriptSrc = GetExportedIncludeFilename(fs, gdjsRoot, includeFile); gd::String scriptSrc = GetExportedIncludeFilename(includeFile);
scriptFilesElement.AddChild("scriptFile") scriptFilesElement.AddChild("scriptFile")
.SetStringAttribute("path", scriptSrc) .SetStringAttribute("path", scriptSrc)
.SetIntAttribute( .SetIntAttribute(
"hash", "hash",
hashIt != options.includeFileHashes.end() ? hashIt->second : 0); hashIt != options.includeFileHashes.end() ? hashIt->second : 0);
} }
// Export the project
ExportProjectData(fs,
exportedProject,
codeOutputDir + "/data.js",
runtimeGameOptions,
projectUsedResources,
scenesUsedResources);
includesFiles.push_back(codeOutputDir + "/data.js");
previousTime = LogTimeSpent("Project data export", previousTime);
// Copy all the dependencies and their source maps
ExportIncludesAndLibs(includesFiles, options.exportPath, true);
ExportIncludesAndLibs(resourcesFiles, options.exportPath, true);
// Create the index file
if (!ExportIndexFile(exportedProject,
gdjsRoot + "/Runtime/index.html",
options.exportPath,
includesFiles,
usedExtensionsResult.GetUsedSourceFiles(),
options.nonRuntimeScriptsCacheBurst,
"gdjs.runtimeGameOptions"))
return false;
previousTime = LogTimeSpent("Include and libs export", previousTime);
return true;
} }
void ExporterHelper::SerializeProjectData(gd::AbstractFileSystem &fs, gd::String ExporterHelper::ExportProjectData(
const gd::Project &project, gd::AbstractFileSystem &fs,
const PreviewExportOptions &options, gd::Project &project,
gd::SerializerElement &rootElement) { gd::String filename,
gd::Project clonedProject = project; const gd::SerializerElement &runtimeGameOptions,
std::set<gd::String> &projectUsedResources,
// Replace all resource file paths with the one used in exported projects. std::unordered_map<gd::String, std::set<gd::String>> &scenesUsedResources) {
auto projectDirectory = fs.DirNameFrom(project.GetProjectFile()); fs.MkDir(fs.DirNameFrom(filename));
gd::ResourcesMergingHelper resourcesMergingHelper(
clonedProject.GetResourcesManager(), fs);
resourcesMergingHelper.SetBaseDirectory(projectDirectory);
if (options.isInGameEdition) {
resourcesMergingHelper.SetShouldUseOriginalAbsoluteFilenames();
} else {
resourcesMergingHelper.PreserveDirectoriesStructure(false);
resourcesMergingHelper.PreserveAbsoluteFilenames(false);
}
gd::ResourceExposer::ExposeWholeProjectResources(clonedProject,
resourcesMergingHelper);
ExporterHelper::StriptAndSerializeProjectData(clonedProject, rootElement);
}
void ExporterHelper::StriptAndSerializeProjectData(
gd::Project &project, gd::SerializerElement &rootElement) {
auto projectUsedResources =
gd::SceneResourcesFinder::FindProjectResources(project);
std::unordered_map<gd::String, std::set<gd::String>> scenesUsedResources;
for (std::size_t layoutIndex = 0;
layoutIndex < project.GetLayoutsCount(); layoutIndex++) {
auto &layout = project.GetLayout(layoutIndex);
scenesUsedResources[layout.GetName()] =
gd::SceneResourcesFinder::FindSceneResources(project, layout);
}
std::unordered_map<gd::String, std::set<gd::String>>
eventsBasedObjectVariantsUsedResources;
for (std::size_t extensionIndex = 0;
extensionIndex < project.GetEventsFunctionsExtensionsCount();
extensionIndex++) {
auto &eventsFunctionsExtension =
project.GetEventsFunctionsExtension(extensionIndex);
for (auto &&eventsBasedObject :
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
auto eventsBasedObjectType = gd::PlatformExtension::GetObjectFullType(
eventsFunctionsExtension.GetName(), eventsBasedObject->GetName());
eventsBasedObjectVariantsUsedResources[eventsBasedObjectType] =
gd::SceneResourcesFinder::FindEventsBasedObjectVariantResources(
project, eventsBasedObject->GetDefaultVariant());
for (auto &&eventsBasedObjectVariant :
eventsBasedObject->GetVariants().GetInternalVector()) {
auto variantType = gd::PlatformExtension::GetVariantFullType(
eventsFunctionsExtension.GetName(), eventsBasedObject->GetName(),
eventsBasedObjectVariant->GetName());
eventsBasedObjectVariantsUsedResources[variantType] =
gd::SceneResourcesFinder::FindEventsBasedObjectVariantResources(
project, *eventsBasedObjectVariant);
}
}
}
// Strip the project (*after* generating events as the events may use stripped
// things (objects groups...))
gd::ProjectStripper::StripProjectForExport(project);
// Save the project to JSON
gd::SerializerElement rootElement;
project.SerializeTo(rootElement); project.SerializeTo(rootElement);
SerializeUsedResources(rootElement, projectUsedResources, scenesUsedResources, SerializeUsedResources(
eventsBasedObjectVariantsUsedResources); rootElement, projectUsedResources, scenesUsedResources);
gd::String output =
"gdjs.projectData = " + gd::Serializer::ToJSON(rootElement) + ";\n" +
"gdjs.runtimeGameOptions = " +
gd::Serializer::ToJSON(runtimeGameOptions) + ";\n";
if (!fs.WriteToFile(filename, output)) return "Unable to write " + filename;
return "";
} }
void ExporterHelper::SerializeUsedResources( void ExporterHelper::SerializeUsedResources(
gd::SerializerElement &rootElement, gd::SerializerElement &rootElement,
std::set<gd::String> &projectUsedResources, std::set<gd::String> &projectUsedResources,
std::unordered_map<gd::String, std::set<gd::String>> &scenesUsedResources, std::unordered_map<gd::String, std::set<gd::String>> &scenesUsedResources) {
std::unordered_map<gd::String, std::set<gd::String>>
&eventsBasedObjectVariantsUsedResources) {
auto serializeUsedResources = auto serializeUsedResources =
[](gd::SerializerElement &element, [](gd::SerializerElement &element,
std::set<gd::String> &usedResources) -> void { std::set<gd::String> &usedResources) -> void {
@@ -578,41 +385,6 @@ void ExporterHelper::SerializeUsedResources(
auto &layoutUsedResources = scenesUsedResources[layoutName]; auto &layoutUsedResources = scenesUsedResources[layoutName];
serializeUsedResources(layoutElement, layoutUsedResources); serializeUsedResources(layoutElement, layoutUsedResources);
} }
auto &extensionsElement = rootElement.GetChild("eventsFunctionsExtensions");
for (std::size_t extensionIndex = 0;
extensionIndex < extensionsElement.GetChildrenCount();
extensionIndex++) {
auto &extensionElement = extensionsElement.GetChild(extensionIndex);
const auto extensionName = extensionElement.GetStringAttribute("name");
auto &objectsElement = extensionElement.GetChild("eventsBasedObjects");
for (std::size_t objectIndex = 0;
objectIndex < objectsElement.GetChildrenCount(); objectIndex++) {
auto &objectElement = objectsElement.GetChild(objectIndex);
const auto objectName = objectElement.GetStringAttribute("name");
auto eventsBasedObjectType =
gd::PlatformExtension::GetObjectFullType(extensionName, objectName);
auto &objectUsedResources =
eventsBasedObjectVariantsUsedResources[eventsBasedObjectType];
serializeUsedResources(objectElement, objectUsedResources);
auto &variantsElement = objectElement.GetChild("variants");
for (std::size_t variantIndex = 0;
variantIndex < variantsElement.GetChildrenCount(); variantIndex++) {
auto &variantElement = variantsElement.GetChild(variantIndex);
const auto variantName = variantElement.GetStringAttribute("name");
auto variantType = gd::PlatformExtension::GetVariantFullType(
extensionName, objectName, variantName);
auto &variantUsedResources =
eventsBasedObjectVariantsUsedResources[variantType];
serializeUsedResources(variantElement, variantUsedResources);
}
}
}
} }
bool ExporterHelper::ExportIndexFile( bool ExporterHelper::ExportIndexFile(
@@ -1003,7 +775,7 @@ bool ExporterHelper::CompleteIndexFile(
gd::String codeFilesIncludes; gd::String codeFilesIncludes;
for (auto &include : includesFiles) { for (auto &include : includesFiles) {
gd::String scriptSrc = gd::String scriptSrc =
GetExportedIncludeFilename(fs, gdjsRoot, include, nonRuntimeScriptsCacheBurst); GetExportedIncludeFilename(include, nonRuntimeScriptsCacheBurst);
// Sanity check if the file exists - if not skip it to avoid // Sanity check if the file exists - if not skip it to avoid
// including it in the list of scripts. // including it in the list of scripts.
@@ -1029,7 +801,6 @@ bool ExporterHelper::CompleteIndexFile(
void ExporterHelper::AddLibsInclude(bool pixiRenderers, void ExporterHelper::AddLibsInclude(bool pixiRenderers,
bool pixiInThreeRenderers, bool pixiInThreeRenderers,
bool isInGameEdition,
bool includeWebsocketDebuggerClient, bool includeWebsocketDebuggerClient,
bool includeWindowMessageDebuggerClient, bool includeWindowMessageDebuggerClient,
bool includeMinimalDebuggerClient, bool includeMinimalDebuggerClient,
@@ -1106,7 +877,6 @@ void ExporterHelper::AddLibsInclude(bool pixiRenderers,
InsertUnique(includesFiles, "debugger-client/hot-reloader.js"); InsertUnique(includesFiles, "debugger-client/hot-reloader.js");
InsertUnique(includesFiles, "debugger-client/abstract-debugger-client.js"); InsertUnique(includesFiles, "debugger-client/abstract-debugger-client.js");
InsertUnique(includesFiles, "debugger-client/InGameDebugger.js"); InsertUnique(includesFiles, "debugger-client/InGameDebugger.js");
InsertUnique(includesFiles, "InGameEditor/InGameEditor.js");
} }
if (includeWebsocketDebuggerClient) { if (includeWebsocketDebuggerClient) {
InsertUnique(includesFiles, "debugger-client/websocket-debugger-client.js"); InsertUnique(includesFiles, "debugger-client/websocket-debugger-client.js");
@@ -1119,16 +889,14 @@ void ExporterHelper::AddLibsInclude(bool pixiRenderers,
InsertUnique(includesFiles, "debugger-client/minimal-debugger-client.js"); InsertUnique(includesFiles, "debugger-client/minimal-debugger-client.js");
} }
if (pixiInThreeRenderers || isInGameEdition) { if (pixiInThreeRenderers) {
InsertUnique(includesFiles, "pixi-renderers/three.js"); InsertUnique(includesFiles, "pixi-renderers/three.js");
InsertUnique(includesFiles, "pixi-renderers/ThreeAddons.js"); InsertUnique(includesFiles, "pixi-renderers/ThreeAddons.js");
InsertUnique(includesFiles, "pixi-renderers/draco/gltf/draco_decoder.wasm"); InsertUnique(includesFiles, "pixi-renderers/draco/gltf/draco_decoder.wasm");
InsertUnique(includesFiles, InsertUnique(includesFiles,
"pixi-renderers/draco/gltf/draco_wasm_wrapper.js"); "pixi-renderers/draco/gltf/draco_wasm_wrapper.js");
// Extensions in JS may use it.
InsertUnique(includesFiles, "Extensions/3D/Scene3DTools.js");
} }
if (pixiRenderers || isInGameEdition) { if (pixiRenderers) {
InsertUnique(includesFiles, "pixi-renderers/pixi.js"); InsertUnique(includesFiles, "pixi-renderers/pixi.js");
InsertUnique(includesFiles, "pixi-renderers/pixi-filters-tools.js"); InsertUnique(includesFiles, "pixi-renderers/pixi-filters-tools.js");
InsertUnique(includesFiles, "pixi-renderers/runtimegame-pixi-renderer.js"); InsertUnique(includesFiles, "pixi-renderers/runtimegame-pixi-renderer.js");
@@ -1152,12 +920,7 @@ void ExporterHelper::AddLibsInclude(bool pixiRenderers,
includesFiles, includesFiles,
"fontfaceobserver-font-manager/fontfaceobserver-font-manager.js"); "fontfaceobserver-font-manager/fontfaceobserver-font-manager.js");
} }
if (isInGameEdition) { if (pixiInThreeRenderers) {
// `InGameEditor` uses the `is3D` function.
InsertUnique(includesFiles, "Extensions/3D/Base3DBehavior.js");
InsertUnique(includesFiles, "Extensions/3D/HemisphereLight.js");
}
if (pixiInThreeRenderers || isInGameEdition) {
InsertUnique(includesFiles, "Extensions/3D/A_RuntimeObject3D.js"); InsertUnique(includesFiles, "Extensions/3D/A_RuntimeObject3D.js");
InsertUnique(includesFiles, "Extensions/3D/A_RuntimeObject3DRenderer.js"); InsertUnique(includesFiles, "Extensions/3D/A_RuntimeObject3DRenderer.js");
InsertUnique(includesFiles, "Extensions/3D/CustomRuntimeObject3D.js"); InsertUnique(includesFiles, "Extensions/3D/CustomRuntimeObject3D.js");
@@ -1195,7 +958,7 @@ bool ExporterHelper::ExportEffectIncludes(
return true; return true;
} }
bool ExporterHelper::ExportScenesEventsCode( bool ExporterHelper::ExportEventsCode(
const gd::Project &project, const gd::Project &project,
gd::String outputDir, gd::String outputDir,
std::vector<gd::String> &includesFiles, std::vector<gd::String> &includesFiles,
@@ -1231,7 +994,6 @@ bool ExporterHelper::ExportScenesEventsCode(
} }
gd::String ExporterHelper::GetExportedIncludeFilename( gd::String ExporterHelper::GetExportedIncludeFilename(
gd::AbstractFileSystem &fs, const gd::String &gdjsRoot,
const gd::String &include, unsigned int nonRuntimeScriptsCacheBurst) { const gd::String &include, unsigned int nonRuntimeScriptsCacheBurst) {
auto addSearchParameterToUrl = [](const gd::String &url, auto addSearchParameterToUrl = [](const gd::String &url,
const gd::String &urlEncodedParameterName, const gd::String &urlEncodedParameterName,

View File

@@ -42,9 +42,9 @@ struct PreviewExportOptions {
useWindowMessageDebuggerClient(false), useWindowMessageDebuggerClient(false),
useMinimalDebuggerClient(false), useMinimalDebuggerClient(false),
nativeMobileApp(false), nativeMobileApp(false),
projectDataOnlyExport(false),
fullLoadingScreen(false), fullLoadingScreen(false),
isDevelopmentEnvironment(false), isDevelopmentEnvironment(false),
isInGameEdition(false),
nonRuntimeScriptsCacheBurst(0), nonRuntimeScriptsCacheBurst(0),
inAppTutorialMessageInPreview(""), inAppTutorialMessageInPreview(""),
inAppTutorialMessagePositionInPreview(""), inAppTutorialMessagePositionInPreview(""),
@@ -145,26 +145,6 @@ struct PreviewExportOptions {
return *this; return *this;
} }
/**
* \brief Set the (optional) events-based object to be instantiated in the scene
* at the beginning of the previewed game.
*/
PreviewExportOptions &SetEventsBasedObjectType(
const gd::String &eventsBasedObjectType_) {
eventsBasedObjectType = eventsBasedObjectType_;
return *this;
}
/**
* \brief Set the (optional) events-based object variant to be instantiated in the scene
* at the beginning of the previewed game.
*/
PreviewExportOptions &SetEventsBasedObjectVariantName(
const gd::String &eventsBasedObjectVariantName_) {
eventsBasedObjectVariantName = eventsBasedObjectVariantName_;
return *this;
}
/** /**
* \brief Set the hash associated to an include file. Useful for the preview * \brief Set the hash associated to an include file. Useful for the preview
* hot-reload, to know if a file changed. * hot-reload, to know if a file changed.
@@ -176,34 +156,11 @@ struct PreviewExportOptions {
} }
/** /**
* \brief Set if the exported folder should be cleared befor the export. * \brief Set if the export should only export the project data, not
* exporting events code.
*/ */
PreviewExportOptions &SetShouldClearExportFolder(bool enable) { PreviewExportOptions &SetProjectDataOnlyExport(bool enable) {
shouldClearExportFolder = enable; projectDataOnlyExport = enable;
return *this;
}
/**
* \brief Set if the `ProjectData` must be reloaded.
*/
PreviewExportOptions &SetShouldReloadProjectData(bool enable) {
shouldReloadProjectData = enable;
return *this;
}
/**
* \brief Set if GDJS libraries must be reloaded.
*/
PreviewExportOptions &SetShouldReloadLibraries(bool enable) {
shouldReloadLibraries = enable;
return *this;
}
/**
* \brief Set if the export should export events code.
*/
PreviewExportOptions &SetShouldGenerateScenesEventsCode(bool enable) {
shouldGenerateScenesEventsCode = enable;
return *this; return *this;
} }
@@ -225,40 +182,6 @@ struct PreviewExportOptions {
return *this; return *this;
} }
/**
* \brief Set if the export is made for being edited in the editor.
*/
PreviewExportOptions &SetIsInGameEdition(bool enable) {
isInGameEdition = enable;
return *this;
}
/**
* \brief Set the in-game editor identifier.
*/
PreviewExportOptions &SetEditorId(const gd::String &editorId_) {
editorId = editorId_;
return *this;
}
/**
* \brief Set the camera state to use in the in-game editor.
*/
PreviewExportOptions &
SetEditorCameraState3D(const gd::String &cameraMode, double positionX,
double positionY, double positionZ,
double rotationAngle, double elevationAngle,
double distance) {
editorCamera3DCameraMode = cameraMode;
editorCamera3DPositionX = positionX;
editorCamera3DPositionY = positionY;
editorCamera3DPositionZ = positionZ;
editorCamera3DRotationAngle = rotationAngle;
editorCamera3DElevationAngle = elevationAngle;
editorCamera3DDistance = distance;
return *this;
}
/** /**
* \brief If set to a non zero value, the exported script URLs will have an * \brief If set to a non zero value, the exported script URLs will have an
* extra search parameter added (with the given value) to ensure browser cache * extra search parameter added (with the given value) to ensure browser cache
@@ -371,8 +294,6 @@ struct PreviewExportOptions {
bool useMinimalDebuggerClient; bool useMinimalDebuggerClient;
gd::String layoutName; gd::String layoutName;
gd::String externalLayoutName; gd::String externalLayoutName;
gd::String eventsBasedObjectType;
gd::String eventsBasedObjectVariantName;
gd::String fallbackAuthorUsername; gd::String fallbackAuthorUsername;
gd::String fallbackAuthorId; gd::String fallbackAuthorId;
gd::String playerId; gd::String playerId;
@@ -382,21 +303,9 @@ struct PreviewExportOptions {
gd::String inAppTutorialMessagePositionInPreview; gd::String inAppTutorialMessagePositionInPreview;
bool nativeMobileApp; bool nativeMobileApp;
std::map<gd::String, int> includeFileHashes; std::map<gd::String, int> includeFileHashes;
bool shouldClearExportFolder = true; bool projectDataOnlyExport;
bool shouldReloadProjectData = true;
bool shouldReloadLibraries = true;
bool shouldGenerateScenesEventsCode = true;
bool fullLoadingScreen; bool fullLoadingScreen;
bool isDevelopmentEnvironment; bool isDevelopmentEnvironment;
bool isInGameEdition;
gd::String editorId;
gd::String editorCamera3DCameraMode;
double editorCamera3DPositionX = 0;
double editorCamera3DPositionY = 0;
double editorCamera3DPositionZ = 0;
double editorCamera3DRotationAngle = 0;
double editorCamera3DElevationAngle = 0;
double editorCamera3DDistance = 0;
unsigned int nonRuntimeScriptsCacheBurst; unsigned int nonRuntimeScriptsCacheBurst;
gd::String electronRemoteRequirePath; gd::String electronRemoteRequirePath;
gd::String gdevelopResourceToken; gd::String gdevelopResourceToken;
@@ -470,50 +379,23 @@ class ExporterHelper {
const gd::String &GetLastError() const { return lastError; }; const gd::String &GetLastError() const { return lastError; };
/** /**
* \brief Export a project without its events and options to 2 JS variables * \brief Export a project to JSON
* *
* \param fs The abstract file system to use to write the file * \param fs The abstract file system to use to write the file
* \param project The project to be exported. * \param project The project to be exported.
* \param filename The filename where export the project * \param filename The filename where export the project
* \param runtimeGameOptions The content of the extra configuration to store * \param runtimeGameOptions The content of the extra configuration to store
* in gdjs.runtimeGameOptions * in gdjs.runtimeGameOptions \return Empty string if everything is ok,
*
* \return Empty string if everything is ok,
* description of the error otherwise. * description of the error otherwise.
*/ */
static gd::String static gd::String ExportProjectData(
ExportProjectData(gd::AbstractFileSystem &fs, gd::Project &project, gd::AbstractFileSystem &fs,
gd::String filename, gd::Project &project,
const gd::SerializerElement &runtimeGameOptions); gd::String filename,
const gd::SerializerElement &runtimeGameOptions,
/** std::set<gd::String> &projectUsedResources,
* \brief Serialize a project without its events to JSON std::unordered_map<gd::String, std::set<gd::String>>
* &layersUsedResources);
* \param fs The abstract file system to use to write the file
* \param project The project to be exported.
* \param projectDataElement The element where the project data is serialized
*/
static void SerializeProjectData(gd::AbstractFileSystem &fs,
const gd::Project &project,
const PreviewExportOptions &options,
gd::SerializerElement &projectDataElement);
/**
* \brief Serialize the content of the extra configuration to store
* in gdjs.runtimeGameOptions to JSON
*
* \param fs The abstract file system to use to write the file
* \param options The content of the extra configuration
* \param includesFiles The list of scripts files - useful for hot-reloading
* \param runtimeGameOptionsElement The element where the game options are
* serialized
*/
static void
SerializeRuntimeGameOptions(gd::AbstractFileSystem &fs,
const gd::String &gdjsRoot,
const PreviewExportOptions &options,
std::vector<gd::String> &includesFiles,
gd::SerializerElement &runtimeGameOptionsElement);
/** /**
* \brief Copy all the resources of the project to to the export directory, * \brief Copy all the resources of the project to to the export directory,
@@ -534,7 +416,6 @@ class ExporterHelper {
*/ */
void AddLibsInclude(bool pixiRenderers, void AddLibsInclude(bool pixiRenderers,
bool pixiInThreeRenderers, bool pixiInThreeRenderers,
bool isInGameEdition,
bool includeWebsocketDebuggerClient, bool includeWebsocketDebuggerClient,
bool includeWindowMessageDebuggerClient, bool includeWindowMessageDebuggerClient,
bool includeMinimalDebuggerClient, bool includeMinimalDebuggerClient,
@@ -572,7 +453,7 @@ class ExporterHelper {
* includesFiles A reference to a vector that will be filled with JS files to * includesFiles A reference to a vector that will be filled with JS files to
* be exported along with the project. ( including "codeX.js" files ). * be exported along with the project. ( including "codeX.js" files ).
*/ */
bool ExportScenesEventsCode( bool ExportEventsCode(
const gd::Project &project, const gd::Project &project,
gd::String outputDir, gd::String outputDir,
std::vector<gd::String> &includesFiles, std::vector<gd::String> &includesFiles,
@@ -697,17 +578,14 @@ class ExporterHelper {
* a browser pointing to the preview. * a browser pointing to the preview.
* *
* \param options The options to generate the preview. * \param options The options to generate the preview.
* \param includesFiles The list of scripts files - useful for hot-reloading
*/ */
bool ExportProjectForPixiPreview(const PreviewExportOptions &options, bool ExportProjectForPixiPreview(const PreviewExportOptions &options);
std::vector<gd::String> &includesFiles);
/** /**
* \brief Given an include file, returns the name of the file to reference * \brief Given an include file, returns the name of the file to reference
* in the exported game. * in the exported game.
*/ */
static gd::String GetExportedIncludeFilename( gd::String GetExportedIncludeFilename(
gd::AbstractFileSystem &fs, const gd::String &gdjsRoot,
const gd::String &include, unsigned int nonRuntimeScriptsCacheBurst = 0); const gd::String &include, unsigned int nonRuntimeScriptsCacheBurst = 0);
/** /**
@@ -734,22 +612,11 @@ class ExporterHelper {
///< be then copied to the final output directory. ///< be then copied to the final output directory.
private: private:
static void static void SerializeUsedResources(
SerializeUsedResources(gd::SerializerElement &rootElement, gd::SerializerElement &rootElement,
std::set<gd::String> &projectUsedResources, std::set<gd::String> &projectUsedResources,
std::unordered_map<gd::String, std::set<gd::String>> std::unordered_map<gd::String, std::set<gd::String>>
&layersUsedResources, &layersUsedResources);
std::unordered_map<gd::String, std::set<gd::String>>
&eventsBasedObjectVariantsUsedResources);
/**
* \brief Stript a project and serialize it to JSON
*
* \param project The project to be exported.
*/
static void
StriptAndSerializeProjectData(gd::Project &project,
gd::SerializerElement &rootElement);
}; };
} // namespace gdjs } // namespace gdjs

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