mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
58 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c4e230d9ba | ||
![]() |
56ab2fdd05 | ||
![]() |
872f4032ff | ||
![]() |
428b4c21a8 | ||
![]() |
cb24f191fd | ||
![]() |
994f6bf150 | ||
![]() |
3e2f05460a | ||
![]() |
c775cde9df | ||
![]() |
6ab736a048 | ||
![]() |
f805182ce4 | ||
![]() |
a14f1a187e | ||
![]() |
d08bf97471 | ||
![]() |
093e15e105 | ||
![]() |
60e36f37b1 | ||
![]() |
ad7ce3c725 | ||
![]() |
c6f83f4431 | ||
![]() |
4a685db574 | ||
![]() |
f3dea010fb | ||
![]() |
5025e03dff | ||
![]() |
64771c6faf | ||
![]() |
d4987c4739 | ||
![]() |
56575e7afd | ||
![]() |
9a0df077b3 | ||
![]() |
4bf3ef8ad4 | ||
![]() |
6242e8c97a | ||
![]() |
d6c99b27af | ||
![]() |
7844ee102e | ||
![]() |
7d713d9428 | ||
![]() |
22056d3c08 | ||
![]() |
2ce35a1520 | ||
![]() |
b04c15f23c | ||
![]() |
2ab246696b | ||
![]() |
6b4c00c987 | ||
![]() |
9c4a190a4d | ||
![]() |
1070a489e7 | ||
![]() |
d2a8cb6727 | ||
![]() |
2638c4f593 | ||
![]() |
4be2386efe | ||
![]() |
8be099d50a | ||
![]() |
713698d3d6 | ||
![]() |
8b36908fd8 | ||
![]() |
c0722dc441 | ||
![]() |
9c6a1bed2c | ||
![]() |
a8a4d14ee1 | ||
![]() |
b27abfbe5d | ||
![]() |
28b585aefa | ||
![]() |
0623b6acd9 | ||
![]() |
1a833bc388 | ||
![]() |
827f187e10 | ||
![]() |
0f25b80a66 | ||
![]() |
fbf9710cc5 | ||
![]() |
3d80709029 | ||
![]() |
5ab9c565b0 | ||
![]() |
e237fc4b21 | ||
![]() |
18892f97f3 | ||
![]() |
0ec0654032 | ||
![]() |
8e29c723e8 | ||
![]() |
6acde2865a |
@@ -1358,12 +1358,30 @@ gd::String EventsCodeGenerator::GeneratePropertyGetter(const gd::PropertiesConta
|
||||
return "getProperty" + property.GetName() + "As" + type + "()";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GeneratePropertyGetterWithoutCasting(
|
||||
const gd::PropertiesContainer &propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor &property) {
|
||||
return "getProperty" + property.GetName() + "()";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GeneratePropertySetterWithoutCasting(
|
||||
const gd::PropertiesContainer &propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor &property,
|
||||
const gd::String &operandCode) {
|
||||
return "setProperty" + property.GetName() + "(" + operandCode + ")";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateParameterGetter(const gd::ParameterMetadata& parameter,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
return "getParameter" + parameter.GetName() + "As" + type + "()";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateParameterGetterWithoutCasting(
|
||||
const gd::ParameterMetadata ¶meter) {
|
||||
return "getParameter" + parameter.GetName() + "()";
|
||||
}
|
||||
|
||||
EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
|
||||
const gd::Layout& layout,
|
||||
const gd::Platform& platform_)
|
||||
|
@@ -467,7 +467,14 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
*/
|
||||
virtual gd::String GetCodeNamespace() { return ""; };
|
||||
|
||||
enum VariableScope { LAYOUT_VARIABLE = 0, PROJECT_VARIABLE, OBJECT_VARIABLE, ANY_VARIABLE };
|
||||
enum VariableScope {
|
||||
LAYOUT_VARIABLE = 0,
|
||||
PROJECT_VARIABLE,
|
||||
OBJECT_VARIABLE,
|
||||
ANY_VARIABLE,
|
||||
VARIABLE_OR_PROPERTY,
|
||||
VARIABLE_OR_PROPERTY_OR_PARAMETER
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a single unique number for the specified instruction.
|
||||
@@ -510,6 +517,11 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
GenerateAnyOrSceneVariableGetter(const gd::Expression &variableExpression,
|
||||
EventsCodeGenerationContext &context);
|
||||
|
||||
virtual gd::String GeneratePropertySetterWithoutCasting(
|
||||
const gd::PropertiesContainer &propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor &property,
|
||||
const gd::String &operandCode);
|
||||
|
||||
protected:
|
||||
virtual const gd::String GenerateRelationalOperatorCodes(
|
||||
const gd::String& operatorString);
|
||||
@@ -565,7 +577,8 @@ protected:
|
||||
const gd::String& variableName,
|
||||
const VariableScope& scope,
|
||||
gd::EventsCodeGenerationContext& context,
|
||||
const gd::String& objectName) {
|
||||
const gd::String& objectName,
|
||||
bool hasChild) {
|
||||
// This code is only used as a mock.
|
||||
// See the real implementation in GDJS.
|
||||
if (scope == LAYOUT_VARIABLE) {
|
||||
@@ -573,7 +586,9 @@ protected:
|
||||
|
||||
} else if (scope == PROJECT_VARIABLE) {
|
||||
return "getProjectVariable(" + variableName + ")";
|
||||
} else if (scope == ANY_VARIABLE) {
|
||||
} else if (scope == ANY_VARIABLE || scope == VARIABLE_OR_PROPERTY ||
|
||||
scope == VARIABLE_OR_PROPERTY_OR_PARAMETER) {
|
||||
// TODO Split the 3 cases to make tests stronger.
|
||||
return "getAnyVariable(" + variableName + ")";
|
||||
}
|
||||
|
||||
@@ -627,11 +642,18 @@ protected:
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context);
|
||||
|
||||
virtual gd::String GeneratePropertyGetterWithoutCasting(
|
||||
const gd::PropertiesContainer &propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor &property);
|
||||
|
||||
virtual gd::String GenerateParameterGetter(
|
||||
const gd::ParameterMetadata& parameter,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context);
|
||||
|
||||
virtual gd::String
|
||||
GenerateParameterGetterWithoutCasting(const gd::ParameterMetadata ¶meter);
|
||||
|
||||
/**
|
||||
* \brief Generate the code to reference an object which is
|
||||
* in an empty/null state.
|
||||
|
@@ -135,18 +135,20 @@ void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) {
|
||||
EventsCodeGenerator::VariableScope scope =
|
||||
type == "variable"
|
||||
? gd::EventsCodeGenerator::ANY_VARIABLE
|
||||
: type == "globalvar"
|
||||
? gd::EventsCodeGenerator::PROJECT_VARIABLE
|
||||
: type == "scenevar"
|
||||
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE;
|
||||
: type == "variableOrProperty"
|
||||
? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY
|
||||
: type == "variableOrPropertyOrParameter"
|
||||
? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY_OR_PARAMETER
|
||||
: type == "globalvar" ? gd::EventsCodeGenerator::PROJECT_VARIABLE
|
||||
: type == "scenevar" ? gd::EventsCodeGenerator::LAYOUT_VARIABLE
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE;
|
||||
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
rootObjectName,
|
||||
node);
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.name, scope, context, objectName);
|
||||
node.name, scope, context, objectName, node.child != nullptr);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
} else {
|
||||
// The node represents a variable or an object variable in an expression waiting for its *value* to be returned.
|
||||
@@ -163,7 +165,7 @@ void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) {
|
||||
output += codeGenerator.GenerateVariableValueAs(type);
|
||||
}, [&]() {
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.name, gd::EventsCodeGenerator::ANY_VARIABLE, context, "");
|
||||
node.name, gd::EventsCodeGenerator::ANY_VARIABLE, context, "", node.child != nullptr);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
output += codeGenerator.GenerateVariableValueAs(type);
|
||||
}, [&]() {
|
||||
@@ -184,8 +186,9 @@ void ExpressionCodeGenerator::OnVisitVariableAccessorNode(
|
||||
VariableAccessorNode& node) {
|
||||
if (!objectNameToUseForVariableAccessor.empty()) {
|
||||
// Use the name of the object passed by the parent, as we need both to access an object variable.
|
||||
output += codeGenerator.GenerateGetVariable(node.name,
|
||||
gd::EventsCodeGenerator::OBJECT_VARIABLE, context, objectNameToUseForVariableAccessor);
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.name, gd::EventsCodeGenerator::OBJECT_VARIABLE, context,
|
||||
objectNameToUseForVariableAccessor, node.child != nullptr);
|
||||
|
||||
// We have accessed an object variable, from now we can continue accessing the child variables
|
||||
// (including using the bracket notation).
|
||||
@@ -222,24 +225,27 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
|
||||
output +=
|
||||
codeGenerator.GenerateObject(node.identifierName, type, context);
|
||||
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
EventsCodeGenerator::VariableScope scope =
|
||||
EventsCodeGenerator::VariableScope scope =
|
||||
type == "variable"
|
||||
? gd::EventsCodeGenerator::ANY_VARIABLE
|
||||
: type == "globalvar"
|
||||
? gd::EventsCodeGenerator::PROJECT_VARIABLE
|
||||
: type == "scenevar"
|
||||
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE;
|
||||
: type == "variableOrProperty"
|
||||
? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY
|
||||
: type == "variableOrPropertyOrParameter"
|
||||
? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY_OR_PARAMETER
|
||||
: type == "globalvar" ? gd::EventsCodeGenerator::PROJECT_VARIABLE
|
||||
: type == "scenevar" ? gd::EventsCodeGenerator::LAYOUT_VARIABLE
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE;
|
||||
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
rootObjectName,
|
||||
node);
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.identifierName, scope, context, objectName);
|
||||
if (!node.childIdentifierName.empty()) {
|
||||
output += codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
|
||||
}
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(
|
||||
codeGenerator.GetPlatform(), codeGenerator.GetObjectsContainersList(),
|
||||
rootObjectName, node);
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.identifierName, scope, context, objectName,
|
||||
!node.childIdentifierName.empty());
|
||||
if (!node.childIdentifierName.empty()) {
|
||||
output +=
|
||||
codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
|
||||
}
|
||||
} else {
|
||||
const auto& variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList();
|
||||
const auto& propertiesContainersList = codeGenerator.GetProjectScopedContainers().GetPropertiesContainersList();
|
||||
@@ -249,12 +255,13 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
|
||||
codeGenerator.GetProjectScopedContainers().MatchIdentifierWithName<void>(node.identifierName, [&]() {
|
||||
// Generate the code to access the object variable.
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.childIdentifierName, gd::EventsCodeGenerator::OBJECT_VARIABLE, context, node.identifierName);
|
||||
node.childIdentifierName, gd::EventsCodeGenerator::OBJECT_VARIABLE,
|
||||
context, node.identifierName, !node.childIdentifierName.empty());
|
||||
output += codeGenerator.GenerateVariableValueAs(type);
|
||||
}, [&]() {
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.identifierName, gd::EventsCodeGenerator::ANY_VARIABLE, context,
|
||||
"");
|
||||
node.identifierName, gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY_OR_PARAMETER, context,
|
||||
"", !node.childIdentifierName.empty());
|
||||
if (!node.childIdentifierName.empty()) {
|
||||
output += codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
|
||||
}
|
||||
|
@@ -18,8 +18,6 @@ namespace gd {
|
||||
|
||||
EventsList BaseEvent::badSubEvents;
|
||||
VariablesContainer BaseEvent::badLocalVariables;
|
||||
std::vector<gd::String> BaseEvent::emptyDependencies;
|
||||
gd::String BaseEvent::emptySourceFile;
|
||||
|
||||
BaseEvent::BaseEvent()
|
||||
: totalTimeDuringLastSession(0),
|
||||
|
@@ -175,26 +175,6 @@ class GD_CORE_API BaseEvent {
|
||||
noExpr;
|
||||
return noExpr;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Returns the dependencies on source files of the project.
|
||||
* \note Default implementation returns an empty list of dependencies. This is
|
||||
* fine for most events that are not related to adding custom user source
|
||||
* code.
|
||||
*/
|
||||
virtual const std::vector<gd::String>& GetSourceFileDependencies() const {
|
||||
return emptyDependencies;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Returns the name of the source file associated with the event
|
||||
* \note Default implementation returns an empty string. This is fine for most
|
||||
* events that are not related to adding custom user source code.
|
||||
*/
|
||||
virtual const gd::String& GetAssociatedGDManagedSourceFile(
|
||||
gd::Project& project) const {
|
||||
return emptySourceFile;
|
||||
};
|
||||
///@}
|
||||
|
||||
/** \name Code generation
|
||||
@@ -327,8 +307,6 @@ class GD_CORE_API BaseEvent {
|
||||
|
||||
static gd::EventsList badSubEvents;
|
||||
static gd::VariablesContainer badLocalVariables;
|
||||
static std::vector<gd::String> emptyDependencies;
|
||||
static gd::String emptySourceFile;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -35,7 +35,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
|
||||
"res/conditions/keyboard24.png",
|
||||
"res/conditions/keyboard.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("key", _("Key"));
|
||||
.AddParameter("key", _("Key to check"))
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddCondition("KeyReleased",
|
||||
@@ -46,33 +47,32 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
|
||||
"res/conditions/keyboard24.png",
|
||||
"res/conditions/keyboard.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("key", _("Key"));
|
||||
.AddParameter("key", _("Key to check"))
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddCondition("KeyFromTextPressed",
|
||||
_("Key pressed (text expression)"),
|
||||
_("Check if a key, retrieved from the result of the "
|
||||
"expression, is pressed"),
|
||||
_("Key pressed"),
|
||||
_("Check if a key is pressed"),
|
||||
_("_PARAM1_ key is pressed"),
|
||||
"",
|
||||
"res/conditions/keyboard24.png",
|
||||
"res/conditions/keyboard.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Expression generating the key to check"))
|
||||
.MarkAsAdvanced();
|
||||
.AddParameter("keyboardKey", _("Key to check"))
|
||||
.MarkAsSimple();
|
||||
|
||||
extension
|
||||
.AddCondition("KeyFromTextReleased",
|
||||
_("Key released (text expression)"),
|
||||
_("Check if a key, retrieved from the result of the "
|
||||
"expression, was just released"),
|
||||
_("Key released"),
|
||||
_("Check if a key was just released"),
|
||||
_("_PARAM1_ key is released"),
|
||||
"",
|
||||
"res/conditions/keyboard24.png",
|
||||
"res/conditions/keyboard.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Expression generating the key to check"))
|
||||
.MarkAsAdvanced();
|
||||
.AddParameter("keyboardKey", _("Key to check"))
|
||||
.MarkAsSimple();
|
||||
|
||||
extension
|
||||
.AddCondition("AnyKeyPressed",
|
||||
|
@@ -252,7 +252,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
|
||||
"res/conditions/mouse.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("mouse", _("Button to check"))
|
||||
.MarkAsSimple();
|
||||
.MarkAsSimple()
|
||||
.SetHidden();
|
||||
|
||||
// Support for deprecated names:
|
||||
extension.AddDuplicatedCondition("SourisBouton", "MouseButtonPressed")
|
||||
@@ -262,49 +263,41 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
|
||||
.AddCondition("MouseButtonReleased",
|
||||
_("Mouse button released"),
|
||||
_("Check if the specified mouse button was released."),
|
||||
_("_PARAM1_ mouse button was released"),
|
||||
_("Touch or _PARAM1_ mouse button is released"),
|
||||
"",
|
||||
"res/conditions/mouse24.png",
|
||||
"res/conditions/mouse.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("mouse", _("Button to check"))
|
||||
.MarkAsSimple();
|
||||
.MarkAsSimple()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
"MouseButtonFromTextPressed",
|
||||
_("Mouse button pressed or touch held (text expression)"),
|
||||
_("Check if a mouse button, retrieved from the result of the "
|
||||
"expression, is pressed."),
|
||||
_("_PARAM1_ mouse button is pressed"),
|
||||
_("Mouse button pressed or touch held"),
|
||||
_("Check if the specified mouse button is pressed or "
|
||||
"if a touch is in contact with the screen."),
|
||||
_("Touch or _PARAM1_ mouse button is down"),
|
||||
"",
|
||||
"res/conditions/mouse24.png",
|
||||
"res/conditions/mouse.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("stringWithSelector",
|
||||
_("Expression generating the mouse button to check"),
|
||||
"[\"Left\", \"Right\", \"Middle\"]")
|
||||
.SetParameterLongDescription(
|
||||
_("Possible values are Left, Right and Middle."))
|
||||
.MarkAsAdvanced();
|
||||
.AddParameter("mouseButton", _("Button to check"))
|
||||
.MarkAsSimple();
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
"MouseButtonFromTextReleased",
|
||||
_("Mouse button released (text expression)"),
|
||||
_("Check if a mouse button, retrieved from the result of the "
|
||||
"expression, was just released."),
|
||||
_("_PARAM1_ mouse button is released"),
|
||||
_("Mouse button released"),
|
||||
_("Check if the specified mouse button was released."),
|
||||
_("Touch or _PARAM1_ mouse button is released"),
|
||||
"",
|
||||
"res/conditions/mouse24.png",
|
||||
"res/conditions/mouse.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("stringWithSelector",
|
||||
_("Expression generating the mouse button to check"),
|
||||
"[\"Left\", \"Right\", \"Middle\"]")
|
||||
.SetParameterLongDescription(
|
||||
_("Possible values are Left, Right and Middle."))
|
||||
.MarkAsAdvanced();
|
||||
.AddParameter("mouseButton", _("Button to check"))
|
||||
.MarkAsSimple();
|
||||
|
||||
extension
|
||||
.AddExpressionAndCondition("number",
|
||||
|
@@ -33,7 +33,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"",
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions());
|
||||
|
||||
@@ -45,7 +45,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"",
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string", ParameterOptions::MakeNewOptions());
|
||||
|
||||
@@ -58,7 +58,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"",
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
|
||||
.AddParameter("trueorfalse", _("Check if the value is"))
|
||||
.SetDefaultValue("true")
|
||||
// This parameter allows to keep the operand expression
|
||||
@@ -73,7 +73,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"",
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.AddParameter("variableOrProperty", _("Variable"))
|
||||
.UseStandardOperatorParameters("number",
|
||||
ParameterOptions::MakeNewOptions());
|
||||
|
||||
@@ -85,7 +85,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"",
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.AddParameter("variableOrProperty", _("Variable"))
|
||||
.UseStandardOperatorParameters("string",
|
||||
ParameterOptions::MakeNewOptions());
|
||||
|
||||
@@ -98,7 +98,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"",
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.AddParameter("variableOrProperty", _("Variable"))
|
||||
.AddParameter("operator", _("Value"), "boolean")
|
||||
// This parameter allows to keep the operand expression
|
||||
// when the editor switch between variable instructions.
|
||||
|
@@ -272,7 +272,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
||||
* Check if the behavior is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
bool IsPrivate() const { return isPrivate; }
|
||||
bool IsPrivate() const override { return isPrivate; }
|
||||
|
||||
/**
|
||||
* Set that the behavior is private - it can't be used outside of its
|
||||
|
@@ -174,6 +174,7 @@ public:
|
||||
virtual const gd::String &GetFullName() const = 0;
|
||||
virtual const gd::String &GetDescription() const = 0;
|
||||
virtual const gd::String &GetIconFilename() const = 0;
|
||||
virtual bool IsPrivate() const = 0;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to a map containing the names of the actions
|
||||
|
@@ -46,30 +46,25 @@ ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
const gd::String& fullname_,
|
||||
const gd::String& description_,
|
||||
const gd::String& icon24x24)
|
||||
: ObjectMetadata(extensionNamespace_,
|
||||
name_,
|
||||
fullname_,
|
||||
description_,
|
||||
icon24x24,
|
||||
[]() -> std::unique_ptr<gd::ObjectConfiguration> {
|
||||
gd::LogFatalError(
|
||||
"Error: Event-based objects don't have blueprint. "
|
||||
"This method should never be called.");
|
||||
return nullptr;
|
||||
}) {}
|
||||
: name(name_),
|
||||
iconFilename(icon24x24),
|
||||
extensionNamespace(extensionNamespace_) {
|
||||
SetFullName(gd::String(fullname_));
|
||||
SetDescription(gd::String(description_));
|
||||
}
|
||||
|
||||
ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
const gd::String& name_,
|
||||
const gd::String& fullname_,
|
||||
const gd::String& description_,
|
||||
const gd::String& icon24x24,
|
||||
CreateFunPtr createFunPtrP)
|
||||
: name(name_),
|
||||
iconFilename(icon24x24),
|
||||
createFunPtr(createFunPtrP),
|
||||
extensionNamespace(extensionNamespace_) {
|
||||
SetFullName(gd::String(fullname_));
|
||||
SetDescription(gd::String(description_));
|
||||
CreateFunPtr createFunPtr_)
|
||||
: ObjectMetadata(extensionNamespace_,
|
||||
name_,
|
||||
fullname_,
|
||||
description_,
|
||||
icon24x24) {
|
||||
createFunPtr = createFunPtr_;
|
||||
}
|
||||
|
||||
gd::InstructionMetadata& ObjectMetadata::AddCondition(
|
||||
|
@@ -39,6 +39,8 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
/**
|
||||
* \brief Construct an object metadata, using a "blueprint" object that will
|
||||
* be copied when a new object is requested.
|
||||
*
|
||||
* \note This is used for objects declared in JavaScript extensions.
|
||||
*/
|
||||
ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
const gd::String& name_,
|
||||
@@ -47,9 +49,9 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
const gd::String& icon24x24_,
|
||||
std::shared_ptr<gd::ObjectConfiguration> blueprintObject_);
|
||||
/**
|
||||
* \brief Construct an object metadata, without "blueprint" object
|
||||
* \brief Construct an object metadata.
|
||||
*
|
||||
* \note This is used by events based objects.
|
||||
* \note This is used by events based objects ("custom objects").
|
||||
*/
|
||||
ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
const gd::String& name_,
|
||||
@@ -60,14 +62,17 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
/**
|
||||
* \brief Construct an object metadata, with a function that will be called
|
||||
* to instantiate a new object.
|
||||
*
|
||||
* \note This is used for objects declared in C++ extensions.
|
||||
*/
|
||||
ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
const gd::String& name_,
|
||||
const gd::String& fullname_,
|
||||
const gd::String& description_,
|
||||
const gd::String& icon24x24_,
|
||||
CreateFunPtr createFunPtrP);
|
||||
ObjectMetadata() : createFunPtr(NULL) {}
|
||||
CreateFunPtr createFunPtr_);
|
||||
|
||||
ObjectMetadata() {}
|
||||
virtual ~ObjectMetadata(){};
|
||||
|
||||
/**
|
||||
@@ -300,6 +305,22 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
*/
|
||||
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() override { return strExpressionsInfos; };
|
||||
|
||||
|
||||
/**
|
||||
* Check if the behavior is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
bool IsPrivate() const override { return isPrivate; }
|
||||
|
||||
/**
|
||||
* Set that the behavior is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
ObjectMetadata &SetPrivate() {
|
||||
isPrivate = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the object to be hidden in the IDE.
|
||||
*
|
||||
@@ -344,7 +365,7 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
|
||||
std::vector<gd::String> includeFiles;
|
||||
gd::String className;
|
||||
CreateFunPtr createFunPtr;
|
||||
CreateFunPtr createFunPtr = nullptr;
|
||||
|
||||
private:
|
||||
gd::String extensionNamespace;
|
||||
@@ -356,6 +377,7 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
gd::String iconFilename;
|
||||
gd::String categoryFullName;
|
||||
std::set<gd::String> defaultBehaviorTypes;
|
||||
bool isPrivate = false;
|
||||
bool hidden = false;
|
||||
bool isRenderedIn3D = false;
|
||||
gd::String openFullEditorLabel;
|
||||
|
@@ -33,7 +33,8 @@ void ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
const auto& parameter = parameters.GetParameter(i);
|
||||
if (parameter.GetName().empty()) continue;
|
||||
|
||||
if (gd::ParameterMetadata::IsObject(parameter.GetType())) {
|
||||
auto &valueTypeMetadata = parameter.GetValueTypeMetadata();
|
||||
if (valueTypeMetadata.IsObject()) {
|
||||
const gd::String& objectName = parameter.GetName();
|
||||
const gd::String& objectType = parameter.GetExtraInfo();
|
||||
allObjectNames.insert(objectName);
|
||||
@@ -68,7 +69,7 @@ void ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
// Search "lastObjectName" in the codebase for other place where this
|
||||
// convention is enforced.
|
||||
lastObjectName = objectName;
|
||||
} else if (gd::ParameterMetadata::IsBehavior(parameter.GetType())) {
|
||||
} else if (valueTypeMetadata.IsBehavior()) {
|
||||
if (!lastObjectName.empty()) {
|
||||
if (outputObjectsContainer.HasObjectNamed(lastObjectName)) {
|
||||
const gd::String& behaviorName = parameter.GetName();
|
||||
|
56
Core/GDCore/Extensions/Metadata/SourceFileMetadata.h
Normal file
56
Core/GDCore/Extensions/Metadata/SourceFileMetadata.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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/String.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
namespace gd {
|
||||
/**
|
||||
* \brief Contains information about a source file that must be included
|
||||
* when an extension is used.
|
||||
*/
|
||||
class GD_CORE_API SourceFileMetadata {
|
||||
public:
|
||||
/**
|
||||
* Construct a new dependency metadata, though you probably want to call
|
||||
* `AddSourceFile` on gd::PlatformExtension.
|
||||
*
|
||||
* \see gd::PlatformExtension
|
||||
*/
|
||||
SourceFileMetadata() {};
|
||||
|
||||
SourceFileMetadata& SetResourceName(const gd::String& resourceName_) {
|
||||
resourceName = resourceName_;
|
||||
return *this;
|
||||
};
|
||||
|
||||
SourceFileMetadata& SetIncludePosition(const gd::String& includePosition_) {
|
||||
includePosition = includePosition_;
|
||||
return *this;
|
||||
};
|
||||
|
||||
const gd::String& GetResourceName() const { return resourceName; };
|
||||
|
||||
gd::String& GetResourceName() { return resourceName; };
|
||||
|
||||
const gd::String& GetIncludePosition() const { return includePosition; };
|
||||
|
||||
void SerializeTo(SerializerElement& element) const {
|
||||
element.AddChild("resourceName").SetStringValue(resourceName);
|
||||
element.AddChild("includePosition").SetStringValue(includePosition);
|
||||
}
|
||||
|
||||
void UnserializeFrom(const SerializerElement& element) {
|
||||
resourceName = element.GetStringAttribute("resourceName");
|
||||
includePosition = element.GetStringAttribute("includePosition", "last");
|
||||
}
|
||||
|
||||
private:
|
||||
gd::String resourceName; ///< The name of the resource in the project.
|
||||
gd::String includePosition = "last"; ///< "first" or "last".
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -79,6 +79,8 @@ const gd::String ValueTypeMetadata::colorValueType = "color";
|
||||
const gd::String ValueTypeMetadata::choiceValueType = "stringWithSelector";
|
||||
const gd::String ValueTypeMetadata::behaviorValueType = "behavior";
|
||||
const gd::String ValueTypeMetadata::leaderboardIdValueType = "leaderboardId";
|
||||
const gd::String ValueTypeMetadata::objectAnimationNameValueType = "objectAnimationName";
|
||||
const gd::String ValueTypeMetadata::keyboardKeyValueType = "keyboardKey";
|
||||
|
||||
const gd::String &ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
const gd::String &propertyType) {
|
||||
@@ -94,8 +96,12 @@ const gd::String &ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
return behaviorValueType;
|
||||
} else if (propertyType == "LeaderboardId") {
|
||||
return leaderboardIdValueType;
|
||||
} else if (propertyType == "ObjectAnimationName") {
|
||||
return objectAnimationNameValueType;
|
||||
} else if (propertyType == "KeyboardKey") {
|
||||
return keyboardKeyValueType;
|
||||
}
|
||||
// For "String" or default
|
||||
// For "String", "Resource" or default
|
||||
return stringValueType;
|
||||
};
|
||||
|
||||
|
@@ -129,7 +129,7 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type of the parameter is a number.
|
||||
* \brief Return true if the type of the parameter is a variable.
|
||||
* \note If you had a new type of parameter, also add it in the IDE (
|
||||
* see EventsFunctionParametersEditor, ParameterRenderingService
|
||||
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
|
||||
@@ -148,6 +148,19 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
return gd::ValueTypeMetadata::GetPrimitiveValueType(type) == "variable";
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type of the parameter is a variable and not a
|
||||
* property or a parameter.
|
||||
*/
|
||||
bool IsVariableOnly() const {
|
||||
return
|
||||
// Any variable.
|
||||
name == "variable" ||
|
||||
// Old, "pre-scoped" variables:
|
||||
name == "objectvar" || name == "globalvar" ||
|
||||
name == "scenevar";
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is a variable but from a specific scope
|
||||
* (scene, project or object). In new code, prefer to use the more generic "variable"
|
||||
@@ -212,15 +225,20 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
parameterType == "functionParameterName" ||
|
||||
parameterType == "externalLayoutName" ||
|
||||
parameterType == "leaderboardId" ||
|
||||
parameterType == "keyboardKey" ||
|
||||
parameterType == "mouseButton" ||
|
||||
parameterType == "identifier";
|
||||
} else if (type == "boolean") {
|
||||
return parameterType == "yesorno" || parameterType == "trueorfalse";
|
||||
} else if (type == "variable") {
|
||||
return
|
||||
parameterType == "variable" || // Any variable.
|
||||
// Old, "pre-scoped" variables:
|
||||
parameterType == "objectvar" || parameterType == "globalvar" ||
|
||||
parameterType == "scenevar";
|
||||
// Any variable.
|
||||
parameterType == "variable" ||
|
||||
parameterType == "variableOrProperty" ||
|
||||
parameterType == "variableOrPropertyOrParameter" ||
|
||||
// Old, "pre-scoped" variables:
|
||||
parameterType == "objectvar" || parameterType == "globalvar" ||
|
||||
parameterType == "scenevar";
|
||||
} else if (type == "resource") {
|
||||
return parameterType == "fontResource" ||
|
||||
parameterType == "audioResource" ||
|
||||
@@ -316,6 +334,8 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
static const gd::String choiceValueType;
|
||||
static const gd::String behaviorValueType;
|
||||
static const gd::String leaderboardIdValueType;
|
||||
static const gd::String objectAnimationNameValueType;
|
||||
static const gd::String keyboardKeyValueType;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -38,12 +38,14 @@ bool Platform::AddExtension(std::shared_ptr<gd::PlatformExtension> extension) {
|
||||
|
||||
extensionsLoaded.push_back(extension);
|
||||
|
||||
// Load all creation/destruction functions for objects provided by the
|
||||
// extension
|
||||
// Load all creation functions for objects provided by the
|
||||
// extension.
|
||||
vector<gd::String> objectsTypes = extension->GetExtensionObjectsTypes();
|
||||
for (std::size_t i = 0; i < objectsTypes.size(); ++i) {
|
||||
creationFunctionTable[objectsTypes[i]] =
|
||||
extension->GetObjectCreationFunctionPtr(objectsTypes[i]);
|
||||
CreateFunPtr createFunPtr = extension->GetObjectCreationFunctionPtr(objectsTypes[i]);
|
||||
if (createFunPtr != nullptr) {
|
||||
creationFunctionTable[objectsTypes[i]] = createFunPtr;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& it :
|
||||
@@ -62,7 +64,9 @@ void Platform::RemoveExtension(const gd::String& name) {
|
||||
if (extension->GetName() == name) {
|
||||
vector<gd::String> objectsTypes = extension->GetExtensionObjectsTypes();
|
||||
for (std::size_t i = 0; i < objectsTypes.size(); ++i) {
|
||||
creationFunctionTable.erase(objectsTypes[i]);
|
||||
if (creationFunctionTable.find(objectsTypes[i]) != creationFunctionTable.end()) {
|
||||
creationFunctionTable.erase(objectsTypes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -215,6 +215,11 @@ gd::DependencyMetadata& PlatformExtension::AddDependency() {
|
||||
return extensionDependenciesMetadata.back();
|
||||
}
|
||||
|
||||
gd::SourceFileMetadata& PlatformExtension::AddSourceFile() {
|
||||
extensionSourceFilesMetadata.push_back(SourceFileMetadata());
|
||||
return extensionSourceFilesMetadata.back();
|
||||
}
|
||||
|
||||
gd::ObjectMetadata& PlatformExtension::AddObject(
|
||||
const gd::String& name,
|
||||
const gd::String& fullname,
|
||||
@@ -463,10 +468,22 @@ PlatformExtension::GetAllStrExpressions() {
|
||||
return strExpressionsInfos;
|
||||
}
|
||||
|
||||
const std::vector<gd::DependencyMetadata>& PlatformExtension::GetAllDependencies() const {
|
||||
return extensionDependenciesMetadata;
|
||||
}
|
||||
|
||||
std::vector<gd::DependencyMetadata>& PlatformExtension::GetAllDependencies() {
|
||||
return extensionDependenciesMetadata;
|
||||
}
|
||||
|
||||
const std::vector<gd::SourceFileMetadata>& PlatformExtension::GetAllSourceFiles() const {
|
||||
return extensionSourceFilesMetadata;
|
||||
}
|
||||
|
||||
std::vector<gd::SourceFileMetadata>& PlatformExtension::GetAllSourceFiles() {
|
||||
return extensionSourceFilesMetadata;
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::EventMetadata>& PlatformExtension::GetAllEvents() {
|
||||
return eventsInfos;
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/DependencyMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/SourceFileMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/EffectMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/EventMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionOrExpressionGroupMetadata.h"
|
||||
@@ -214,6 +215,7 @@ class GD_CORE_API PlatformExtension {
|
||||
const gd::String& icon);
|
||||
|
||||
gd::DependencyMetadata& AddDependency();
|
||||
gd::SourceFileMetadata& AddSourceFile();
|
||||
|
||||
/**
|
||||
* \brief Declare a new object as being part of the extension.
|
||||
@@ -552,6 +554,24 @@ class GD_CORE_API PlatformExtension {
|
||||
*/
|
||||
std::vector<gd::DependencyMetadata>& GetAllDependencies();
|
||||
|
||||
/**
|
||||
* \brief Return a reference to a vector containing the metadata of all the
|
||||
* dependencies of the extension.
|
||||
*/
|
||||
const std::vector<gd::DependencyMetadata>& GetAllDependencies() const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to a vector containing the metadata of all the
|
||||
* dependencies of the extension.
|
||||
*/
|
||||
std::vector<gd::SourceFileMetadata>& GetAllSourceFiles();
|
||||
|
||||
/**
|
||||
* \brief Return a reference to a vector containing the metadata of all the
|
||||
* dependencies of the extension.
|
||||
*/
|
||||
const std::vector<gd::SourceFileMetadata>& GetAllSourceFiles() const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to a map containing the names of the actions,
|
||||
* related to the object type, and the metadata associated with.
|
||||
@@ -687,6 +707,7 @@ class GD_CORE_API PlatformExtension {
|
||||
std::map<gd::String, gd::ExpressionMetadata> expressionsInfos;
|
||||
std::map<gd::String, gd::ExpressionMetadata> strExpressionsInfos;
|
||||
std::vector<gd::DependencyMetadata> extensionDependenciesMetadata;
|
||||
std::vector<gd::SourceFileMetadata> extensionSourceFilesMetadata;
|
||||
std::map<gd::String, gd::EventMetadata> eventsInfos;
|
||||
std::map<gd::String, gd::PropertyDescriptor> extensionPropertiesMetadata;
|
||||
std::map<gd::String, InstructionOrExpressionGroupMetadata>
|
||||
|
@@ -12,7 +12,6 @@
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/SourceFile.h"
|
||||
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(const gd::Project& project_,
|
||||
const gd::Layout& layout_)
|
||||
@@ -74,16 +73,6 @@ bool DependenciesAnalyzer::Analyze(const gd::EventsList& events) {
|
||||
}
|
||||
}
|
||||
|
||||
// Search for source files dependencies
|
||||
std::vector<gd::String> dependencies =
|
||||
events[i].GetSourceFileDependencies();
|
||||
sourceFilesDependencies.insert(dependencies.begin(), dependencies.end());
|
||||
|
||||
const gd::String& associatedSourceFile =
|
||||
events[i].GetAssociatedGDManagedSourceFile(const_cast<gd::Project&>(project));
|
||||
if (!associatedSourceFile.empty())
|
||||
sourceFilesDependencies.insert(associatedSourceFile);
|
||||
|
||||
// Analyze sub events dependencies
|
||||
if (events[i].CanHaveSubEvents()) {
|
||||
if (!Analyze(events[i].GetSubEvents())) return false;
|
||||
|
@@ -71,14 +71,6 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
return externalEventsDependencies;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Return the source files being dependencies of the scene or external
|
||||
* events passed in the constructor.
|
||||
*/
|
||||
const std::set<gd::String>& GetSourceFilesDependencies() const {
|
||||
return sourceFilesDependencies;
|
||||
};
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Analyze the dependencies of the events.
|
||||
@@ -92,7 +84,6 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
|
||||
std::set<gd::String> scenesDependencies;
|
||||
std::set<gd::String> externalEventsDependencies;
|
||||
std::set<gd::String> sourceFilesDependencies;
|
||||
std::vector<gd::String>
|
||||
parentScenes; ///< Used to check for circular dependencies.
|
||||
std::vector<gd::String>
|
||||
|
@@ -141,7 +141,7 @@ class GD_CORE_API ExpressionParameterReplacer
|
||||
parameterMetadata->GetValueTypeMetadata();
|
||||
if (gd::EventsParameterReplacer::CanContainParameter(
|
||||
parameterTypeMetadata)) {
|
||||
isParentTypeAVariable = parameterTypeMetadata.IsVariable();
|
||||
isParentTypeAVariable = parameterTypeMetadata.IsVariableOnly();
|
||||
parameter->Visit(*this);
|
||||
}
|
||||
}
|
||||
@@ -197,7 +197,7 @@ bool EventsParameterReplacer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
if (node) {
|
||||
ExpressionParameterReplacer renamer(
|
||||
platform, GetProjectScopedContainers(),
|
||||
parameterMetadata.GetValueTypeMetadata().IsVariable(),
|
||||
parameterMetadata.GetValueTypeMetadata().IsVariableOnly(),
|
||||
oldToNewPropertyNames);
|
||||
node->Visit(renamer);
|
||||
|
||||
@@ -221,7 +221,7 @@ bool EventsParameterReplacer::DoVisitEventExpression(
|
||||
if (node) {
|
||||
ExpressionParameterReplacer renamer(
|
||||
platform, GetProjectScopedContainers(),
|
||||
metadata.GetValueTypeMetadata().IsVariable(), oldToNewPropertyNames);
|
||||
metadata.GetValueTypeMetadata().IsVariableOnly(), oldToNewPropertyNames);
|
||||
node->Visit(renamer);
|
||||
|
||||
if (renamer.HasDoneRenaming()) {
|
||||
|
@@ -168,7 +168,7 @@ class GD_CORE_API ExpressionPropertyReplacer
|
||||
parameterMetadata->GetValueTypeMetadata();
|
||||
if (gd::EventsPropertyReplacer::CanContainProperty(
|
||||
parameterTypeMetadata)) {
|
||||
isParentTypeAVariable = parameterTypeMetadata.IsVariable();
|
||||
isParentTypeAVariable = parameterTypeMetadata.IsVariableOnly();
|
||||
parameter->Visit(*this);
|
||||
}
|
||||
}
|
||||
@@ -231,7 +231,7 @@ bool EventsPropertyReplacer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
if (node) {
|
||||
ExpressionPropertyReplacer renamer(
|
||||
platform, GetProjectScopedContainers(), targetPropertiesContainer,
|
||||
parameterMetadata.GetValueTypeMetadata().IsVariable(),
|
||||
parameterMetadata.GetValueTypeMetadata().IsVariableOnly(),
|
||||
oldToNewPropertyNames, removedPropertyNames);
|
||||
node->Visit(renamer);
|
||||
|
||||
@@ -257,7 +257,7 @@ bool EventsPropertyReplacer::DoVisitEventExpression(
|
||||
if (node) {
|
||||
ExpressionPropertyReplacer renamer(
|
||||
platform, GetProjectScopedContainers(), targetPropertiesContainer,
|
||||
metadata.GetValueTypeMetadata().IsVariable(), oldToNewPropertyNames,
|
||||
metadata.GetValueTypeMetadata().IsVariableOnly(), oldToNewPropertyNames,
|
||||
removedPropertyNames);
|
||||
node->Visit(renamer);
|
||||
|
||||
|
@@ -71,13 +71,18 @@ bool EventsVariableInstructionTypeSwitcher::DoVisitInstruction(gd::Instruction&
|
||||
.GetObjectsContainersList()
|
||||
.GetObjectOrGroupVariablesContainer(lastObjectName);
|
||||
}
|
||||
} else if (type == "variableOrProperty") {
|
||||
variablesContainer =
|
||||
&GetProjectScopedContainers()
|
||||
.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableOrPropertyName(variableName);
|
||||
} else {
|
||||
if (GetProjectScopedContainers().GetVariablesContainersList().Has(
|
||||
variableName)) {
|
||||
variablesContainer =
|
||||
&GetProjectScopedContainers()
|
||||
.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(variableName);
|
||||
.GetVariablesContainerFromVariableOrPropertyOrParameterName(variableName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -122,7 +122,7 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
[&]() {
|
||||
// This is a variable.
|
||||
if (&projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(node.name) ==
|
||||
.GetVariablesContainerFromVariableOrPropertyOrParameterName(node.name) ==
|
||||
&targetVariablesContainer) {
|
||||
// The node represents a variable, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
@@ -235,7 +235,7 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
[&]() {
|
||||
// This is a variable.
|
||||
if (&projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(
|
||||
.GetVariablesContainerFromVariableOrPropertyOrParameterName(
|
||||
node.identifierName) == &targetVariablesContainer) {
|
||||
// The node represents a variable, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
|
@@ -1034,7 +1034,7 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
description.SetVariableType(variable.GetType());
|
||||
description.SetVariableScope(
|
||||
projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(variableName)
|
||||
.GetVariablesContainerFromVariableOrPropertyOrParameterName(variableName)
|
||||
.GetSourceType());
|
||||
completions.push_back(description);
|
||||
|
||||
@@ -1086,7 +1086,7 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
description.SetVariableType(variable.GetType());
|
||||
description.SetVariableScope(
|
||||
projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(variableName)
|
||||
.GetVariablesContainerFromVariableOrPropertyOrParameterName(variableName)
|
||||
.GetSourceType());
|
||||
completions.push_back(description);
|
||||
|
||||
|
@@ -460,10 +460,12 @@ const gd::String& ExpressionValidator::TypeToString(Type type) {
|
||||
case Type::NumberOrString:
|
||||
return numberOrStringTypeString;
|
||||
case Type::Variable:
|
||||
return variableTypeString;
|
||||
// This function is only used to display errors.
|
||||
// Users don't care if it's legacy or not or
|
||||
// if it allows properties and parameters.
|
||||
case Type::VariableOrProperty:
|
||||
case Type::VariableOrPropertyOrParameter:
|
||||
case Type::LegacyVariable:
|
||||
// This function is only used to display error.
|
||||
// Users don't care if it's legacy or not.
|
||||
return variableTypeString;
|
||||
case Type::Object:
|
||||
return objectTypeString;
|
||||
@@ -493,8 +495,11 @@ ExpressionValidator::Type ExpressionValidator::StringToType(
|
||||
ExpressionValidator::variableTypeString, type)) {
|
||||
if (gd::ValueTypeMetadata::IsTypeLegacyPreScopedVariable(type)) {
|
||||
return Type::LegacyVariable;
|
||||
}
|
||||
else {
|
||||
} else if (type == "variableOrProperty") {
|
||||
return Type::VariableOrProperty;
|
||||
} else if (type == "variableOrPropertyOrParameter") {
|
||||
return Type::VariableOrPropertyOrParameter;
|
||||
} else {
|
||||
return Type::Variable;
|
||||
}
|
||||
}
|
||||
|
@@ -203,10 +203,12 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
ReportAnyError(node);
|
||||
|
||||
if (parentType == Type::Variable) {
|
||||
if (parentType == Type::Variable ||
|
||||
parentType == Type::VariableOrProperty ||
|
||||
parentType == Type::VariableOrPropertyOrParameter) {
|
||||
childType = parentType;
|
||||
|
||||
CheckVariableExistence(node.location, node.name);
|
||||
CheckVariableExistence(node.location, node.name, node.child != nullptr);
|
||||
if (node.child) {
|
||||
node.child->Visit(*this);
|
||||
}
|
||||
@@ -216,7 +218,8 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
if (node.child) {
|
||||
node.child->Visit(*this);
|
||||
}
|
||||
} else if (parentType == Type::String || parentType == Type::Number || parentType == Type::NumberOrString) {
|
||||
} else if (parentType == Type::String || parentType == Type::Number ||
|
||||
parentType == Type::NumberOrString) {
|
||||
// The node represents a variable or an object variable in an expression waiting for its *value* to be returned.
|
||||
childType = parentType;
|
||||
|
||||
@@ -336,11 +339,12 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
_("You must enter a number or a text, wrapped inside double quotes (example: \"Hello world\"), or a variable name."),
|
||||
node.location);
|
||||
}
|
||||
}
|
||||
else if (parentType == Type::Variable) {
|
||||
CheckVariableExistence(node.location, node.identifierName);
|
||||
}
|
||||
else if (parentType != Type::Object && parentType != Type::LegacyVariable) {
|
||||
} else if (parentType == Type::Variable ||
|
||||
parentType == Type::VariableOrProperty ||
|
||||
parentType == Type::VariableOrPropertyOrParameter) {
|
||||
CheckVariableExistence(node.location, node.identifierName, !node.childIdentifierName.empty());
|
||||
} else if (parentType != Type::Object &&
|
||||
parentType != Type::LegacyVariable) {
|
||||
// It can't happen.
|
||||
RaiseTypeError(
|
||||
_("You've entered a name, but this type was expected:") + " " + TypeToString(parentType),
|
||||
@@ -376,8 +380,19 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
childType = Type::Empty;
|
||||
}
|
||||
|
||||
private:
|
||||
enum Type {Unknown = 0, Number, String, NumberOrString, Variable, LegacyVariable, Object, Empty};
|
||||
private:
|
||||
enum Type {
|
||||
Unknown = 0,
|
||||
Number,
|
||||
String,
|
||||
NumberOrString,
|
||||
Variable,
|
||||
LegacyVariable,
|
||||
Object,
|
||||
Empty,
|
||||
VariableOrProperty,
|
||||
VariableOrPropertyOrParameter
|
||||
};
|
||||
Type ValidateFunction(const gd::FunctionCallNode& function);
|
||||
bool ValidateObjectVariableOrVariableOrProperty(const gd::IdentifierNode& identifier);
|
||||
bool ValidateObjectVariableOrVariableOrProperty(
|
||||
@@ -386,8 +401,10 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
const gd::String &childIdentifierName,
|
||||
const gd::ExpressionParserLocation childIdentifierNameLocation);
|
||||
|
||||
void CheckVariableExistence(const ExpressionParserLocation &location, const gd::String& name) {
|
||||
if (!currentParameterExtraInfo || *currentParameterExtraInfo != "AllowUndeclaredVariable") {
|
||||
void CheckVariableExistence(const ExpressionParserLocation &location,
|
||||
const gd::String &name, bool hasChild) {
|
||||
if (!currentParameterExtraInfo ||
|
||||
*currentParameterExtraInfo != "AllowUndeclaredVariable") {
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(
|
||||
name,
|
||||
[&]() {
|
||||
@@ -402,19 +419,28 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
},
|
||||
[&]() {
|
||||
// This is a property.
|
||||
// This error won't happen unless the priority is changed.
|
||||
RaiseVariableNameCollisionError(
|
||||
_("This variable has the same name as a property. Consider "
|
||||
"renaming one or the other."),
|
||||
location, name);
|
||||
if (parentType != Type::VariableOrProperty &&
|
||||
parentType != Type::VariableOrPropertyOrParameter) {
|
||||
RaiseVariableNameCollisionError(
|
||||
_("This variable has the same name as a property. Consider "
|
||||
"renaming one or the other."),
|
||||
location, name);
|
||||
} else if (hasChild) {
|
||||
RaiseMalformedVariableParameter(
|
||||
_("Properties can't have children."), location, name);
|
||||
}
|
||||
},
|
||||
[&]() {
|
||||
// This is a parameter.
|
||||
// This error won't happen unless the priority is changed.
|
||||
RaiseVariableNameCollisionError(
|
||||
_("This variable has the same name as a parameter. Consider "
|
||||
"renaming one or the other."),
|
||||
location, name);
|
||||
if (parentType != Type::VariableOrPropertyOrParameter) {
|
||||
RaiseVariableNameCollisionError(
|
||||
_("This variable has the same name as a parameter. Consider "
|
||||
"renaming one or the other."),
|
||||
location, name);
|
||||
} else if (hasChild) {
|
||||
RaiseMalformedVariableParameter(
|
||||
_("Properties can't have children."), location, name);
|
||||
}
|
||||
},
|
||||
[&]() {
|
||||
// This is something else.
|
||||
@@ -476,6 +502,13 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
message, location, false, variableName, objectName);
|
||||
}
|
||||
|
||||
void RaiseMalformedVariableParameter(const gd::String &message,
|
||||
const ExpressionParserLocation &location,
|
||||
const gd::String &variableName) {
|
||||
RaiseError(gd::ExpressionParserError::ErrorType::MalformedVariableParameter,
|
||||
message, location, true, variableName, "");
|
||||
}
|
||||
|
||||
void RaiseTypeError(const gd::String &message,
|
||||
const ExpressionParserLocation &location,
|
||||
bool isFatal = true) {
|
||||
|
@@ -215,7 +215,7 @@ class GD_CORE_API ExpressionVariablePathFinder
|
||||
if (projectScopedContainers.GetVariablesContainersList().Has(identifier)) {
|
||||
variablesContainer =
|
||||
&(projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(identifier));
|
||||
.GetVariablesContainerFromVariableOrPropertyOrParameterName(identifier));
|
||||
variableName = identifier;
|
||||
if (childIdentifier) {
|
||||
childVariableNames.push_back(*childIdentifier);
|
||||
@@ -223,12 +223,28 @@ class GD_CORE_API ExpressionVariablePathFinder
|
||||
}
|
||||
},
|
||||
[&]() {
|
||||
// Ignore properties here.
|
||||
// There is no support for "children" of properties.
|
||||
// This is a property.
|
||||
if (parameterType != "objectvar" &&
|
||||
projectScopedContainers.GetVariablesContainersList().Has(
|
||||
identifier)) {
|
||||
variablesContainer =
|
||||
&(projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableOrPropertyOrParameterName(identifier));
|
||||
variableName = identifier;
|
||||
// There is no support for "children" of properties.
|
||||
}
|
||||
},
|
||||
[&]() {
|
||||
// Ignore parameters here.
|
||||
// There is no support for "children" of parameters.
|
||||
// This is a parameter.
|
||||
if (parameterType != "objectvar" &&
|
||||
projectScopedContainers.GetVariablesContainersList().Has(
|
||||
identifier)) {
|
||||
variablesContainer =
|
||||
&(projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableOrPropertyOrParameterName(identifier));
|
||||
variableName = identifier;
|
||||
// There is no support for "children" of parameters.
|
||||
}
|
||||
},
|
||||
[&]() {
|
||||
// Ignore unrecognised identifiers here.
|
||||
|
@@ -13,6 +13,18 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
void UsedExtensionsResult::AddUsedExtension(const gd::PlatformExtension& extension) {
|
||||
usedExtensions.insert(extension.GetName());
|
||||
|
||||
usedSourceFiles.insert(usedSourceFiles.end(),
|
||||
extension.GetAllSourceFiles().begin(),
|
||||
extension.GetAllSourceFiles().end());
|
||||
}
|
||||
|
||||
void UsedExtensionsResult::AddUsedBuiltinExtension(const gd::String& extensionName) {
|
||||
usedExtensions.insert(extensionName);
|
||||
}
|
||||
|
||||
const UsedExtensionsResult UsedExtensionsFinder::ScanProject(gd::Project& project) {
|
||||
UsedExtensionsFinder worker(project);
|
||||
gd::ProjectBrowserHelper::ExposeProjectObjects(project, worker);
|
||||
@@ -28,9 +40,9 @@ void UsedExtensionsFinder::DoVisitObject(gd::Object &object) {
|
||||
if (metadata.GetMetadata().IsRenderedIn3D()) {
|
||||
result.MarkAsHaving3DObjects();
|
||||
}
|
||||
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||
result.AddUsedExtension(metadata.GetExtension());
|
||||
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
|
||||
result.GetUsedIncludeFiles().insert(includeFile);
|
||||
result.AddUsedIncludeFiles(includeFile);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,12 +51,12 @@ void UsedExtensionsFinder::DoVisitObject(gd::Object &object) {
|
||||
void UsedExtensionsFinder::DoVisitBehavior(gd::Behavior &behavior) {
|
||||
auto metadata = gd::MetadataProvider::GetExtensionAndBehaviorMetadata(
|
||||
project.GetCurrentPlatform(), behavior.GetTypeName());
|
||||
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||
result.AddUsedExtension(metadata.GetExtension());
|
||||
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
|
||||
result.GetUsedIncludeFiles().insert(includeFile);
|
||||
result.AddUsedIncludeFiles(includeFile);
|
||||
}
|
||||
for (auto &&includeFile : metadata.GetMetadata().requiredFiles) {
|
||||
result.GetUsedRequiredFiles().insert(includeFile);
|
||||
result.AddUsedRequiredFiles(includeFile);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -57,9 +69,9 @@ bool UsedExtensionsFinder::DoVisitInstruction(gd::Instruction& instruction,
|
||||
project.GetCurrentPlatform(), instruction.GetType())
|
||||
: gd::MetadataProvider::GetExtensionAndActionMetadata(
|
||||
project.GetCurrentPlatform(), instruction.GetType());
|
||||
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||
result.AddUsedExtension(metadata.GetExtension());
|
||||
for (auto&& includeFile : metadata.GetMetadata().GetIncludeFiles()) {
|
||||
result.GetUsedIncludeFiles().insert(includeFile);
|
||||
result.AddUsedIncludeFiles(includeFile);
|
||||
}
|
||||
|
||||
gd::ParameterMetadataTools::IterateOverParameters(
|
||||
@@ -77,7 +89,7 @@ bool UsedExtensionsFinder::DoVisitInstruction(gd::Instruction& instruction,
|
||||
rootType = "number";
|
||||
parameterValue.GetRootNode()->Visit(*this);
|
||||
} else if (gd::ParameterMetadata::IsExpression("variable", parameterType))
|
||||
result.GetUsedExtensions().insert("BuiltinVariables");
|
||||
result.AddUsedBuiltinExtension("BuiltinVariables");
|
||||
});
|
||||
|
||||
return false;
|
||||
@@ -110,7 +122,7 @@ void UsedExtensionsFinder::OnVisitUnaryOperatorNode(UnaryOperatorNode& node) {
|
||||
|
||||
// Add variable extension and visit sub-expressions on variable nodes
|
||||
void UsedExtensionsFinder::OnVisitVariableNode(VariableNode& node) {
|
||||
result.GetUsedExtensions().insert("BuiltinVariables");
|
||||
result.AddUsedBuiltinExtension("BuiltinVariables");
|
||||
|
||||
auto type = gd::ExpressionTypeFinder::GetType(
|
||||
project.GetCurrentPlatform(), GetProjectScopedContainers(), rootType, node);
|
||||
@@ -123,9 +135,9 @@ void UsedExtensionsFinder::OnVisitVariableNode(VariableNode& node) {
|
||||
// This represents an object.
|
||||
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
|
||||
project.GetCurrentPlatform(), node.name);
|
||||
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||
result.AddUsedExtension(metadata.GetExtension());
|
||||
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
|
||||
result.GetUsedIncludeFiles().insert(includeFile);
|
||||
result.AddUsedIncludeFiles(includeFile);
|
||||
}
|
||||
}, [&]() {
|
||||
// This is a variable.
|
||||
@@ -143,13 +155,13 @@ void UsedExtensionsFinder::OnVisitVariableNode(VariableNode& node) {
|
||||
|
||||
void UsedExtensionsFinder::OnVisitVariableAccessorNode(
|
||||
VariableAccessorNode& node) {
|
||||
result.GetUsedExtensions().insert("BuiltinVariables");
|
||||
result.AddUsedBuiltinExtension("BuiltinVariables");
|
||||
if (node.child) node.child->Visit(*this);
|
||||
};
|
||||
|
||||
void UsedExtensionsFinder::OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) {
|
||||
result.GetUsedExtensions().insert("BuiltinVariables");
|
||||
result.AddUsedBuiltinExtension("BuiltinVariables");
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
};
|
||||
@@ -163,9 +175,9 @@ void UsedExtensionsFinder::OnVisitIdentifierNode(IdentifierNode &node) {
|
||||
// An object or object variable is used.
|
||||
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
|
||||
project.GetCurrentPlatform(), node.identifierName);
|
||||
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||
result.AddUsedExtension(metadata.GetExtension());
|
||||
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
|
||||
result.GetUsedIncludeFiles().insert(includeFile);
|
||||
result.AddUsedIncludeFiles(includeFile);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -187,9 +199,9 @@ void UsedExtensionsFinder::OnVisitFunctionCallNode(FunctionCallNode& node) {
|
||||
return;
|
||||
}
|
||||
|
||||
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||
result.AddUsedExtension(metadata.GetExtension());
|
||||
for (auto&& includeFile : metadata.GetMetadata().GetIncludeFiles()) {
|
||||
result.GetUsedIncludeFiles().insert(includeFile);
|
||||
result.AddUsedIncludeFiles(includeFile);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -9,6 +9,8 @@
|
||||
#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"
|
||||
@@ -44,6 +46,10 @@ public:
|
||||
return usedRequiredFiles;
|
||||
}
|
||||
|
||||
const std::vector<gd::SourceFileMetadata>& GetUsedSourceFiles() const {
|
||||
return usedSourceFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true when at least 1 object uses the 3D renderer.
|
||||
*/
|
||||
@@ -51,20 +57,10 @@ public:
|
||||
return has3DObjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* The extensions used by the project (or part of it).
|
||||
*/
|
||||
std::set<gd::String> &GetUsedExtensions() { return usedExtensions; }
|
||||
|
||||
/**
|
||||
* The include files used at runtime by the project (or part of it).
|
||||
*/
|
||||
std::set<gd::String> &GetUsedIncludeFiles() { return usedIncludeFiles; }
|
||||
|
||||
/**
|
||||
* The additional files required at runtime by the project (or part of it).
|
||||
*/
|
||||
std::set<gd::String> &GetUsedRequiredFiles() { return usedRequiredFiles; }
|
||||
void AddUsedExtension(const gd::PlatformExtension& extension);
|
||||
void AddUsedBuiltinExtension(const gd::String& extensionName);
|
||||
void AddUsedIncludeFiles(const gd::String& includeFile) { usedIncludeFiles.insert(includeFile); }
|
||||
void AddUsedRequiredFiles(const gd::String& requiredFile) { usedRequiredFiles.insert(requiredFile); }
|
||||
|
||||
void MarkAsHaving3DObjects() {
|
||||
has3DObjects = true;
|
||||
@@ -74,6 +70,7 @@ private:
|
||||
std::set<gd::String> usedExtensions;
|
||||
std::set<gd::String> usedIncludeFiles;
|
||||
std::set<gd::String> usedRequiredFiles;
|
||||
std::vector<gd::SourceFileMetadata> usedSourceFiles;
|
||||
bool has3DObjects = false;
|
||||
};
|
||||
|
||||
|
@@ -9,7 +9,10 @@
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
//#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/ParameterMetadataContainer.h"
|
||||
#include "GDCore/Project/PropertiesContainer.h"
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
#include "GDCore/Project/EventsFunction.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
@@ -100,4 +103,72 @@ void EventsFunctionTools::ObjectEventsFunctionToObjectsContainer(
|
||||
}
|
||||
}
|
||||
|
||||
void EventsFunctionTools::ParametersToVariablesContainer(
|
||||
const ParameterMetadataContainer ¶meters,
|
||||
gd::VariablesContainer &outputVariablesContainer) {
|
||||
if (outputVariablesContainer.GetSourceType() !=
|
||||
gd::VariablesContainer::SourceType::Parameters) {
|
||||
throw std::logic_error("Tried to generate a variables container from "
|
||||
"parameters with the wrong source type.");
|
||||
}
|
||||
outputVariablesContainer.Clear();
|
||||
|
||||
gd::String lastObjectName;
|
||||
for (std::size_t i = 0; i < parameters.GetParametersCount(); ++i) {
|
||||
const auto ¶meter = parameters.GetParameter(i);
|
||||
if (parameter.GetName().empty())
|
||||
continue;
|
||||
|
||||
auto &valueTypeMetadata = parameter.GetValueTypeMetadata();
|
||||
if (valueTypeMetadata.IsNumber()) {
|
||||
auto &variable = outputVariablesContainer.InsertNew(
|
||||
parameter.GetName(), outputVariablesContainer.Count());
|
||||
variable.SetValue(0);
|
||||
} else if (valueTypeMetadata.IsString()) {
|
||||
auto &variable = outputVariablesContainer.InsertNew(
|
||||
parameter.GetName(), outputVariablesContainer.Count());
|
||||
variable.SetString("");
|
||||
} else if (valueTypeMetadata.IsBoolean()) {
|
||||
auto &variable = outputVariablesContainer.InsertNew(
|
||||
parameter.GetName(), outputVariablesContainer.Count());
|
||||
variable.SetBool(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventsFunctionTools::PropertiesToVariablesContainer(
|
||||
const PropertiesContainer &properties,
|
||||
gd::VariablesContainer &outputVariablesContainer) {
|
||||
if (outputVariablesContainer.GetSourceType() !=
|
||||
gd::VariablesContainer::SourceType::Properties) {
|
||||
throw std::logic_error("Tried to generate a variables container from "
|
||||
"properties with the wrong source type.");
|
||||
}
|
||||
outputVariablesContainer.Clear();
|
||||
|
||||
gd::String lastObjectName;
|
||||
for (std::size_t i = 0; i < properties.GetCount(); ++i) {
|
||||
const auto &property = properties.Get(i);
|
||||
if (property.GetName().empty())
|
||||
continue;
|
||||
|
||||
auto &propertyType = gd::ValueTypeMetadata::GetPrimitiveValueType(
|
||||
gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
property.GetType()));
|
||||
if (propertyType == "number") {
|
||||
auto &variable = outputVariablesContainer.InsertNew(
|
||||
property.GetName(), outputVariablesContainer.Count());
|
||||
variable.SetValue(0);
|
||||
} else if (propertyType == "string") {
|
||||
auto &variable = outputVariablesContainer.InsertNew(
|
||||
property.GetName(), outputVariablesContainer.Count());
|
||||
variable.SetString("");
|
||||
} else if (propertyType == "boolean") {
|
||||
auto &variable = outputVariablesContainer.InsertNew(
|
||||
property.GetName(), outputVariablesContainer.Count());
|
||||
variable.SetBool(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -12,6 +12,9 @@ namespace gd {
|
||||
class Project;
|
||||
class EventsFunctionsContainer;
|
||||
class ObjectsContainer;
|
||||
class ParameterMetadataContainer;
|
||||
class PropertiesContainer;
|
||||
class VariablesContainer;
|
||||
class ParameterMetadata;
|
||||
class EventsFunction;
|
||||
class EventsBasedBehavior;
|
||||
@@ -68,5 +71,13 @@ class GD_CORE_API EventsFunctionTools {
|
||||
const gd::EventsBasedObject& eventsBasedObject,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& outputObjectsContainer);
|
||||
|
||||
static void ParametersToVariablesContainer(
|
||||
const ParameterMetadataContainer ¶meters,
|
||||
gd::VariablesContainer &outputVariablesContainer);
|
||||
|
||||
static void PropertiesToVariablesContainer(
|
||||
const PropertiesContainer &properties,
|
||||
gd::VariablesContainer &outputVariablesContainer);
|
||||
};
|
||||
} // namespace gd
|
||||
|
@@ -62,6 +62,11 @@ void ArbitraryResourceWorker::ExposeSpine(gd::String& resourceName){
|
||||
// do.
|
||||
};
|
||||
|
||||
void ArbitraryResourceWorker::ExposeJavaScript(gd::String& resourceName){
|
||||
// Nothing to do by default - each child class can define here the action to
|
||||
// do.
|
||||
};
|
||||
|
||||
void ArbitraryResourceWorker::ExposeVideo(gd::String& videoName){
|
||||
// Nothing to do by default - each child class can define here the action to
|
||||
// do.
|
||||
@@ -195,6 +200,10 @@ void ArbitraryResourceWorker::ExposeResourceWithType(
|
||||
ExposeSpine(resourceName);
|
||||
return;
|
||||
}
|
||||
if (resourceType == "javascript") {
|
||||
ExposeJavaScript(resourceName);
|
||||
return;
|
||||
}
|
||||
gd::LogError("Unexpected resource type: " + resourceType + " for: " + resourceName);
|
||||
return;
|
||||
}
|
||||
|
@@ -96,7 +96,7 @@ public:
|
||||
* \brief Expose a 3D model, which is always a reference to a "model3D" resource.
|
||||
*/
|
||||
virtual void ExposeModel3D(gd::String &resourceName);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Expose an atlas, which is always a reference to a "atlas" resource.
|
||||
*/
|
||||
@@ -112,6 +112,11 @@ public:
|
||||
*/
|
||||
virtual void ExposeVideo(gd::String &videoName);
|
||||
|
||||
/**
|
||||
* \brief Expose a JavaScript file, which is always a reference to a "javascript" resource.
|
||||
*/
|
||||
virtual void ExposeJavaScript(gd::String &javaScriptName);
|
||||
|
||||
/**
|
||||
* \brief Expose a bitmap font, which is always a reference to a "bitmapFont" resource.
|
||||
*/
|
||||
|
@@ -38,6 +38,10 @@ void AssetResourcePathCleaner::ExposeVideo(gd::String &videoName) {
|
||||
ExposeResourceAsFile(videoName);
|
||||
}
|
||||
|
||||
void AssetResourcePathCleaner::ExposeJavaScript(gd::String &javaScriptResourceName) {
|
||||
ExposeResourceAsFile(javaScriptResourceName);
|
||||
}
|
||||
|
||||
void AssetResourcePathCleaner::ExposeBitmapFont(gd::String &bitmapFontName) {
|
||||
ExposeResourceAsFile(bitmapFontName);
|
||||
}
|
||||
|
@@ -46,6 +46,7 @@ public:
|
||||
void ExposeTileset(gd::String &tilesetName) override;
|
||||
void ExposeVideo(gd::String &videoName) override;
|
||||
void ExposeBitmapFont(gd::String &bitmapFontName) override;
|
||||
void ExposeJavaScript(gd::String &javaScriptResourceName) override;
|
||||
void ExposeFile(gd::String &resource) override;
|
||||
|
||||
protected:
|
||||
|
@@ -73,6 +73,9 @@ public:
|
||||
virtual void ExposeVideo(gd::String& otherResourceName) override {
|
||||
MatchResourceName(otherResourceName);
|
||||
};
|
||||
virtual void ExposeJavaScript(gd::String& otherResourceName) override {
|
||||
MatchResourceName(otherResourceName);
|
||||
};
|
||||
virtual void ExposeBitmapFont(gd::String& otherResourceName) override {
|
||||
MatchResourceName(otherResourceName);
|
||||
};
|
||||
|
@@ -60,6 +60,7 @@ public:
|
||||
if (resourceType == "model3D") return allModel3Ds;
|
||||
if (resourceType == "atlas") return allAtlases;
|
||||
if (resourceType == "spine") return allSpines;
|
||||
if (resourceType == "javascript") return allJavaScripts;
|
||||
|
||||
return emptyResources;
|
||||
};
|
||||
@@ -88,6 +89,9 @@ public:
|
||||
virtual void ExposeVideo(gd::String& resourceName) override {
|
||||
allVideos.insert(resourceName);
|
||||
};
|
||||
virtual void ExposeJavaScript(gd::String& resourceName) override {
|
||||
allJavaScripts.insert(resourceName);
|
||||
};
|
||||
virtual void ExposeBitmapFont(gd::String& resourceName) override {
|
||||
allBitmapFonts.insert(resourceName);
|
||||
};
|
||||
@@ -114,6 +118,7 @@ public:
|
||||
std::set<gd::String> allModel3Ds;
|
||||
std::set<gd::String> allAtlases;
|
||||
std::set<gd::String> allSpines;
|
||||
std::set<gd::String> allJavaScripts;
|
||||
std::set<gd::String> emptyResources;
|
||||
|
||||
static const std::vector<gd::String> resourceTypes;
|
||||
|
@@ -59,6 +59,9 @@ class ResourcesRenamer : public gd::ArbitraryResourceWorker {
|
||||
virtual void ExposeVideo(gd::String& videoResourceName) override {
|
||||
RenameIfNeeded(videoResourceName);
|
||||
};
|
||||
virtual void ExposeJavaScript(gd::String& javaScriptResourceName) override {
|
||||
RenameIfNeeded(javaScriptResourceName);
|
||||
};
|
||||
virtual void ExposeBitmapFont(gd::String& bitmapFontName) override {
|
||||
RenameIfNeeded(bitmapFontName);
|
||||
};
|
||||
|
@@ -74,6 +74,9 @@ private:
|
||||
void ExposeVideo(gd::String &videoResourceName) override {
|
||||
AddUsedResource(videoResourceName);
|
||||
};
|
||||
void ExposeJavaScript(gd::String &javaScriptResourceName) override {
|
||||
AddUsedResource(javaScriptResourceName);
|
||||
};
|
||||
void ExposeBitmapFont(gd::String &bitmapFontName) override {
|
||||
AddUsedResource(bitmapFontName);
|
||||
};
|
||||
|
@@ -26,8 +26,8 @@ namespace gd {
|
||||
|
||||
void ProjectBrowserHelper::ExposeProjectEvents(
|
||||
gd::Project &project, gd::ArbitraryEventsWorker &worker) {
|
||||
// See also gd::Project::ExposeResources for a method that traverses the whole
|
||||
// project (this time for resources).
|
||||
// See also gd::ResourceExposer::ExposeWholeProjectResources
|
||||
// for a method that traverses the whole project (this time for resources).
|
||||
|
||||
ExposeProjectEventsWithoutExtensions(project, worker);
|
||||
|
||||
@@ -106,16 +106,16 @@ void ProjectBrowserHelper::ExposeLayoutEventsAndDependencies(
|
||||
}
|
||||
for (const gd::String& sceneName : dependenciesAnalyzer.GetScenesDependencies()) {
|
||||
gd::Layout& dependencyLayout = project.GetLayout(sceneName);
|
||||
|
||||
|
||||
worker.Launch(dependencyLayout.GetEvents());
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectBrowserHelper::ExposeProjectEvents(
|
||||
gd::Project &project, gd::ArbitraryEventsWorkerWithContext &worker) {
|
||||
// See also gd::Project::ExposeResources for a method that traverse the whole
|
||||
// project (this time for resources) and ExposeProjectEffects (this time for
|
||||
// effects).
|
||||
// See also gd::ResourceExposer::ExposeWholeProjectResources
|
||||
// for a method that traverses the whole project (this time for resources)
|
||||
// and ExposeProjectEffects (this time for effects).
|
||||
|
||||
// Add layouts events
|
||||
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
|
||||
@@ -147,7 +147,8 @@ void ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
|
||||
gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
gd::ArbitraryEventsWorker &worker) {
|
||||
// Add (free) events functions
|
||||
for (auto &&eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
|
||||
for (auto &&eventsFunction :
|
||||
eventsFunctionsExtension.GetEventsFunctions().GetInternalVector()) {
|
||||
worker.Launch(eventsFunction->GetEvents());
|
||||
}
|
||||
|
||||
@@ -169,13 +170,18 @@ void ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
|
||||
gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker) {
|
||||
// Add (free) events functions
|
||||
for (auto &&eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
|
||||
for (auto &&eventsFunction :
|
||||
eventsFunctionsExtension.GetEventsFunctions().GetInternalVector()) {
|
||||
gd::ObjectsContainer parameterObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
gd::VariablesContainer propertyVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Properties);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsFunctionsExtension, *eventsFunction,
|
||||
parameterObjectsContainer);
|
||||
parameterObjectsContainer, parameterVariablesContainer);
|
||||
|
||||
worker.Launch(eventsFunction->GetEvents(), projectScopedContainers);
|
||||
}
|
||||
@@ -207,15 +213,32 @@ void ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
|
||||
gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker) {
|
||||
gd::VariablesContainer propertyVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Properties);
|
||||
gd::ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
|
||||
project, eventsFunctionsExtension,
|
||||
eventsBasedBehavior,
|
||||
propertyVariablesContainer,
|
||||
worker);
|
||||
}
|
||||
|
||||
void ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
|
||||
gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
gd::VariablesContainer &propertyVariablesContainer,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker) {
|
||||
auto &behaviorEventsFunctions = eventsBasedBehavior.GetEventsFunctions();
|
||||
for (auto &&eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
|
||||
|
||||
gd::ObjectsContainer parameterObjectsContainers(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForBehaviorEventsFunction(
|
||||
project, eventsFunctionsExtension, eventsBasedBehavior,
|
||||
*eventsFunction, parameterObjectsContainers);
|
||||
*eventsFunction, parameterObjectsContainers,
|
||||
parameterVariablesContainer, propertyVariablesContainer);
|
||||
|
||||
worker.Launch(eventsFunction->GetEvents(), projectScopedContainers);
|
||||
}
|
||||
@@ -235,15 +258,31 @@ void ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker) {
|
||||
gd::VariablesContainer propertyVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Properties);
|
||||
gd::ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
||||
project, eventsFunctionsExtension, eventsBasedObject,
|
||||
propertyVariablesContainer, worker);
|
||||
}
|
||||
|
||||
void ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
||||
gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
gd::VariablesContainer &propertyVariablesContainer,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker) {
|
||||
auto &objectEventsFunctions = eventsBasedObject.GetEventsFunctions();
|
||||
for (auto &&eventsFunction : objectEventsFunctions.GetInternalVector()) {
|
||||
|
||||
gd::ObjectsContainer parameterObjectsContainers(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForObjectEventsFunction(
|
||||
project, eventsFunctionsExtension, eventsBasedObject,
|
||||
*eventsFunction, parameterObjectsContainers);
|
||||
*eventsFunction, parameterObjectsContainers,
|
||||
parameterVariablesContainer, propertyVariablesContainer);
|
||||
|
||||
worker.Launch(eventsFunction->GetEvents(), projectScopedContainers);
|
||||
}
|
||||
@@ -287,7 +326,7 @@ void ProjectBrowserHelper::ExposeProjectFunctions(
|
||||
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
||||
e++) {
|
||||
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
||||
worker.Launch(eventsFunctionsExtension);
|
||||
worker.Launch(eventsFunctionsExtension.GetEventsFunctions());
|
||||
|
||||
for (auto &&eventsBasedBehavior :
|
||||
eventsFunctionsExtension.GetEventsBasedBehaviors()
|
||||
|
@@ -19,6 +19,7 @@ class ArbitraryEventsFunctionsWorker;
|
||||
class ArbitraryObjectsWorker;
|
||||
class ArbitraryEventBasedBehaviorsWorker;
|
||||
class ArbitraryBehaviorSharedDataWorker;
|
||||
class VariablesContainer;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -127,6 +128,20 @@ public:
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker);
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on all events of the event-based
|
||||
* behavior.
|
||||
*
|
||||
* This should be the preferred way to traverse all the events of an
|
||||
* event-based behavior.
|
||||
*/
|
||||
static void ExposeEventsBasedBehaviorEvents(
|
||||
gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
gd::VariablesContainer &propertyVariablesContainer,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker);
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on all events of the event-based
|
||||
* object.
|
||||
@@ -152,6 +167,20 @@ public:
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker);
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on all events of the event-based
|
||||
* object.
|
||||
*
|
||||
* This should be the preferred way to traverse all the events of an
|
||||
* event-based object.
|
||||
*/
|
||||
static void ExposeEventsBasedObjectEvents(
|
||||
gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
gd::VariablesContainer &propertyVariablesContainer,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker);
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on all ObjectContainers of the project
|
||||
* (global, layouts...)
|
||||
|
@@ -63,7 +63,7 @@ void GD_CORE_API ProjectStripper::StripProjectForExport(gd::Project &project) {
|
||||
eventsBasedObject.GetPropertyDescriptors().GetInternalVector().clear();
|
||||
}
|
||||
extension.GetEventsBasedBehaviors().Clear();
|
||||
extension.ClearEventsFunctions();
|
||||
extension.GetEventsFunctions().ClearEventsFunctions();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -245,9 +245,11 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
bool PropertyFunctionGenerator::CanGenerateGetterAndSetter(
|
||||
const gd::AbstractEventsBasedEntity &eventsBasedEntity,
|
||||
const gd::NamedPropertyDescriptor &property) {
|
||||
auto &type = property.GetType();
|
||||
if (type != "Boolean" && type != "Number" && type != "String" &&
|
||||
type != "Choice" && type != "Color" && type != "LeaderboardId") {
|
||||
const auto &primitiveType = gd::ValueTypeMetadata::GetPrimitiveValueType(
|
||||
gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
property.GetType()));
|
||||
if (primitiveType != "boolean" && primitiveType != "number" &&
|
||||
primitiveType != "string") {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -5,21 +5,22 @@
|
||||
*/
|
||||
#include "ResourceExposer.h"
|
||||
|
||||
#include "GDCore/Extensions/Metadata/EffectMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCore/IDE/ProjectBrowserHelper.h"
|
||||
#include "GDCore/Project/Effect.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/Effect.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/EffectMetadata.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
void ResourceExposer::ExposeWholeProjectResources(gd::Project& project, gd::ArbitraryResourceWorker& worker) {
|
||||
void ResourceExposer::ExposeWholeProjectResources(
|
||||
gd::Project &project, gd::ArbitraryResourceWorker &worker) {
|
||||
// See also gd::ProjectBrowserHelper::ExposeProjectEvents for a method that
|
||||
// traverse the whole project (this time for events) and ExposeProjectEffects
|
||||
// (this time for effects).
|
||||
@@ -31,13 +32,11 @@ void ResourceExposer::ExposeWholeProjectResources(gd::Project& project, gd::Arbi
|
||||
|
||||
// Expose event resources
|
||||
auto eventWorker = gd::GetResourceWorkerOnEvents(project, worker);
|
||||
gd::ProjectBrowserHelper::ExposeProjectEvents(
|
||||
project, eventWorker);
|
||||
gd::ProjectBrowserHelper::ExposeProjectEvents(project, eventWorker);
|
||||
|
||||
// Expose object configuration resources
|
||||
auto objectWorker = gd::GetResourceWorkerOnObjects(project, worker);
|
||||
gd::ProjectBrowserHelper::ExposeProjectObjects(
|
||||
project, objectWorker);
|
||||
gd::ProjectBrowserHelper::ExposeProjectObjects(project, objectWorker);
|
||||
|
||||
// Expose layer effect resources
|
||||
for (std::size_t layoutIndex = 0; layoutIndex < project.GetLayoutsCount();
|
||||
@@ -52,28 +51,36 @@ void ResourceExposer::ExposeWholeProjectResources(gd::Project& project, gd::Arbi
|
||||
for (size_t effectIndex = 0; effectIndex < effects.GetEffectsCount();
|
||||
effectIndex++) {
|
||||
auto &effect = effects.GetEffect(effectIndex);
|
||||
gd::ResourceExposer::ExposeEffectResources(project.GetCurrentPlatform(),
|
||||
effect, worker);
|
||||
gd::ResourceExposer::ExposeEffectResources(
|
||||
project.GetCurrentPlatform(), effect, worker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expose loading screen background image if present
|
||||
auto& loadingScreen = project.GetLoadingScreen();
|
||||
auto &loadingScreen = project.GetLoadingScreen();
|
||||
if (loadingScreen.GetBackgroundImageResourceName() != "")
|
||||
worker.ExposeImage(loadingScreen.GetBackgroundImageResourceName());
|
||||
|
||||
// Expose extension source files
|
||||
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
||||
e++) {
|
||||
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
||||
ExposeExtensionResources(eventsFunctionsExtension, worker);
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceExposer::ExposeProjectResources(gd::Project& project, gd::ArbitraryResourceWorker& worker) {
|
||||
void ResourceExposer::ExposeProjectResources(
|
||||
gd::Project &project, gd::ArbitraryResourceWorker &worker) {
|
||||
// Expose global objects configuration resources
|
||||
auto objectWorker = gd::GetResourceWorkerOnObjects(project, worker);
|
||||
objectWorker.Launch(project.GetObjects());
|
||||
}
|
||||
|
||||
void ResourceExposer::ExposeLayoutResources(
|
||||
gd::Project &project, gd::Layout &layout,
|
||||
gd::Project &project,
|
||||
gd::Layout &layout,
|
||||
gd::ArbitraryResourceWorker &worker) {
|
||||
|
||||
// Expose object configuration resources
|
||||
auto objectWorker = gd::GetResourceWorkerOnObjects(project, worker);
|
||||
gd::ProjectBrowserHelper::ExposeLayoutObjects(layout, objectWorker);
|
||||
@@ -87,15 +94,15 @@ void ResourceExposer::ExposeLayoutResources(
|
||||
for (size_t effectIndex = 0; effectIndex < effects.GetEffectsCount();
|
||||
effectIndex++) {
|
||||
auto &effect = effects.GetEffect(effectIndex);
|
||||
gd::ResourceExposer::ExposeEffectResources(project.GetCurrentPlatform(),
|
||||
effect, worker);
|
||||
gd::ResourceExposer::ExposeEffectResources(
|
||||
project.GetCurrentPlatform(), effect, worker);
|
||||
}
|
||||
}
|
||||
|
||||
// Expose event resources
|
||||
auto eventWorker = gd::GetResourceWorkerOnEvents(project, worker);
|
||||
gd::ProjectBrowserHelper::ExposeLayoutEventsAndDependencies(project, layout,
|
||||
eventWorker);
|
||||
gd::ProjectBrowserHelper::ExposeLayoutEventsAndDependencies(
|
||||
project, layout, eventWorker);
|
||||
|
||||
// Exposed extension event resources
|
||||
// Note that using resources in extensions is very unlikely and probably not
|
||||
@@ -103,12 +110,14 @@ void ResourceExposer::ExposeLayoutResources(
|
||||
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
||||
e++) {
|
||||
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
||||
gd::ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(project, eventsFunctionsExtension, eventWorker);
|
||||
gd::ProjectBrowserHelper::ExposeEventsFunctionsExtensionEvents(
|
||||
project, eventsFunctionsExtension, eventWorker);
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceExposer::ExposeEffectResources(
|
||||
gd::Platform &platform, gd::Effect &effect,
|
||||
gd::Platform &platform,
|
||||
gd::Effect &effect,
|
||||
gd::ArbitraryResourceWorker &worker) {
|
||||
auto &effectMetadata =
|
||||
MetadataProvider::GetEffectMetadata(platform, effect.GetEffectType());
|
||||
@@ -127,11 +136,20 @@ void ResourceExposer::ExposeEffectResources(
|
||||
worker.ExposeResourceWithType(resourceType,
|
||||
potentiallyUpdatedResourceName);
|
||||
if (potentiallyUpdatedResourceName != resourceName) {
|
||||
effect.SetStringParameter(propertyName, potentiallyUpdatedResourceName);
|
||||
effect.SetStringParameter(propertyName,
|
||||
potentiallyUpdatedResourceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
void ResourceExposer::ExposeExtensionResources(
|
||||
gd::EventsFunctionsExtension &extension,
|
||||
gd::ArbitraryResourceWorker &worker) {
|
||||
for (auto &sourceFile : extension.GetAllSourceFiles()) {
|
||||
worker.ExposeJavaScript(sourceFile.GetResourceName());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -9,9 +9,10 @@ namespace gd {
|
||||
class Platform;
|
||||
class Project;
|
||||
class ArbitraryResourceWorker;
|
||||
class EventsFunctionsExtension;
|
||||
class Effect;
|
||||
class Layout;
|
||||
} // namespace gd
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -19,7 +20,7 @@ namespace gd {
|
||||
* \brief
|
||||
*/
|
||||
class GD_CORE_API ResourceExposer {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* \brief Called ( e.g. during compilation ) so as to inventory internal
|
||||
* resources, sometimes update their filename or any other work or resources.
|
||||
@@ -34,7 +35,7 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Expose only the resources used globally on a project.
|
||||
*
|
||||
*
|
||||
* It doesn't include resources used in layouts.
|
||||
*/
|
||||
static void ExposeProjectResources(gd::Project &project,
|
||||
@@ -42,17 +43,25 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Expose the resources used in a given layout.
|
||||
*
|
||||
*
|
||||
* It doesn't include resources used globally.
|
||||
*/
|
||||
static void ExposeLayoutResources(gd::Project &project, gd::Layout &layout,
|
||||
gd::ArbitraryResourceWorker &worker);
|
||||
static void ExposeLayoutResources(gd::Project &project,
|
||||
gd::Layout &layout,
|
||||
gd::ArbitraryResourceWorker &worker);
|
||||
|
||||
/**
|
||||
* @brief Expose the resources used in a given effect.
|
||||
*/
|
||||
static void ExposeEffectResources(gd::Platform &platform, gd::Effect &effect,
|
||||
static void ExposeEffectResources(gd::Platform &platform,
|
||||
gd::Effect &effect,
|
||||
gd::ArbitraryResourceWorker &worker);
|
||||
|
||||
/**
|
||||
* @brief Expose the resources used in an extension.
|
||||
*/
|
||||
static void ExposeExtensionResources(gd::EventsFunctionsExtension &extension,
|
||||
gd::ArbitraryResourceWorker &worker);
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
} // namespace gd
|
||||
|
@@ -600,7 +600,8 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
// instructions after they are renamed.
|
||||
|
||||
// Free expressions
|
||||
for (auto &&eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
|
||||
for (auto &&eventsFunction :
|
||||
eventsFunctionsExtension.GetEventsFunctions().GetInternalVector()) {
|
||||
if (eventsFunction->IsExpression()) {
|
||||
renameEventsFunction(*eventsFunction);
|
||||
}
|
||||
@@ -617,7 +618,8 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
}
|
||||
|
||||
// Free instructions
|
||||
for (auto &&eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
|
||||
for (auto &&eventsFunction :
|
||||
eventsFunctionsExtension.GetEventsFunctions().GetInternalVector()) {
|
||||
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
|
||||
renameEventsFunction(*eventsFunction);
|
||||
}
|
||||
@@ -697,11 +699,12 @@ void WholeProjectRefactorer::RenameEventsFunction(
|
||||
gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::String &oldFunctionName, const gd::String &newFunctionName) {
|
||||
if (!eventsFunctionsExtension.HasEventsFunctionNamed(oldFunctionName))
|
||||
const auto &eventsFunctions = eventsFunctionsExtension.GetEventsFunctions();
|
||||
if (!eventsFunctions.HasEventsFunctionNamed(oldFunctionName))
|
||||
return;
|
||||
|
||||
const gd::EventsFunction &eventsFunction =
|
||||
eventsFunctionsExtension.GetEventsFunction(oldFunctionName);
|
||||
eventsFunctions.GetEventsFunction(oldFunctionName);
|
||||
|
||||
const WholeProjectBrowser wholeProjectExposer;
|
||||
DoRenameEventsFunction(
|
||||
@@ -714,7 +717,7 @@ void WholeProjectRefactorer::RenameEventsFunction(
|
||||
|
||||
if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::ExpressionAndCondition) {
|
||||
for (auto &&otherFunction : eventsFunctionsExtension.GetInternalVector()) {
|
||||
for (auto &&otherFunction : eventsFunctions.GetInternalVector()) {
|
||||
if (otherFunction->GetFunctionType() ==
|
||||
gd::EventsFunction::ActionWithOperator &&
|
||||
otherFunction->GetGetterName() == oldFunctionName) {
|
||||
@@ -862,16 +865,34 @@ void WholeProjectRefactorer::RenameParameter(
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::ChangeParameterType(
|
||||
gd::Project &project, gd::ProjectScopedContainers &projectScopedContainers,
|
||||
gd::EventsFunction &eventsFunction,
|
||||
const gd::ObjectsContainer ¶meterObjectsContainer,
|
||||
const gd::String ¶meterName) {
|
||||
std::unordered_set<gd::String> typeChangedPropertyNames;
|
||||
typeChangedPropertyNames.insert(parameterName);
|
||||
gd::VariablesContainer propertyVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Properties);
|
||||
gd::EventsVariableInstructionTypeSwitcher
|
||||
eventsVariableInstructionTypeSwitcher(project.GetCurrentPlatform(),
|
||||
typeChangedPropertyNames,
|
||||
propertyVariablesContainer);
|
||||
eventsVariableInstructionTypeSwitcher.Launch(eventsFunction.GetEvents(),
|
||||
projectScopedContainers);
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::MoveEventsFunctionParameter(
|
||||
gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::String &functionName, std::size_t oldIndex,
|
||||
std::size_t newIndex) {
|
||||
if (!eventsFunctionsExtension.HasEventsFunctionNamed(functionName))
|
||||
const auto &eventsFunctions = eventsFunctionsExtension.GetEventsFunctions();
|
||||
if (!eventsFunctions.HasEventsFunctionNamed(functionName))
|
||||
return;
|
||||
|
||||
const gd::EventsFunction &eventsFunction =
|
||||
eventsFunctionsExtension.GetEventsFunction(functionName);
|
||||
eventsFunctions.GetEventsFunction(functionName);
|
||||
|
||||
const gd::String &eventsFunctionType =
|
||||
gd::PlatformExtension::GetEventsFunctionFullType(
|
||||
@@ -1175,6 +1196,42 @@ void WholeProjectRefactorer::RenameEventsBasedObjectProperty(
|
||||
gd::ProjectBrowserHelper::ExposeProjectEvents(project, conditionRenamer);
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::ChangeEventsBasedBehaviorPropertyType(
|
||||
gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
const gd::String &propertyName) {
|
||||
std::unordered_set<gd::String> typeChangedPropertyNames;
|
||||
typeChangedPropertyNames.insert(propertyName);
|
||||
gd::VariablesContainer propertyVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Properties);
|
||||
gd::EventsVariableInstructionTypeSwitcher
|
||||
eventsVariableInstructionTypeSwitcher(project.GetCurrentPlatform(),
|
||||
typeChangedPropertyNames,
|
||||
propertyVariablesContainer);
|
||||
gd::ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
|
||||
project, eventsFunctionsExtension, eventsBasedBehavior,
|
||||
propertyVariablesContainer, eventsVariableInstructionTypeSwitcher);
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::ChangeEventsBasedObjectPropertyType(
|
||||
gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::String &propertyName) {
|
||||
std::unordered_set<gd::String> typeChangedPropertyNames;
|
||||
typeChangedPropertyNames.insert(propertyName);
|
||||
gd::VariablesContainer propertyVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Properties);
|
||||
gd::EventsVariableInstructionTypeSwitcher
|
||||
eventsVariableInstructionTypeSwitcher(project.GetCurrentPlatform(),
|
||||
typeChangedPropertyNames,
|
||||
propertyVariablesContainer);
|
||||
gd::ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
||||
project, eventsFunctionsExtension, eventsBasedObject,
|
||||
propertyVariablesContainer, eventsVariableInstructionTypeSwitcher);
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
|
||||
gd::Project &project, gd::Object &object, const gd::String &behaviorType,
|
||||
const gd::String &behaviorName) {
|
||||
|
@@ -191,6 +191,16 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
const gd::String &oldParameterName,
|
||||
const gd::String &newParameterName);
|
||||
|
||||
/**
|
||||
* \brief Refactor the function **after** a parameter has changed of type.
|
||||
*/
|
||||
static void
|
||||
ChangeParameterType(gd::Project &project,
|
||||
gd::ProjectScopedContainers &projectScopedContainers,
|
||||
gd::EventsFunction &eventsFunction,
|
||||
const gd::ObjectsContainer ¶meterObjectsContainer,
|
||||
const gd::String ¶meterName);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **before** an events function parameter
|
||||
* is moved.
|
||||
@@ -283,6 +293,26 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
const gd::String& oldPropertyName,
|
||||
const gd::String& newPropertyName);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **after** a property of a behavior has
|
||||
* changed of type.
|
||||
*/
|
||||
static void ChangeEventsBasedBehaviorPropertyType(
|
||||
gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
const gd::String &propertyName);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **after** a property of an object has
|
||||
* changed of type.
|
||||
*/
|
||||
static void ChangeEventsBasedObjectPropertyType(
|
||||
gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::String &propertyName);
|
||||
|
||||
/**
|
||||
* \brief Add a behavior to an object and add required behaviors if necessary
|
||||
* to fill every behavior properties of the added behaviors.
|
||||
|
@@ -23,6 +23,9 @@ void AbstractEventsBasedEntity::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("description", description);
|
||||
element.SetAttribute("name", name);
|
||||
element.SetAttribute("fullName", fullName);
|
||||
if (isPrivate) {
|
||||
element.SetBoolAttribute("private", isPrivate);
|
||||
}
|
||||
|
||||
gd::SerializerElement& eventsFunctionsElement =
|
||||
element.AddChild("eventsFunctions");
|
||||
@@ -36,6 +39,7 @@ void AbstractEventsBasedEntity::UnserializeFrom(
|
||||
description = element.GetStringAttribute("description");
|
||||
name = element.GetStringAttribute("name");
|
||||
fullName = element.GetStringAttribute("fullName");
|
||||
isPrivate = element.GetBoolAttribute("private");
|
||||
|
||||
const gd::SerializerElement& eventsFunctionsElement =
|
||||
element.GetChild("eventsFunctions");
|
||||
|
@@ -3,8 +3,7 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_ABSTRACTEVENTSBASEDENTITY_H
|
||||
#define GDCORE_ABSTRACTEVENTSBASEDENTITY_H
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "GDCore/Project/NamedPropertyDescriptor.h"
|
||||
@@ -40,6 +39,21 @@ class GD_CORE_API AbstractEventsBasedEntity {
|
||||
*/
|
||||
AbstractEventsBasedEntity* Clone() const { return new AbstractEventsBasedEntity(*this); };
|
||||
|
||||
/**
|
||||
* \brief Check if the behavior or object is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
bool IsPrivate() const { return isPrivate; }
|
||||
|
||||
/**
|
||||
* \brief Set that the behavior or object is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
AbstractEventsBasedEntity& SetPrivate(bool isPrivate_) {
|
||||
isPrivate = isPrivate_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the description of the behavior or object, that is displayed in the
|
||||
* editor.
|
||||
@@ -151,8 +165,7 @@ class GD_CORE_API AbstractEventsBasedEntity {
|
||||
gd::EventsFunctionsContainer eventsFunctionsContainer;
|
||||
gd::PropertiesContainer propertyDescriptors;
|
||||
gd::String extensionName;
|
||||
bool isPrivate = false;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_ABSTRACTEVENTSBASEDENTITY_H
|
||||
|
@@ -22,15 +22,17 @@ void CustomConfigurationHelper::InitializeContent(
|
||||
gd::SerializerElement &configurationContent) {
|
||||
for (auto &&property : properties.GetInternalVector()) {
|
||||
auto &element = configurationContent.AddChild(property->GetName());
|
||||
auto propertyType = property->GetType();
|
||||
|
||||
if (propertyType == "String" || propertyType == "Choice" ||
|
||||
propertyType == "Color" || propertyType == "Behavior" ||
|
||||
propertyType == "Resource" || propertyType == "LeaderboardId") {
|
||||
const auto &valueType =
|
||||
gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
property->GetType());
|
||||
const auto &primitiveType =
|
||||
gd::ValueTypeMetadata::GetPrimitiveValueType(valueType);
|
||||
if (primitiveType == "string" || valueType == "behavior") {
|
||||
element.SetStringValue(property->GetValue());
|
||||
} else if (propertyType == "Number") {
|
||||
} else if (primitiveType == "number") {
|
||||
element.SetDoubleValue(property->GetValue().To<double>());
|
||||
} else if (propertyType == "Boolean") {
|
||||
} else if (primitiveType == "boolean") {
|
||||
element.SetBoolValue(property->GetValue() == "true");
|
||||
}
|
||||
}
|
||||
@@ -43,23 +45,25 @@ std::map<gd::String, gd::PropertyDescriptor> CustomConfigurationHelper::GetPrope
|
||||
|
||||
for (auto &property : properties.GetInternalVector()) {
|
||||
const auto &propertyName = property->GetName();
|
||||
const auto &propertyType = property->GetType();
|
||||
|
||||
// Copy the property
|
||||
objectProperties[propertyName] = *property;
|
||||
|
||||
auto &newProperty = objectProperties[propertyName];
|
||||
|
||||
const auto &valueType =
|
||||
gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
property->GetType());
|
||||
const auto &primitiveType =
|
||||
gd::ValueTypeMetadata::GetPrimitiveValueType(valueType);
|
||||
if (configurationContent.HasChild(propertyName)) {
|
||||
if (propertyType == "String" || propertyType == "Choice" ||
|
||||
propertyType == "Color" || propertyType == "Behavior" ||
|
||||
propertyType == "Resource" || propertyType == "LeaderboardId") {
|
||||
if (primitiveType == "string" || valueType == "behavior") {
|
||||
newProperty.SetValue(
|
||||
configurationContent.GetChild(propertyName).GetStringValue());
|
||||
} else if (propertyType == "Number") {
|
||||
} else if (primitiveType == "number") {
|
||||
newProperty.SetValue(gd::String::From(
|
||||
configurationContent.GetChild(propertyName).GetDoubleValue()));
|
||||
} else if (propertyType == "Boolean") {
|
||||
} else if (primitiveType == "boolean") {
|
||||
newProperty.SetValue(
|
||||
configurationContent.GetChild(propertyName).GetBoolValue()
|
||||
? "true"
|
||||
@@ -85,15 +89,16 @@ bool CustomConfigurationHelper::UpdateProperty(
|
||||
const auto &property = properties.Get(propertyName);
|
||||
|
||||
auto &element = configurationContent.AddChild(propertyName);
|
||||
const gd::String &propertyType = property.GetType();
|
||||
|
||||
if (propertyType == "String" || propertyType == "Choice" ||
|
||||
propertyType == "Color" || propertyType == "Behavior" ||
|
||||
propertyType == "Resource" || propertyType == "LeaderboardId") {
|
||||
const auto &valueType =
|
||||
gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(property.GetType());
|
||||
const auto &primitiveType =
|
||||
gd::ValueTypeMetadata::GetPrimitiveValueType(valueType);
|
||||
if (primitiveType == "string" || valueType == "behavior") {
|
||||
element.SetStringValue(newValue);
|
||||
} else if (propertyType == "Number") {
|
||||
} else if (primitiveType == "number") {
|
||||
element.SetDoubleValue(newValue.To<double>());
|
||||
} else if (propertyType == "Boolean") {
|
||||
} else if (primitiveType == "boolean") {
|
||||
element.SetBoolValue(newValue == "1");
|
||||
}
|
||||
|
||||
|
@@ -21,9 +21,6 @@ EventsBasedBehavior::EventsBasedBehavior()
|
||||
void EventsBasedBehavior::SerializeTo(SerializerElement& element) const {
|
||||
AbstractEventsBasedEntity::SerializeTo(element);
|
||||
element.SetAttribute("objectType", objectType);
|
||||
if (isPrivate) {
|
||||
element.SetBoolAttribute("private", isPrivate);
|
||||
}
|
||||
sharedPropertyDescriptors.SerializeElementsTo(
|
||||
"propertyDescriptor", element.AddChild("sharedPropertyDescriptors"));
|
||||
if (quickCustomizationVisibility != QuickCustomization::Visibility::Default) {
|
||||
@@ -39,7 +36,6 @@ void EventsBasedBehavior::UnserializeFrom(gd::Project& project,
|
||||
const SerializerElement& element) {
|
||||
AbstractEventsBasedEntity::UnserializeFrom(project, element);
|
||||
objectType = element.GetStringAttribute("objectType");
|
||||
isPrivate = element.GetBoolAttribute("private");
|
||||
sharedPropertyDescriptors.UnserializeElementsFrom(
|
||||
"propertyDescriptor", element.GetChild("sharedPropertyDescriptors"));
|
||||
if (element.HasChild("quickCustomizationVisibility")) {
|
||||
|
@@ -3,8 +3,7 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EVENTSBASEDBEHAVIOR_H
|
||||
#define GDCORE_EVENTSBASEDBEHAVIOR_H
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "GDCore/Project/AbstractEventsBasedEntity.h"
|
||||
@@ -75,17 +74,11 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the behavior is private - it can't be used outside of its
|
||||
* \brief Set that the behavior or object is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
bool IsPrivate() const { return isPrivate; }
|
||||
|
||||
/**
|
||||
* \brief Set that the behavior is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
EventsBasedBehavior& SetPrivate(bool _isPrivate) {
|
||||
isPrivate = _isPrivate;
|
||||
EventsBasedBehavior& SetPrivate(bool isPrivate) {
|
||||
AbstractEventsBasedEntity::SetPrivate(isPrivate);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -149,11 +142,8 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
|
||||
|
||||
private:
|
||||
gd::String objectType;
|
||||
bool isPrivate = false;
|
||||
gd::PropertiesContainer sharedPropertyDescriptors;
|
||||
QuickCustomization::Visibility quickCustomizationVisibility;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_EVENTSBASEDBEHAVIOR_H
|
||||
|
@@ -72,6 +72,15 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set that the object is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
EventsBasedObject& SetPrivate(bool isPrivate) {
|
||||
AbstractEventsBasedEntity::SetPrivate(isPrivate);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Declare a usage of the 3D renderer.
|
||||
*/
|
||||
|
@@ -33,6 +33,20 @@ public:
|
||||
|
||||
EventsFunctionsContainer(FunctionOwner source_) : owner(source_) {}
|
||||
|
||||
EventsFunctionsContainer(const EventsFunctionsContainer &other)
|
||||
: owner(other.owner) {
|
||||
Init(other);
|
||||
}
|
||||
|
||||
EventsFunctionsContainer &operator=(const EventsFunctionsContainer &other) {
|
||||
if (this != &other) {
|
||||
owner = other.owner;
|
||||
Init(other);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the source of the function container.
|
||||
*
|
||||
|
@@ -15,14 +15,13 @@
|
||||
namespace gd {
|
||||
|
||||
EventsFunctionsExtension::EventsFunctionsExtension() :
|
||||
gd::EventsFunctionsContainer(
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Extension),
|
||||
eventsFunctionsContainer(gd::EventsFunctionsContainer::FunctionOwner::Extension),
|
||||
globalVariables(gd::VariablesContainer::SourceType::ExtensionGlobal),
|
||||
sceneVariables(gd::VariablesContainer::SourceType::ExtensionScene) {}
|
||||
|
||||
EventsFunctionsExtension::EventsFunctionsExtension(
|
||||
const EventsFunctionsExtension& other) :
|
||||
gd::EventsFunctionsContainer(
|
||||
eventsFunctionsContainer(
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Extension) {
|
||||
Init(other);
|
||||
}
|
||||
@@ -48,7 +47,7 @@ void EventsFunctionsExtension::Init(const gd::EventsFunctionsExtension& other) {
|
||||
previewIconUrl = other.previewIconUrl;
|
||||
iconUrl = other.iconUrl;
|
||||
helpPath = other.helpPath;
|
||||
EventsFunctionsContainer::Init(other);
|
||||
eventsFunctionsContainer = other.eventsFunctionsContainer;
|
||||
eventsBasedBehaviors = other.eventsBasedBehaviors;
|
||||
eventsBasedObjects = other.eventsBasedObjects;
|
||||
globalVariables = other.GetGlobalVariables();
|
||||
@@ -87,10 +86,18 @@ void EventsFunctionsExtension::SerializeTo(SerializerElement& element) const {
|
||||
for (auto& dependency : dependencies)
|
||||
SerializeDependencyTo(dependency, dependenciesElement.AddChild(""));
|
||||
|
||||
if (!sourceFiles.empty()) {
|
||||
auto& sourceFilesElement = element.AddChild("sourceFiles");
|
||||
sourceFilesElement.ConsiderAsArray();
|
||||
for (auto& sourceFile : sourceFiles)
|
||||
sourceFile.SerializeTo(sourceFilesElement.AddChild(""));
|
||||
}
|
||||
|
||||
GetGlobalVariables().SerializeTo(element.AddChild("globalVariables"));
|
||||
GetSceneVariables().SerializeTo(element.AddChild("sceneVariables"));
|
||||
|
||||
SerializeEventsFunctionsTo(element.AddChild("eventsFunctions"));
|
||||
eventsFunctionsContainer.SerializeEventsFunctionsTo(
|
||||
element.AddChild("eventsFunctions"));
|
||||
eventsBasedBehaviors.SerializeElementsTo(
|
||||
"eventsBasedBehavior", element.AddChild("eventsBasedBehaviors"));
|
||||
eventsBasedObjects.SerializeElementsTo(
|
||||
@@ -159,6 +166,17 @@ void EventsFunctionsExtension::UnserializeExtensionDeclarationFrom(
|
||||
dependencies.push_back(
|
||||
UnserializeDependencyFrom(dependenciesElement.GetChild(i)));
|
||||
|
||||
sourceFiles.clear();
|
||||
if (element.HasChild("sourceFiles")) {
|
||||
const auto& sourceFilesElement = element.GetChild("sourceFiles");
|
||||
sourceFilesElement.ConsiderAsArray();
|
||||
for (size_t i = 0; i < sourceFilesElement.GetChildrenCount(); ++i) {
|
||||
SourceFileMetadata sourceFile;
|
||||
sourceFile.UnserializeFrom(sourceFilesElement.GetChild(i));
|
||||
sourceFiles.push_back(sourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
globalVariables.UnserializeFrom(element.GetChild("globalVariables"));
|
||||
sceneVariables.UnserializeFrom(element.GetChild("sceneVariables"));
|
||||
|
||||
@@ -187,7 +205,8 @@ void EventsFunctionsExtension::UnserializeExtensionDeclarationFrom(
|
||||
void EventsFunctionsExtension::UnserializeExtensionImplementationFrom(
|
||||
gd::Project& project,
|
||||
const SerializerElement& element) {
|
||||
UnserializeEventsFunctionsFrom(project, element.GetChild("eventsFunctions"));
|
||||
eventsFunctionsContainer.UnserializeEventsFunctionsFrom(
|
||||
project, element.GetChild("eventsFunctions"));
|
||||
eventsBasedBehaviors.UnserializeElementsFrom(
|
||||
"eventsBasedBehavior", project, element.GetChild("eventsBasedBehaviors"));
|
||||
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Extensions/Metadata/DependencyMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/SourceFileMetadata.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
#include "GDCore/Project/EventsFunctionsContainer.h"
|
||||
@@ -35,7 +36,7 @@ namespace gd {
|
||||
*
|
||||
* \ingroup PlatformDefinition
|
||||
*/
|
||||
class GD_CORE_API EventsFunctionsExtension : public EventsFunctionsContainer {
|
||||
class GD_CORE_API EventsFunctionsExtension {
|
||||
public:
|
||||
EventsFunctionsExtension();
|
||||
EventsFunctionsExtension(const EventsFunctionsExtension&);
|
||||
@@ -180,6 +181,21 @@ class GD_CORE_API EventsFunctionsExtension : public EventsFunctionsContainer {
|
||||
return originIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the functions of the events based behavior or object.
|
||||
*/
|
||||
EventsFunctionsContainer& GetEventsFunctions() {
|
||||
return eventsFunctionsContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return a const reference to the functions of the events based
|
||||
* behavior or object.
|
||||
*/
|
||||
const EventsFunctionsContainer& GetEventsFunctions() const {
|
||||
return eventsFunctionsContainer;
|
||||
}
|
||||
|
||||
/** \name Dependencies
|
||||
*/
|
||||
///@{
|
||||
@@ -289,6 +305,42 @@ class GD_CORE_API EventsFunctionsExtension : public EventsFunctionsContainer {
|
||||
const gd::String& eventsFunctionName);
|
||||
///@}
|
||||
|
||||
/** \name Source files
|
||||
*/
|
||||
///@{
|
||||
|
||||
/**
|
||||
* \brief Adds a new source file.
|
||||
*/
|
||||
gd::SourceFileMetadata& AddSourceFile() {
|
||||
gd::SourceFileMetadata sourceFile;
|
||||
sourceFiles.push_back(sourceFile);
|
||||
return sourceFiles.back();
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Removes a source file.
|
||||
*/
|
||||
void RemoveSourceFileAt(size_t index) {
|
||||
sourceFiles.erase(sourceFiles.begin() + index);
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Returns the list of source files.
|
||||
*/
|
||||
std::vector<gd::SourceFileMetadata>& GetAllSourceFiles() {
|
||||
return sourceFiles;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Returns the list of source files.
|
||||
*/
|
||||
const std::vector<gd::SourceFileMetadata>& GetAllSourceFiles() const {
|
||||
return sourceFiles;
|
||||
};
|
||||
|
||||
///@}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialize object using another object. Used by copy-ctor and assign-op.
|
||||
@@ -336,7 +388,9 @@ class GD_CORE_API EventsFunctionsExtension : public EventsFunctionsContainer {
|
||||
gd::SerializableWithNameList<EventsBasedBehavior> eventsBasedBehaviors;
|
||||
gd::SerializableWithNameList<EventsBasedObject> eventsBasedObjects;
|
||||
std::vector<gd::DependencyMetadata> dependencies;
|
||||
|
||||
std::vector<gd::SourceFileMetadata> sourceFiles;
|
||||
|
||||
gd::EventsFunctionsContainer eventsFunctionsContainer;
|
||||
gd::VariablesContainer globalVariables;
|
||||
gd::VariablesContainer sceneVariables;
|
||||
};
|
||||
|
@@ -137,6 +137,15 @@ void ObjectFolderOrObject::RemoveRecursivelyObjectNamed(
|
||||
}
|
||||
};
|
||||
|
||||
void ObjectFolderOrObject::Clear() {
|
||||
if (IsFolder()) {
|
||||
for (auto& it : children) {
|
||||
it->Clear();
|
||||
}
|
||||
children.clear();
|
||||
}
|
||||
};
|
||||
|
||||
bool ObjectFolderOrObject::IsADescendantOf(
|
||||
const ObjectFolderOrObject& otherObjectFolderOrObject) {
|
||||
if (parent == nullptr) return false;
|
||||
|
@@ -134,6 +134,10 @@ class GD_CORE_API ObjectFolderOrObject {
|
||||
* the instance children and recursively does it for every folder children.
|
||||
*/
|
||||
void RemoveRecursivelyObjectNamed(const gd::String& name);
|
||||
/**
|
||||
* \brief Clears all children
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* \brief Inserts an instance representing the given object at the given
|
||||
|
@@ -7,12 +7,12 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "GDCore/Tools/PolymorphicClone.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectFolderOrObject.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/PolymorphicClone.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -28,8 +28,7 @@ ObjectsContainer::ObjectsContainer(const ObjectsContainer& other) {
|
||||
Init(other);
|
||||
}
|
||||
|
||||
ObjectsContainer& ObjectsContainer::operator=(
|
||||
const ObjectsContainer& other) {
|
||||
ObjectsContainer& ObjectsContainer::operator=(const ObjectsContainer& other) {
|
||||
if (this != &other) Init(other);
|
||||
|
||||
return *this;
|
||||
@@ -69,7 +68,7 @@ void ObjectsContainer::AddMissingObjectsInRootFolder() {
|
||||
|
||||
void ObjectsContainer::UnserializeObjectsFrom(
|
||||
gd::Project& project, const SerializerElement& element) {
|
||||
initialObjects.clear();
|
||||
Clear();
|
||||
element.ConsiderAsArrayOf("object", "Objet");
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount(); ++i) {
|
||||
const SerializerElement& objectElement = element.GetChild(i);
|
||||
@@ -184,6 +183,11 @@ void ObjectsContainer::RemoveObject(const gd::String& name) {
|
||||
initialObjects.erase(objectIt);
|
||||
}
|
||||
|
||||
void ObjectsContainer::Clear() {
|
||||
rootFolder->Clear();
|
||||
initialObjects.clear();
|
||||
}
|
||||
|
||||
void ObjectsContainer::MoveObjectFolderOrObjectToAnotherContainerInFolder(
|
||||
gd::ObjectFolderOrObject& objectFolderOrObject,
|
||||
gd::ObjectsContainer& newContainer,
|
||||
|
@@ -166,6 +166,11 @@ class GD_CORE_API ObjectsContainer {
|
||||
gd::ObjectFolderOrObject& newParentFolder,
|
||||
std::size_t newPosition);
|
||||
|
||||
/**
|
||||
* \brief Clear all groups of the container.
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* Provide a raw access to the vector containing the objects
|
||||
*/
|
||||
|
@@ -30,7 +30,6 @@
|
||||
#include "GDCore/Project/ObjectConfiguration.h"
|
||||
#include "GDCore/Project/ObjectGroupsContainer.h"
|
||||
#include "GDCore/Project/ResourcesManager.h"
|
||||
#include "GDCore/Project/SourceFile.h"
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
@@ -67,7 +66,6 @@ Project::Project()
|
||||
isAntialisingEnabledOnMobile(false),
|
||||
projectUuid(""),
|
||||
useDeprecatedZeroAsDefaultZOrder(false),
|
||||
useExternalSourceFiles(false),
|
||||
isPlayableWithKeyboard(false),
|
||||
isPlayableWithGamepad(false),
|
||||
isPlayableWithMobile(false),
|
||||
@@ -742,9 +740,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
loadingScreen.UnserializeFrom(propElement.GetChild("loadingScreen"));
|
||||
watermark.UnserializeFrom(propElement.GetChild("watermark"));
|
||||
|
||||
useExternalSourceFiles =
|
||||
propElement.GetBoolAttribute("useExternalSourceFiles");
|
||||
|
||||
authorIds.clear();
|
||||
auto& authorIdsElement = propElement.GetChild("authorIds");
|
||||
authorIdsElement.ConsiderAsArray();
|
||||
@@ -917,19 +912,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
InsertNewExternalLayout("", GetExternalLayoutsCount());
|
||||
newExternalLayout.UnserializeFrom(externalLayoutElement);
|
||||
}
|
||||
|
||||
externalSourceFiles.clear();
|
||||
const SerializerElement& externalSourceFilesElement =
|
||||
element.GetChild("externalSourceFiles", 0, "ExternalSourceFiles");
|
||||
externalSourceFilesElement.ConsiderAsArrayOf("sourceFile", "SourceFile");
|
||||
for (std::size_t i = 0; i < externalSourceFilesElement.GetChildrenCount();
|
||||
++i) {
|
||||
const SerializerElement& sourceFileElement =
|
||||
externalSourceFilesElement.GetChild(i);
|
||||
|
||||
gd::SourceFile& newSourceFile = InsertNewSourceFile("", "");
|
||||
newSourceFile.UnserializeFrom(sourceFileElement);
|
||||
}
|
||||
}
|
||||
|
||||
void Project::UnserializeAndInsertExtensionsFrom(
|
||||
@@ -1109,7 +1091,6 @@ void Project::SerializeTo(SerializerElement& element) const {
|
||||
propElement.AddChild("platformSpecificAssets"));
|
||||
loadingScreen.SerializeTo(propElement.AddChild("loadingScreen"));
|
||||
watermark.SerializeTo(propElement.AddChild("watermark"));
|
||||
propElement.SetAttribute("useExternalSourceFiles", useExternalSourceFiles);
|
||||
|
||||
auto& authorIdsElement = propElement.AddChild("authorIds");
|
||||
authorIdsElement.ConsiderAsArray();
|
||||
@@ -1197,13 +1178,6 @@ void Project::SerializeTo(SerializerElement& element) const {
|
||||
for (std::size_t i = 0; i < externalLayouts.size(); ++i)
|
||||
externalLayouts[i]->SerializeTo(
|
||||
externalLayoutsElement.AddChild("externalLayout"));
|
||||
|
||||
SerializerElement& externalSourceFilesElement =
|
||||
element.AddChild("externalSourceFiles");
|
||||
externalSourceFilesElement.ConsiderAsArrayOf("sourceFile");
|
||||
for (std::size_t i = 0; i < externalSourceFiles.size(); ++i)
|
||||
externalSourceFiles[i]->SerializeTo(
|
||||
externalSourceFilesElement.AddChild("sourceFile"));
|
||||
}
|
||||
|
||||
bool Project::IsNameSafe(const gd::String& name) {
|
||||
@@ -1244,63 +1218,6 @@ gd::String Project::GetSafeName(const gd::String& name) {
|
||||
return newName;
|
||||
}
|
||||
|
||||
bool Project::HasSourceFile(gd::String name, gd::String language) const {
|
||||
vector<std::unique_ptr<SourceFile> >::const_iterator sourceFile =
|
||||
find_if(externalSourceFiles.begin(),
|
||||
externalSourceFiles.end(),
|
||||
[&name](const std::unique_ptr<SourceFile>& sourceFile) {
|
||||
return sourceFile->GetFileName() == name;
|
||||
});
|
||||
|
||||
if (sourceFile == externalSourceFiles.end()) return false;
|
||||
|
||||
return language.empty() || (*sourceFile)->GetLanguage() == language;
|
||||
}
|
||||
|
||||
gd::SourceFile& Project::GetSourceFile(const gd::String& name) {
|
||||
return *(*find_if(externalSourceFiles.begin(),
|
||||
externalSourceFiles.end(),
|
||||
[&name](const std::unique_ptr<SourceFile>& sourceFile) {
|
||||
return sourceFile->GetFileName() == name;
|
||||
}));
|
||||
}
|
||||
|
||||
const gd::SourceFile& Project::GetSourceFile(const gd::String& name) const {
|
||||
return *(*find_if(externalSourceFiles.begin(),
|
||||
externalSourceFiles.end(),
|
||||
[&name](const std::unique_ptr<SourceFile>& sourceFile) {
|
||||
return sourceFile->GetFileName() == name;
|
||||
}));
|
||||
}
|
||||
|
||||
void Project::RemoveSourceFile(const gd::String& name) {
|
||||
std::vector<std::unique_ptr<gd::SourceFile> >::iterator sourceFile =
|
||||
find_if(externalSourceFiles.begin(),
|
||||
externalSourceFiles.end(),
|
||||
[&name](const std::unique_ptr<SourceFile>& sourceFile) {
|
||||
return sourceFile->GetFileName() == name;
|
||||
});
|
||||
if (sourceFile == externalSourceFiles.end()) return;
|
||||
|
||||
externalSourceFiles.erase(sourceFile);
|
||||
}
|
||||
|
||||
gd::SourceFile& Project::InsertNewSourceFile(const gd::String& name,
|
||||
const gd::String& language,
|
||||
std::size_t position) {
|
||||
if (HasSourceFile(name, language)) return GetSourceFile(name);
|
||||
|
||||
gd::SourceFile& newlyInsertedSourceFile = *(
|
||||
*(externalSourceFiles.emplace(position < externalSourceFiles.size()
|
||||
? externalSourceFiles.begin() + position
|
||||
: externalSourceFiles.end(),
|
||||
new SourceFile())));
|
||||
newlyInsertedSourceFile.SetLanguage(language);
|
||||
newlyInsertedSourceFile.SetFileName(name);
|
||||
|
||||
return newlyInsertedSourceFile;
|
||||
}
|
||||
|
||||
Project::Project(const Project &other)
|
||||
: objectsContainer(gd::ObjectsContainer::SourceType::Global) {
|
||||
Init(other);
|
||||
@@ -1367,10 +1284,6 @@ void Project::Init(const gd::Project& game) {
|
||||
externalLayouts = gd::Clone(game.externalLayouts);
|
||||
eventsFunctionsExtensions = gd::Clone(game.eventsFunctionsExtensions);
|
||||
|
||||
useExternalSourceFiles = game.useExternalSourceFiles;
|
||||
|
||||
externalSourceFiles = gd::Clone(game.externalSourceFiles);
|
||||
|
||||
variables = game.GetVariables();
|
||||
|
||||
projectFile = game.GetProjectFile();
|
||||
|
@@ -32,7 +32,6 @@ class Object;
|
||||
class ObjectConfiguration;
|
||||
class VariablesContainer;
|
||||
class ArbitraryResourceWorker;
|
||||
class SourceFile;
|
||||
class Behavior;
|
||||
class BehaviorsSharedData;
|
||||
class BaseEvent;
|
||||
@@ -1019,56 +1018,6 @@ class GD_CORE_API Project {
|
||||
static gd::String GetSafeName(const gd::String& name);
|
||||
///@}
|
||||
|
||||
/** \name External source files
|
||||
* To manage external C++ or Javascript source files used by the game
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Return true if the game activated the use of external source files.
|
||||
*/
|
||||
bool UseExternalSourceFiles() const { return useExternalSourceFiles; }
|
||||
|
||||
/**
|
||||
* \brief Return a const reference to the vector containing all the source
|
||||
* files used by the game.
|
||||
*/
|
||||
const std::vector<std::unique_ptr<gd::SourceFile> >& GetAllSourceFiles()
|
||||
const {
|
||||
return externalSourceFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the source file with the specified name is used by
|
||||
* the game. \param name The filename of the source file. \param language
|
||||
* Optional. If specified, check that the source file that exists is in this
|
||||
* language.
|
||||
*/
|
||||
bool HasSourceFile(gd::String name, gd::String language = "") const;
|
||||
|
||||
/**
|
||||
* Return a reference to the external source file with the given name.
|
||||
*/
|
||||
SourceFile& GetSourceFile(const gd::String& name);
|
||||
|
||||
/**
|
||||
* Return a reference to the external source file with the given name.
|
||||
*/
|
||||
const SourceFile& GetSourceFile(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Remove the specified source file.
|
||||
*/
|
||||
void RemoveSourceFile(const gd::String& name);
|
||||
|
||||
/**
|
||||
* Add a new source file the specified position in the external source files
|
||||
* list.
|
||||
*/
|
||||
gd::SourceFile& InsertNewSourceFile(const gd::String& name,
|
||||
const gd::String& language,
|
||||
std::size_t position = -1);
|
||||
///@}
|
||||
|
||||
gd::WholeProjectDiagnosticReport& GetWholeProjectDiagnosticReport() {
|
||||
return wholeProjectDiagnosticReport;
|
||||
}
|
||||
@@ -1141,10 +1090,6 @@ class GD_CORE_API Project {
|
||||
std::vector<gd::Platform*>
|
||||
platforms; ///< Pointers to the platforms this project supports.
|
||||
gd::String firstLayout;
|
||||
bool useExternalSourceFiles =
|
||||
false; ///< True if game used external source files.
|
||||
std::vector<std::unique_ptr<gd::SourceFile> >
|
||||
externalSourceFiles; ///< List of external source files used.
|
||||
gd::String author; ///< Game author name, for publishing purpose.
|
||||
std::vector<gd::String>
|
||||
authorIds; ///< Game author ids, from GDevelop users DB.
|
||||
|
@@ -70,24 +70,29 @@ ProjectScopedContainers::MakeNewProjectScopedContainersForEventsFunctionsExtensi
|
||||
|
||||
ProjectScopedContainers
|
||||
ProjectScopedContainers::MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
const gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::ObjectsContainer ¶meterObjectsContainer) {
|
||||
gd::ObjectsContainer ¶meterObjectsContainer,
|
||||
gd::VariablesContainer ¶meterVariablesContainer) {
|
||||
|
||||
gd::EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
|
||||
project, eventsFunctionsExtension, eventsFunction, parameterObjectsContainer);
|
||||
project, eventsFunctionsExtension.GetEventsFunctions(), eventsFunction,
|
||||
parameterObjectsContainer);
|
||||
|
||||
ProjectScopedContainers projectScopedContainers(
|
||||
ObjectsContainersList::MakeNewObjectsContainersListForContainer(
|
||||
parameterObjectsContainer),
|
||||
VariablesContainersList::
|
||||
MakeNewVariablesContainersListForEventsFunctionsExtension(eventsFunctionsExtension),
|
||||
MakeNewVariablesContainersListForFreeEventsFunction(
|
||||
eventsFunctionsExtension, eventsFunction,
|
||||
parameterVariablesContainer),
|
||||
&eventsFunctionsExtension.GetGlobalVariables(),
|
||||
&eventsFunctionsExtension.GetSceneVariables(),
|
||||
PropertiesContainersList::MakeNewEmptyPropertiesContainersList());
|
||||
|
||||
projectScopedContainers.AddParameters(
|
||||
eventsFunction.GetParametersForEvents(eventsFunctionsExtension));
|
||||
projectScopedContainers.AddParameters(eventsFunction.GetParametersForEvents(
|
||||
eventsFunctionsExtension.GetEventsFunctions()));
|
||||
|
||||
return projectScopedContainers;
|
||||
};
|
||||
@@ -97,7 +102,9 @@ ProjectScopedContainers::MakeNewProjectScopedContainersForBehaviorEventsFunction
|
||||
const gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::ObjectsContainer ¶meterObjectsContainer) {
|
||||
gd::ObjectsContainer ¶meterObjectsContainer,
|
||||
gd::VariablesContainer ¶meterVariablesContainer,
|
||||
gd::VariablesContainer &propertyVariablesContainer) {
|
||||
|
||||
gd::EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
|
||||
project,
|
||||
@@ -109,7 +116,9 @@ ProjectScopedContainers::MakeNewProjectScopedContainersForBehaviorEventsFunction
|
||||
ObjectsContainersList::MakeNewObjectsContainersListForContainer(
|
||||
parameterObjectsContainer),
|
||||
VariablesContainersList::
|
||||
MakeNewVariablesContainersListForEventsFunctionsExtension(eventsFunctionsExtension),
|
||||
MakeNewVariablesContainersListForBehaviorEventsFunction(
|
||||
eventsFunctionsExtension, eventsBasedBehavior, eventsFunction,
|
||||
parameterVariablesContainer, propertyVariablesContainer),
|
||||
&eventsFunctionsExtension.GetGlobalVariables(),
|
||||
&eventsFunctionsExtension.GetSceneVariables(),
|
||||
PropertiesContainersList::MakeNewEmptyPropertiesContainersList());
|
||||
@@ -130,7 +139,9 @@ ProjectScopedContainers::MakeNewProjectScopedContainersForObjectEventsFunction(
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::ObjectsContainer ¶meterObjectsContainer) {
|
||||
gd::ObjectsContainer ¶meterObjectsContainer,
|
||||
gd::VariablesContainer ¶meterVariablesContainer,
|
||||
gd::VariablesContainer &propertyVariablesContainer) {
|
||||
|
||||
gd::EventsFunctionTools::ObjectEventsFunctionToObjectsContainer(
|
||||
project, eventsBasedObject, eventsFunction, parameterObjectsContainer);
|
||||
@@ -140,8 +151,9 @@ ProjectScopedContainers::MakeNewProjectScopedContainersForObjectEventsFunction(
|
||||
eventsBasedObject.GetObjects(),
|
||||
parameterObjectsContainer),
|
||||
VariablesContainersList::
|
||||
MakeNewVariablesContainersListForEventsFunctionsExtension(
|
||||
eventsFunctionsExtension),
|
||||
MakeNewVariablesContainersListForObjectEventsFunction(
|
||||
eventsFunctionsExtension, eventsBasedObject, eventsFunction,
|
||||
parameterVariablesContainer, propertyVariablesContainer),
|
||||
&eventsFunctionsExtension.GetGlobalVariables(),
|
||||
&eventsFunctionsExtension.GetSceneVariables(),
|
||||
PropertiesContainersList::MakeNewEmptyPropertiesContainersList());
|
||||
@@ -166,7 +178,7 @@ ProjectScopedContainers::MakeNewProjectScopedContainersForEventsBasedObject(
|
||||
// created below.
|
||||
// Search for "ProjectScopedContainers wrongly containing temporary objects containers or objects"
|
||||
// in the codebase.
|
||||
outputObjectsContainer.GetObjects().clear();
|
||||
outputObjectsContainer.Clear();
|
||||
outputObjectsContainer.GetObjectGroups().Clear();
|
||||
|
||||
// This object named "Object" represents the parent and is used by events.
|
||||
|
@@ -69,8 +69,9 @@ class ProjectScopedContainers {
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
const gd::Project &project,
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& parameterObjectsContainer);
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::ObjectsContainer ¶meterObjectsContainer,
|
||||
gd::VariablesContainer ¶meterVariablesContainer);
|
||||
|
||||
static ProjectScopedContainers
|
||||
MakeNewProjectScopedContainersForBehaviorEventsFunction(
|
||||
@@ -78,7 +79,9 @@ class ProjectScopedContainers {
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::ObjectsContainer ¶meterObjectsContainer);
|
||||
gd::ObjectsContainer ¶meterObjectsContainer,
|
||||
gd::VariablesContainer ¶meterVariablesContainer,
|
||||
gd::VariablesContainer &propertyVariablesContainer);
|
||||
|
||||
static ProjectScopedContainers
|
||||
MakeNewProjectScopedContainersForObjectEventsFunction(
|
||||
@@ -86,7 +89,9 @@ class ProjectScopedContainers {
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::ObjectsContainer ¶meterObjectsContainer);
|
||||
gd::ObjectsContainer ¶meterObjectsContainer,
|
||||
gd::VariablesContainer ¶meterVariablesContainer,
|
||||
gd::VariablesContainer &propertyVariablesContainer);
|
||||
|
||||
static ProjectScopedContainers
|
||||
MakeNewProjectScopedContainersForEventsBasedObject(
|
||||
@@ -124,9 +129,17 @@ class ProjectScopedContainers {
|
||||
std::function<ReturnType()> notFoundCallback) const {
|
||||
if (objectsContainersList.HasObjectOrGroupNamed(name))
|
||||
return objectCallback();
|
||||
else if (variablesContainersList.Has(name))
|
||||
else if (variablesContainersList.Has(name)) {
|
||||
const auto &variablesContainer =
|
||||
variablesContainersList.GetVariablesContainerFromVariableOrPropertyOrParameterName(name);
|
||||
const auto sourceType = variablesContainer.GetSourceType();
|
||||
if (sourceType == gd::VariablesContainer::SourceType::Properties) {
|
||||
return propertyCallback();
|
||||
} else if (sourceType == gd::VariablesContainer::SourceType::Parameters) {
|
||||
return parameterCallback();
|
||||
}
|
||||
return variableCallback();
|
||||
else if (ParameterMetadataTools::Has(parametersVectorsList, name))
|
||||
} else if (ParameterMetadataTools::Has(parametersVectorsList, name))
|
||||
return parameterCallback();
|
||||
else if (propertiesContainersList.Has(name))
|
||||
return propertyCallback();
|
||||
|
@@ -97,6 +97,8 @@ std::shared_ptr<Resource> ResourcesManager::CreateResource(
|
||||
return std::make_shared<AtlasResource>();
|
||||
else if (kind == "spine")
|
||||
return std::make_shared<SpineResource>();
|
||||
else if (kind == "javascript")
|
||||
return std::make_shared<JavaScriptResource>();
|
||||
|
||||
std::cout << "Bad resource created (type: " << kind << ")" << std::endl;
|
||||
return std::make_shared<Resource>();
|
||||
@@ -767,6 +769,20 @@ void AtlasResource::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("file", GetFile());
|
||||
}
|
||||
|
||||
void JavaScriptResource::SetFile(const gd::String& newFile) {
|
||||
file = NormalizePathSeparator(newFile);
|
||||
}
|
||||
|
||||
void JavaScriptResource::UnserializeFrom(const SerializerElement& element) {
|
||||
SetUserAdded(element.GetBoolAttribute("userAdded"));
|
||||
SetFile(element.GetStringAttribute("file"));
|
||||
}
|
||||
|
||||
void JavaScriptResource::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("userAdded", IsUserAdded());
|
||||
element.SetAttribute("file", GetFile());
|
||||
}
|
||||
|
||||
ResourceFolder::ResourceFolder(const ResourceFolder& other) { Init(other); }
|
||||
|
||||
ResourceFolder& ResourceFolder::operator=(const ResourceFolder& other) {
|
||||
|
@@ -547,6 +547,32 @@ class GD_CORE_API AtlasResource : public Resource {
|
||||
gd::String file;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Describe a video file used by a project.
|
||||
*
|
||||
* \see Resource
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API JavaScriptResource : public Resource {
|
||||
public:
|
||||
JavaScriptResource() : Resource() { SetKind("javascript"); };
|
||||
virtual ~JavaScriptResource(){};
|
||||
virtual JavaScriptResource* Clone() const override {
|
||||
return new JavaScriptResource(*this);
|
||||
}
|
||||
|
||||
virtual const gd::String& GetFile() const override { return file; };
|
||||
virtual void SetFile(const gd::String& newFile) override;
|
||||
|
||||
virtual bool UseFile() const override { return true; }
|
||||
void SerializeTo(SerializerElement& element) const override;
|
||||
|
||||
void UnserializeFrom(const SerializerElement& element) override;
|
||||
|
||||
private:
|
||||
gd::String file;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Inventory all resources used by a project
|
||||
*
|
||||
|
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include "GDCore/Project/SourceFile.h"
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
SourceFile::SourceFile() : gdManaged(false) {
|
||||
// ctor
|
||||
}
|
||||
|
||||
SourceFile::~SourceFile() {
|
||||
// dtor
|
||||
}
|
||||
|
||||
void SourceFile::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("filename", filename);
|
||||
element.SetAttribute("language", language);
|
||||
element.SetAttribute("gdManaged", gdManaged);
|
||||
}
|
||||
|
||||
void SourceFile::UnserializeFrom(const SerializerElement& element) {
|
||||
filename = element.GetStringAttribute("filename");
|
||||
language = element.GetStringAttribute("language", "C++");
|
||||
gdManaged = element.GetBoolAttribute("gdManaged");
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef SOURCEFILE_H
|
||||
#define SOURCEFILE_H
|
||||
#include <ctime>
|
||||
#include <memory>
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
class BaseEvent;
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Represents a "physical" source file.
|
||||
*
|
||||
* Source file can be compiled (or just integrated to the exported project)
|
||||
* by platforms. Most of the time, special events are provided to use functions
|
||||
* created in such files.
|
||||
*/
|
||||
class GD_CORE_API SourceFile {
|
||||
public:
|
||||
SourceFile();
|
||||
virtual ~SourceFile();
|
||||
|
||||
/**
|
||||
* \brief Return a pointer to a new SourceFile constructed from this one.
|
||||
*/
|
||||
SourceFile* Clone() const { return new SourceFile(*this); };
|
||||
|
||||
/**
|
||||
* \brief Get the filename
|
||||
*/
|
||||
gd::String GetFileName() const { return filename; };
|
||||
|
||||
/**
|
||||
* \brief Change the filename
|
||||
*/
|
||||
void SetFileName(gd::String filename_) { filename = filename_; };
|
||||
|
||||
/**
|
||||
* \brief Serialize the source file.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the source file.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
|
||||
/**
|
||||
* \brief Set if the file is hidden from the user point of view and is only
|
||||
* managed by GDevelop
|
||||
*/
|
||||
void SetGDManaged(bool gdManaged_) { gdManaged = gdManaged_; };
|
||||
|
||||
/**
|
||||
* \brief Return true if the file is hidden from the user point of view and is
|
||||
* only managed by GDevelop
|
||||
*/
|
||||
bool IsGDManaged() const { return gdManaged; };
|
||||
|
||||
/**
|
||||
* \brief Change the language of the source file
|
||||
*/
|
||||
void SetLanguage(gd::String lang) { language = lang; }
|
||||
|
||||
/**
|
||||
* \brief Get the language of the source file
|
||||
*/
|
||||
const gd::String& GetLanguage() const { return language; }
|
||||
|
||||
private:
|
||||
gd::String filename; ///< Filename
|
||||
bool gdManaged; ///< True if the source file is hidden from the user point of
|
||||
///< view and is managed only by GDevelop.
|
||||
gd::String language; ///< String identifying the language of this source file
|
||||
///< (typically "C++ or "Javascript").
|
||||
std::weak_ptr<BaseEvent>
|
||||
associatedGdEvent; ///< When a source file is GD-managed, it is usually
|
||||
///< created for a specific event. This member is not
|
||||
///< saved: It is the event responsibility to call
|
||||
///< SetAssociatedEvent.
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // SOURCEFILE_H
|
@@ -34,7 +34,9 @@ class GD_CORE_API VariablesContainer {
|
||||
Object,
|
||||
Local,
|
||||
ExtensionGlobal,
|
||||
ExtensionScene
|
||||
ExtensionScene,
|
||||
Parameters,
|
||||
Properties,
|
||||
};
|
||||
|
||||
VariablesContainer();
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/Variable.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/IDE/EventsFunctionTools.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -41,6 +42,78 @@ VariablesContainersList::MakeNewVariablesContainersListForEventsFunctionsExtensi
|
||||
return variablesContainersList;
|
||||
}
|
||||
|
||||
VariablesContainersList
|
||||
VariablesContainersList::MakeNewVariablesContainersListForFreeEventsFunction(
|
||||
const gd::EventsFunctionsExtension &extension,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::VariablesContainer ¶meterVariablesContainer) {
|
||||
VariablesContainersList variablesContainersList;
|
||||
variablesContainersList.Push(extension.GetGlobalVariables());
|
||||
variablesContainersList.Push(extension.GetSceneVariables());
|
||||
|
||||
gd::EventsFunctionTools::ParametersToVariablesContainer(
|
||||
eventsFunction.GetParametersForEvents(extension.GetEventsFunctions()),
|
||||
parameterVariablesContainer);
|
||||
variablesContainersList.Push(parameterVariablesContainer);
|
||||
|
||||
variablesContainersList.firstLocalVariableContainerIndex = 3;
|
||||
return variablesContainersList;
|
||||
}
|
||||
|
||||
VariablesContainersList VariablesContainersList::
|
||||
MakeNewVariablesContainersListForBehaviorEventsFunction(
|
||||
const gd::EventsFunctionsExtension &extension,
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::VariablesContainer ¶meterVariablesContainer,
|
||||
gd::VariablesContainer &propertyVariablesContainer) {
|
||||
VariablesContainersList variablesContainersList;
|
||||
variablesContainersList.Push(extension.GetGlobalVariables());
|
||||
variablesContainersList.Push(extension.GetSceneVariables());
|
||||
|
||||
gd::EventsFunctionTools::PropertiesToVariablesContainer(
|
||||
eventsBasedBehavior.GetSharedPropertyDescriptors(), propertyVariablesContainer);
|
||||
variablesContainersList.Push(propertyVariablesContainer);
|
||||
|
||||
gd::EventsFunctionTools::PropertiesToVariablesContainer(
|
||||
eventsBasedBehavior.GetPropertyDescriptors(), propertyVariablesContainer);
|
||||
variablesContainersList.Push(propertyVariablesContainer);
|
||||
|
||||
gd::EventsFunctionTools::ParametersToVariablesContainer(
|
||||
eventsFunction.GetParametersForEvents(
|
||||
eventsBasedBehavior.GetEventsFunctions()),
|
||||
parameterVariablesContainer);
|
||||
variablesContainersList.Push(parameterVariablesContainer);
|
||||
|
||||
variablesContainersList.firstLocalVariableContainerIndex = 5;
|
||||
return variablesContainersList;
|
||||
}
|
||||
|
||||
VariablesContainersList
|
||||
VariablesContainersList::MakeNewVariablesContainersListForObjectEventsFunction(
|
||||
const gd::EventsFunctionsExtension &extension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::VariablesContainer ¶meterVariablesContainer,
|
||||
gd::VariablesContainer &propertyVariablesContainer) {
|
||||
VariablesContainersList variablesContainersList;
|
||||
variablesContainersList.Push(extension.GetGlobalVariables());
|
||||
variablesContainersList.Push(extension.GetSceneVariables());
|
||||
|
||||
gd::EventsFunctionTools::PropertiesToVariablesContainer(
|
||||
eventsBasedObject.GetPropertyDescriptors(), propertyVariablesContainer);
|
||||
variablesContainersList.Push(propertyVariablesContainer);
|
||||
|
||||
gd::EventsFunctionTools::ParametersToVariablesContainer(
|
||||
eventsFunction.GetParametersForEvents(
|
||||
eventsBasedObject.GetEventsFunctions()),
|
||||
parameterVariablesContainer);
|
||||
variablesContainersList.Push(parameterVariablesContainer);
|
||||
|
||||
variablesContainersList.firstLocalVariableContainerIndex = 4;
|
||||
return variablesContainersList;
|
||||
}
|
||||
|
||||
VariablesContainersList
|
||||
VariablesContainersList::MakeNewVariablesContainersListPushing(
|
||||
const VariablesContainersList& variablesContainersList, const gd::VariablesContainer& variablesContainer) {
|
||||
@@ -74,7 +147,7 @@ const Variable& VariablesContainersList::Get(const gd::String& name) const {
|
||||
}
|
||||
|
||||
const VariablesContainer &
|
||||
VariablesContainersList::GetVariablesContainerFromVariableName(
|
||||
VariablesContainersList::GetVariablesContainerFromVariableOrPropertyOrParameterName(
|
||||
const gd::String &variableName) const {
|
||||
for (auto it = variablesContainers.rbegin(); it != variablesContainers.rend();
|
||||
++it) {
|
||||
@@ -84,6 +157,34 @@ VariablesContainersList::GetVariablesContainerFromVariableName(
|
||||
return badVariablesContainer;
|
||||
}
|
||||
|
||||
const VariablesContainer &VariablesContainersList::
|
||||
GetVariablesContainerFromVariableOrPropertyName(
|
||||
const gd::String &variableName) const {
|
||||
for (auto it = variablesContainers.rbegin(); it != variablesContainers.rend();
|
||||
++it) {
|
||||
if ((*it)->GetSourceType() !=
|
||||
gd::VariablesContainer::SourceType::Parameters &&
|
||||
(*it)->Has(variableName))
|
||||
return **it;
|
||||
}
|
||||
return badVariablesContainer;
|
||||
}
|
||||
|
||||
const VariablesContainer &VariablesContainersList::
|
||||
GetVariablesContainerFromVariableNameOnly(
|
||||
const gd::String &variableName) const {
|
||||
for (auto it = variablesContainers.rbegin(); it != variablesContainers.rend();
|
||||
++it) {
|
||||
if ((*it)->GetSourceType() !=
|
||||
gd::VariablesContainer::SourceType::Parameters &&
|
||||
(*it)->GetSourceType() !=
|
||||
gd::VariablesContainer::SourceType::Properties &&
|
||||
(*it)->Has(variableName))
|
||||
return **it;
|
||||
}
|
||||
return badVariablesContainer;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
VariablesContainersList::GetVariablesContainerPositionFromVariableName(
|
||||
const gd::String &variableName) const {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace gd {
|
||||
class String;
|
||||
@@ -9,7 +9,10 @@ class Layout;
|
||||
class VariablesContainer;
|
||||
class Variable;
|
||||
class EventsFunctionsExtension;
|
||||
} // namespace gd
|
||||
class EventsBasedBehavior;
|
||||
class EventsBasedObject;
|
||||
class EventsFunction;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -24,20 +27,42 @@ namespace gd {
|
||||
* \ingroup PlatformDefinition
|
||||
*/
|
||||
class GD_CORE_API VariablesContainersList {
|
||||
public:
|
||||
public:
|
||||
virtual ~VariablesContainersList(){};
|
||||
|
||||
static VariablesContainersList
|
||||
MakeNewVariablesContainersListForProjectAndLayout(const gd::Project& project,
|
||||
const gd::Layout& layout);
|
||||
MakeNewVariablesContainersListForProjectAndLayout(const gd::Project &project,
|
||||
const gd::Layout &layout);
|
||||
|
||||
static VariablesContainersList
|
||||
MakeNewVariablesContainersListForProject(const gd::Project& project);
|
||||
MakeNewVariablesContainersListForProject(const gd::Project &project);
|
||||
|
||||
static VariablesContainersList
|
||||
MakeNewVariablesContainersListForEventsFunctionsExtension(
|
||||
const gd::EventsFunctionsExtension &extension);
|
||||
|
||||
static VariablesContainersList
|
||||
MakeNewVariablesContainersListForFreeEventsFunction(
|
||||
const gd::EventsFunctionsExtension &extension,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::VariablesContainer ¶meterVariablesContainer);
|
||||
|
||||
static VariablesContainersList
|
||||
MakeNewVariablesContainersListForBehaviorEventsFunction(
|
||||
const gd::EventsFunctionsExtension &extension,
|
||||
const gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::VariablesContainer ¶meterVariablesContainer,
|
||||
gd::VariablesContainer &propertyVariablesContainer);
|
||||
|
||||
static VariablesContainersList
|
||||
MakeNewVariablesContainersListForObjectEventsFunction(
|
||||
const gd::EventsFunctionsExtension &extension,
|
||||
const gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::EventsFunction &eventsFunction,
|
||||
gd::VariablesContainer ¶meterVariablesContainer,
|
||||
gd::VariablesContainer &propertyVariablesContainer);
|
||||
|
||||
static VariablesContainersList MakeNewVariablesContainersListPushing(
|
||||
const VariablesContainersList &variablesContainersList,
|
||||
const gd::VariablesContainer &variablesContainer);
|
||||
@@ -50,28 +75,31 @@ class GD_CORE_API VariablesContainersList {
|
||||
/**
|
||||
* \brief Return true if the specified variable is in one of the containers.
|
||||
*/
|
||||
bool Has(const gd::String& name) const;
|
||||
bool Has(const gd::String &name) const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the variable called \a name.
|
||||
*/
|
||||
const Variable& Get(const gd::String& name) const;
|
||||
const Variable &Get(const gd::String &name) const;
|
||||
|
||||
/**
|
||||
* \brief Return true if the specified variable container is present.
|
||||
*/
|
||||
bool HasVariablesContainer(const gd::VariablesContainer& variablesContainer) const;
|
||||
bool
|
||||
HasVariablesContainer(const gd::VariablesContainer &variablesContainer) const;
|
||||
|
||||
// TODO: Rename GetTopMostVariablesContainer and GetBottomMostVariablesContainer
|
||||
// to give a clearer access to segments of the container list.
|
||||
// For instance, a project tree segment and an event tree segment.
|
||||
// TODO: Rename GetTopMostVariablesContainer and
|
||||
// GetBottomMostVariablesContainer to give a clearer access to segments of the
|
||||
// container list. For instance, a project tree segment and an event tree
|
||||
// segment.
|
||||
|
||||
/**
|
||||
* Get the variables container at the top of the scope (so the most "global" one).
|
||||
* \brief Avoid using apart when a scope must be forced.
|
||||
* Get the variables container at the top of the scope (so the most "global"
|
||||
* one). \brief Avoid using apart when a scope must be forced.
|
||||
*/
|
||||
const VariablesContainer* GetTopMostVariablesContainer() const {
|
||||
if (variablesContainers.empty()) return nullptr;
|
||||
const VariablesContainer *GetTopMostVariablesContainer() const {
|
||||
if (variablesContainers.empty())
|
||||
return nullptr;
|
||||
return variablesContainers.front();
|
||||
};
|
||||
|
||||
@@ -80,16 +108,29 @@ class GD_CORE_API VariablesContainersList {
|
||||
* (so the most "local" one) excluding local variables.
|
||||
* \brief Avoid using apart when a scope must be forced.
|
||||
*/
|
||||
const VariablesContainer* GetBottomMostVariablesContainer() const {
|
||||
if (variablesContainers.empty()) return nullptr;
|
||||
const VariablesContainer *GetBottomMostVariablesContainer() const {
|
||||
if (variablesContainers.empty())
|
||||
return nullptr;
|
||||
return variablesContainers.at(firstLocalVariableContainerIndex - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the variables container for a given variable or property or parameter.
|
||||
*/
|
||||
const VariablesContainer &
|
||||
GetVariablesContainerFromVariableOrPropertyOrParameterName(const gd::String &variableName) const;
|
||||
|
||||
/**
|
||||
* Get the variables container for a given variable or property.
|
||||
*/
|
||||
const VariablesContainer &
|
||||
GetVariablesContainerFromVariableOrPropertyName(const gd::String &variableName) const;
|
||||
|
||||
/**
|
||||
* Get the variables container for a given variable.
|
||||
*/
|
||||
const VariablesContainer &
|
||||
GetVariablesContainerFromVariableName(const gd::String &variableName) const;
|
||||
GetVariablesContainerFromVariableNameOnly(const gd::String &variableName) const;
|
||||
|
||||
/**
|
||||
* Get the variables container index for a given variable.
|
||||
@@ -109,43 +150,47 @@ class GD_CORE_API VariablesContainersList {
|
||||
* \warning Trying to access to a not existing variable container will result
|
||||
* in undefined behavior.
|
||||
*/
|
||||
const gd::VariablesContainer& GetVariablesContainer(std::size_t index) const {
|
||||
const gd::VariablesContainer &GetVariablesContainer(std::size_t index) const {
|
||||
return *variablesContainers.at(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the number variable containers.
|
||||
*/
|
||||
std::size_t GetVariablesContainersCount() const { return variablesContainers.size(); }
|
||||
std::size_t GetVariablesContainersCount() const {
|
||||
return variablesContainers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Call the callback for each variable having a name matching the specified search.
|
||||
* \brief Call the callback for each variable having a name matching the
|
||||
* specified search.
|
||||
*/
|
||||
void ForEachVariableMatchingSearch(const gd::String& search, std::function<void(const gd::String& name, const gd::Variable& variable)> fn) const;
|
||||
void ForEachVariableMatchingSearch(
|
||||
const gd::String &search,
|
||||
std::function<void(const gd::String &name, const gd::Variable &variable)>
|
||||
fn) const;
|
||||
|
||||
/**
|
||||
* \brief Push a new variables container to the context.
|
||||
*/
|
||||
void Push(const gd::VariablesContainer& variablesContainer) {
|
||||
void Push(const gd::VariablesContainer &variablesContainer) {
|
||||
variablesContainers.push_back(&variablesContainer);
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Pop a variables container from the context.
|
||||
*/
|
||||
void Pop() {
|
||||
variablesContainers.pop_back();
|
||||
};
|
||||
void Pop() { variablesContainers.pop_back(); };
|
||||
|
||||
/** Do not use - should be private but accessible to let Emscripten create a
|
||||
* temporary. */
|
||||
VariablesContainersList() : firstLocalVariableContainerIndex(0){};
|
||||
|
||||
/** Do not use - should be private but accessible to let Emscripten create a temporary. */
|
||||
VariablesContainersList(): firstLocalVariableContainerIndex(0) {};
|
||||
private:
|
||||
|
||||
std::vector<const gd::VariablesContainer*> variablesContainers;
|
||||
private:
|
||||
std::vector<const gd::VariablesContainer *> variablesContainers;
|
||||
std::size_t firstLocalVariableContainerIndex;
|
||||
static Variable badVariable;
|
||||
static VariablesContainer badVariablesContainer;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
} // namespace gd
|
@@ -268,8 +268,9 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
||||
ArbitraryResourceWorkerTest worker(project.GetResourcesManager());
|
||||
|
||||
auto& extension = project.InsertNewEventsFunctionsExtension("MyEventExtension", 0);
|
||||
auto& function = extension.InsertNewEventsFunction("MyFreeFunction", 0);
|
||||
|
||||
auto &function = extension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeFunction", 0);
|
||||
|
||||
gd::StandardEvent standardEvent;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("MyExtension::DoSomethingWithResources");
|
||||
@@ -777,8 +778,9 @@ TEST_CASE("ArbitraryResourceWorker", "[common][resources]") {
|
||||
ArbitraryResourceWorkerTest worker(project.GetResourcesManager());
|
||||
|
||||
auto& extension = project.InsertNewEventsFunctionsExtension("MyEventExtension", 0);
|
||||
auto& function = extension.InsertNewEventsFunction("MyFreeFunction", 0);
|
||||
|
||||
auto &function = extension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeFunction", 0);
|
||||
|
||||
gd::StandardEvent standardEvent;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("MyExtension::DoSomethingWithResources");
|
||||
|
@@ -32,7 +32,6 @@ TEST_CASE("DependenciesAnalyzer", "[common]") {
|
||||
REQUIRE(analyzer.GetScenesDependencies().find("Layout2") !=
|
||||
analyzer.GetScenesDependencies().end());
|
||||
REQUIRE(analyzer.GetExternalEventsDependencies().size() == 0);
|
||||
REQUIRE(analyzer.GetSourceFilesDependencies().size() == 0);
|
||||
}
|
||||
|
||||
SECTION("Can detect a simple external events dependency") {
|
||||
@@ -55,7 +54,6 @@ TEST_CASE("DependenciesAnalyzer", "[common]") {
|
||||
REQUIRE(analyzer.GetExternalEventsDependencies().size() == 1);
|
||||
REQUIRE(analyzer.GetExternalEventsDependencies().find("ExternalEvents1") !=
|
||||
analyzer.GetExternalEventsDependencies().end());
|
||||
REQUIRE(analyzer.GetSourceFilesDependencies().size() == 0);
|
||||
}
|
||||
|
||||
SECTION("Can detect a transitive scene and external events dependency") {
|
||||
@@ -87,7 +85,6 @@ TEST_CASE("DependenciesAnalyzer", "[common]") {
|
||||
REQUIRE(analyzer.GetExternalEventsDependencies().size() == 1);
|
||||
REQUIRE(analyzer.GetExternalEventsDependencies().find("ExternalEvents1") !=
|
||||
analyzer.GetExternalEventsDependencies().end());
|
||||
REQUIRE(analyzer.GetSourceFilesDependencies().size() == 0);
|
||||
}
|
||||
|
||||
SECTION("Can detect a (nested) circular dependency with scenes") {
|
||||
|
@@ -263,6 +263,46 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
|
||||
extension->SetExtensionInformation(
|
||||
"BuiltinVariables", "My testing extension for variables", "", "", "");
|
||||
|
||||
extension
|
||||
->AddCondition("NumberVariable",
|
||||
"Variable value",
|
||||
"Compare the number value of a variable.",
|
||||
"The variable _PARAM0_",
|
||||
"",
|
||||
"",
|
||||
"")
|
||||
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", gd::ParameterOptions::MakeNewOptions());
|
||||
|
||||
extension
|
||||
->AddCondition("StringVariable",
|
||||
"Variable value",
|
||||
"Compare the text (string) of a variable.",
|
||||
"The variable _PARAM0_",
|
||||
"",
|
||||
"",
|
||||
"")
|
||||
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string", gd::ParameterOptions::MakeNewOptions());
|
||||
|
||||
extension
|
||||
->AddCondition(
|
||||
"BooleanVariable",
|
||||
"Variable value",
|
||||
"Compare the boolean value of a variable.",
|
||||
"The variable _PARAM0_ is _PARAM1_",
|
||||
"",
|
||||
"",
|
||||
"")
|
||||
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
|
||||
.AddParameter("trueorfalse", _("Check if the value is"))
|
||||
.SetDefaultValue("true")
|
||||
// This parameter allows to keep the operand expression
|
||||
// when the editor switch between variable instructions.
|
||||
.AddCodeOnlyParameter("trueorfalse", "");
|
||||
|
||||
extension
|
||||
->AddAction("SetNumberVariable",
|
||||
"Change variable value",
|
||||
@@ -271,7 +311,7 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
|
||||
"",
|
||||
"",
|
||||
"")
|
||||
.AddParameter("variable", "Variable")
|
||||
.AddParameter("variableOrProperty", "Variable")
|
||||
.AddParameter("operator", "Operator", "number")
|
||||
.AddParameter("number", "Value")
|
||||
.SetFunctionName("setNumberVariable");
|
||||
@@ -284,7 +324,7 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
|
||||
"",
|
||||
"",
|
||||
"")
|
||||
.AddParameter("variable", "Variable")
|
||||
.AddParameter("variableOrProperty", "Variable")
|
||||
.AddParameter("operator", "Operator", "string")
|
||||
.AddParameter("string", "Value")
|
||||
.SetFunctionName("setStringVariable");
|
||||
@@ -297,7 +337,7 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
|
||||
"",
|
||||
"",
|
||||
"")
|
||||
.AddParameter("variable", "Variable")
|
||||
.AddParameter("variableOrProperty", "Variable")
|
||||
.AddParameter("operator", "Operator", "boolean")
|
||||
// This parameter allows to keep the operand expression
|
||||
// when the editor switch between variable instructions.
|
||||
|
@@ -38,6 +38,8 @@ TEST_CASE("EventsFunctionsContainer", "[common]") {
|
||||
"Function2.x");
|
||||
REQUIRE(eventsFunctionContainer.GetEventsFunction(2).GetName() ==
|
||||
"Function3");
|
||||
REQUIRE(eventsFunctionContainer.GetOwner() ==
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Extension);
|
||||
REQUIRE(eventsFunctionContainer2.GetEventsFunctionsCount() == 3);
|
||||
REQUIRE(eventsFunctionContainer2.GetEventsFunction(0).GetName() ==
|
||||
"Function1.y");
|
||||
|
@@ -11,9 +11,10 @@
|
||||
TEST_CASE("EventsFunctionsExtension", "[common]") {
|
||||
SECTION("Sanity checks") {
|
||||
gd::EventsFunctionsExtension eventsFunctionExtension;
|
||||
eventsFunctionExtension.InsertNewEventsFunction("Function1", 0);
|
||||
eventsFunctionExtension.InsertNewEventsFunction("Function2", 1);
|
||||
eventsFunctionExtension.InsertNewEventsFunction("Function3", 2);
|
||||
auto &freeEventsFunctions = eventsFunctionExtension.GetEventsFunctions();
|
||||
freeEventsFunctions.InsertNewEventsFunction("Function1", 0);
|
||||
freeEventsFunctions.InsertNewEventsFunction("Function2", 1);
|
||||
freeEventsFunctions.InsertNewEventsFunction("Function3", 2);
|
||||
eventsFunctionExtension.GetEventsBasedBehaviors().InsertNew("MyBehavior",
|
||||
0);
|
||||
eventsFunctionExtension.GetEventsBasedBehaviors().InsertNew("MyBehavior2",
|
||||
@@ -22,12 +23,13 @@ TEST_CASE("EventsFunctionsExtension", "[common]") {
|
||||
// Check that copy operator is working
|
||||
gd::EventsFunctionsExtension eventsFunctionExtension2 =
|
||||
eventsFunctionExtension;
|
||||
REQUIRE(eventsFunctionExtension2.GetEventsFunctionsCount() == 3);
|
||||
REQUIRE(eventsFunctionExtension2.GetEventsFunction(0).GetName() ==
|
||||
auto &freeEventsFunctions2 = eventsFunctionExtension2.GetEventsFunctions();
|
||||
REQUIRE(freeEventsFunctions2.GetEventsFunctionsCount() == 3);
|
||||
REQUIRE(freeEventsFunctions2.GetEventsFunction(0).GetName() ==
|
||||
"Function1");
|
||||
REQUIRE(eventsFunctionExtension2.GetEventsFunction(1).GetName() ==
|
||||
REQUIRE(freeEventsFunctions2.GetEventsFunction(1).GetName() ==
|
||||
"Function2");
|
||||
REQUIRE(eventsFunctionExtension2.GetEventsFunction(2).GetName() ==
|
||||
REQUIRE(freeEventsFunctions2.GetEventsFunction(2).GetName() ==
|
||||
"Function3");
|
||||
REQUIRE(eventsFunctionExtension2.GetEventsBasedBehaviors().GetCount() == 2);
|
||||
REQUIRE(
|
||||
@@ -39,21 +41,21 @@ TEST_CASE("EventsFunctionsExtension", "[common]") {
|
||||
|
||||
// Check that the copy has not somehow shared the same pointers
|
||||
// to the events functions.
|
||||
eventsFunctionExtension.GetEventsFunction(1).SetName("Function2.x");
|
||||
eventsFunctionExtension2.GetEventsFunction(0).SetName("Function1.y");
|
||||
REQUIRE(eventsFunctionExtension.GetEventsFunctionsCount() == 3);
|
||||
REQUIRE(eventsFunctionExtension.GetEventsFunction(0).GetName() ==
|
||||
freeEventsFunctions.GetEventsFunction(1).SetName("Function2.x");
|
||||
freeEventsFunctions2.GetEventsFunction(0).SetName("Function1.y");
|
||||
REQUIRE(freeEventsFunctions.GetEventsFunctionsCount() == 3);
|
||||
REQUIRE(freeEventsFunctions.GetEventsFunction(0).GetName() ==
|
||||
"Function1");
|
||||
REQUIRE(eventsFunctionExtension.GetEventsFunction(1).GetName() ==
|
||||
REQUIRE(freeEventsFunctions.GetEventsFunction(1).GetName() ==
|
||||
"Function2.x");
|
||||
REQUIRE(eventsFunctionExtension.GetEventsFunction(2).GetName() ==
|
||||
REQUIRE(freeEventsFunctions.GetEventsFunction(2).GetName() ==
|
||||
"Function3");
|
||||
REQUIRE(eventsFunctionExtension2.GetEventsFunctionsCount() == 3);
|
||||
REQUIRE(eventsFunctionExtension2.GetEventsFunction(0).GetName() ==
|
||||
REQUIRE(freeEventsFunctions2.GetEventsFunctionsCount() == 3);
|
||||
REQUIRE(freeEventsFunctions2.GetEventsFunction(0).GetName() ==
|
||||
"Function1.y");
|
||||
REQUIRE(eventsFunctionExtension2.GetEventsFunction(1).GetName() ==
|
||||
REQUIRE(freeEventsFunctions2.GetEventsFunction(1).GetName() ==
|
||||
"Function2");
|
||||
REQUIRE(eventsFunctionExtension2.GetEventsFunction(2).GetName() ==
|
||||
REQUIRE(freeEventsFunctions2.GetEventsFunction(2).GetName() ==
|
||||
"Function3");
|
||||
}
|
||||
}
|
||||
|
@@ -2035,6 +2035,319 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Valid property (in variableOrPropertyOrParameter parameter)") {
|
||||
{
|
||||
gd::PropertiesContainer propertiesContainer(
|
||||
gd::EventsFunctionsContainer::Extension);
|
||||
|
||||
auto projectScopedContainersWithProperties = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
projectScopedContainersWithProperties.AddPropertiesContainer(
|
||||
propertiesContainer);
|
||||
|
||||
propertiesContainer.InsertNew("MyProperty");
|
||||
|
||||
auto node = parser.ParseExpression("MyProperty");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithProperties,
|
||||
"variableOrPropertyOrParameter");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetAllErrors().size() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Valid property (in variableOrProperty parameter)") {
|
||||
{
|
||||
gd::PropertiesContainer propertiesContainer(
|
||||
gd::EventsFunctionsContainer::Extension);
|
||||
|
||||
auto projectScopedContainersWithProperties = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
projectScopedContainersWithProperties.AddPropertiesContainer(
|
||||
propertiesContainer);
|
||||
|
||||
propertiesContainer.InsertNew("MyProperty");
|
||||
|
||||
auto node = parser.ParseExpression("MyProperty");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithProperties,
|
||||
"variableOrProperty");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetAllErrors().size() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Invalid property (in variable parameter)") {
|
||||
{
|
||||
gd::PropertiesContainer propertiesContainer(
|
||||
gd::EventsFunctionsContainer::Extension);
|
||||
|
||||
auto projectScopedContainersWithProperties = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
projectScopedContainersWithProperties.AddPropertiesContainer(
|
||||
propertiesContainer);
|
||||
|
||||
propertiesContainer.InsertNew("MyProperty");
|
||||
|
||||
auto node = parser.ParseExpression("MyProperty");
|
||||
|
||||
gd::ExpressionValidator validator(
|
||||
platform, projectScopedContainersWithProperties, "variable");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetAllErrors().size() == 1);
|
||||
REQUIRE(validator.GetAllErrors()[0]->GetMessage() ==
|
||||
"This variable has the same name as a property. Consider "
|
||||
"renaming one or the other.");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Invalid property (property with child in variableOrProperty parameter)") {
|
||||
{
|
||||
gd::PropertiesContainer propertiesContainer(
|
||||
gd::EventsFunctionsContainer::Extension);
|
||||
|
||||
auto projectScopedContainersWithProperties = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
projectScopedContainersWithProperties.AddPropertiesContainer(
|
||||
propertiesContainer);
|
||||
|
||||
propertiesContainer.InsertNew("MyProperty");
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyProperty.MyChild");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithProperties,
|
||||
"variableOrProperty");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyProperty.MyChild.MyGrandChild");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithProperties,
|
||||
"variableOrProperty");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyProperty[\"MyChild\"]");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithProperties,
|
||||
"variableOrProperty");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyProperty[0]");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithProperties,
|
||||
"variableOrProperty");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Invalid property (property with child in variableOrPropertyOrParameter parameter)") {
|
||||
{
|
||||
gd::PropertiesContainer propertiesContainer(
|
||||
gd::EventsFunctionsContainer::Extension);
|
||||
|
||||
auto projectScopedContainersWithProperties = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
projectScopedContainersWithProperties.AddPropertiesContainer(
|
||||
propertiesContainer);
|
||||
|
||||
propertiesContainer.InsertNew("MyProperty");
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyProperty.MyChild");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithProperties,
|
||||
"variableOrPropertyOrParameter");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyProperty.MyChild.MyGrandChild");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithProperties,
|
||||
"variableOrPropertyOrParameter");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyProperty[\"MyChild\"]");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithProperties,
|
||||
"variableOrPropertyOrParameter");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyProperty[0]");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithProperties,
|
||||
"variableOrPropertyOrParameter");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Valid parameter (in variableOrPropertyOrParameter parameter)") {
|
||||
{
|
||||
gd::ParameterMetadataContainer parameters;
|
||||
parameters.InsertNewParameter("MyParameter", 0).SetType("number");
|
||||
|
||||
auto projectScopedContainersWithParameters = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
projectScopedContainersWithParameters.AddParameters(parameters);
|
||||
|
||||
auto node = parser.ParseExpression("MyParameter");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithParameters,
|
||||
"variableOrPropertyOrParameter");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetAllErrors().size() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Invalid parameter (in variableOrProperty parameter)") {
|
||||
{
|
||||
gd::ParameterMetadataContainer parameters;
|
||||
parameters.InsertNewParameter("MyParameter", 0).SetType("number");
|
||||
|
||||
auto projectScopedContainersWithParameters = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
projectScopedContainersWithParameters.AddParameters(parameters);
|
||||
|
||||
auto node = parser.ParseExpression("MyParameter");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithParameters,
|
||||
"variableOrProperty");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetAllErrors().size() == 1);
|
||||
REQUIRE(validator.GetAllErrors()[0]->GetMessage() ==
|
||||
"This variable has the same name as a parameter. Consider "
|
||||
"renaming one or the other.");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Invalid parameter (in variable parameter)") {
|
||||
{
|
||||
gd::ParameterMetadataContainer parameters;
|
||||
parameters.InsertNewParameter("MyParameter", 0).SetType("number");
|
||||
|
||||
auto projectScopedContainersWithParameters = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
projectScopedContainersWithParameters.AddParameters(parameters);
|
||||
|
||||
auto node = parser.ParseExpression("MyParameter");
|
||||
|
||||
gd::ExpressionValidator validator(
|
||||
platform, projectScopedContainersWithParameters, "variable");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetAllErrors().size() == 1);
|
||||
REQUIRE(validator.GetAllErrors()[0]->GetMessage() ==
|
||||
"This variable has the same name as a parameter. Consider "
|
||||
"renaming one or the other.");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Invalid parameter (parameter with child in variableOrPropertyOrParameter parameter)") {
|
||||
{
|
||||
gd::ParameterMetadataContainer parameters;
|
||||
parameters.InsertNewParameter("MyParameter", 0).SetType("number");
|
||||
|
||||
auto projectScopedContainersWithParameters = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForProjectAndLayout(project, layout1);
|
||||
projectScopedContainersWithParameters.AddParameters(parameters);
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyParameter.MyChild");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithParameters,
|
||||
"variableOrPropertyOrParameter");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyParameter.MyChild.MyGrandChild");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithParameters,
|
||||
"variableOrPropertyOrParameter");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyParameter[\"MyChild\"]");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithParameters,
|
||||
"variableOrPropertyOrParameter");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
|
||||
{
|
||||
auto node = parser.ParseExpression("MyParameter[0]");
|
||||
|
||||
gd::ExpressionValidator validator(platform,
|
||||
projectScopedContainersWithParameters,
|
||||
"variableOrPropertyOrParameter");
|
||||
node->Visit(validator);
|
||||
REQUIRE(validator.GetFatalErrors().size() == 1);
|
||||
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
|
||||
"Properties can't have children.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Valid parameter") {
|
||||
gd::ParameterMetadataContainer parameters;
|
||||
parameters.InsertNewParameter("MyParameter1", 0).SetType("number");
|
||||
|
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
/**
|
||||
* @file Tests covering common features of GDevelop Core.
|
||||
*/
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/SourceFile.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
TEST_CASE("SourceFile", "[common]") {
|
||||
SECTION("Basics") {
|
||||
gd::Project project;
|
||||
project.InsertNewSourceFile("test.cpp", "C++");
|
||||
project.InsertNewSourceFile("test.js", "Javascript");
|
||||
REQUIRE(project.HasSourceFile("test.cpp", "C++") == true);
|
||||
REQUIRE(project.HasSourceFile("test.cpp", "JS") == false);
|
||||
REQUIRE(project.HasSourceFile("test.cpp") == true);
|
||||
gd::SourceFile& cppSourceFile = project.GetSourceFile("test.cpp");
|
||||
REQUIRE(cppSourceFile.GetFileName() == "test.cpp");
|
||||
REQUIRE(cppSourceFile.GetLanguage() == "C++");
|
||||
|
||||
project.RemoveSourceFile("test.cpp");
|
||||
REQUIRE(project.HasSourceFile("test.cpp") == false);
|
||||
REQUIRE(project.HasSourceFile("test.js") == true);
|
||||
}
|
||||
}
|
@@ -1540,7 +1540,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto projectScopedContainers =
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, scene);
|
||||
REQUIRE(&projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName("MyVariable") == &scene.GetVariables());
|
||||
.GetVariablesContainerFromVariableOrPropertyOrParameterName("MyVariable") == &scene.GetVariables());
|
||||
|
||||
// Do the changes and launch the refactoring.
|
||||
scene.GetVariables().ResetPersistentUuid();
|
||||
@@ -1722,7 +1722,8 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer",
|
||||
auto &extension = project.InsertNewEventsFunctionsExtension("Extension", 0);
|
||||
extension.GetSceneVariables().InsertNew("MySceneVariable").SetValue(123);
|
||||
|
||||
auto &function = extension.InsertNewEventsFunction("MyFunction", 0);
|
||||
auto &function =
|
||||
extension.GetEventsFunctions().InsertNewEventsFunction("MyFunction", 0);
|
||||
gd::StandardEvent &event =
|
||||
dynamic_cast<gd::StandardEvent &>(function.GetEvents().InsertNewEvent(
|
||||
project, "BuiltinCommonInstructions::Standard"));
|
||||
|
@@ -136,6 +136,74 @@ CreateInstructionWithVariableParameter(gd::Project &project,
|
||||
return event.GetActions().Insert(instruction);
|
||||
}
|
||||
|
||||
const gd::Instruction &
|
||||
CreateNumberVariableSetterAction(gd::Project &project,
|
||||
gd::EventsList &events,
|
||||
const gd::String &variableName,
|
||||
const gd::String &expression) {
|
||||
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
|
||||
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
|
||||
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("SetNumberVariable");
|
||||
instruction.SetParametersCount(3);
|
||||
instruction.SetParameter(0, variableName);
|
||||
instruction.SetParameter(1, "=");
|
||||
instruction.SetParameter(2, expression);
|
||||
return event.GetActions().Insert(instruction);
|
||||
}
|
||||
|
||||
const gd::Instruction &
|
||||
CreateNumberVariableGetterCondition(gd::Project &project,
|
||||
gd::EventsList &events,
|
||||
const gd::String &variableName,
|
||||
const gd::String &expression) {
|
||||
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
|
||||
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
|
||||
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("NumberVariable");
|
||||
instruction.SetParametersCount(3);
|
||||
instruction.SetParameter(0, variableName);
|
||||
instruction.SetParameter(1, "=");
|
||||
instruction.SetParameter(2, expression);
|
||||
return event.GetConditions().Insert(instruction);
|
||||
}
|
||||
|
||||
const gd::Instruction &
|
||||
CreateStringVariableSetterAction(gd::Project &project,
|
||||
gd::EventsList &events,
|
||||
const gd::String &variableName,
|
||||
const gd::String &expression) {
|
||||
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
|
||||
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
|
||||
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("SetStringVariable");
|
||||
instruction.SetParametersCount(3);
|
||||
instruction.SetParameter(0, variableName);
|
||||
instruction.SetParameter(1, "=");
|
||||
instruction.SetParameter(2, expression);
|
||||
return event.GetActions().Insert(instruction);
|
||||
}
|
||||
|
||||
const gd::Instruction &
|
||||
CreateStringVariableGetterCondition(gd::Project &project,
|
||||
gd::EventsList &events,
|
||||
const gd::String &variableName,
|
||||
const gd::String &expression) {
|
||||
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
|
||||
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
|
||||
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("StringVariable");
|
||||
instruction.SetParametersCount(3);
|
||||
instruction.SetParameter(0, variableName);
|
||||
instruction.SetParameter(1, "=");
|
||||
instruction.SetParameter(2, expression);
|
||||
return event.GetConditions().Insert(instruction);
|
||||
}
|
||||
|
||||
enum TestEvent {
|
||||
FreeFunctionAction,
|
||||
FreeFunctionWithExpression,
|
||||
@@ -201,8 +269,9 @@ const std::vector<const gd::EventsList *> GetEventsListsNotAssociatedToScene(gd:
|
||||
.GetEventsFunctions()
|
||||
.GetEventsFunction("MyBehaviorEventsFunction")
|
||||
.GetEvents();
|
||||
auto &freeFunctionEvents =
|
||||
eventsExtension.GetEventsFunction("MyOtherEventsFunction").GetEvents();
|
||||
auto &freeFunctionEvents = eventsExtension.GetEventsFunctions()
|
||||
.GetEventsFunction("MyOtherEventsFunction")
|
||||
.GetEvents();
|
||||
eventLists.push_back(&objectFunctionEvents);
|
||||
eventLists.push_back(&behaviorFunctionEvents);
|
||||
eventLists.push_back(&freeFunctionEvents);
|
||||
@@ -1129,8 +1198,9 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
|
||||
// Add (free) functions and a (free) expression
|
||||
{
|
||||
auto &freeEventsFunctions = eventsExtension.GetEventsFunctions();
|
||||
auto &action =
|
||||
eventsExtension.InsertNewEventsFunction("MyEventsFunction", 0);
|
||||
freeEventsFunctions.InsertNewEventsFunction("MyEventsFunction", 0);
|
||||
action.GetParameters()
|
||||
.InsertNewParameter("currentScene", 0)
|
||||
.SetType("")
|
||||
@@ -1145,21 +1215,21 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior");
|
||||
|
||||
auto &expression =
|
||||
eventsExtension.InsertNewEventsFunction("MyEventsFunctionExpression", 1)
|
||||
freeEventsFunctions.InsertNewEventsFunction("MyEventsFunctionExpression", 1)
|
||||
.SetFunctionType(gd::EventsFunction::Expression);
|
||||
expression.GetParameters()
|
||||
.InsertNewParameter("currentScene", 0)
|
||||
.SetType("")
|
||||
.SetCodeOnly(true);
|
||||
|
||||
auto &freeExpressionAndCondition = eventsExtension.InsertNewEventsFunction("MyEventsFunctionExpressionAndCondition", 2)
|
||||
auto &freeExpressionAndCondition = freeEventsFunctions.InsertNewEventsFunction("MyEventsFunctionExpressionAndCondition", 2)
|
||||
.SetFunctionType(gd::EventsFunction::ExpressionAndCondition);
|
||||
freeExpressionAndCondition.GetParameters().InsertNewParameter("Value1", 0)
|
||||
.SetType("expression");
|
||||
freeExpressionAndCondition.GetParameters().InsertNewParameter("Value2", 1)
|
||||
.SetType("expression");
|
||||
|
||||
eventsExtension.InsertNewEventsFunction("MyEventsFunctionActionWithOperator", 2)
|
||||
freeEventsFunctions.InsertNewEventsFunction("MyEventsFunctionActionWithOperator", 2)
|
||||
.SetFunctionType(gd::EventsFunction::ActionWithOperator)
|
||||
.SetGetterName("MyEventsFunctionExpressionAndCondition");
|
||||
}
|
||||
@@ -1168,8 +1238,8 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
// object and behavior.
|
||||
{
|
||||
// Add functions, and parameters that should be there by convention.
|
||||
auto &action =
|
||||
eventsExtension.InsertNewEventsFunction("MyOtherEventsFunction", 0);
|
||||
auto &action = eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyOtherEventsFunction", 0);
|
||||
// Define the same objects as in the layout to be consistent with events.
|
||||
action.GetParameters()
|
||||
.InsertNewParameter("ObjectWithMyBehavior", 0)
|
||||
@@ -1231,7 +1301,8 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
|
||||
.GetEventsFunctions()
|
||||
.GetEventsFunction("MyBehaviorEventsFunction")
|
||||
.GetEvents());
|
||||
SetupEvents(eventsExtension.GetEventsFunction("MyOtherEventsFunction")
|
||||
SetupEvents(eventsExtension.GetEventsFunctions()
|
||||
.GetEventsFunction("MyOtherEventsFunction")
|
||||
.GetEvents());
|
||||
}
|
||||
|
||||
@@ -1583,7 +1654,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
|
||||
// Add a (free) function with an object group
|
||||
gd::EventsFunction &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyEventsFunction", 0);
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyEventsFunction", 0);
|
||||
gd::ObjectGroup &objectGroup =
|
||||
eventsFunction.GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
objectGroup.AddObject("Object1");
|
||||
@@ -1594,10 +1666,12 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer);
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
|
||||
// Trigger the refactoring before the renaming of an object
|
||||
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
|
||||
@@ -1618,15 +1692,18 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsFunction =
|
||||
eventsExtension.GetEventsFunction("MyOtherEventsFunction");
|
||||
eventsExtension.GetEventsFunctions().GetEventsFunction(
|
||||
"MyOtherEventsFunction");
|
||||
|
||||
// Create the objects container for the events function
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer);
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
|
||||
// Simulate a variable in ObjectWithMyBehavior, even if this is not
|
||||
// supported by the editor.
|
||||
@@ -1868,7 +1945,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
|
||||
// Add a (free) function with an object group
|
||||
gd::EventsFunction &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyEventsFunction", 0);
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyEventsFunction", 0);
|
||||
gd::ObjectGroup &objectGroup =
|
||||
eventsFunction.GetObjectGroups().InsertNew("MyGroup", 0);
|
||||
objectGroup.AddObject("Object1");
|
||||
@@ -2066,7 +2144,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
// Add the function used by the instruction that is checked in this test.
|
||||
// When the function doesn't exist the destination extension, the
|
||||
// instruction keeps pointing to the old extension.
|
||||
destinationExtension.InsertNewEventsFunction("MyEventsFunction", 0);
|
||||
destinationExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyEventsFunction", 0);
|
||||
|
||||
auto &duplicatedBehavior =
|
||||
destinationExtension.GetEventsBasedBehaviors().InsertNew(
|
||||
@@ -2108,7 +2187,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
// Add the function used by the instruction that is checked in this test.
|
||||
// When the function doesn't exist the destination extension, the
|
||||
// instruction keeps pointing to the old extension.
|
||||
destinationExtension.InsertNewEventsFunction("MyEventsFunction", 0);
|
||||
destinationExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyEventsFunction", 0);
|
||||
|
||||
auto &duplicatedObject =
|
||||
destinationExtension.GetEventsBasedObjects().InsertNew(
|
||||
@@ -2217,6 +2297,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
// Free function
|
||||
auto &myEventsFunction =
|
||||
project.GetEventsFunctionsExtension("MyEventsExtension")
|
||||
.GetEventsFunctions()
|
||||
.GetEventsFunction("MyEventsFunction");
|
||||
REQUIRE(myEventsFunction.GetParameters().GetParameter(1).GetExtraInfo() ==
|
||||
"MyRenamedExtension::MyEventsBasedObject");
|
||||
@@ -2333,8 +2414,10 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
"MyEventsExtension::MyRenamedFunctionExpressionAndCondition");
|
||||
|
||||
// Check that the action still refer to the right ExpressionAndCondition.
|
||||
REQUIRE(eventsExtension.GetEventsFunction("MyEventsFunctionActionWithOperator")
|
||||
.GetGetterName() == "MyRenamedFunctionExpressionAndCondition");
|
||||
REQUIRE(eventsExtension.GetEventsFunctions()
|
||||
.GetEventsFunction("MyEventsFunctionActionWithOperator")
|
||||
.GetGetterName() ==
|
||||
"MyRenamedFunctionExpressionAndCondition");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2345,7 +2428,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0);
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeEventsFunction", 0);
|
||||
eventsFunction.GetParameters()
|
||||
.AddNewParameter("MyParameter")
|
||||
.GetValueTypeMetadata()
|
||||
@@ -2358,10 +2442,12 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer);
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
gd::WholeProjectRefactorer::RenameParameter(
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
parametersObjectsContainer, "MyParameter", "MyRenamedParameter");
|
||||
@@ -2372,6 +2458,134 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
"MyExtension::GetVariableAsNumber(MyVariable.MyChild[MyRenamedParameter])");
|
||||
}
|
||||
|
||||
SECTION("(Free function) number parameter renamed (in variable setter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &eventsFunction =
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeEventsFunction", 0);
|
||||
eventsFunction.GetParameters()
|
||||
.AddNewParameter("MyParameter")
|
||||
.GetValueTypeMetadata()
|
||||
.SetName("number");
|
||||
auto &instruction = CreateNumberVariableSetterAction(
|
||||
project, eventsFunction.GetEvents(), "MyParameter", "123");
|
||||
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
gd::WholeProjectRefactorer::RenameParameter(
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
parametersObjectsContainer, "MyParameter", "MyRenamedParameter");
|
||||
|
||||
REQUIRE(instruction.GetParameter(0).GetPlainString() ==
|
||||
"MyRenamedParameter");
|
||||
}
|
||||
|
||||
SECTION("(Free function) number parameter renamed (in variable getter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &eventsFunction =
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeEventsFunction", 0);
|
||||
eventsFunction.GetParameters()
|
||||
.AddNewParameter("MyParameter")
|
||||
.GetValueTypeMetadata()
|
||||
.SetName("number");
|
||||
auto &instruction = CreateNumberVariableGetterCondition(
|
||||
project, eventsFunction.GetEvents(), "MyParameter", "123");
|
||||
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
gd::WholeProjectRefactorer::RenameParameter(
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
parametersObjectsContainer, "MyParameter", "MyRenamedParameter");
|
||||
|
||||
REQUIRE(instruction.GetParameter(0).GetPlainString() ==
|
||||
"MyRenamedParameter");
|
||||
}
|
||||
|
||||
SECTION("(Free function) parameter type changed (in variable setter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &eventsFunction =
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeEventsFunction", 0);
|
||||
eventsFunction.GetParameters()
|
||||
.AddNewParameter("MyParameter")
|
||||
.GetValueTypeMetadata()
|
||||
.SetName("number");
|
||||
// The property was of type "string".
|
||||
auto &instruction = CreateStringVariableSetterAction(
|
||||
project, eventsFunction.GetEvents(), "MyParameter", "123");
|
||||
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
gd::WholeProjectRefactorer::ChangeParameterType(
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
parametersObjectsContainer, "MyParameter");
|
||||
|
||||
REQUIRE(instruction.GetType() == "SetNumberVariable");
|
||||
}
|
||||
|
||||
SECTION("(Free function) parameter type changed (in variable getter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &eventsFunction =
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeEventsFunction", 0);
|
||||
eventsFunction.GetParameters()
|
||||
.AddNewParameter("MyParameter")
|
||||
.GetValueTypeMetadata()
|
||||
.SetName("number");
|
||||
// The property was of type "string".
|
||||
auto &instruction = CreateStringVariableGetterCondition(
|
||||
project, eventsFunction.GetEvents(), "MyParameter", "123");
|
||||
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
gd::WholeProjectRefactorer::ChangeParameterType(
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
parametersObjectsContainer, "MyParameter");
|
||||
|
||||
REQUIRE(instruction.GetType() == "NumberVariable");
|
||||
}
|
||||
|
||||
SECTION("(Free function) number parameter not renamed (in variable parameter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
@@ -2379,7 +2593,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0);
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeEventsFunction", 0);
|
||||
eventsFunction.GetParameters()
|
||||
.AddNewParameter("MyParameter")
|
||||
.GetValueTypeMetadata()
|
||||
@@ -2393,10 +2608,12 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer);
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
gd::WholeProjectRefactorer::RenameParameter(
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
parametersObjectsContainer, "MyParameter", "MyRenamedParameter");
|
||||
@@ -2415,7 +2632,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0);
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeEventsFunction", 0);
|
||||
eventsFunction.GetParameters()
|
||||
.AddNewParameter("MyObject")
|
||||
.GetValueTypeMetadata()
|
||||
@@ -2431,10 +2649,12 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer);
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
gd::WholeProjectRefactorer::RenameParameter(
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
parametersObjectsContainer, "MyObject", "MyRenamedObject");
|
||||
@@ -2454,7 +2674,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0);
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeEventsFunction", 0);
|
||||
eventsFunction.GetParameters()
|
||||
.AddNewParameter("MyObject")
|
||||
.GetValueTypeMetadata()
|
||||
@@ -2469,10 +2690,12 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer);
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
gd::WholeProjectRefactorer::RenameParameter(
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
parametersObjectsContainer, "MyObject", "MyRenamedObject");
|
||||
@@ -2491,7 +2714,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0);
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeEventsFunction", 0);
|
||||
eventsFunction.GetParameters()
|
||||
.AddNewParameter("MyObject")
|
||||
.GetValueTypeMetadata()
|
||||
@@ -2512,10 +2736,12 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer);
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
gd::WholeProjectRefactorer::RenameParameter(
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
parametersObjectsContainer, "MyBehavior", "MyRenamedBehavior");
|
||||
@@ -2535,7 +2761,8 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
|
||||
auto &eventsFunction =
|
||||
eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0);
|
||||
eventsExtension.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyFreeEventsFunction", 0);
|
||||
eventsFunction.GetParameters()
|
||||
.AddNewParameter("MyObject")
|
||||
.GetValueTypeMetadata()
|
||||
@@ -2555,10 +2782,12 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
|
||||
gd::ObjectsContainer parametersObjectsContainer(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsExtension, eventsFunction,
|
||||
parametersObjectsContainer);
|
||||
parametersObjectsContainer, parameterVariablesContainer);
|
||||
gd::WholeProjectRefactorer::RenameParameter(
|
||||
project, projectScopedContainers, eventsFunction,
|
||||
parametersObjectsContainer, "MyBehavior", "MyRenamedBehavior");
|
||||
@@ -2727,6 +2956,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
// Free function
|
||||
auto &myEventsFunction =
|
||||
project.GetEventsFunctionsExtension("MyEventsExtension")
|
||||
.GetEventsFunctions()
|
||||
.GetEventsFunction("MyEventsFunction");
|
||||
REQUIRE(myEventsFunction.GetParameters().GetParameter(2).GetExtraInfo() ==
|
||||
"MyEventsExtension::MyRenamedEventsBasedBehavior");
|
||||
@@ -2837,6 +3067,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
// Free function
|
||||
auto &myEventsFunction =
|
||||
project.GetEventsFunctionsExtension("MyEventsExtension")
|
||||
.GetEventsFunctions()
|
||||
.GetEventsFunction("MyEventsFunction");
|
||||
REQUIRE(myEventsFunction.GetParameters().GetParameter(1).GetExtraInfo() ==
|
||||
"MyEventsExtension::MyRenamedEventsBasedObject");
|
||||
@@ -3366,6 +3597,54 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
"MyExtension::GetVariableAsNumber(MyVariable.MyChild[MyRenamedProperty])");
|
||||
}
|
||||
|
||||
SECTION("(Events based behavior) property renamed (in variable setter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsBasedBehavior =
|
||||
eventsExtension.GetEventsBasedBehaviors().Get("MyEventsBasedBehavior");
|
||||
|
||||
auto &behaviorAction =
|
||||
eventsBasedBehavior.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyBehaviorEventsFunction", 0);
|
||||
gd::WholeProjectRefactorer::EnsureBehaviorEventsFunctionsProperParameters(
|
||||
eventsExtension, eventsBasedBehavior);
|
||||
auto &instruction = CreateNumberVariableSetterAction(
|
||||
project, behaviorAction.GetEvents(), "MyProperty", "123");
|
||||
|
||||
gd::WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
|
||||
project, eventsExtension, eventsBasedBehavior, "MyProperty",
|
||||
"MyRenamedProperty");
|
||||
|
||||
REQUIRE(instruction.GetParameter(0).GetPlainString() ==
|
||||
"MyRenamedProperty");
|
||||
}
|
||||
|
||||
SECTION("(Events based behavior) property renamed (in variable getter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsBasedBehavior =
|
||||
eventsExtension.GetEventsBasedBehaviors().Get("MyEventsBasedBehavior");
|
||||
|
||||
auto &behaviorAction =
|
||||
eventsBasedBehavior.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyBehaviorEventsFunction", 0);
|
||||
gd::WholeProjectRefactorer::EnsureBehaviorEventsFunctionsProperParameters(
|
||||
eventsExtension, eventsBasedBehavior);
|
||||
auto &instruction = CreateNumberVariableGetterCondition(
|
||||
project, behaviorAction.GetEvents(), "MyProperty", "123");
|
||||
|
||||
gd::WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
|
||||
project, eventsExtension, eventsBasedBehavior, "MyProperty",
|
||||
"MyRenamedProperty");
|
||||
|
||||
REQUIRE(instruction.GetParameter(0).GetPlainString() ==
|
||||
"MyRenamedProperty");
|
||||
}
|
||||
|
||||
SECTION("(Events based behavior) property not renamed (in variable parameter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
@@ -3397,6 +3676,52 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
"MyExtension::GetVariableAsNumber(MyProperty)");
|
||||
}
|
||||
|
||||
SECTION("(Events based behavior) property type changed (in variable setter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsBasedBehavior =
|
||||
eventsExtension.GetEventsBasedBehaviors().Get("MyEventsBasedBehavior");
|
||||
|
||||
auto &behaviorAction =
|
||||
eventsBasedBehavior.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyBehaviorEventsFunction", 0);
|
||||
gd::WholeProjectRefactorer::EnsureBehaviorEventsFunctionsProperParameters(
|
||||
eventsExtension, eventsBasedBehavior);
|
||||
// The property was of type "string".
|
||||
auto &instruction = CreateStringVariableSetterAction(
|
||||
project, behaviorAction.GetEvents(), "MyProperty", "123");
|
||||
|
||||
gd::WholeProjectRefactorer::ChangeEventsBasedBehaviorPropertyType(
|
||||
project, eventsExtension, eventsBasedBehavior, "MyProperty");
|
||||
|
||||
REQUIRE(instruction.GetType() == "SetNumberVariable");
|
||||
}
|
||||
|
||||
SECTION("(Events based behavior) property type changed (in variable getter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsBasedBehavior =
|
||||
eventsExtension.GetEventsBasedBehaviors().Get("MyEventsBasedBehavior");
|
||||
|
||||
auto &behaviorAction =
|
||||
eventsBasedBehavior.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyBehaviorEventsFunction", 0);
|
||||
gd::WholeProjectRefactorer::EnsureBehaviorEventsFunctionsProperParameters(
|
||||
eventsExtension, eventsBasedBehavior);
|
||||
// The property was of type "string".
|
||||
auto &instruction = CreateStringVariableGetterCondition(
|
||||
project, behaviorAction.GetEvents(), "MyProperty", "123");
|
||||
|
||||
gd::WholeProjectRefactorer::ChangeEventsBasedBehaviorPropertyType(
|
||||
project, eventsExtension, eventsBasedBehavior, "MyProperty");
|
||||
|
||||
REQUIRE(instruction.GetType() == "NumberVariable");
|
||||
}
|
||||
|
||||
SECTION("(Events based behavior) shared property renamed") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
@@ -3536,6 +3861,54 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
"MyExtension::GetVariableAsNumber(MyVariable.MyChild[MyRenamedProperty])");
|
||||
}
|
||||
|
||||
SECTION("(Events based object) property renamed (in variable setter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsBasedObject =
|
||||
eventsExtension.GetEventsBasedObjects().Get("MyEventsBasedObject");
|
||||
|
||||
auto &behaviorAction =
|
||||
eventsBasedObject.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyObjectEventsFunction", 0);
|
||||
gd::WholeProjectRefactorer::EnsureObjectEventsFunctionsProperParameters(
|
||||
eventsExtension, eventsBasedObject);
|
||||
auto &instruction = CreateNumberVariableSetterAction(
|
||||
project, behaviorAction.GetEvents(), "MyProperty", "123");
|
||||
|
||||
gd::WholeProjectRefactorer::RenameEventsBasedObjectProperty(
|
||||
project, eventsExtension, eventsBasedObject, "MyProperty",
|
||||
"MyRenamedProperty");
|
||||
|
||||
REQUIRE(instruction.GetParameter(0).GetPlainString() ==
|
||||
"MyRenamedProperty");
|
||||
}
|
||||
|
||||
SECTION("(Events based object) property renamed (in variable getter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsBasedObject =
|
||||
eventsExtension.GetEventsBasedObjects().Get("MyEventsBasedObject");
|
||||
|
||||
auto &behaviorAction =
|
||||
eventsBasedObject.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyObjectEventsFunction", 0);
|
||||
gd::WholeProjectRefactorer::EnsureObjectEventsFunctionsProperParameters(
|
||||
eventsExtension, eventsBasedObject);
|
||||
auto &instruction = CreateNumberVariableGetterCondition(
|
||||
project, behaviorAction.GetEvents(), "MyProperty", "123");
|
||||
|
||||
gd::WholeProjectRefactorer::RenameEventsBasedObjectProperty(
|
||||
project, eventsExtension, eventsBasedObject, "MyProperty",
|
||||
"MyRenamedProperty");
|
||||
|
||||
REQUIRE(instruction.GetParameter(0).GetPlainString() ==
|
||||
"MyRenamedProperty");
|
||||
}
|
||||
|
||||
SECTION("(Events based object) property not renamed (in variable parameter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
@@ -3566,6 +3939,52 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
|
||||
REQUIRE(instruction2.GetParameter(0).GetPlainString() ==
|
||||
"MyExtension::GetVariableAsNumber(MyProperty)");
|
||||
}
|
||||
|
||||
SECTION("(Events based object) property type changed (in variable setter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsBasedObject =
|
||||
eventsExtension.GetEventsBasedObjects().Get("MyEventsBasedObject");
|
||||
|
||||
auto &behaviorAction =
|
||||
eventsBasedObject.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyObjectEventsFunction", 0);
|
||||
gd::WholeProjectRefactorer::EnsureObjectEventsFunctionsProperParameters(
|
||||
eventsExtension, eventsBasedObject);
|
||||
// The property was of type "string".
|
||||
auto &instruction = CreateStringVariableSetterAction(
|
||||
project, behaviorAction.GetEvents(), "MyProperty", "123");
|
||||
|
||||
gd::WholeProjectRefactorer::ChangeEventsBasedObjectPropertyType(
|
||||
project, eventsExtension, eventsBasedObject, "MyProperty");
|
||||
|
||||
REQUIRE(instruction.GetType() == "SetNumberVariable");
|
||||
}
|
||||
|
||||
SECTION("(Events based object) property type changed (in variable getter)") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
|
||||
auto &eventsBasedObject =
|
||||
eventsExtension.GetEventsBasedObjects().Get("MyEventsBasedObject");
|
||||
|
||||
auto &behaviorAction =
|
||||
eventsBasedObject.GetEventsFunctions().InsertNewEventsFunction(
|
||||
"MyObjectEventsFunction", 0);
|
||||
gd::WholeProjectRefactorer::EnsureObjectEventsFunctionsProperParameters(
|
||||
eventsExtension, eventsBasedObject);
|
||||
// The property was of type "string".
|
||||
auto &instruction = CreateStringVariableGetterCondition(
|
||||
project, behaviorAction.GetEvents(), "MyProperty", "123");
|
||||
|
||||
gd::WholeProjectRefactorer::ChangeEventsBasedObjectPropertyType(
|
||||
project, eventsExtension, eventsBasedObject, "MyProperty");
|
||||
|
||||
REQUIRE(instruction.GetType() == "NumberVariable");
|
||||
}
|
||||
}
|
||||
// TODO: Check that this works when behaviors are attached to a child-object.
|
||||
TEST_CASE("WholeProjectRefactorer (FindInvalidRequiredBehaviorProperties)",
|
||||
|
@@ -2332,9 +2332,9 @@ module.exports = {
|
||||
this._pixiObject = new PIXI.Graphics();
|
||||
this._pixiContainer.addChild(this._pixiObject);
|
||||
|
||||
this._faceResourceNames = ['', '', '', '', '', ''];
|
||||
this._faceVisibilities = [true, true, true, true, true, true];
|
||||
this._shouldRepeatTextureOnFace = [true, true, true, true, true, true];
|
||||
this._faceResourceNames = new Array(6).fill(null);
|
||||
this._faceVisibilities = new Array(6).fill(null);
|
||||
this._shouldRepeatTextureOnFace = new Array(6).fill(null);
|
||||
this._facesOrientation = 'Y';
|
||||
this._backFaceUpThroughWhichAxisRotation = 'X';
|
||||
this._shouldUseTransparentTexture = false;
|
||||
|
@@ -26,7 +26,8 @@ PanelSpriteObject::PanelSpriteObject()
|
||||
leftMargin(0),
|
||||
topMargin(0),
|
||||
rightMargin(0),
|
||||
bottomMargin(0) {}
|
||||
bottomMargin(0),
|
||||
tiled(false) {}
|
||||
|
||||
PanelSpriteObject::~PanelSpriteObject() {}
|
||||
|
||||
|
@@ -964,7 +964,7 @@ namespace gdjs {
|
||||
// It would be useless to try to recreate it as updateBodyFromObject already does it.
|
||||
// If the body is null, we just don't do anything
|
||||
// (but still run the physics simulation - this is independent).
|
||||
if (this._body !== null) {
|
||||
if (this._body !== null && !this.isStatic() && this._body.IsAwake()) {
|
||||
this.owner.setX(
|
||||
this._body.GetPosition().get_x() * this._sharedData.worldScale -
|
||||
this.owner.getWidth() / 2 +
|
||||
|
@@ -20,7 +20,7 @@ module.exports = {
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
'Physics3D',
|
||||
_('3D Physics Engine'),
|
||||
_('3D physics engine'),
|
||||
"The physics engine simulates realistic object physics, with gravity, forces, joints, etc. It's perfect for games that need to have realistic behaving objects and a gameplay centered around it.",
|
||||
'Florian Rival',
|
||||
'MIT'
|
||||
@@ -29,7 +29,7 @@ module.exports = {
|
||||
.setCategory('Movement')
|
||||
.setTags('physics, gravity, obstacle, collision');
|
||||
extension
|
||||
.addInstructionOrExpressionGroupMetadata(_('3D Physics Engine'))
|
||||
.addInstructionOrExpressionGroupMetadata(_('3D physics engine'))
|
||||
.setIcon('JsPlatform/Extensions/physics3d.svg');
|
||||
{
|
||||
const behavior = new gd.BehaviorJsImplementation();
|
||||
@@ -998,8 +998,8 @@ module.exports = {
|
||||
'number',
|
||||
'AngularVelocityX',
|
||||
_('Angular velocity X'),
|
||||
_('the object angular velocity on X.'),
|
||||
_('the angular velocity on X'),
|
||||
_('the object angular velocity around X.'),
|
||||
_('the angular velocity around X'),
|
||||
_('Velocity'),
|
||||
'JsPlatform/Extensions/physics3d.svg'
|
||||
)
|
||||
@@ -1019,8 +1019,8 @@ module.exports = {
|
||||
'number',
|
||||
'AngularVelocityY',
|
||||
_('Angular velocity Y'),
|
||||
_('the object angular velocity on Y.'),
|
||||
_('the angular velocity on Y'),
|
||||
_('the object angular velocity around Y.'),
|
||||
_('the angular velocity around Y'),
|
||||
_('Velocity'),
|
||||
'JsPlatform/Extensions/physics3d.svg'
|
||||
)
|
||||
@@ -1040,8 +1040,8 @@ module.exports = {
|
||||
'number',
|
||||
'AngularVelocityZ',
|
||||
_('Angular velocity Z'),
|
||||
_('the object angular velocity on Z.'),
|
||||
_('the angular velocity on Z'),
|
||||
_('the object angular velocity around Z.'),
|
||||
_('the angular velocity around Z'),
|
||||
_('Velocity'),
|
||||
'JsPlatform/Extensions/physics3d.svg'
|
||||
)
|
||||
@@ -1551,6 +1551,13 @@ module.exports = {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (propertyName === 'canBePushed') {
|
||||
behaviorContent
|
||||
.getChild('canBePushed')
|
||||
.setBoolValue(newValue === '1');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
behavior.getProperties = function (behaviorContent) {
|
||||
@@ -1745,6 +1752,22 @@ module.exports = {
|
||||
.setAdvanced(true)
|
||||
.setQuickCustomizationVisibility(gd.QuickCustomization.Hidden);
|
||||
|
||||
if (!behaviorContent.hasChild('canBePushed')) {
|
||||
behaviorContent.addChild('canBePushed').setBoolValue(true);
|
||||
}
|
||||
behaviorProperties
|
||||
.getOrCreate('canBePushed')
|
||||
.setLabel('Can be pushed by other characters')
|
||||
.setGroup(_('Walk'))
|
||||
.setType('Boolean')
|
||||
.setValue(
|
||||
behaviorContent.getChild('canBePushed').getBoolValue()
|
||||
? 'true'
|
||||
: 'false'
|
||||
)
|
||||
.setAdvanced(true)
|
||||
.setQuickCustomizationVisibility(gd.QuickCustomization.Hidden);
|
||||
|
||||
return behaviorProperties;
|
||||
};
|
||||
|
||||
@@ -1765,6 +1788,7 @@ module.exports = {
|
||||
behaviorContent
|
||||
.addChild('shouldBindObjectAndForwardAngle')
|
||||
.setBoolValue(true);
|
||||
behaviorContent.addChild('canBePushed').setBoolValue(true);
|
||||
};
|
||||
|
||||
const aut = extension
|
||||
|
@@ -807,17 +807,25 @@ namespace gdjs {
|
||||
*/
|
||||
getBodyLayer(): number {
|
||||
return Jolt.ObjectLayerPairFilterMask.prototype.sGetObjectLayer(
|
||||
// Make sure objects don't register in the wrong layer group.
|
||||
this.bodyType === 'Static'
|
||||
? this.layers & gdjs.Physics3DSharedData.staticLayersMask
|
||||
: this.layers & gdjs.Physics3DSharedData.dynamicLayersMask,
|
||||
// Static objects accept all collisions as it's the mask of dynamic objects that matters.
|
||||
this.bodyType === 'Static'
|
||||
? gdjs.Physics3DSharedData.allLayersMask
|
||||
: this.masks
|
||||
this.getLayersAccordingToBodyType(),
|
||||
this.getMasksAccordingToBodyType()
|
||||
);
|
||||
}
|
||||
|
||||
private getLayersAccordingToBodyType(): integer {
|
||||
// Make sure objects don't register in the wrong layer group.
|
||||
return this.isStatic()
|
||||
? this.layers & gdjs.Physics3DSharedData.staticLayersMask
|
||||
: this.layers & gdjs.Physics3DSharedData.dynamicLayersMask;
|
||||
}
|
||||
|
||||
private getMasksAccordingToBodyType(): integer {
|
||||
// Static objects accept all collisions as it's the mask of dynamic objects that matters.
|
||||
return this.isStatic()
|
||||
? gdjs.Physics3DSharedData.allLayersMask
|
||||
: this.masks;
|
||||
}
|
||||
|
||||
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
|
||||
// Step the world if not done this frame yet.
|
||||
// Don't step at the first frame to allow events to handle overlapping objects.
|
||||
@@ -1691,6 +1699,14 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
canCollideAgainst(otherBehavior: gdjs.Physics3DRuntimeBehavior): boolean {
|
||||
return (
|
||||
(this.getMasksAccordingToBodyType() &
|
||||
otherBehavior.getLayersAccordingToBodyType()) !==
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
static areObjectsColliding(
|
||||
object1: gdjs.RuntimeObject,
|
||||
object2: gdjs.RuntimeObject,
|
||||
@@ -1805,7 +1821,7 @@ namespace gdjs {
|
||||
// It would be useless to try to recreate it as updateBodyFromObject already does it.
|
||||
// If the body is null, we just don't do anything
|
||||
// (but still run the physics simulation - this is independent).
|
||||
if (_body !== null) {
|
||||
if (_body !== null && _body.IsActive()) {
|
||||
behavior.moveObjectToPhysicsPosition(_body.GetPosition());
|
||||
behavior.moveObjectToPhysicsRotation(_body.GetRotation());
|
||||
}
|
||||
@@ -1819,8 +1835,6 @@ namespace gdjs {
|
||||
}
|
||||
const body = behavior._body!;
|
||||
|
||||
// TODO the `if` is probably unnecessary because `SetPositionAndRotationWhenChanged` already check this.
|
||||
// The object object transform has changed, update body transform:
|
||||
if (
|
||||
this.behavior._objectOldX !== owner3D.getX() ||
|
||||
this.behavior._objectOldY !== owner3D.getY() ||
|
||||
|
@@ -72,6 +72,7 @@ namespace gdjs {
|
||||
private _jumpSpeed: float;
|
||||
private _jumpSustainTime: float;
|
||||
private _stairHeightMax: float;
|
||||
_canBePushed: boolean;
|
||||
|
||||
private _hasPressedForwardKey: boolean = false;
|
||||
private _hasPressedBackwardKey: boolean = false;
|
||||
@@ -145,6 +146,10 @@ namespace gdjs {
|
||||
behaviorData.stairHeightMax === undefined
|
||||
? 20
|
||||
: behaviorData.stairHeightMax;
|
||||
this._canBePushed =
|
||||
behaviorData.canBePushed === undefined
|
||||
? true
|
||||
: behaviorData.canBePushed;
|
||||
}
|
||||
|
||||
private getVec3(x: float, y: float, z: float): Jolt.Vec3 {
|
||||
@@ -327,6 +332,21 @@ namespace gdjs {
|
||||
return result;
|
||||
}
|
||||
|
||||
getPhysicsRotation(result: Jolt.Quat): Jolt.Quat {
|
||||
// Characters body should not rotate around X and Y.
|
||||
const rotation = result.sEulerAngles(
|
||||
this.getVec3(0, 0, gdjs.toRad(this.owner3D.getAngle()))
|
||||
);
|
||||
result.Set(
|
||||
rotation.GetX(),
|
||||
rotation.GetY(),
|
||||
rotation.GetZ(),
|
||||
rotation.GetW()
|
||||
);
|
||||
Jolt.destroy(rotation);
|
||||
return result;
|
||||
}
|
||||
|
||||
moveObjectToPhysicsPosition(physicsPosition: Jolt.RVec3): void {
|
||||
const { behavior } = this.getPhysics3D();
|
||||
this.owner3D.setCenterXInScene(
|
||||
@@ -341,6 +361,19 @@ namespace gdjs {
|
||||
);
|
||||
}
|
||||
|
||||
moveObjectToPhysicsRotation(physicsRotation: Jolt.Quat): void {
|
||||
const threeObject = this.owner3D.get3DRendererObject();
|
||||
threeObject.quaternion.x = physicsRotation.GetX();
|
||||
threeObject.quaternion.y = physicsRotation.GetY();
|
||||
threeObject.quaternion.z = physicsRotation.GetZ();
|
||||
threeObject.quaternion.w = physicsRotation.GetW();
|
||||
// TODO Avoid this instantiation
|
||||
const euler = new THREE.Euler(0, 0, 0, 'ZYX');
|
||||
euler.setFromQuaternion(threeObject.quaternion);
|
||||
// No need to update the rotation for X and Y as CharacterVirtual doesn't change it.
|
||||
this.owner3D.setAngle(gdjs.toDegrees(euler.z));
|
||||
}
|
||||
|
||||
onDeActivate() {
|
||||
this.collisionChecker.clearContacts();
|
||||
}
|
||||
@@ -1224,7 +1257,7 @@ namespace gdjs {
|
||||
* @returns Returns true if it is falling and false if not.
|
||||
*/
|
||||
isFallingWithoutJumping(): boolean {
|
||||
return !this.isOnFloor() && this._currentJumpSpeed === 0;
|
||||
return !this.isOnFloor() && !this.isJumping();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1241,7 +1274,8 @@ namespace gdjs {
|
||||
*/
|
||||
isFalling(): boolean {
|
||||
return (
|
||||
!this.isOnFloor() && this._currentJumpSpeed < this._currentFallSpeed
|
||||
this.isFallingWithoutJumping() ||
|
||||
(this.isJumping() && this._currentFallSpeed > this._currentJumpSpeed)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1323,6 +1357,8 @@ namespace gdjs {
|
||||
export namespace PhysicsCharacter3DRuntimeBehavior {
|
||||
export class CharacterBodyUpdater {
|
||||
characterBehavior: gdjs.PhysicsCharacter3DRuntimeBehavior;
|
||||
/** Handle collisions between characters that can push each other. */
|
||||
static characterVsCharacterCollision: Jolt.CharacterVsCharacterCollisionSimple | null = null;
|
||||
|
||||
constructor(characterBehavior: gdjs.PhysicsCharacter3DRuntimeBehavior) {
|
||||
this.characterBehavior = characterBehavior;
|
||||
@@ -1335,7 +1371,13 @@ namespace gdjs {
|
||||
const shape = behavior.createShape();
|
||||
|
||||
const settings = new Jolt.CharacterVirtualSettings();
|
||||
settings.mInnerBodyLayer = behavior.getBodyLayer();
|
||||
// Characters innerBody are Kinematic body, they don't allow other
|
||||
// characters to push them.
|
||||
// The layer 0 doesn't allow any collision as masking them always result to 0.
|
||||
// This allows CharacterVsCharacterCollisionSimple to handle the collisions.
|
||||
settings.mInnerBodyLayer = this.characterBehavior._canBePushed
|
||||
? 0
|
||||
: behavior.getBodyLayer();
|
||||
settings.mInnerBodyShape = shape;
|
||||
settings.mMass = shape.GetMassProperties().get_mMass();
|
||||
settings.mMaxSlopeAngle = gdjs.toRad(_slopeMaxAngle);
|
||||
@@ -1375,13 +1417,112 @@ namespace gdjs {
|
||||
.GetBodyLockInterface()
|
||||
.TryGetBody(character.GetInnerBodyID());
|
||||
this.characterBehavior.character = character;
|
||||
|
||||
if (this.characterBehavior._canBePushed) {
|
||||
// CharacterVsCharacterCollisionSimple handle characters pushing each other.
|
||||
let characterVsCharacterCollision =
|
||||
CharacterBodyUpdater.characterVsCharacterCollision;
|
||||
if (!characterVsCharacterCollision) {
|
||||
characterVsCharacterCollision = new Jolt.CharacterVsCharacterCollisionSimple();
|
||||
CharacterBodyUpdater.characterVsCharacterCollision = characterVsCharacterCollision;
|
||||
}
|
||||
characterVsCharacterCollision.Add(character);
|
||||
character.SetCharacterVsCharacterCollision(
|
||||
characterVsCharacterCollision
|
||||
);
|
||||
|
||||
const characterContactListener = new Jolt.CharacterContactListenerJS();
|
||||
characterContactListener.OnAdjustBodyVelocity = (
|
||||
character,
|
||||
body2Ptr,
|
||||
linearVelocityPtr,
|
||||
angularVelocity
|
||||
) => {};
|
||||
characterContactListener.OnContactValidate = (
|
||||
character,
|
||||
bodyID2,
|
||||
subShapeID2
|
||||
) => {
|
||||
return true;
|
||||
};
|
||||
characterContactListener.OnCharacterContactValidate = (
|
||||
characterPtr,
|
||||
otherCharacterPtr,
|
||||
subShapeID2
|
||||
) => {
|
||||
// CharacterVsCharacterCollisionSimple doesn't handle collision layers.
|
||||
// We have to filter characters ourself.
|
||||
const character = Jolt.wrapPointer(
|
||||
characterPtr,
|
||||
Jolt.CharacterVirtual
|
||||
);
|
||||
const otherCharacter = Jolt.wrapPointer(
|
||||
otherCharacterPtr,
|
||||
Jolt.CharacterVirtual
|
||||
);
|
||||
|
||||
const body = _sharedData.physicsSystem
|
||||
.GetBodyLockInterface()
|
||||
.TryGetBody(character.GetInnerBodyID());
|
||||
const otherBody = _sharedData.physicsSystem
|
||||
.GetBodyLockInterface()
|
||||
.TryGetBody(otherCharacter.GetInnerBodyID());
|
||||
|
||||
const physicsBehavior = body.gdjsAssociatedBehavior;
|
||||
const otherPhysicsBehavior = otherBody.gdjsAssociatedBehavior;
|
||||
|
||||
if (!physicsBehavior || !otherPhysicsBehavior) {
|
||||
return true;
|
||||
}
|
||||
return physicsBehavior.canCollideAgainst(otherPhysicsBehavior);
|
||||
};
|
||||
characterContactListener.OnContactAdded = (
|
||||
character,
|
||||
bodyID2,
|
||||
subShapeID2,
|
||||
contactPosition,
|
||||
contactNormal,
|
||||
settings
|
||||
) => {};
|
||||
characterContactListener.OnCharacterContactAdded = (
|
||||
character,
|
||||
otherCharacter,
|
||||
subShapeID2,
|
||||
contactPosition,
|
||||
contactNormal,
|
||||
settings
|
||||
) => {};
|
||||
characterContactListener.OnContactSolve = (
|
||||
character,
|
||||
bodyID2,
|
||||
subShapeID2,
|
||||
contactPosition,
|
||||
contactNormal,
|
||||
contactVelocity,
|
||||
contactMaterial,
|
||||
characterVelocity,
|
||||
newCharacterVelocity
|
||||
) => {};
|
||||
characterContactListener.OnCharacterContactSolve = (
|
||||
character,
|
||||
otherCharacter,
|
||||
subShapeID2,
|
||||
contactPosition,
|
||||
contactNormal,
|
||||
contactVelocity,
|
||||
contactMaterial,
|
||||
characterVelocityPtr,
|
||||
newCharacterVelocityPtr
|
||||
) => {};
|
||||
character.SetListener(characterContactListener);
|
||||
}
|
||||
|
||||
// TODO This is not really reliable. We could choose to disable it and force user to use the "is on platform" condition.
|
||||
//body.SetCollideKinematicVsNonDynamic(true);
|
||||
return body;
|
||||
}
|
||||
|
||||
updateObjectFromBody() {
|
||||
const { behavior } = this.characterBehavior.getPhysics3D();
|
||||
const { character } = this.characterBehavior;
|
||||
if (!character) {
|
||||
return;
|
||||
@@ -1390,8 +1531,9 @@ namespace gdjs {
|
||||
this.characterBehavior.moveObjectToPhysicsPosition(
|
||||
character.GetPosition()
|
||||
);
|
||||
// TODO No need to update the rotation for X and Y as CharacterVirtual doesn't change it.
|
||||
behavior.moveObjectToPhysicsRotation(character.GetRotation());
|
||||
this.characterBehavior.moveObjectToPhysicsRotation(
|
||||
character.GetRotation()
|
||||
);
|
||||
}
|
||||
|
||||
updateBodyFromObject() {
|
||||
@@ -1412,9 +1554,10 @@ namespace gdjs {
|
||||
behavior._objectOldRotationY !== owner3D.getRotationY() ||
|
||||
behavior._objectOldRotationZ !== owner3D.getAngle()
|
||||
) {
|
||||
// TODO No need to update the rotation for X and Y as CharacterVirtual doesn't change it.
|
||||
character.SetRotation(
|
||||
behavior.getPhysicsRotation(_sharedData.getQuat(0, 0, 0, 1))
|
||||
this.characterBehavior.getPhysicsRotation(
|
||||
_sharedData.getQuat(0, 0, 0, 1)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -78,6 +78,18 @@ module.exports = {
|
||||
} else if (propertyName === 'disabled') {
|
||||
objectContent.disabled = newValue === '1';
|
||||
return true;
|
||||
} else if (propertyName === 'maxLength') {
|
||||
objectContent.maxLength = newValue;
|
||||
return true;
|
||||
} else if (propertyName === 'paddingX') {
|
||||
objectContent.paddingX = Math.max(0, parseFloat(newValue));
|
||||
return true;
|
||||
} else if (propertyName === 'paddingY') {
|
||||
objectContent.paddingY = Math.max(0, parseFloat(newValue));
|
||||
return true;
|
||||
} else if (propertyName === 'textAlign') {
|
||||
objectContent.textAlign = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -200,6 +212,50 @@ module.exports = {
|
||||
.setLabel(_('Width'))
|
||||
.setGroup(_('Border appearance'));
|
||||
|
||||
objectProperties
|
||||
.getOrCreate('paddingX')
|
||||
.setValue(
|
||||
(objectContent.paddingX !== undefined
|
||||
? objectContent.paddingX
|
||||
: 2
|
||||
).toString()
|
||||
)
|
||||
.setType('number')
|
||||
.setLabel(_('Padding (horizontal)'))
|
||||
.setGroup(_('Field appearance'));
|
||||
objectProperties
|
||||
.getOrCreate('paddingY')
|
||||
.setValue(
|
||||
(objectContent.paddingY !== undefined
|
||||
? objectContent.paddingY
|
||||
: 1
|
||||
).toString()
|
||||
)
|
||||
.setType('number')
|
||||
.setLabel(_('Padding (vertical)'))
|
||||
.setGroup(_('Field appearance'));
|
||||
objectProperties
|
||||
.getOrCreate('maxLength')
|
||||
.setValue((objectContent.maxLength || 0).toString())
|
||||
.setType('number')
|
||||
.setLabel(_('Max length'))
|
||||
.setDescription(
|
||||
_(
|
||||
'The maximum length of the input value (this property will be ignored if the input type is a number).'
|
||||
)
|
||||
)
|
||||
.setAdvanced(true);
|
||||
|
||||
objectProperties
|
||||
.getOrCreate('textAlign')
|
||||
.setValue(objectContent.textAlign || 'left')
|
||||
.setType('choice')
|
||||
.addExtraInfo('left')
|
||||
.addExtraInfo('center')
|
||||
.addExtraInfo('right')
|
||||
.setLabel(_('Text alignment'))
|
||||
.setGroup(_('Field appearance'));
|
||||
|
||||
return objectProperties;
|
||||
};
|
||||
textInputObject.content = {
|
||||
@@ -216,6 +272,10 @@ module.exports = {
|
||||
borderWidth: 1,
|
||||
readOnly: false,
|
||||
disabled: false,
|
||||
paddingX: 2,
|
||||
paddingY: 1,
|
||||
textAlign: 'left',
|
||||
maxLength: 0,
|
||||
};
|
||||
|
||||
textInputObject.updateInitialInstanceProperty = function (
|
||||
@@ -572,6 +632,22 @@ module.exports = {
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('isFocused');
|
||||
|
||||
object
|
||||
.addScopedCondition(
|
||||
'IsInputSubmitted',
|
||||
_('Input is submitted'),
|
||||
_(
|
||||
'Check if the input is submitted, which usually happens when the Enter key is pressed on a keyboard, or a specific button on mobile virtual keyboards.'
|
||||
),
|
||||
_('_PARAM0_ value was submitted'),
|
||||
'',
|
||||
'res/conditions/surObject24.png',
|
||||
'res/conditions/surObject.png'
|
||||
)
|
||||
.addParameter('object', _('Text input'), 'TextInputObject', false)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('isSubmitted');
|
||||
|
||||
object
|
||||
.addScopedAction(
|
||||
'Focus',
|
||||
@@ -627,7 +703,6 @@ module.exports = {
|
||||
|
||||
const DEFAULT_WIDTH = 300;
|
||||
const DEFAULT_HEIGHT = 30;
|
||||
const TEXT_MASK_PADDING = 2;
|
||||
|
||||
class RenderedTextInputObjectInstance extends RenderedInstance {
|
||||
constructor(
|
||||
@@ -741,24 +816,51 @@ module.exports = {
|
||||
);
|
||||
|
||||
const borderWidth = object.content.borderWidth || 0;
|
||||
const paddingX =
|
||||
object.content.paddingX !== undefined
|
||||
? Math.min(
|
||||
parseFloat(object.content.paddingX),
|
||||
width / 2 - borderWidth
|
||||
)
|
||||
: 2;
|
||||
const paddingY =
|
||||
object.content.paddingY !== undefined
|
||||
? Math.min(
|
||||
parseFloat(object.content.paddingY),
|
||||
height / 2 - borderWidth
|
||||
)
|
||||
: 1;
|
||||
|
||||
// Draw the mask for the text.
|
||||
const textOffset = borderWidth + TEXT_MASK_PADDING;
|
||||
const textOffsetX = borderWidth + paddingX;
|
||||
// textOffsetY does not include the paddingY because browsers display the text, even if it is supposed to be cut off by vertical padding.
|
||||
const textOffsetY = borderWidth;
|
||||
this._pixiTextMask.clear();
|
||||
this._pixiTextMask.beginFill(0xdddddd, 1);
|
||||
this._pixiTextMask.drawRect(
|
||||
textOffset,
|
||||
textOffset,
|
||||
width - 2 * textOffset,
|
||||
height - 2 * textOffset
|
||||
textOffsetX,
|
||||
textOffsetY,
|
||||
width - 2 * textOffsetX,
|
||||
height - 2 * textOffsetY
|
||||
);
|
||||
this._pixiTextMask.endFill();
|
||||
|
||||
const isTextArea = object.content.inputType === 'text area';
|
||||
const textAlign = object.content.textAlign
|
||||
? object.content.textAlign
|
||||
: 'left';
|
||||
|
||||
if (textAlign === 'left') this._pixiText.position.x = textOffsetX;
|
||||
else if (textAlign === 'right')
|
||||
this._pixiText.position.x =
|
||||
0 + width - this._pixiText.width - textOffsetX;
|
||||
else if (textAlign === 'center') {
|
||||
this._pixiText.align = 'center';
|
||||
this._pixiText.position.x = 0 + width / 2 - this._pixiText.width / 2;
|
||||
}
|
||||
|
||||
this._pixiText.position.x = textOffset;
|
||||
this._pixiText.position.y = isTextArea
|
||||
? textOffset
|
||||
? textOffsetY + paddingY
|
||||
: height / 2 - this._pixiText.height / 2;
|
||||
|
||||
// Draw the background and border.
|
||||
|
@@ -25,6 +25,10 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
|
||||
borderWidth: 2,
|
||||
disabled: false,
|
||||
readOnly: false,
|
||||
paddingX: 2,
|
||||
paddingY: 1,
|
||||
textAlign: 'left',
|
||||
maxLength: 20,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -166,33 +170,33 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
|
||||
object,
|
||||
} = await setupObjectAndGetDomElementContainer();
|
||||
|
||||
const inputElement = gameDomElementContainer.querySelector('input');
|
||||
if (!inputElement) throw new Error('Expected input element to be found');
|
||||
const formElement = gameDomElementContainer.querySelector('form');
|
||||
if (!formElement) throw new Error('Expected form element to be found');
|
||||
|
||||
// Check visibility of the DOM element is visible by default, if it should be visible
|
||||
// on the screen.
|
||||
runtimeScene.renderAndStep(1000 / 60);
|
||||
expect(inputElement.style.display).to.be('initial');
|
||||
expect(formElement.style.display).to.be('initial');
|
||||
|
||||
// Check visibility of the DOM element is updated at each frame,
|
||||
// according to the object visibility.
|
||||
object.hide(true);
|
||||
runtimeScene.renderAndStep(1000 / 60);
|
||||
expect(inputElement.style.display).to.be('none');
|
||||
expect(formElement.style.display).to.be('none');
|
||||
|
||||
object.hide(false);
|
||||
runtimeScene.renderAndStep(1000 / 60);
|
||||
expect(inputElement.style.display).to.be('initial');
|
||||
expect(formElement.style.display).to.be('initial');
|
||||
|
||||
// Check visibility of the DOM element is updated at each frame,
|
||||
// according to the layer visibility.
|
||||
runtimeScene.getLayer('').show(false);
|
||||
runtimeScene.renderAndStep(1000 / 60);
|
||||
expect(inputElement.style.display).to.be('none');
|
||||
expect(formElement.style.display).to.be('none');
|
||||
|
||||
runtimeScene.getLayer('').show(true);
|
||||
runtimeScene.renderAndStep(1000 / 60);
|
||||
expect(inputElement.style.display).to.be('initial');
|
||||
expect(formElement.style.display).to.be('initial');
|
||||
|
||||
// Clean up - not mandatory but to avoid overloading the testing browser.
|
||||
runtimeScene.unloadScene();
|
||||
@@ -205,31 +209,31 @@ describe('gdjs.TextInputRuntimeObject (using a PixiJS RuntimeGame with DOM eleme
|
||||
object,
|
||||
} = await setupObjectAndGetDomElementContainer();
|
||||
|
||||
const inputElement = gameDomElementContainer.querySelector('input');
|
||||
if (!inputElement) throw new Error('Expected input element to be found');
|
||||
const formElement = gameDomElementContainer.querySelector('form');
|
||||
if (!formElement) throw new Error('Expected input element to be found');
|
||||
|
||||
// Check visibility of the DOM element is visible by default, if it should be visible
|
||||
// on the screen.
|
||||
runtimeScene.renderAndStep(1000 / 60);
|
||||
expect(inputElement.style.display).to.be('initial');
|
||||
expect(formElement.style.display).to.be('initial');
|
||||
|
||||
// Check visibility of the DOM element is updated at each frame,
|
||||
// according to the object position of screen.
|
||||
object.setX(-500); // -500 + 300 (object default width) = -200, still outside the camera.
|
||||
runtimeScene.renderAndStep(1000 / 60);
|
||||
expect(inputElement.style.display).to.be('none');
|
||||
expect(formElement.style.display).to.be('none');
|
||||
|
||||
object.setWidth(600); // -500 + 600 = 100, inside the camera
|
||||
runtimeScene.renderAndStep(1000 / 60);
|
||||
expect(inputElement.style.display).to.be('initial');
|
||||
expect(formElement.style.display).to.be('initial');
|
||||
|
||||
runtimeScene.getLayer('').setCameraX(900);
|
||||
runtimeScene.renderAndStep(1000 / 60);
|
||||
expect(inputElement.style.display).to.be('none');
|
||||
expect(formElement.style.display).to.be('none');
|
||||
|
||||
runtimeScene.getLayer('').setCameraX(400);
|
||||
runtimeScene.renderAndStep(1000 / 60);
|
||||
expect(inputElement.style.display).to.be('initial');
|
||||
expect(formElement.style.display).to.be('initial');
|
||||
|
||||
// Clean up - not mandatory but to avoid overloading the testing browser.
|
||||
runtimeScene.unloadScene();
|
||||
|
@@ -31,6 +31,7 @@ namespace gdjs {
|
||||
private _input: HTMLInputElement | HTMLTextAreaElement | null = null;
|
||||
private _instanceContainer: gdjs.RuntimeInstanceContainer;
|
||||
private _runtimeGame: gdjs.RuntimeGame;
|
||||
private _form: HTMLFormElement | null = null;
|
||||
|
||||
constructor(
|
||||
runtimeObject: gdjs.TextInputRuntimeObject,
|
||||
@@ -47,18 +48,34 @@ namespace gdjs {
|
||||
if (!!this._input)
|
||||
throw new Error('Tried to recreate an input while it already exists.');
|
||||
|
||||
this._form = document.createElement('form');
|
||||
|
||||
const isTextArea = this._object.getInputType() === 'text area';
|
||||
this._input = document.createElement(isTextArea ? 'textarea' : 'input');
|
||||
this._input.style.border = '1px solid black';
|
||||
|
||||
this._form.style.border = '0px';
|
||||
this._form.style.borderRadius = '0px';
|
||||
this._form.style.backgroundColor = 'transparent';
|
||||
this._form.style.position = 'absolute';
|
||||
this._form.style.pointerEvents = 'auto'; // Element can be clicked/touched.
|
||||
this._form.style.display = 'none'; // Hide while object is being set up.
|
||||
this._form.style.boxSizing = 'border-box';
|
||||
this._form.style.textAlign = this._object.getTextAlign();
|
||||
|
||||
this._input.autocomplete = 'off';
|
||||
this._input.style.borderRadius = '0px';
|
||||
this._input.style.backgroundColor = 'white';
|
||||
this._input.style.position = 'absolute';
|
||||
this._input.style.resize = 'none';
|
||||
this._input.style.outline = 'none';
|
||||
this._input.style.pointerEvents = 'auto'; // Element can be clicked/touched.
|
||||
this._input.style.display = 'none'; // Hide while object is being set up.
|
||||
this._input.style.boxSizing = 'border-box'; // Important for iOS, because border is added to width/height.
|
||||
this._input.style.outline = 'none'; // Remove any style added by the browser to highlight the focused field in a form (:focus & :focus-visible modifiers).
|
||||
this._input.style.resize = 'none'; // Prevent user from resizing the input when it's a text area.
|
||||
this._input.style.border = '1px solid black';
|
||||
this._input.style.boxSizing = 'border-box';
|
||||
this._input.style.width = '100%';
|
||||
this._input.style.height = '100%';
|
||||
this._input.maxLength = this._object.getMaxLength();
|
||||
this._input.style.padding = `${this._object
|
||||
.getPaddingY()
|
||||
.toFixed(2)}px ${this._object.getPaddingX().toFixed(2)}px`;
|
||||
|
||||
this._form.appendChild(this._input);
|
||||
|
||||
this._input.addEventListener('input', () => {
|
||||
if (!this._input) return;
|
||||
@@ -72,6 +89,11 @@ namespace gdjs {
|
||||
if (document.activeElement !== this._input) this._input.focus();
|
||||
});
|
||||
|
||||
this._form.addEventListener('submit', (event) => {
|
||||
event.preventDefault();
|
||||
this._object.onRendererFormSubmitted();
|
||||
});
|
||||
|
||||
this.updateString();
|
||||
this.updateFont();
|
||||
this.updatePlaceholder();
|
||||
@@ -83,11 +105,14 @@ namespace gdjs {
|
||||
this.updateBorderWidth();
|
||||
this.updateDisabled();
|
||||
this.updateReadOnly();
|
||||
this.updateTextAlign();
|
||||
this.updateMaxLength();
|
||||
this.updatePadding();
|
||||
|
||||
this._runtimeGame
|
||||
.getRenderer()
|
||||
.getDomElementContainer()!
|
||||
.appendChild(this._input);
|
||||
.appendChild(this._form);
|
||||
}
|
||||
|
||||
_destroyElement() {
|
||||
@@ -116,13 +141,12 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
updatePreRender() {
|
||||
if (!this._input) return;
|
||||
|
||||
if (!this._input || !this._form) return;
|
||||
// Hide the input entirely if the object is hidden.
|
||||
// Because this object is rendered as a DOM element (and not part of the PixiJS
|
||||
// scene graph), we have to do this manually.
|
||||
if (this._object.isHidden()) {
|
||||
this._input.style.display = 'none';
|
||||
this._form.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -136,7 +160,7 @@ namespace gdjs {
|
||||
do {
|
||||
const layer = instanceContainer.getLayer(object.getLayer());
|
||||
if (!layer.isVisible() || !object.isVisible()) {
|
||||
this._input.style.display = 'none';
|
||||
this._form.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
// TODO Declare an interface to move up in the object tree.
|
||||
@@ -184,7 +208,7 @@ namespace gdjs {
|
||||
canvasLeft > runtimeGame.getGameResolutionWidth() ||
|
||||
canvasTop > runtimeGame.getGameResolutionHeight();
|
||||
if (isOutsideCanvas) {
|
||||
this._input.style.display = 'none';
|
||||
this._form.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -210,12 +234,17 @@ namespace gdjs {
|
||||
const widthInContainer = pageRight - pageLeft;
|
||||
const heightInContainer = pageBottom - pageTop;
|
||||
|
||||
this._input.style.left = pageLeft + 'px';
|
||||
this._input.style.top = pageTop + 'px';
|
||||
this._input.style.width = widthInContainer + 'px';
|
||||
this._input.style.height = heightInContainer + 'px';
|
||||
this._input.style.transform =
|
||||
this._form.style.left = pageLeft + 'px';
|
||||
this._form.style.top = pageTop + 'px';
|
||||
this._form.style.width = widthInContainer + 'px';
|
||||
this._form.style.height = heightInContainer + 'px';
|
||||
this._form.style.transform =
|
||||
'rotate3d(0,0,1,' + (this._object.getAngle() % 360) + 'deg)';
|
||||
this._form.style.textAlign = this._object.getTextAlign();
|
||||
|
||||
this._input.style.padding = `${this._object
|
||||
.getPaddingY()
|
||||
.toFixed(2)}px ${this._object.getPaddingX().toFixed(2)}px`;
|
||||
|
||||
// Automatically adjust the font size to follow the game scale.
|
||||
this._input.style.fontSize =
|
||||
@@ -224,7 +253,7 @@ namespace gdjs {
|
||||
'px';
|
||||
|
||||
// Display after the object is positioned.
|
||||
this._input.style.display = 'initial';
|
||||
this._form.style.display = 'initial';
|
||||
}
|
||||
|
||||
updateString() {
|
||||
@@ -246,8 +275,8 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
updateOpacity() {
|
||||
if (!this._input) return;
|
||||
this._input.style.opacity = '' + this._object.getOpacity() / 255;
|
||||
if (!this._form) return;
|
||||
this._form.style.opacity = (this._object.getOpacity() / 255).toFixed(3);
|
||||
}
|
||||
|
||||
updateInputType() {
|
||||
@@ -297,14 +326,39 @@ namespace gdjs {
|
||||
this._input.style.borderWidth = this._object.getBorderWidth() + 'px';
|
||||
}
|
||||
updateDisabled() {
|
||||
if (!this._input) return;
|
||||
if (!this._form) return;
|
||||
|
||||
this._input.disabled = this._object.isDisabled();
|
||||
this._form.disabled = this._object.isDisabled();
|
||||
}
|
||||
updateReadOnly() {
|
||||
if (!this._form) return;
|
||||
|
||||
this._form.readOnly = this._object.isReadOnly();
|
||||
}
|
||||
|
||||
updateMaxLength() {
|
||||
const input = this._input;
|
||||
if (!input) return;
|
||||
if (this._object.getMaxLength() <= 0) {
|
||||
input.removeAttribute('maxLength');
|
||||
return;
|
||||
}
|
||||
input.maxLength = this._object.getMaxLength();
|
||||
}
|
||||
|
||||
updatePadding() {
|
||||
if (!this._input) return;
|
||||
|
||||
this._input.readOnly = this._object.isReadOnly();
|
||||
this._input.style.padding = `${this._object
|
||||
.getPaddingY()
|
||||
.toFixed(2)}px ${this._object.getPaddingX().toFixed(2)}px`;
|
||||
}
|
||||
|
||||
updateTextAlign() {
|
||||
if (!this._input) return;
|
||||
|
||||
const newTextAlign = this._object.getTextAlign();
|
||||
this._input.style.textAlign = newTextAlign;
|
||||
}
|
||||
|
||||
isFocused() {
|
||||
@@ -317,7 +371,6 @@ namespace gdjs {
|
||||
this._input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
export const TextInputRuntimeObjectRenderer = TextInputRuntimeObjectPixiRenderer;
|
||||
export type TextInputRuntimeObjectRenderer = TextInputRuntimeObjectPixiRenderer;
|
||||
}
|
||||
|
@@ -9,9 +9,10 @@ namespace gdjs {
|
||||
'search',
|
||||
'text area',
|
||||
] as const;
|
||||
const supportedTextAlign = ['left', 'center', 'right'] as const;
|
||||
|
||||
type SupportedInputType = typeof supportedInputTypes[number];
|
||||
|
||||
type SupportedTextAlign = typeof supportedTextAlign[number];
|
||||
const parseInputType = (potentialInputType: string): SupportedInputType => {
|
||||
const lowercasedNewInputType = potentialInputType.toLowerCase();
|
||||
|
||||
@@ -22,6 +23,19 @@ namespace gdjs {
|
||||
return 'text';
|
||||
};
|
||||
|
||||
const parseTextAlign = (
|
||||
potentialTextAlign: string | undefined
|
||||
): SupportedTextAlign => {
|
||||
if (!potentialTextAlign) return 'left';
|
||||
const lowercasedNewTextAlign = potentialTextAlign.toLowerCase();
|
||||
|
||||
// @ts-ignore - we're actually checking that this value is correct.
|
||||
if (supportedTextAlign.includes(lowercasedNewTextAlign))
|
||||
return potentialTextAlign as SupportedTextAlign;
|
||||
|
||||
return 'left';
|
||||
};
|
||||
|
||||
/** Base parameters for {@link gdjs.TextInputRuntimeObject} */
|
||||
export interface TextInputObjectData extends ObjectData {
|
||||
/** The base parameters of the TextInput */
|
||||
@@ -39,6 +53,12 @@ namespace gdjs {
|
||||
borderWidth: float;
|
||||
disabled: boolean;
|
||||
readOnly: boolean;
|
||||
// ---- Values can be undefined because of support for these feature was added in v5.5.222.
|
||||
paddingX?: float;
|
||||
paddingY?: float;
|
||||
textAlign?: SupportedTextAlign;
|
||||
maxLength?: integer;
|
||||
// ----
|
||||
};
|
||||
}
|
||||
|
||||
@@ -67,6 +87,10 @@ namespace gdjs {
|
||||
const DEFAULT_WIDTH = 300;
|
||||
const DEFAULT_HEIGHT = 30;
|
||||
|
||||
const clampPadding = (value: float, dimension: float, borderWidth: float) => {
|
||||
return Math.max(0, Math.min(dimension / 2 - borderWidth, value));
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows a text input on the screen the player can type text into.
|
||||
*/
|
||||
@@ -84,12 +108,16 @@ namespace gdjs {
|
||||
private _textColor: [float, float, float];
|
||||
private _fillColor: [float, float, float];
|
||||
private _fillOpacity: float;
|
||||
private _paddingX: integer;
|
||||
private _paddingY: integer;
|
||||
private _textAlign: SupportedTextAlign;
|
||||
private _maxLength: integer;
|
||||
private _borderColor: [float, float, float];
|
||||
private _borderOpacity: float;
|
||||
private _borderWidth: float;
|
||||
private _disabled: boolean;
|
||||
private _readOnly: boolean;
|
||||
|
||||
private _isSubmitted: boolean;
|
||||
_renderer: TextInputRuntimeObjectRenderer;
|
||||
|
||||
constructor(
|
||||
@@ -113,7 +141,17 @@ namespace gdjs {
|
||||
this._borderWidth = objectData.content.borderWidth;
|
||||
this._disabled = objectData.content.disabled;
|
||||
this._readOnly = objectData.content.readOnly;
|
||||
|
||||
this._textAlign = parseTextAlign(objectData.content.textAlign);
|
||||
this._maxLength = objectData.content.maxLength || 0;
|
||||
this._paddingX =
|
||||
objectData.content.paddingX !== undefined
|
||||
? objectData.content.paddingX
|
||||
: 2;
|
||||
this._paddingY =
|
||||
objectData.content.paddingY !== undefined
|
||||
? objectData.content.paddingY
|
||||
: 1;
|
||||
this._isSubmitted = false;
|
||||
this._renderer = new gdjs.TextInputRuntimeObjectRenderer(
|
||||
this,
|
||||
instanceContainer
|
||||
@@ -189,6 +227,31 @@ namespace gdjs {
|
||||
if (oldObjectData.content.readOnly !== newObjectData.content.readOnly) {
|
||||
this.setReadOnly(newObjectData.content.readOnly);
|
||||
}
|
||||
if (
|
||||
newObjectData.content.maxLength !== undefined &&
|
||||
oldObjectData.content.maxLength !== newObjectData.content.maxLength
|
||||
) {
|
||||
this.setMaxLength(newObjectData.content.maxLength);
|
||||
}
|
||||
if (
|
||||
newObjectData.content.textAlign &&
|
||||
oldObjectData.content.textAlign !== newObjectData.content.textAlign
|
||||
) {
|
||||
this._textAlign = newObjectData.content.textAlign;
|
||||
}
|
||||
if (
|
||||
newObjectData.content.paddingX !== undefined &&
|
||||
oldObjectData.content.paddingX !== newObjectData.content.paddingX
|
||||
) {
|
||||
this.setPaddingX(newObjectData.content.paddingX);
|
||||
}
|
||||
if (
|
||||
newObjectData.content.paddingY !== undefined &&
|
||||
oldObjectData.content.paddingY !== newObjectData.content.paddingY
|
||||
) {
|
||||
this.setPaddingY(newObjectData.content.paddingY);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -236,6 +299,7 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
updatePreRender(instanceContainer: RuntimeInstanceContainer): void {
|
||||
this._isSubmitted = false;
|
||||
this._renderer.updatePreRender();
|
||||
}
|
||||
|
||||
@@ -253,6 +317,7 @@ namespace gdjs {
|
||||
if (initialInstanceData.customSize) {
|
||||
this.setWidth(initialInstanceData.width);
|
||||
this.setHeight(initialInstanceData.height);
|
||||
this._renderer.updatePadding();
|
||||
}
|
||||
if (initialInstanceData.opacity !== undefined) {
|
||||
this.setOpacity(initialInstanceData.opacity);
|
||||
@@ -288,10 +353,12 @@ namespace gdjs {
|
||||
|
||||
setWidth(width: float): void {
|
||||
this._width = width;
|
||||
this._renderer.updatePadding();
|
||||
}
|
||||
|
||||
setHeight(height: float): void {
|
||||
this._height = height;
|
||||
this._renderer.updatePadding();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,6 +416,10 @@ namespace gdjs {
|
||||
this._string = inputValue;
|
||||
}
|
||||
|
||||
onRendererFormSubmitted() {
|
||||
this._isSubmitted = true;
|
||||
}
|
||||
|
||||
getFontResourceName() {
|
||||
return this._fontResourceName;
|
||||
}
|
||||
@@ -500,6 +571,58 @@ namespace gdjs {
|
||||
isFocused(): boolean {
|
||||
return this._renderer.isFocused();
|
||||
}
|
||||
isSubmitted(): boolean {
|
||||
return this._isSubmitted;
|
||||
}
|
||||
|
||||
getMaxLength(): integer {
|
||||
return this._maxLength;
|
||||
}
|
||||
setMaxLength(value: integer) {
|
||||
if (this._maxLength === value) return;
|
||||
|
||||
this._maxLength = value;
|
||||
this._renderer.updateMaxLength();
|
||||
}
|
||||
|
||||
getPaddingX(): integer {
|
||||
return clampPadding(this._paddingX, this._width, this._borderWidth);
|
||||
}
|
||||
setPaddingX(value: integer) {
|
||||
if (this._paddingX === value) return;
|
||||
if (value < 0) {
|
||||
this._paddingX = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
this._paddingX = value;
|
||||
this._renderer.updatePadding();
|
||||
}
|
||||
getPaddingY(): integer {
|
||||
return clampPadding(this._paddingY, this._height, this._borderWidth);
|
||||
}
|
||||
setPaddingY(value: integer) {
|
||||
if (this._paddingY === value) return;
|
||||
if (value < 0) {
|
||||
this._paddingY = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
this._paddingY = value;
|
||||
this._renderer.updatePadding();
|
||||
}
|
||||
|
||||
getTextAlign(): SupportedTextAlign {
|
||||
return this._textAlign;
|
||||
}
|
||||
|
||||
setTextAlign(newTextAlign: string) {
|
||||
const parsedTextAlign = parseTextAlign(newTextAlign);
|
||||
if (parsedTextAlign === this._textAlign) return;
|
||||
|
||||
this._textAlign = parsedTextAlign;
|
||||
this._renderer.updateTextAlign();
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
if (!this.isFocused()) {
|
||||
|
@@ -175,7 +175,8 @@ std::map<gd::String, gd::PropertyDescriptor> TextObject::GetProperties() const {
|
||||
.AddExtraInfo("center")
|
||||
.AddExtraInfo("bottom")
|
||||
.SetLabel(_("Vertical alignment"))
|
||||
.SetGroup(_("Font"));
|
||||
.SetGroup(_("Font"))
|
||||
.SetQuickCustomizationVisibility(gd::QuickCustomization::Hidden);
|
||||
|
||||
objectProperties["isOutlineEnabled"]
|
||||
.SetValue(isOutlineEnabled ? "true" : "false")
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/SourceFile.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
@@ -420,15 +420,18 @@ gd::String BehaviorCodeGenerator::GenerateUpdatePropertyFromNetworkSyncDataCode(
|
||||
|
||||
gd::String BehaviorCodeGenerator::GeneratePropertyValueCode(
|
||||
const gd::PropertyDescriptor& property) {
|
||||
if (property.GetType() == "String" || property.GetType() == "Choice" ||
|
||||
property.GetType() == "Color" || property.GetType() == "Behavior" ||
|
||||
property.GetType() == "Resource") {
|
||||
|
||||
const auto &valueType =
|
||||
gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(property.GetType());
|
||||
const auto &primitiveType =
|
||||
gd::ValueTypeMetadata::GetPrimitiveValueType(valueType);
|
||||
if (primitiveType == "string" || valueType == "behavior") {
|
||||
return EventsCodeGenerator::ConvertToStringExplicit(property.GetValue());
|
||||
} else if (property.GetType() == "Number") {
|
||||
} else if (primitiveType == "number") {
|
||||
return "Number(" +
|
||||
EventsCodeGenerator::ConvertToStringExplicit(property.GetValue()) +
|
||||
") || 0";
|
||||
} else if (property.GetType() == "Boolean") { // TODO: Check if working
|
||||
} else if (primitiveType == "boolean") { // TODO: Check if working
|
||||
return property.GetValue() == "true" ? "true" : "false";
|
||||
}
|
||||
|
||||
|
@@ -131,10 +131,12 @@ gd::String EventsCodeGenerator::GenerateEventsFunctionCode(
|
||||
bool compilationForRuntime) {
|
||||
gd::ObjectsContainer parameterObjectsAndGroups(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForFreeEventsFunction(
|
||||
project, eventsFunctionsExtension, eventsFunction,
|
||||
parameterObjectsAndGroups);
|
||||
parameterObjectsAndGroups, parameterVariablesContainer);
|
||||
|
||||
EventsCodeGenerator codeGenerator(projectScopedContainers);
|
||||
codeGenerator.SetCodeNamespace(codeNamespace);
|
||||
@@ -144,18 +146,15 @@ gd::String EventsCodeGenerator::GenerateEventsFunctionCode(
|
||||
codeGenerator.SetDiagnosticReport(&diagnosticReport);
|
||||
|
||||
gd::String output = GenerateEventsListCompleteFunctionCode(
|
||||
codeGenerator,
|
||||
codeGenerator.GetCodeNamespaceAccessor() + "func",
|
||||
codeGenerator, codeGenerator.GetCodeNamespaceAccessor() + "func",
|
||||
codeGenerator.GenerateEventsFunctionParameterDeclarationsList(
|
||||
eventsFunction.GetParametersForEvents(eventsFunctionsExtension),
|
||||
0,
|
||||
true),
|
||||
eventsFunction.GetParametersForEvents(
|
||||
eventsFunctionsExtension.GetEventsFunctions()),
|
||||
0, true),
|
||||
codeGenerator.GenerateFreeEventsFunctionContext(
|
||||
eventsFunctionsExtension,
|
||||
eventsFunction,
|
||||
eventsFunctionsExtension, eventsFunction,
|
||||
"runtimeScene.getOnceTriggers()"),
|
||||
eventsFunction.GetEvents(),
|
||||
"",
|
||||
eventsFunction.GetEvents(), "",
|
||||
codeGenerator.GenerateEventsFunctionReturn(eventsFunction));
|
||||
|
||||
// TODO: the editor should pass the diagnostic report and display it to the
|
||||
@@ -185,10 +184,15 @@ gd::String EventsCodeGenerator::GenerateBehaviorEventsFunctionCode(
|
||||
bool compilationForRuntime) {
|
||||
gd::ObjectsContainer parameterObjectsContainers(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
gd::VariablesContainer propertyVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Properties);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForBehaviorEventsFunction(
|
||||
project, eventsFunctionsExtension, eventsBasedBehavior,
|
||||
eventsFunction, parameterObjectsContainers);
|
||||
eventsFunction, parameterObjectsContainers,
|
||||
parameterVariablesContainer, propertyVariablesContainer);
|
||||
|
||||
EventsCodeGenerator codeGenerator(projectScopedContainers);
|
||||
codeGenerator.SetCodeNamespace(codeNamespace);
|
||||
@@ -265,10 +269,15 @@ gd::String EventsCodeGenerator::GenerateObjectEventsFunctionCode(
|
||||
bool compilationForRuntime) {
|
||||
gd::ObjectsContainer parameterObjectsContainers(
|
||||
gd::ObjectsContainer::SourceType::Function);
|
||||
gd::VariablesContainer parameterVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Parameters);
|
||||
gd::VariablesContainer propertyVariablesContainer(
|
||||
gd::VariablesContainer::SourceType::Properties);
|
||||
auto projectScopedContainers = gd::ProjectScopedContainers::
|
||||
MakeNewProjectScopedContainersForObjectEventsFunction(
|
||||
project, eventsFunctionsExtension, eventsBasedObject, eventsFunction,
|
||||
parameterObjectsContainers);
|
||||
parameterObjectsContainers, parameterVariablesContainer,
|
||||
propertyVariablesContainer);
|
||||
|
||||
EventsCodeGenerator codeGenerator(projectScopedContainers);
|
||||
codeGenerator.SetCodeNamespace(codeNamespace);
|
||||
@@ -375,7 +384,7 @@ gd::String EventsCodeGenerator::GenerateFreeEventsFunctionContext(
|
||||
gd::String objectArraysMap;
|
||||
gd::String behaviorNamesMap;
|
||||
return GenerateEventsFunctionContext(eventsFunctionsExtension,
|
||||
eventsFunctionsExtension,
|
||||
eventsFunctionsExtension.GetEventsFunctions(),
|
||||
eventsFunction,
|
||||
onceTriggersVariable,
|
||||
objectsGettersMap,
|
||||
@@ -1350,15 +1359,25 @@ gd::String EventsCodeGenerator::GenerateGetVariable(
|
||||
const gd::String& variableName,
|
||||
const VariableScope& scope,
|
||||
gd::EventsCodeGenerationContext& context,
|
||||
const gd::String& objectName) {
|
||||
const gd::String& objectName,
|
||||
bool hasChild) {
|
||||
gd::String output;
|
||||
const gd::VariablesContainer* variables = NULL;
|
||||
if (scope == ANY_VARIABLE) {
|
||||
if (scope == ANY_VARIABLE || scope == VARIABLE_OR_PROPERTY ||
|
||||
scope == VARIABLE_OR_PROPERTY_OR_PARAMETER) {
|
||||
const auto variablesContainersList =
|
||||
GetProjectScopedContainers().GetVariablesContainersList();
|
||||
const auto& variablesContainer =
|
||||
variablesContainersList.GetVariablesContainerFromVariableName(
|
||||
variableName);
|
||||
const auto &variablesContainer =
|
||||
scope == VARIABLE_OR_PROPERTY_OR_PARAMETER
|
||||
? variablesContainersList.GetVariablesContainerFromVariableOrPropertyOrParameterName(
|
||||
variableName)
|
||||
: scope == VARIABLE_OR_PROPERTY
|
||||
? variablesContainersList
|
||||
.GetVariablesContainerFromVariableOrPropertyName(
|
||||
variableName)
|
||||
: variablesContainersList
|
||||
.GetVariablesContainerFromVariableNameOnly(
|
||||
variableName);
|
||||
const auto sourceType = variablesContainer.GetSourceType();
|
||||
if (sourceType == gd::VariablesContainer::SourceType::Scene) {
|
||||
variables = &variablesContainer;
|
||||
@@ -1381,6 +1400,30 @@ gd::String EventsCodeGenerator::GenerateGetVariable(
|
||||
gd::VariablesContainer::SourceType::ExtensionScene) {
|
||||
variables = &variablesContainer;
|
||||
output = "eventsFunctionContext.sceneVariablesForExtension";
|
||||
} else if (sourceType ==
|
||||
gd::VariablesContainer::SourceType::Properties) {
|
||||
if (hasChild) {
|
||||
// Properties with children are not supported.
|
||||
return "gdjs.VariablesContainer.badVariablesContainer";
|
||||
}
|
||||
const auto &propertiesContainersList =
|
||||
GetProjectScopedContainers().GetPropertiesContainersList();
|
||||
const auto &propertiesContainerAndProperty =
|
||||
propertiesContainersList.Get(variableName);
|
||||
return GeneratePropertyGetterWithoutCasting(
|
||||
propertiesContainerAndProperty.first,
|
||||
propertiesContainerAndProperty.second);
|
||||
} else if (sourceType ==
|
||||
gd::VariablesContainer::SourceType::Parameters) {
|
||||
if (hasChild) {
|
||||
// Parameters with children are not supported.
|
||||
return "gdjs.VariablesContainer.badVariablesContainer";
|
||||
}
|
||||
const auto ¶metersVectorsList =
|
||||
GetProjectScopedContainers().GetParametersVectorsList();
|
||||
const auto ¶meter =
|
||||
gd::ParameterMetadataTools::Get(parametersVectorsList, variableName);
|
||||
return GenerateParameterGetterWithoutCasting(parameter);
|
||||
}
|
||||
} else if (scope == LAYOUT_VARIABLE) {
|
||||
output = "runtimeScene.getScene().getVariables()";
|
||||
@@ -1489,11 +1532,10 @@ gd::String EventsCodeGenerator::GenerateProfilerSectionEnd(
|
||||
ConvertToStringExplicit(section) + "); }";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GeneratePropertyGetter(
|
||||
const gd::PropertiesContainer& propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor& property,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
gd::String EventsCodeGenerator::GeneratePropertySetterWithoutCasting(
|
||||
const gd::PropertiesContainer &propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor &property,
|
||||
const gd::String &operandCode) {
|
||||
bool isLocalProperty =
|
||||
projectScopedContainers.GetPropertiesContainersList()
|
||||
.GetBottomMostPropertiesContainer() == &propertiesContainer;
|
||||
@@ -1506,6 +1548,34 @@ gd::String EventsCodeGenerator::GeneratePropertyGetter(
|
||||
gd::EventsFunctionsContainer::Object
|
||||
? "eventsFunctionContext.getObjects(\"Object\")[0]"
|
||||
: "eventsFunctionContext.getProperties()");
|
||||
|
||||
gd::String propertySetterCode =
|
||||
propertyHolderCode + "." +
|
||||
(isLocalProperty
|
||||
? BehaviorCodeGenerator::GetBehaviorPropertySetterName(
|
||||
property.GetName())
|
||||
: BehaviorCodeGenerator::GetBehaviorSharedPropertySetterName(
|
||||
property.GetName())) +
|
||||
"(" + operandCode + ")\n";
|
||||
return propertySetterCode;
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GeneratePropertyGetterWithoutCasting(
|
||||
const gd::PropertiesContainer &propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor &property) {
|
||||
bool isLocalProperty =
|
||||
projectScopedContainers.GetPropertiesContainersList()
|
||||
.GetBottomMostPropertiesContainer() == &propertiesContainer;
|
||||
|
||||
gd::String propertyHolderCode =
|
||||
propertiesContainer.GetOwner() == gd::EventsFunctionsContainer::Behavior
|
||||
? "eventsFunctionContext.getObjects(\"Object\")[0].getBehavior(" +
|
||||
GenerateGetBehaviorNameCode("Behavior") + ")"
|
||||
: (propertiesContainer.GetOwner() ==
|
||||
gd::EventsFunctionsContainer::Object
|
||||
? "eventsFunctionContext.getObjects(\"Object\")[0]"
|
||||
: "eventsFunctionContext.getProperties()");
|
||||
|
||||
gd::String propertyGetterCode =
|
||||
propertyHolderCode + "." +
|
||||
(isLocalProperty
|
||||
@@ -1514,6 +1584,16 @@ gd::String EventsCodeGenerator::GeneratePropertyGetter(
|
||||
: BehaviorCodeGenerator::GetBehaviorSharedPropertyGetterName(
|
||||
property.GetName())) +
|
||||
"()";
|
||||
return propertyGetterCode;
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GeneratePropertyGetter(
|
||||
const gd::PropertiesContainer& propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor& property,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
gd::String propertyGetterCode =
|
||||
GeneratePropertyGetterWithoutCasting(propertiesContainer, property);
|
||||
|
||||
if (type == "number|string") {
|
||||
if (property.GetType() == "Number") {
|
||||
@@ -1548,13 +1628,18 @@ gd::String EventsCodeGenerator::GeneratePropertyGetter(
|
||||
}
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateParameterGetterWithoutCasting(
|
||||
const gd::ParameterMetadata ¶meter) {
|
||||
return "eventsFunctionContext.getArgument(" +
|
||||
ConvertToStringExplicit(parameter.GetName()) + ")";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateParameterGetter(
|
||||
const gd::ParameterMetadata& parameter,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
gd::String parameterGetterCode =
|
||||
"eventsFunctionContext.getArgument(" +
|
||||
ConvertToStringExplicit(parameter.GetName()) + ")";
|
||||
GenerateParameterGetterWithoutCasting(parameter);
|
||||
|
||||
if (type == "number|string") {
|
||||
if (parameter.GetValueTypeMetadata().IsNumber()) {
|
||||
|
@@ -225,6 +225,11 @@ class EventsCodeGenerator : public gd::EventsCodeGenerator {
|
||||
codeNamespace = codeNamespace_;
|
||||
};
|
||||
|
||||
virtual gd::String GeneratePropertySetterWithoutCasting(
|
||||
const gd::PropertiesContainer &propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor &property,
|
||||
const gd::String &operandCode) override;
|
||||
|
||||
protected:
|
||||
virtual gd::String GenerateParameterCodes(
|
||||
const gd::Expression& parameter,
|
||||
@@ -303,7 +308,8 @@ class EventsCodeGenerator : public gd::EventsCodeGenerator {
|
||||
const gd::String& variableName,
|
||||
const VariableScope& scope,
|
||||
gd::EventsCodeGenerationContext& context,
|
||||
const gd::String& objectName) override;
|
||||
const gd::String& objectName,
|
||||
bool hasChild) override;
|
||||
|
||||
virtual gd::String GenerateVariableAccessor(gd::String childName) override {
|
||||
// This could be probably optimised by using `getChildNamed`.
|
||||
@@ -329,10 +335,17 @@ class EventsCodeGenerator : public gd::EventsCodeGenerator {
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context) override;
|
||||
|
||||
virtual gd::String GeneratePropertyGetterWithoutCasting(
|
||||
const gd::PropertiesContainer &propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor &property) override;
|
||||
|
||||
virtual gd::String GenerateParameterGetter(const gd::ParameterMetadata& parameter,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context) override;
|
||||
|
||||
virtual gd::String GenerateParameterGetterWithoutCasting(
|
||||
const gd::ParameterMetadata ¶meter) override;
|
||||
|
||||
virtual gd::String GenerateBadObject() override { return "null"; }
|
||||
|
||||
virtual gd::String GenerateObject(const gd::String& objectName,
|
||||
|
@@ -53,6 +53,10 @@ void MetadataDeclarationHelper::DeclareExtension(
|
||||
extension.SetCategory(eventsFunctionsExtension.GetCategory());
|
||||
|
||||
DeclareExtensionDependencies(extension, eventsFunctionsExtension);
|
||||
|
||||
for (const auto &sourceFile : eventsFunctionsExtension.GetAllSourceFiles()) {
|
||||
extension.AddSourceFile() = sourceFile;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,6 +158,9 @@ gd::ObjectMetadata &MetadataDeclarationHelper::DeclareObjectMetadata(
|
||||
.AddDefaultBehavior("TextContainerCapability::TextContainerBehavior");
|
||||
}
|
||||
|
||||
if (eventsBasedObject.IsPrivate())
|
||||
objectMetadata.SetPrivate();
|
||||
|
||||
// TODO EBO Use full type to identify object to avoid collision.
|
||||
// Objects are identified by their name alone.
|
||||
const gd::String &objectType = eventsBasedObject.GetName();
|
||||
@@ -510,6 +517,7 @@ MetadataDeclarationHelper::DeclareExpressionMetadata(
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsFunction &eventsFunction) {
|
||||
auto functionType = eventsFunction.GetFunctionType();
|
||||
auto &freeEventsFunctions = eventsFunctionsExtension.GetEventsFunctions();
|
||||
if (functionType == gd::EventsFunction::ExpressionAndCondition) {
|
||||
auto expressionAndCondition = extension.AddExpressionAndCondition(
|
||||
gd::ValueTypeMetadata::GetPrimitiveValueType(
|
||||
@@ -523,7 +531,7 @@ MetadataDeclarationHelper::DeclareExpressionMetadata(
|
||||
eventsFunction.GetGroup(), GetExtensionIconUrl(extension));
|
||||
// By convention, first parameter is always the Runtime Scene.
|
||||
expressionAndCondition.AddCodeOnlyParameter("currentScene", "");
|
||||
DeclareEventsFunctionParameters(eventsFunctionsExtension, eventsFunction,
|
||||
DeclareEventsFunctionParameters(freeEventsFunctions, eventsFunction,
|
||||
expressionAndCondition, 0);
|
||||
expressionAndConditions.push_back(expressionAndCondition);
|
||||
return expressionAndConditions.back();
|
||||
@@ -544,7 +552,7 @@ MetadataDeclarationHelper::DeclareExpressionMetadata(
|
||||
eventsFunction.GetGroup(), GetExtensionIconUrl(extension));
|
||||
// By convention, first parameter is always the Runtime Scene.
|
||||
expression.AddCodeOnlyParameter("currentScene", "");
|
||||
DeclareEventsFunctionParameters(eventsFunctionsExtension, eventsFunction,
|
||||
DeclareEventsFunctionParameters(freeEventsFunctions, eventsFunction,
|
||||
expression, 0);
|
||||
return expression;
|
||||
}
|
||||
@@ -559,6 +567,7 @@ gd::InstructionMetadata &MetadataDeclarationHelper::DeclareInstructionMetadata(
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
|
||||
const gd::EventsFunction &eventsFunction) {
|
||||
auto functionType = eventsFunction.GetFunctionType();
|
||||
auto &freeEventsFunctions = eventsFunctionsExtension.GetEventsFunctions();
|
||||
if (functionType == gd::EventsFunction::Condition) {
|
||||
auto &condition = extension.AddCondition(
|
||||
eventsFunction.GetName(),
|
||||
@@ -568,14 +577,14 @@ gd::InstructionMetadata &MetadataDeclarationHelper::DeclareInstructionMetadata(
|
||||
GetExtensionIconUrl(extension), GetExtensionIconUrl(extension));
|
||||
// By convention, first parameter is always the Runtime Scene.
|
||||
condition.AddCodeOnlyParameter("currentScene", "");
|
||||
DeclareEventsFunctionParameters(eventsFunctionsExtension, eventsFunction,
|
||||
DeclareEventsFunctionParameters(freeEventsFunctions, eventsFunction,
|
||||
condition, 0);
|
||||
return condition;
|
||||
} else if (functionType == gd::EventsFunction::ActionWithOperator) {
|
||||
if (eventsFunctionsExtension.HasEventsFunctionNamed(
|
||||
if (freeEventsFunctions.HasEventsFunctionNamed(
|
||||
eventsFunction.GetGetterName())) {
|
||||
auto &getterFunction = eventsFunctionsExtension.GetEventsFunction(
|
||||
eventsFunction.GetGetterName());
|
||||
auto &getterFunction =
|
||||
freeEventsFunctions.GetEventsFunction(eventsFunction.GetGetterName());
|
||||
|
||||
auto &action = extension.AddAction(
|
||||
eventsFunction.GetName(),
|
||||
@@ -594,7 +603,7 @@ gd::InstructionMetadata &MetadataDeclarationHelper::DeclareInstructionMetadata(
|
||||
getterFunction));
|
||||
// By convention, first parameter is always the Runtime Scene.
|
||||
action.AddCodeOnlyParameter("currentScene", "");
|
||||
DeclareEventsFunctionParameters(eventsFunctionsExtension, eventsFunction,
|
||||
DeclareEventsFunctionParameters(freeEventsFunctions, eventsFunction,
|
||||
action, 0);
|
||||
return action;
|
||||
} else {
|
||||
@@ -608,7 +617,7 @@ gd::InstructionMetadata &MetadataDeclarationHelper::DeclareInstructionMetadata(
|
||||
GetExtensionIconUrl(extension));
|
||||
// By convention, first parameter is always the Runtime Scene.
|
||||
action.AddCodeOnlyParameter("currentScene", "");
|
||||
DeclareEventsFunctionParameters(eventsFunctionsExtension, eventsFunction,
|
||||
DeclareEventsFunctionParameters(freeEventsFunctions, eventsFunction,
|
||||
action, 0);
|
||||
return action;
|
||||
}
|
||||
@@ -621,7 +630,7 @@ gd::InstructionMetadata &MetadataDeclarationHelper::DeclareInstructionMetadata(
|
||||
GetExtensionIconUrl(extension), GetExtensionIconUrl(extension));
|
||||
// By convention, first parameter is always the Runtime Scene.
|
||||
action.AddCodeOnlyParameter("currentScene", "");
|
||||
DeclareEventsFunctionParameters(eventsFunctionsExtension, eventsFunction,
|
||||
DeclareEventsFunctionParameters(freeEventsFunctions, eventsFunction,
|
||||
action, 0);
|
||||
return action;
|
||||
}
|
||||
|
@@ -327,14 +327,16 @@ gd::String ObjectCodeGenerator::GenerateUpdatePropertyFromObjectDataCode(
|
||||
|
||||
gd::String ObjectCodeGenerator::GeneratePropertyValueCode(
|
||||
const gd::PropertyDescriptor& property) {
|
||||
if (property.GetType() == "String" || property.GetType() == "Choice" ||
|
||||
property.GetType() == "Color" || property.GetType() == "Resource") {
|
||||
const auto &primitiveType = gd::ValueTypeMetadata::GetPrimitiveValueType(
|
||||
gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
property.GetType()));
|
||||
if (primitiveType == "string") {
|
||||
return EventsCodeGenerator::ConvertToStringExplicit(property.GetValue());
|
||||
} else if (property.GetType() == "Number") {
|
||||
} else if (primitiveType == "number") {
|
||||
return "Number(" +
|
||||
EventsCodeGenerator::ConvertToStringExplicit(property.GetValue()) +
|
||||
") || 0";
|
||||
} else if (property.GetType() == "Boolean") { // TODO: Check if working
|
||||
} else if (primitiveType == "boolean") { // TODO: Check if working
|
||||
return property.GetValue() == "true" ? "true" : "false";
|
||||
}
|
||||
|
||||
|
@@ -36,7 +36,6 @@ FileExtension::FileExtension() {
|
||||
GetAllActions()["DeleteGroupFichier"].SetFunctionName(
|
||||
"gdjs.evtTools.storage.deleteElementFromJSONFile");
|
||||
GetAllActions()["DeleteFichier"]
|
||||
.SetGroup(_("Storage"))
|
||||
.SetFunctionName("gdjs.evtTools.storage.clearJSONFile");
|
||||
|
||||
StripUnimplementedInstructionsAndExpressions(); // Unimplemented things are
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user