mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
207 Commits
v5.0.144
...
feature/im
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ffa7708a6d | ||
![]() |
2185c25e35 | ||
![]() |
db11465b87 | ||
![]() |
48c532ad71 | ||
![]() |
72319df6f1 | ||
![]() |
c596335b7b | ||
![]() |
a9b42de64b | ||
![]() |
64ea3461d0 | ||
![]() |
cef473ca0e | ||
![]() |
9378b325d0 | ||
![]() |
238043655c | ||
![]() |
731a64aa0f | ||
![]() |
e1e7344ca5 | ||
![]() |
a5d5f0b7a5 | ||
![]() |
3dcbe46fc7 | ||
![]() |
4d3d96a889 | ||
![]() |
23631cc2ce | ||
![]() |
3937b59d73 | ||
![]() |
3b594ded7d | ||
![]() |
e8a7cad17c | ||
![]() |
2557cf556c | ||
![]() |
7c51f0af81 | ||
![]() |
dc146a7411 | ||
![]() |
7620bac88a | ||
![]() |
c51e4be22d | ||
![]() |
98499dfc53 | ||
![]() |
36de82c93f | ||
![]() |
7e97edcad0 | ||
![]() |
5abb0fd9e3 | ||
![]() |
d80c21244f | ||
![]() |
70f4d545b4 | ||
![]() |
85355c3f17 | ||
![]() |
044cc5354f | ||
![]() |
5ff02b11fc | ||
![]() |
9bf24f9baf | ||
![]() |
958482ee44 | ||
![]() |
7a1fb5b033 | ||
![]() |
33b2fb0168 | ||
![]() |
5cad2be194 | ||
![]() |
2b38aa5445 | ||
![]() |
32279f02e9 | ||
![]() |
7452358656 | ||
![]() |
d2ec483d71 | ||
![]() |
4cb62d15bf | ||
![]() |
96bdbfc70b | ||
![]() |
a64815f500 | ||
![]() |
5ab8a3cd73 | ||
![]() |
7d0ecf113a | ||
![]() |
de30049182 | ||
![]() |
c2a1fb63e1 | ||
![]() |
8562019953 | ||
![]() |
f8232953b5 | ||
![]() |
d52ac6fc3e | ||
![]() |
be4aab6d5c | ||
![]() |
4ed8ff15dd | ||
![]() |
2dd1105a10 | ||
![]() |
0fce6aaaaa | ||
![]() |
29797b7a2f | ||
![]() |
7df7f9f458 | ||
![]() |
fc61fa2c54 | ||
![]() |
fccd3b8f2e | ||
![]() |
5ca91cfac4 | ||
![]() |
628d18ac5a | ||
![]() |
61d5c08549 | ||
![]() |
34497c2783 | ||
![]() |
4627facfd5 | ||
![]() |
aee15424f2 | ||
![]() |
6c44f6e937 | ||
![]() |
a115df260f | ||
![]() |
6e7bc9c809 | ||
![]() |
57ce8dcbbf | ||
![]() |
f86d0197c1 | ||
![]() |
c7b0f345c7 | ||
![]() |
9803b4b8f4 | ||
![]() |
ef4815a37e | ||
![]() |
fd7d27e727 | ||
![]() |
ce94c6ae2f | ||
![]() |
c638a38275 | ||
![]() |
e539fdb0e9 | ||
![]() |
2a9193e4c2 | ||
![]() |
cf8361be0c | ||
![]() |
2ba5f03e67 | ||
![]() |
d9435eda5a | ||
![]() |
bc807acf8a | ||
![]() |
194b60aa72 | ||
![]() |
02bbdfecd4 | ||
![]() |
bf19ec5a68 | ||
![]() |
59094110ca | ||
![]() |
a35ead0ab2 | ||
![]() |
669c10c462 | ||
![]() |
2859f2a3b6 | ||
![]() |
be675fc5e6 | ||
![]() |
2be238bc9e | ||
![]() |
5c08fb06d8 | ||
![]() |
8ec96a7446 | ||
![]() |
792ce82a28 | ||
![]() |
da444d53cd | ||
![]() |
62a6d42488 | ||
![]() |
53e70c5a8f | ||
![]() |
74ffba0f17 | ||
![]() |
4e03cf559d | ||
![]() |
4f5690503e | ||
![]() |
8ac7284118 | ||
![]() |
16cdc9a047 | ||
![]() |
ee43afa301 | ||
![]() |
92bc846190 | ||
![]() |
beb832be8b | ||
![]() |
961c78b468 | ||
![]() |
2d7467bc27 | ||
![]() |
0a9d9b940b | ||
![]() |
f8bd457346 | ||
![]() |
6deeae76c5 | ||
![]() |
473b16bbc1 | ||
![]() |
20a328dcd6 | ||
![]() |
578aae7a69 | ||
![]() |
27f89b1b0f | ||
![]() |
bc75d6003c | ||
![]() |
fd03deb4ea | ||
![]() |
71f20d7852 | ||
![]() |
9d121d0085 | ||
![]() |
6292e338bc | ||
![]() |
c5eb0bcc00 | ||
![]() |
a732fda4d9 | ||
![]() |
398bff8492 | ||
![]() |
f30e92a953 | ||
![]() |
8210c25acb | ||
![]() |
6a13940e17 | ||
![]() |
622aa7c08c | ||
![]() |
a71558a490 | ||
![]() |
37539aa788 | ||
![]() |
789f819f25 | ||
![]() |
52ebfb8100 | ||
![]() |
ecc5c689d2 | ||
![]() |
5b1e169557 | ||
![]() |
386e23b042 | ||
![]() |
fc76bafc7c | ||
![]() |
de53f4df4f | ||
![]() |
9fedf124db | ||
![]() |
2c68bb4bdd | ||
![]() |
2360cf899f | ||
![]() |
3fc57c2b06 | ||
![]() |
b4f41e96ae | ||
![]() |
b20108ddcb | ||
![]() |
a58b039994 | ||
![]() |
a7f218622e | ||
![]() |
8d95eb4269 | ||
![]() |
4e46690418 | ||
![]() |
db1737281e | ||
![]() |
d5eecda570 | ||
![]() |
80cb6d697c | ||
![]() |
6b08fec747 | ||
![]() |
2c92ce74ce | ||
![]() |
30643ced07 | ||
![]() |
bf27761cff | ||
![]() |
58df3aeca1 | ||
![]() |
69f8961e9e | ||
![]() |
1abb39ec17 | ||
![]() |
c5226c1e45 | ||
![]() |
d40789005b | ||
![]() |
fcbe5c364e | ||
![]() |
df3433c55f | ||
![]() |
7d892fd976 | ||
![]() |
56320d7253 | ||
![]() |
05acd061bd | ||
![]() |
7991ceb351 | ||
![]() |
bf6d18ccbe | ||
![]() |
536b7dcc62 | ||
![]() |
a157f32d4a | ||
![]() |
49f579f32d | ||
![]() |
8f4ecd373f | ||
![]() |
a3a53415b1 | ||
![]() |
c278c0a432 | ||
![]() |
862f270b83 | ||
![]() |
7232dbc2fa | ||
![]() |
78cbe48718 | ||
![]() |
e153d295de | ||
![]() |
1b8510655e | ||
![]() |
bd88127563 | ||
![]() |
01b9f09604 | ||
![]() |
0db30f02c9 | ||
![]() |
a852e91690 | ||
![]() |
79d6281061 | ||
![]() |
eba6b2540c | ||
![]() |
0706a54305 | ||
![]() |
d929fd6e48 | ||
![]() |
4dbabab052 | ||
![]() |
827c5d6442 | ||
![]() |
46be0e0ffc | ||
![]() |
72e3cf5b99 | ||
![]() |
54f32a2542 | ||
![]() |
b826f66455 | ||
![]() |
6fc03cccc6 | ||
![]() |
ed7313a330 | ||
![]() |
7390f7cd6a | ||
![]() |
4619ae824b | ||
![]() |
0f69ee435f | ||
![]() |
f46241d5a2 | ||
![]() |
4c8ec48004 | ||
![]() |
3ac121be4c | ||
![]() |
3aa636861c | ||
![]() |
6d4b422be6 | ||
![]() |
b8ee27f62c | ||
![]() |
6996ff452d | ||
![]() |
da7934c6ac | ||
![]() |
90bebcb404 | ||
![]() |
a29e7aae44 | ||
![]() |
52201e2a36 |
@@ -43,7 +43,7 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
|
||||
std::size_t relationalOperatorIndex = instrInfos.parameters.size();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
|
||||
++i) {
|
||||
if (instrInfos.parameters[i].type == "relationalOperator")
|
||||
if (instrInfos.parameters[i].GetType() == "relationalOperator")
|
||||
relationalOperatorIndex = i;
|
||||
}
|
||||
// Ensure that there is at least one parameter after the relational operator
|
||||
@@ -95,7 +95,7 @@ gd::String EventsCodeGenerator::GenerateOperatorCall(
|
||||
std::size_t operatorIndex = instrInfos.parameters.size();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
|
||||
++i) {
|
||||
if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
|
||||
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
|
||||
}
|
||||
|
||||
// Ensure that there is at least one parameter after the operator
|
||||
@@ -164,7 +164,7 @@ gd::String EventsCodeGenerator::GenerateCompoundOperatorCall(
|
||||
std::size_t operatorIndex = instrInfos.parameters.size();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
|
||||
++i) {
|
||||
if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
|
||||
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
|
||||
}
|
||||
|
||||
// Ensure that there is at least one parameter after the operator
|
||||
@@ -215,7 +215,7 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
|
||||
std::size_t operatorIndex = instrInfos.parameters.size();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
|
||||
++i) {
|
||||
if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
|
||||
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
|
||||
}
|
||||
|
||||
// Ensure that there is at least one parameter after the operator
|
||||
@@ -293,7 +293,7 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
|
||||
// Verify that there are no mismatchs between object type in parameters.
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].type)) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
|
||||
gd::String objectInParameter =
|
||||
condition.GetParameter(pNb).GetPlainString();
|
||||
|
||||
@@ -303,11 +303,11 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
|
||||
objectInParameter)) {
|
||||
return "/* Unknown object - skipped. */";
|
||||
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
|
||||
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
|
||||
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
objectInParameter) !=
|
||||
instrInfos.parameters[pNb].supplementaryInformation) {
|
||||
instrInfos.parameters[pNb].GetExtraInfo()) {
|
||||
return "/* Mismatched object type - skipped. */";
|
||||
}
|
||||
}
|
||||
@@ -485,7 +485,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
|
||||
// Verify that there are no mismatchs between object type in parameters.
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].type)) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
|
||||
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
|
||||
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
|
||||
@@ -493,11 +493,11 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
|
||||
objectInParameter)) {
|
||||
return "/* Unknown object - skipped. */";
|
||||
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
|
||||
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
|
||||
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
objectInParameter) !=
|
||||
instrInfos.parameters[pNb].supplementaryInformation) {
|
||||
instrInfos.parameters[pNb].GetExtraInfo()) {
|
||||
return "/* Mismatched object type - skipped. */";
|
||||
}
|
||||
}
|
||||
@@ -670,6 +670,18 @@ gd::String EventsCodeGenerator::GenerateActionsListCode(
|
||||
return outputCode;
|
||||
}
|
||||
|
||||
const gd::String EventsCodeGenerator::GenerateRelationalOperatorCodes(const gd::String &operatorString) {
|
||||
if (operatorString == "=") {
|
||||
return "==";
|
||||
}
|
||||
if (operatorString != "<" && operatorString != ">" &&
|
||||
operatorString != "<=" && operatorString != ">=" && operatorString != "!=") {
|
||||
cout << "Warning: Bad relational operator: Set to == by default." << endl;
|
||||
return "==";
|
||||
}
|
||||
return operatorString;
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
const gd::Expression& parameter,
|
||||
const gd::ParameterMetadata& metadata,
|
||||
@@ -679,31 +691,24 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
supplementaryParametersTypes) {
|
||||
gd::String argOutput;
|
||||
|
||||
if (ParameterMetadata::IsExpression("number", metadata.type)) {
|
||||
if (ParameterMetadata::IsExpression("number", metadata.GetType())) {
|
||||
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
*this, context, "number", parameter, lastObjectName);
|
||||
} else if (ParameterMetadata::IsExpression("string", metadata.type)) {
|
||||
} else if (ParameterMetadata::IsExpression("string", metadata.GetType())) {
|
||||
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
*this, context, "string", parameter, lastObjectName);
|
||||
} else if (ParameterMetadata::IsExpression("variable", metadata.type)) {
|
||||
} else if (ParameterMetadata::IsExpression("variable", metadata.GetType())) {
|
||||
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
*this, context, metadata.type, parameter, lastObjectName);
|
||||
} else if (ParameterMetadata::IsObject(metadata.type)) {
|
||||
*this, context, metadata.GetType(), parameter, lastObjectName);
|
||||
} else if (ParameterMetadata::IsObject(metadata.GetType())) {
|
||||
// It would be possible to run a gd::ExpressionCodeGenerator if later
|
||||
// objects can have nested objects, or function returning objects.
|
||||
argOutput =
|
||||
GenerateObject(parameter.GetPlainString(), metadata.type, context);
|
||||
} else if (metadata.type == "relationalOperator") {
|
||||
auto parameterString = parameter.GetPlainString();
|
||||
argOutput += parameterString == "=" ? "==" : parameterString;
|
||||
if (argOutput != "==" && argOutput != "<" && argOutput != ">" &&
|
||||
argOutput != "<=" && argOutput != ">=" && argOutput != "!=") {
|
||||
cout << "Warning: Bad relational operator: Set to == by default." << endl;
|
||||
argOutput = "==";
|
||||
}
|
||||
|
||||
GenerateObject(parameter.GetPlainString(), metadata.GetType(), context);
|
||||
} else if (metadata.GetType() == "relationalOperator") {
|
||||
argOutput += GenerateRelationalOperatorCodes(parameter.GetPlainString());
|
||||
argOutput = "\"" + argOutput + "\"";
|
||||
} else if (metadata.type == "operator") {
|
||||
} else if (metadata.GetType() == "operator") {
|
||||
argOutput += parameter.GetPlainString();
|
||||
if (argOutput != "=" && argOutput != "+" && argOutput != "-" &&
|
||||
argOutput != "/" && argOutput != "*") {
|
||||
@@ -712,28 +717,28 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
}
|
||||
|
||||
argOutput = "\"" + argOutput + "\"";
|
||||
} else if (ParameterMetadata::IsBehavior(metadata.type)) {
|
||||
} else if (ParameterMetadata::IsBehavior(metadata.GetType())) {
|
||||
argOutput = GenerateGetBehaviorNameCode(parameter.GetPlainString());
|
||||
} else if (metadata.type == "key") {
|
||||
} else if (metadata.GetType() == "key") {
|
||||
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
|
||||
} else if (metadata.type == "audioResource" ||
|
||||
metadata.type == "bitmapFontResource" ||
|
||||
metadata.type == "fontResource" ||
|
||||
metadata.type == "imageResource" ||
|
||||
metadata.type == "jsonResource" ||
|
||||
metadata.type == "videoResource" ||
|
||||
} else if (metadata.GetType() == "audioResource" ||
|
||||
metadata.GetType() == "bitmapFontResource" ||
|
||||
metadata.GetType() == "fontResource" ||
|
||||
metadata.GetType() == "imageResource" ||
|
||||
metadata.GetType() == "jsonResource" ||
|
||||
metadata.GetType() == "videoResource" ||
|
||||
// Deprecated, old parameter names:
|
||||
metadata.type == "password" || metadata.type == "musicfile" ||
|
||||
metadata.type == "soundfile" || metadata.type == "police") {
|
||||
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||
|
||||
metadata.GetType() == "soundfile" || metadata.GetType() == "police") {
|
||||
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
|
||||
} else if (metadata.type == "mouse") {
|
||||
} else if (metadata.GetType() == "mouse") {
|
||||
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
|
||||
} else if (metadata.type == "yesorno") {
|
||||
} else if (metadata.GetType() == "yesorno") {
|
||||
auto parameterString = parameter.GetPlainString();
|
||||
argOutput += (parameterString == "yes" || parameterString == "oui")
|
||||
? GenerateTrue()
|
||||
: GenerateFalse();
|
||||
} else if (metadata.type == "trueorfalse") {
|
||||
} else if (metadata.GetType() == "trueorfalse") {
|
||||
auto parameterString = parameter.GetPlainString();
|
||||
// This is duplicated in AdvancedExtension.cpp for GDJS
|
||||
argOutput += (parameterString == "True" || parameterString == "Vrai")
|
||||
@@ -741,21 +746,21 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
: GenerateFalse();
|
||||
}
|
||||
// Code only parameter type
|
||||
else if (metadata.type == "inlineCode") {
|
||||
argOutput += metadata.supplementaryInformation;
|
||||
else if (metadata.GetType() == "inlineCode") {
|
||||
argOutput += metadata.GetExtraInfo();
|
||||
} else {
|
||||
// Try supplementary types if provided
|
||||
if (supplementaryParametersTypes) {
|
||||
for (std::size_t i = 0; i < supplementaryParametersTypes->size(); ++i) {
|
||||
if ((*supplementaryParametersTypes)[i].first == metadata.type)
|
||||
if ((*supplementaryParametersTypes)[i].first == metadata.GetType())
|
||||
argOutput += (*supplementaryParametersTypes)[i].second;
|
||||
}
|
||||
}
|
||||
|
||||
// Type unknown
|
||||
if (argOutput.empty()) {
|
||||
if (!metadata.type.empty())
|
||||
cout << "Warning: Unknown type of parameter \"" << metadata.type
|
||||
if (!metadata.GetType().empty())
|
||||
cout << "Warning: Unknown type of parameter \"" << metadata.GetType()
|
||||
<< "\"." << std::endl;
|
||||
argOutput += "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
|
||||
}
|
||||
@@ -1030,7 +1035,7 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
|
||||
for (std::size_t i = 0; i < instrInfos.parameters.size();
|
||||
++i) // Some conditions already have a "conditionInverted" parameter
|
||||
{
|
||||
if (instrInfos.parameters[i].type == "conditionInverted")
|
||||
if (instrInfos.parameters[i].GetType() == "conditionInverted")
|
||||
conditionAlreadyTakeCareOfInversion = true;
|
||||
}
|
||||
if (!conditionAlreadyTakeCareOfInversion && conditionInverted)
|
||||
@@ -1051,7 +1056,7 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
|
||||
// Prepare call
|
||||
// Add a static_cast if necessary
|
||||
gd::String objectFunctionCallNamePart =
|
||||
(!instrInfos.parameters[0].supplementaryInformation.empty())
|
||||
(!instrInfos.parameters[0].GetExtraInfo().empty())
|
||||
? "static_cast<" + objInfo.className + "*>(" +
|
||||
GetObjectListName(objectName, context) + "[i])->" +
|
||||
instrInfos.codeExtraInformation.functionCallName
|
||||
|
@@ -481,6 +481,9 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
*/
|
||||
size_t GenerateSingleUsageUniqueIdForEventsList();
|
||||
|
||||
virtual const gd::String GenerateRelationalOperatorCodes(
|
||||
const gd::String& operatorString);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Generate the code for a single parameter.
|
||||
|
@@ -55,6 +55,10 @@ void Instruction::SetParameter(std::size_t nb, const gd::Expression& val) {
|
||||
parameters[nb] = val;
|
||||
}
|
||||
|
||||
void Instruction::AddParameter(const gd::Expression& val) {
|
||||
parameters.push_back(val);
|
||||
}
|
||||
|
||||
std::shared_ptr<Instruction> GD_CORE_API
|
||||
CloneRememberingOriginalElement(std::shared_ptr<Instruction> instruction) {
|
||||
std::shared_ptr<Instruction> copy =
|
||||
|
@@ -123,6 +123,11 @@ class GD_CORE_API Instruction {
|
||||
*/
|
||||
void SetParameter(std::size_t nb, const gd::Expression& val);
|
||||
|
||||
/** Add a parameter at the end
|
||||
* \param val The new value of the parameter
|
||||
*/
|
||||
void AddParameter(const gd::Expression& val);
|
||||
|
||||
/** \brief Get a reference to the std::vector containing the parameters.
|
||||
* \return A std::vector containing the parameters
|
||||
*/
|
||||
|
@@ -184,8 +184,8 @@ void EventsListSerialization::UpdateInstructionsFromGD2x(
|
||||
for (std::size_t j = 0;
|
||||
j < parameters.size() && j < metadata.parameters.size();
|
||||
++j) {
|
||||
if (metadata.parameters[j].type == "relationalOperator" ||
|
||||
metadata.parameters[j].type == "operator") {
|
||||
if (metadata.parameters[j].GetType() == "relationalOperator" ||
|
||||
metadata.parameters[j].GetType() == "operator") {
|
||||
if (j == parameters.size() - 1) {
|
||||
std::cout << "ERROR: No more parameters after a [relational]operator "
|
||||
"when trying to update an instruction from GD2.x";
|
||||
|
@@ -81,7 +81,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
.AddExpression(
|
||||
"GetArgumentAsNumber",
|
||||
_("Get function parameter value"),
|
||||
_("Get function parameter (also called \"argument\") value"),
|
||||
_("Get function parameter (also called \"argument\") value."),
|
||||
"",
|
||||
"res/function16.png")
|
||||
.AddParameter("functionParameterName", "Parameter name");
|
||||
@@ -90,10 +90,34 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
.AddStrExpression(
|
||||
"GetArgumentAsString",
|
||||
_("Get function parameter text"),
|
||||
_("Get function parameter (also called \"argument\") text "),
|
||||
_("Get function parameter (also called \"argument\") text."),
|
||||
"",
|
||||
"res/function16.png")
|
||||
.AddParameter("functionParameterName", "Parameter name");
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
"CompareArgumentAsNumber",
|
||||
_("Compare function parameter value"),
|
||||
_("Compare function parameter (also called \"argument\") value."),
|
||||
_("Parameter _PARAM0_"),
|
||||
"",
|
||||
"res/function32.png",
|
||||
"res/function16.png")
|
||||
.AddParameter("functionParameterName", "Parameter name")
|
||||
.UseStandardRelationalOperatorParameters("number");
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
"CompareArgumentAsString",
|
||||
_("Compare function parameter text"),
|
||||
_("Compare function parameter (also called \"argument\") text."),
|
||||
_("Parameter _PARAM0_"),
|
||||
"",
|
||||
"res/function32.png",
|
||||
"res/function16.png")
|
||||
.AddParameter("functionParameterName", "Parameter name")
|
||||
.UseStandardRelationalOperatorParameters("string");
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -886,7 +886,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/conditions/timer24.png",
|
||||
"res/conditions/timer.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "objectTimer")
|
||||
.AddParameter("expression", _("Time in seconds"))
|
||||
.SetHidden();
|
||||
|
||||
@@ -900,7 +900,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/conditions/timer24.png",
|
||||
"res/conditions/timer.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "objectTimer")
|
||||
.AddParameter("relationalOperator", _("Sign of the test"), "time")
|
||||
.AddParameter("expression", _("Time in seconds"))
|
||||
.SetManipulatedType("number");
|
||||
@@ -913,7 +913,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/conditions/timerPaused24.png",
|
||||
"res/conditions/timerPaused.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "objectTimer")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction(
|
||||
@@ -926,7 +926,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/actions/timer24.png",
|
||||
"res/actions/timer.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"));
|
||||
.AddParameter("identifier", _("Timer's name"), "objectTimer");
|
||||
|
||||
obj.AddAction("PauseObjectTimer",
|
||||
_("Pause an object timer"),
|
||||
@@ -936,7 +936,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/actions/pauseTimer24.png",
|
||||
"res/actions/pauseTimer.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "objectTimer")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("UnPauseObjectTimer",
|
||||
@@ -947,7 +947,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/actions/unPauseTimer24.png",
|
||||
"res/actions/unPauseTimer.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "objectTimer")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("RemoveObjectTimer",
|
||||
@@ -958,7 +958,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/actions/timer24.png",
|
||||
"res/actions/timer.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "objectTimer")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddExpression("X",
|
||||
@@ -1127,7 +1127,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Object timers"),
|
||||
"res/actions/time.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"));
|
||||
.AddParameter("identifier", _("Timer's name"), "objectTimer");
|
||||
|
||||
obj.AddExpression("AngleToObject",
|
||||
_("Angle between two objects"),
|
||||
|
@@ -22,6 +22,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
|
||||
"object or a position.",
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetCategory("Camera")
|
||||
.SetExtensionHelpPath("/interface/scene-editor/layers-and-cameras");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Layers and cameras"))
|
||||
.SetIcon("res/conditions/camera24.png");
|
||||
|
@@ -96,7 +96,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
|
||||
"JSONToVariableStructure",
|
||||
_("Convert JSON to a scene variable"),
|
||||
_("Parse a JSON object and store it into a scene variable"),
|
||||
_("Parse JSON string _PARAM0_ and store it into variable _PARAM1_"),
|
||||
_("Convert JSON string _PARAM0_ and store it into variable _PARAM1_"),
|
||||
"",
|
||||
"res/actions/net24.png",
|
||||
"res/actions/net.png")
|
||||
@@ -108,7 +108,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
|
||||
.AddAction("JSONToGlobalVariableStructure",
|
||||
_("Convert JSON to global variable"),
|
||||
_("Parse a JSON object and store it into a global variable"),
|
||||
_("Parse JSON string _PARAM0_ and store it into global "
|
||||
_("Convert JSON string _PARAM0_ and store it into global "
|
||||
"variable _PARAM1_"),
|
||||
"",
|
||||
"res/actions/net24.png",
|
||||
|
@@ -21,7 +21,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/all-features/storage")
|
||||
.SetCategory("Device");
|
||||
.SetCategory("Advanced");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Storage"))
|
||||
.SetIcon("res/conditions/fichier24.png");
|
||||
|
||||
|
@@ -22,6 +22,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/objects/sprite");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Sprite"))
|
||||
.SetIcon("CppPlatform/Extensions/spriteicon.png");
|
||||
|
||||
gd::ObjectMetadata& obj =
|
||||
extension
|
||||
@@ -322,6 +324,19 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/conditions/animation24.png",
|
||||
"res/conditions/animation.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.MarkAsSimple()
|
||||
.SetHidden();
|
||||
|
||||
obj.AddCondition("AnimationEnded2",
|
||||
_("Animation finished"),
|
||||
_("Check if the animation being played by the Sprite object "
|
||||
"is finished."),
|
||||
_("The animation of _PARAM0_ is finished"),
|
||||
_("Animations and images"),
|
||||
"res/conditions/animation24.png",
|
||||
"res/conditions/animation.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.MarkAsSimple();
|
||||
|
||||
|
@@ -36,7 +36,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
"res/conditions/timer.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("expression", _("Time in seconds"))
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
@@ -50,7 +50,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
"res/conditions/timer24.png",
|
||||
"res/conditions/timer.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
|
||||
.AddParameter("relationalOperator", _("Sign of the test"), "time")
|
||||
.AddParameter("expression", _("Time in seconds"))
|
||||
.SetManipulatedType("number");
|
||||
@@ -78,7 +78,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
"res/conditions/timerPaused24.png",
|
||||
"res/conditions/timerPaused.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -93,7 +93,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
"res/actions/timer24.png",
|
||||
"res/actions/timer.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Timer's name"));
|
||||
.AddParameter("identifier", _("Timer's name"), "sceneTimer");
|
||||
|
||||
extension
|
||||
.AddAction("PauseTimer",
|
||||
@@ -105,7 +105,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
"res/actions/pauseTimer24.png",
|
||||
"res/actions/pauseTimer.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -118,7 +118,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
"res/actions/unPauseTimer24.png",
|
||||
"res/actions/unPauseTimer.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -131,7 +131,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
"res/actions/timer24.png",
|
||||
"res/actions/timer.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -155,7 +155,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
"",
|
||||
"res/timer_black.svg",
|
||||
"res/timer_black.svg")
|
||||
.AddParameter("expression", "Time to wait in seconds")
|
||||
.AddParameter("expression", _("Time to wait in seconds"))
|
||||
.SetHelpPath("/all-features/timers-and-time/wait-action");
|
||||
|
||||
extension
|
||||
@@ -191,7 +191,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
"",
|
||||
"res/actions/time.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Timer's name"));
|
||||
.AddParameter("identifier", _("Timer's name"), "sceneTimer");
|
||||
|
||||
extension
|
||||
.AddExpression("TimeFromStart",
|
||||
|
@@ -20,6 +20,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
|
||||
"these features can be applied.",
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetCategory("User interface")
|
||||
.SetExtensionHelpPath("/all-features/window");
|
||||
extension
|
||||
.AddInstructionOrExpressionGroupMetadata(
|
||||
|
@@ -236,7 +236,6 @@ class GD_CORE_API BehaviorMetadata {
|
||||
}
|
||||
|
||||
const gd::String& GetName() const;
|
||||
#if defined(GD_IDE_ONLY)
|
||||
const gd::String& GetFullName() const { return fullname; }
|
||||
const gd::String& GetDefaultName() const { return defaultName; }
|
||||
const gd::String& GetDescription() const { return description; }
|
||||
@@ -257,7 +256,21 @@ class GD_CORE_API BehaviorMetadata {
|
||||
* \note An empty string means the base object, so any object.
|
||||
*/
|
||||
const gd::String& GetObjectType() const { return objectType; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check if the behavior is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
bool IsPrivate() const { return isPrivate; }
|
||||
|
||||
/**
|
||||
* Set that the behavior is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
BehaviorMetadata &SetPrivate() {
|
||||
isPrivate = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the associated gd::Behavior, handling behavior contents.
|
||||
@@ -315,6 +328,7 @@ class GD_CORE_API BehaviorMetadata {
|
||||
gd::String group;
|
||||
gd::String iconFilename;
|
||||
gd::String objectType;
|
||||
bool isPrivate = false;
|
||||
|
||||
// TODO: Nitpicking: convert these to std::unique_ptr to clarify ownership.
|
||||
std::shared_ptr<gd::Behavior> instance;
|
||||
|
@@ -37,22 +37,24 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
|
||||
const gd::String& supplementaryInformation,
|
||||
bool parameterIsOptional) {
|
||||
gd::ParameterMetadata info;
|
||||
info.type = type;
|
||||
info.SetType(type);
|
||||
info.description = description;
|
||||
info.codeOnly = false;
|
||||
info.optional = parameterIsOptional;
|
||||
info.supplementaryInformation =
|
||||
info.SetOptional(parameterIsOptional);
|
||||
info.SetExtraInfo(
|
||||
// For objects/behavior, the supplementary information
|
||||
// parameter is an object/behavior type...
|
||||
(gd::ParameterMetadata::IsObject(type) ||
|
||||
((gd::ParameterMetadata::IsObject(type) ||
|
||||
gd::ParameterMetadata::IsBehavior(type))
|
||||
// Prefix with the namespace if it's not already there.
|
||||
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
|
||||
? (supplementaryInformation.empty()
|
||||
? ""
|
||||
: extensionNamespace +
|
||||
supplementaryInformation //... so prefix it with the extension
|
||||
// namespace.
|
||||
)
|
||||
: supplementaryInformation; // Otherwise don't change anything
|
||||
: supplementaryInformation); // Otherwise don't change anything
|
||||
|
||||
// TODO: Assert against supplementaryInformation === "emsc" (when running with
|
||||
// Emscripten), and warn about a missing argument when calling addParameter.
|
||||
@@ -64,9 +66,9 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
|
||||
gd::ExpressionMetadata& ExpressionMetadata::AddCodeOnlyParameter(
|
||||
const gd::String& type, const gd::String& supplementaryInformation) {
|
||||
gd::ParameterMetadata info;
|
||||
info.type = type;
|
||||
info.SetType(type);
|
||||
info.codeOnly = true;
|
||||
info.supplementaryInformation = supplementaryInformation;
|
||||
info.SetExtraInfo(supplementaryInformation);
|
||||
|
||||
parameters.push_back(info);
|
||||
return *this;
|
||||
|
@@ -222,6 +222,18 @@ class GD_CORE_API ExpressionMetadata {
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Set the additional information, used for some parameters
|
||||
* with special type (for example, it can contains the type of object accepted
|
||||
* by the parameter), for the last added parameter.
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
ExpressionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
|
||||
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mark this (object) expression as requiring the specified capability,
|
||||
* offered by the base object.
|
||||
@@ -256,7 +268,30 @@ class GD_CORE_API ExpressionMetadata {
|
||||
*/
|
||||
ExpressionCodeGenerationInformation& GetCodeExtraInformation() {
|
||||
return codeExtraInformation;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Erase any existing include file and add the specified include.
|
||||
*/
|
||||
ExpressionMetadata &SetIncludeFile(const gd::String &includeFile) {
|
||||
codeExtraInformation.SetIncludeFile(includeFile);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add a file to the already existing include files.
|
||||
*/
|
||||
ExpressionMetadata &AddIncludeFile(const gd::String &includeFile) {
|
||||
codeExtraInformation.AddIncludeFile(includeFile);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the files that must be included to use the instruction.
|
||||
*/
|
||||
const std::vector<gd::String>& GetIncludeFiles() const {
|
||||
return codeExtraInformation.GetIncludeFiles();
|
||||
}
|
||||
|
||||
ExpressionCodeGenerationInformation codeExtraInformation;
|
||||
|
||||
|
@@ -55,15 +55,17 @@ InstructionMetadata& InstructionMetadata::AddParameter(
|
||||
const gd::String& supplementaryInformation,
|
||||
bool parameterIsOptional) {
|
||||
ParameterMetadata info;
|
||||
info.type = type;
|
||||
info.SetType(type);
|
||||
info.description = description;
|
||||
info.codeOnly = false;
|
||||
info.optional = parameterIsOptional;
|
||||
info.supplementaryInformation =
|
||||
info.SetOptional(parameterIsOptional);
|
||||
info.SetExtraInfo(
|
||||
// For objects/behavior, the supplementary information
|
||||
// parameter is an object/behavior type...
|
||||
(gd::ParameterMetadata::IsObject(type) ||
|
||||
((gd::ParameterMetadata::IsObject(type) ||
|
||||
gd::ParameterMetadata::IsBehavior(type))
|
||||
// Prefix with the namespace if it's not already there.
|
||||
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
|
||||
? (supplementaryInformation.empty()
|
||||
? ""
|
||||
: extensionNamespace +
|
||||
@@ -71,7 +73,7 @@ InstructionMetadata& InstructionMetadata::AddParameter(
|
||||
// extension
|
||||
// namespace.
|
||||
)
|
||||
: supplementaryInformation; // Otherwise don't change anything
|
||||
: supplementaryInformation); // Otherwise don't change anything
|
||||
|
||||
// TODO: Assert against supplementaryInformation === "emsc" (when running with
|
||||
// Emscripten), and warn about a missing argument when calling addParameter.
|
||||
@@ -83,17 +85,19 @@ InstructionMetadata& InstructionMetadata::AddParameter(
|
||||
InstructionMetadata& InstructionMetadata::AddCodeOnlyParameter(
|
||||
const gd::String& type, const gd::String& supplementaryInformation) {
|
||||
ParameterMetadata info;
|
||||
info.type = type;
|
||||
info.SetType(type);
|
||||
info.codeOnly = true;
|
||||
info.supplementaryInformation = supplementaryInformation;
|
||||
info.SetExtraInfo(supplementaryInformation);
|
||||
|
||||
parameters.push_back(info);
|
||||
return *this;
|
||||
}
|
||||
|
||||
InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
|
||||
const gd::String& type) {
|
||||
SetManipulatedType(type);
|
||||
const gd::String& type, const gd::String& typeExtraInfo) {
|
||||
const gd::String& expressionValueType =
|
||||
gd::ValueTypeMetadata::GetPrimitiveValueType(type);
|
||||
SetManipulatedType(expressionValueType);
|
||||
|
||||
if (type == "boolean") {
|
||||
AddParameter("yesorno", _("New value"));
|
||||
@@ -117,8 +121,8 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
|
||||
"_PARAM" + gd::String::From(valueParamIndex) + "_");
|
||||
}
|
||||
} else {
|
||||
AddParameter("operator", _("Modification's sign"), type);
|
||||
AddParameter(type == "number" ? "expression" : type, _("Value"));
|
||||
AddParameter("operator", _("Modification's sign"), expressionValueType);
|
||||
AddParameter(type, _("Value"), typeExtraInfo);
|
||||
|
||||
size_t operatorParamIndex = parameters.size() - 2;
|
||||
size_t valueParamIndex = parameters.size() - 1;
|
||||
@@ -151,8 +155,10 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
|
||||
|
||||
InstructionMetadata&
|
||||
InstructionMetadata::UseStandardRelationalOperatorParameters(
|
||||
const gd::String& type) {
|
||||
SetManipulatedType(type);
|
||||
const gd::String& type, const gd::String& typeExtraInfo) {
|
||||
const gd::String& expressionValueType =
|
||||
gd::ValueTypeMetadata::GetPrimitiveValueType(type);
|
||||
SetManipulatedType(expressionValueType);
|
||||
|
||||
if (type == "boolean") {
|
||||
if (isObjectInstruction || isBehaviorInstruction) {
|
||||
@@ -168,8 +174,8 @@ InstructionMetadata::UseStandardRelationalOperatorParameters(
|
||||
templateSentence.FindAndReplace("<subject>", sentence);
|
||||
}
|
||||
} else {
|
||||
AddParameter("relationalOperator", _("Sign of the test"), type);
|
||||
AddParameter(type == "number" ? "expression" : type, _("Value to compare"));
|
||||
AddParameter("relationalOperator", _("Sign of the test"), expressionValueType);
|
||||
AddParameter(type, _("Value to compare"), typeExtraInfo);
|
||||
size_t operatorParamIndex = parameters.size() - 2;
|
||||
size_t valueParamIndex = parameters.size() - 1;
|
||||
|
||||
|
@@ -206,7 +206,7 @@ class GD_CORE_API InstructionMetadata {
|
||||
if (!parameters.empty())
|
||||
parameters.back().SetLongDescription(longDescription);
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the additional information, used for some parameters
|
||||
@@ -218,20 +218,26 @@ class GD_CORE_API InstructionMetadata {
|
||||
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
|
||||
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add the default parameters for an instruction manipulating the
|
||||
* specified type ("string", "number") with the default operators.
|
||||
*
|
||||
* \note The type "string" can be declined in several subtypes.
|
||||
* \see ParameterMetadata
|
||||
*/
|
||||
InstructionMetadata &UseStandardOperatorParameters(const gd::String &type);
|
||||
InstructionMetadata &UseStandardOperatorParameters(const gd::String &type, const gd::String& typeExtraInfo = "");
|
||||
|
||||
/**
|
||||
* \brief Add the default parameters for an instruction comparing the
|
||||
* specified type ("string", "number") with the default relational operators.
|
||||
*
|
||||
* \note The type "string" can be declined in several subtypes.
|
||||
* \see ParameterMetadata
|
||||
*/
|
||||
InstructionMetadata &UseStandardRelationalOperatorParameters(
|
||||
const gd::String &type);
|
||||
const gd::String &type, const gd::String& typeExtraInfo = "");
|
||||
|
||||
/**
|
||||
* \brief Mark the instruction as an object instruction. Automatically called
|
||||
@@ -276,7 +282,7 @@ class GD_CORE_API InstructionMetadata {
|
||||
*/
|
||||
const gd::String &GetRequiredBaseObjectCapability() const {
|
||||
return requiredBaseObjectCapability;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Consider that the instruction is easy for a user to understand.
|
||||
@@ -487,6 +493,29 @@ class GD_CORE_API InstructionMetadata {
|
||||
return codeExtraInformation.SetAsyncFunctionName(functionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Erase any existing include file and add the specified include.
|
||||
*/
|
||||
InstructionMetadata &SetIncludeFile(const gd::String &includeFile) {
|
||||
codeExtraInformation.SetIncludeFile(includeFile);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add a file to the already existing include files.
|
||||
*/
|
||||
InstructionMetadata &AddIncludeFile(const gd::String &includeFile) {
|
||||
codeExtraInformation.AddIncludeFile(includeFile);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the files that must be included to use the instruction.
|
||||
*/
|
||||
const std::vector<gd::String>& GetIncludeFiles() const {
|
||||
return codeExtraInformation.GetIncludeFiles();
|
||||
};
|
||||
|
||||
std::vector<ParameterMetadata> parameters;
|
||||
|
||||
private:
|
||||
|
@@ -80,6 +80,16 @@ class GD_CORE_API MultipleInstructionMetadata {
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* \see gd::InstructionMetadata::SetParameterExtraInfo
|
||||
*/
|
||||
MultipleInstructionMetadata &SetParameterExtraInfo(const gd::String &defaultValue) {
|
||||
if (expression) expression->SetParameterExtraInfo(defaultValue);
|
||||
if (condition) condition->SetParameterExtraInfo(defaultValue);
|
||||
if (action) action->SetParameterExtraInfo(defaultValue);
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* \see gd::InstructionMetadata::SetParameterLongDescription
|
||||
*/
|
||||
@@ -116,9 +126,9 @@ class GD_CORE_API MultipleInstructionMetadata {
|
||||
* \see gd::InstructionMetadata::UseStandardOperatorParameters
|
||||
* \see gd::InstructionMetadata::UseStandardRelationalOperatorParameters
|
||||
*/
|
||||
MultipleInstructionMetadata &UseStandardParameters(const gd::String &type) {
|
||||
if (condition) condition->UseStandardRelationalOperatorParameters(type);
|
||||
if (action) action->UseStandardOperatorParameters(type);
|
||||
MultipleInstructionMetadata &UseStandardParameters(const gd::String &type, const gd::String& typeExtraInfo = "") {
|
||||
if (condition) condition->UseStandardRelationalOperatorParameters(type, typeExtraInfo);
|
||||
if (action) action->UseStandardOperatorParameters(type, typeExtraInfo);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -154,6 +164,33 @@ class GD_CORE_API MultipleInstructionMetadata {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the files that must be included to use the instruction.
|
||||
*/
|
||||
const std::vector<gd::String>& GetIncludeFiles() const {
|
||||
if (expression)
|
||||
return expression->GetCodeExtraInformation().GetIncludeFiles();
|
||||
if (condition)
|
||||
return condition->GetCodeExtraInformation().GetIncludeFiles();
|
||||
if (action)
|
||||
return action->GetCodeExtraInformation().GetIncludeFiles();
|
||||
// It can't actually happen.
|
||||
throw std::logic_error("no instruction metadata");
|
||||
}
|
||||
|
||||
/**
|
||||
* \see gd::InstructionMetadata::SetPrivate
|
||||
*/
|
||||
MultipleInstructionMetadata &SetPrivate() {
|
||||
if (expression)
|
||||
expression->SetPrivate();
|
||||
if (condition)
|
||||
condition->SetPrivate();
|
||||
if (action)
|
||||
action->SetPrivate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \see gd::InstructionMetadata::MarkAsSimple
|
||||
*/
|
||||
|
@@ -10,43 +10,26 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
ParameterMetadata::ParameterMetadata() : optional(false), codeOnly(false) {}
|
||||
ParameterMetadata::ParameterMetadata() : codeOnly(false) {}
|
||||
|
||||
void ParameterMetadata::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("type", type);
|
||||
element.SetAttribute("supplementaryInformation", supplementaryInformation);
|
||||
element.SetAttribute("optional", optional);
|
||||
valueTypeMetadata.SerializeTo(element);
|
||||
element.SetAttribute("description", description);
|
||||
element.SetAttribute("longDescription", longDescription);
|
||||
element.SetAttribute("codeOnly", codeOnly);
|
||||
element.SetAttribute("defaultValue", defaultValue);
|
||||
if (!longDescription.empty()) {
|
||||
element.SetAttribute("longDescription", longDescription);
|
||||
}
|
||||
if (codeOnly) {
|
||||
element.SetAttribute("codeOnly", codeOnly);
|
||||
}
|
||||
element.SetAttribute("name", name);
|
||||
}
|
||||
|
||||
void ParameterMetadata::UnserializeFrom(const SerializerElement& element) {
|
||||
type = element.GetStringAttribute("type");
|
||||
supplementaryInformation =
|
||||
element.GetStringAttribute("supplementaryInformation");
|
||||
optional = element.GetBoolAttribute("optional");
|
||||
valueTypeMetadata.UnserializeFrom(element);
|
||||
description = element.GetStringAttribute("description");
|
||||
longDescription = element.GetStringAttribute("longDescription");
|
||||
codeOnly = element.GetBoolAttribute("codeOnly");
|
||||
defaultValue = element.GetStringAttribute("defaultValue");
|
||||
name = element.GetStringAttribute("name");
|
||||
}
|
||||
|
||||
// TODO factorize in a file with an enum and helpers?
|
||||
const gd::String ParameterMetadata::numberType = "number";
|
||||
const gd::String ParameterMetadata::stringType = "string";
|
||||
|
||||
const gd::String &ParameterMetadata::GetExpressionValueType(const gd::String ¶meterType) {
|
||||
if (parameterType == "number" || gd::ParameterMetadata::IsExpression("number", parameterType)) {
|
||||
return ParameterMetadata::numberType;
|
||||
}
|
||||
if (parameterType == "string" || gd::ParameterMetadata::IsExpression("string", parameterType)) {
|
||||
return ParameterMetadata::stringType;
|
||||
}
|
||||
return parameterType;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -6,16 +6,13 @@
|
||||
|
||||
#ifndef PARAMETER_METADATA_H
|
||||
#define PARAMETER_METADATA_H
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
|
||||
|
||||
namespace gd {
|
||||
class Project;
|
||||
class Layout;
|
||||
class EventsCodeGenerator;
|
||||
class EventsCodeGenerationContext;
|
||||
class SerializerElement;
|
||||
} // namespace gd
|
||||
|
||||
@@ -32,17 +29,32 @@ class GD_CORE_API ParameterMetadata {
|
||||
ParameterMetadata();
|
||||
virtual ~ParameterMetadata(){};
|
||||
|
||||
/**
|
||||
* \brief Return the metadata of the parameter type.
|
||||
*/
|
||||
gd::ValueTypeMetadata &GetValueTypeMetadata() { return valueTypeMetadata; }
|
||||
|
||||
/**
|
||||
* \brief Set the metadata of the parameter type.
|
||||
*/
|
||||
ParameterMetadata &SetValueTypeMetadata(const gd::ValueTypeMetadata &valueTypeMetadata_) {
|
||||
valueTypeMetadata = valueTypeMetadata_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the type of the parameter.
|
||||
* \see gd::ParameterMetadata::IsObject
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
const gd::String &GetType() const { return type; }
|
||||
const gd::String &GetType() const { return valueTypeMetadata.GetName(); }
|
||||
|
||||
/**
|
||||
* \brief Set the type of the parameter.
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
ParameterMetadata &SetType(const gd::String &type_) {
|
||||
type = type_;
|
||||
valueTypeMetadata.SetName(type_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -71,29 +83,33 @@ class GD_CORE_API ParameterMetadata {
|
||||
* \brief Return an optional additional information, used for some parameters
|
||||
* with special type (for example, it can contains the type of object accepted
|
||||
* by the parameter).
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
const gd::String &GetExtraInfo() const { return supplementaryInformation; }
|
||||
const gd::String &GetExtraInfo() const { return valueTypeMetadata.GetExtraInfo(); }
|
||||
|
||||
/**
|
||||
* \brief Set an optional additional information, used for some parameters
|
||||
* with special type (for example, it can contains the type of object accepted
|
||||
* by the parameter).
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
ParameterMetadata &SetExtraInfo(const gd::String &supplementaryInformation_) {
|
||||
supplementaryInformation = supplementaryInformation_;
|
||||
valueTypeMetadata.SetExtraInfo(supplementaryInformation_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the parameter is optional.
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
bool IsOptional() const { return optional; }
|
||||
bool IsOptional() const { return valueTypeMetadata.IsOptional(); }
|
||||
|
||||
/**
|
||||
* \brief Set if the parameter is optional.
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
ParameterMetadata &SetOptional(bool optional_ = true) {
|
||||
optional = optional_;
|
||||
valueTypeMetadata.SetOptional(optional_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -128,13 +144,15 @@ class GD_CORE_API ParameterMetadata {
|
||||
/**
|
||||
* \brief Get the default value for the parameter.
|
||||
*/
|
||||
const gd::String &GetDefaultValue() const { return defaultValue; }
|
||||
const gd::String &GetDefaultValue() const {
|
||||
return valueTypeMetadata.GetDefaultValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the default value, if the parameter is optional.
|
||||
*/
|
||||
ParameterMetadata &SetDefaultValue(const gd::String &defaultValue_) {
|
||||
defaultValue = defaultValue_;
|
||||
valueTypeMetadata.SetDefaultValue(defaultValue_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -151,26 +169,27 @@ class GD_CORE_API ParameterMetadata {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO Remove these deprecated functions.
|
||||
|
||||
/**
|
||||
* \brief Return true if the type of the parameter is representing one object
|
||||
* (or more, i.e: an object group).
|
||||
*
|
||||
* \see gd::ParameterMetadata::GetType
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
static bool IsObject(const gd::String ¶meterType) {
|
||||
return parameterType == "object" || parameterType == "objectPtr" ||
|
||||
parameterType == "objectList" ||
|
||||
parameterType == "objectListOrEmptyIfJustDeclared" ||
|
||||
parameterType == "objectListOrEmptyWithoutPicking";
|
||||
return gd::ValueTypeMetadata::IsTypeObject(parameterType);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type of the parameter is "behavior".
|
||||
*
|
||||
* \see gd::ParameterMetadata::GetType
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
static bool IsBehavior(const gd::String ¶meterType) {
|
||||
return parameterType == "behavior";
|
||||
return gd::ValueTypeMetadata::IsTypeBehavior(parameterType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,42 +198,22 @@ class GD_CORE_API ParameterMetadata {
|
||||
* \note If you had a new type of parameter, also add it in the IDE (
|
||||
* see EventsFunctionParametersEditor, ParameterRenderingService
|
||||
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
static bool IsExpression(const gd::String &type,
|
||||
const gd::String ¶meterType) {
|
||||
if (type == "number") {
|
||||
return parameterType == "expression" || parameterType == "camera" ||
|
||||
parameterType == "forceMultiplier";
|
||||
} else if (type == "string") {
|
||||
return parameterType == "string" || parameterType == "layer" ||
|
||||
parameterType == "color" || parameterType == "file" ||
|
||||
parameterType == "joyaxis" ||
|
||||
parameterType == "stringWithSelector" ||
|
||||
parameterType == "sceneName" ||
|
||||
parameterType == "layerEffectName" ||
|
||||
parameterType == "layerEffectParameterName" ||
|
||||
parameterType == "objectEffectName" ||
|
||||
parameterType == "objectEffectParameterName" ||
|
||||
parameterType == "objectPointName" ||
|
||||
parameterType == "objectAnimationName" ||
|
||||
parameterType == "functionParameterName" ||
|
||||
parameterType == "externalLayoutName" ||
|
||||
parameterType == "leaderboardId";
|
||||
} else if (type == "variable") {
|
||||
return parameterType == "objectvar" || parameterType == "globalvar" ||
|
||||
parameterType == "scenevar";
|
||||
}
|
||||
return false;
|
||||
return gd::ValueTypeMetadata::IsTypeExpression(type, parameterType);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the expression type from the parameter type.
|
||||
* Declinations of "number" and "string" types (like "forceMultiplier" or
|
||||
* "sceneName") are replaced by "number" and "string".
|
||||
* \deprecated Use gd::ValueTypeMetadata instead.
|
||||
*/
|
||||
static const gd::String &GetExpressionValueType(const gd::String ¶meterType);
|
||||
static const gd::String numberType;
|
||||
static const gd::String stringType;
|
||||
static const gd::String &GetExpressionValueType(const gd::String ¶meterType) {
|
||||
return gd::ValueTypeMetadata::GetPrimitiveValueType(parameterType);
|
||||
}
|
||||
|
||||
/** \name Serialization
|
||||
*/
|
||||
@@ -232,22 +231,17 @@ class GD_CORE_API ParameterMetadata {
|
||||
|
||||
// TODO: Deprecated public fields. Any direct usage should be moved to
|
||||
// getter/setter.
|
||||
gd::String type; ///< Parameter type
|
||||
gd::String supplementaryInformation; ///< Used if needed
|
||||
bool optional; ///< True if the parameter is optional
|
||||
|
||||
gd::String description; ///< Description shown in editor
|
||||
bool codeOnly; ///< True if parameter is relative to code generation only,
|
||||
///< i.e. must not be shown in editor
|
||||
private:
|
||||
gd::ValueTypeMetadata valueTypeMetadata; ///< Parameter type
|
||||
gd::String longDescription; ///< Long description shown in the editor.
|
||||
gd::String defaultValue; ///< Used as a default value in editor or if an
|
||||
///< optional parameter is empty.
|
||||
gd::String name; ///< The name of the parameter to be used in code
|
||||
///< generation. Optional.
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
||||
#endif // PARAMETER_METADATA_H
|
||||
|
@@ -85,7 +85,7 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
const gd::Expression& parameterValue =
|
||||
pNb < parameters.size() ? parameters[pNb].GetPlainString() : "";
|
||||
const gd::Expression& parameterValueOrDefault =
|
||||
parameterValue.GetPlainString().empty() && parameterMetadata.optional
|
||||
parameterValue.GetPlainString().empty() && parameterMetadata.IsOptional()
|
||||
? Expression(parameterMetadata.GetDefaultValue())
|
||||
: parameterValue;
|
||||
|
||||
|
70
Core/GDCore/Extensions/Metadata/ValueTypeMetadata.cpp
Normal file
70
Core/GDCore/Extensions/Metadata/ValueTypeMetadata.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "ValueTypeMetadata.h"
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
ValueTypeMetadata::ValueTypeMetadata() : optional(false) {}
|
||||
|
||||
void ValueTypeMetadata::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("type", name);
|
||||
if (!supplementaryInformation.empty()) {
|
||||
element.SetAttribute("supplementaryInformation", supplementaryInformation);
|
||||
}
|
||||
if (optional) {
|
||||
element.SetAttribute("optional", optional);
|
||||
}
|
||||
if (!defaultValue.empty()) {
|
||||
element.SetAttribute("defaultValue", defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
void ValueTypeMetadata::UnserializeFrom(const SerializerElement& element) {
|
||||
name = element.GetStringAttribute("type");
|
||||
supplementaryInformation =
|
||||
element.GetStringAttribute("supplementaryInformation");
|
||||
optional = element.GetBoolAttribute("optional");
|
||||
defaultValue = element.GetStringAttribute("defaultValue");
|
||||
}
|
||||
|
||||
const gd::String ValueTypeMetadata::numberType = "number";
|
||||
const gd::String ValueTypeMetadata::stringType = "string";
|
||||
|
||||
const gd::String &ValueTypeMetadata::GetPrimitiveValueType(const gd::String ¶meterType) {
|
||||
if (parameterType == "number" || gd::ValueTypeMetadata::IsTypeExpression("number", parameterType)) {
|
||||
return ValueTypeMetadata::numberType;
|
||||
}
|
||||
if (parameterType == "string" || gd::ValueTypeMetadata::IsTypeExpression("string", parameterType)) {
|
||||
return ValueTypeMetadata::stringType;
|
||||
}
|
||||
return parameterType;
|
||||
}
|
||||
|
||||
const gd::String ValueTypeMetadata::numberValueType = "number";
|
||||
const gd::String ValueTypeMetadata::booleanValueType = "boolean";
|
||||
const gd::String ValueTypeMetadata::colorValueType = "color";
|
||||
const gd::String ValueTypeMetadata::choiceValueType = "stringWithSelector";
|
||||
const gd::String ValueTypeMetadata::stringValueType = "string";
|
||||
|
||||
const gd::String &ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
const gd::String &propertyType) {
|
||||
if (propertyType == "Number") {
|
||||
return numberValueType;
|
||||
} else if (propertyType == "Boolean") {
|
||||
return booleanValueType;
|
||||
} else if (propertyType == "Color") {
|
||||
return colorValueType;
|
||||
} else if (propertyType == "Choice") {
|
||||
return choiceValueType;
|
||||
}
|
||||
// For "String" or default
|
||||
return stringValueType;
|
||||
};
|
||||
|
||||
} // namespace gd
|
231
Core/GDCore/Extensions/Metadata/ValueTypeMetadata.h
Normal file
231
Core/GDCore/Extensions/Metadata/ValueTypeMetadata.h
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef VALUE_TYPE_METADATA_H
|
||||
#define VALUE_TYPE_METADATA_H
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Define a type for parameters of a function (action, condition or
|
||||
* expression) or the returned value of an expression.
|
||||
*
|
||||
* \see gd::EventsFunction
|
||||
* \ingroup Events
|
||||
*/
|
||||
class GD_CORE_API ValueTypeMetadata {
|
||||
public:
|
||||
ValueTypeMetadata();
|
||||
virtual ~ValueTypeMetadata(){};
|
||||
|
||||
/**
|
||||
* \brief Return the string representation of the type.
|
||||
*/
|
||||
const gd::String &GetName() const { return name; }
|
||||
|
||||
/**
|
||||
* \brief Set the string representation of the type.
|
||||
*/
|
||||
ValueTypeMetadata &SetName(const gd::String &name_) {
|
||||
name = name_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return an optional additional information, used for some parameters
|
||||
* with special type (for example, it can contains the type of object accepted
|
||||
* by the parameter).
|
||||
*/
|
||||
const gd::String &GetExtraInfo() const { return supplementaryInformation; }
|
||||
|
||||
/**
|
||||
* \brief Set an optional additional information, used for some parameters
|
||||
* with special type (for example, it can contains the type of object accepted
|
||||
* by the parameter).
|
||||
*/
|
||||
ValueTypeMetadata &SetExtraInfo(const gd::String &supplementaryInformation_) {
|
||||
supplementaryInformation = supplementaryInformation_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the parameter is optional.
|
||||
*/
|
||||
bool IsOptional() const { return optional; }
|
||||
|
||||
/**
|
||||
* \brief Set if the parameter is optional.
|
||||
*/
|
||||
ValueTypeMetadata &SetOptional(bool optional_ = true) {
|
||||
optional = optional_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the default value for the parameter.
|
||||
*/
|
||||
const gd::String &GetDefaultValue() const { return defaultValue; }
|
||||
|
||||
/**
|
||||
* \brief Set the default value, if the parameter is optional.
|
||||
*/
|
||||
ValueTypeMetadata &SetDefaultValue(const gd::String &defaultValue_) {
|
||||
defaultValue = defaultValue_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is defined.
|
||||
*/
|
||||
bool IsDefined() const {
|
||||
return !name.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is representing one object
|
||||
* (or more, i.e: an object group).
|
||||
*/
|
||||
bool IsObject() const {
|
||||
return gd::ValueTypeMetadata::IsTypeObject(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is "behavior".
|
||||
*/
|
||||
bool IsBehavior() const {
|
||||
return gd::ValueTypeMetadata::IsTypeBehavior(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is an expression of the
|
||||
* given type.
|
||||
*/
|
||||
bool IsNumber() const {
|
||||
return gd::ValueTypeMetadata::IsTypeExpression("number", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is a string.
|
||||
*/
|
||||
bool IsString() const {
|
||||
return gd::ValueTypeMetadata::IsTypeExpression("string", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type of the parameter is a number.
|
||||
* \note If you had a new type of parameter, also add it in the IDE (
|
||||
* see EventsFunctionParametersEditor, ParameterRenderingService
|
||||
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
|
||||
*/
|
||||
bool IsVariable() const {
|
||||
return gd::ValueTypeMetadata::IsTypeExpression("variable", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is representing one object
|
||||
* (or more, i.e: an object group).
|
||||
*/
|
||||
static bool IsTypeObject(const gd::String ¶meterType) {
|
||||
return parameterType == "object" || parameterType == "objectPtr" ||
|
||||
parameterType == "objectList" ||
|
||||
parameterType == "objectListOrEmptyIfJustDeclared" ||
|
||||
parameterType == "objectListOrEmptyWithoutPicking";
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is "behavior".
|
||||
*/
|
||||
static bool IsTypeBehavior(const gd::String ¶meterType) {
|
||||
return parameterType == "behavior";
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is an expression of the given type.
|
||||
* \note If you are adding a new type of parameter, also add it in the IDE (
|
||||
* see EventsFunctionParametersEditor, ParameterRenderingService
|
||||
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
|
||||
*/
|
||||
static bool IsTypeExpression(const gd::String &type,
|
||||
const gd::String ¶meterType) {
|
||||
if (type == "number") {
|
||||
return parameterType == "number" || parameterType == "expression" ||
|
||||
parameterType == "camera" || parameterType == "forceMultiplier";
|
||||
} else if (type == "string") {
|
||||
return parameterType == "string" || parameterType == "layer" ||
|
||||
parameterType == "color" || parameterType == "file" ||
|
||||
parameterType == "joyaxis" ||
|
||||
parameterType == "stringWithSelector" ||
|
||||
parameterType == "sceneName" ||
|
||||
parameterType == "layerEffectName" ||
|
||||
parameterType == "layerEffectParameterName" ||
|
||||
parameterType == "objectEffectName" ||
|
||||
parameterType == "objectEffectParameterName" ||
|
||||
parameterType == "objectPointName" ||
|
||||
parameterType == "objectAnimationName" ||
|
||||
parameterType == "functionParameterName" ||
|
||||
parameterType == "externalLayoutName" ||
|
||||
parameterType == "leaderboardId" ||
|
||||
parameterType == "identifier";
|
||||
} else if (type == "variable") {
|
||||
return parameterType == "objectvar" || parameterType == "globalvar" ||
|
||||
parameterType == "scenevar";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the expression type from the parameter type.
|
||||
* Declinations of "number" and "string" types (like "forceMultiplier" or
|
||||
* "sceneName") are replaced by "number" and "string".
|
||||
*/
|
||||
static const gd::String &GetPrimitiveValueType(const gd::String ¶meterType);
|
||||
static const gd::String numberType;
|
||||
static const gd::String stringType;
|
||||
|
||||
/**
|
||||
* \brief Return the ValueTypeMetadata name for a property type.
|
||||
* \see gd::PropertyDescriptor
|
||||
*/
|
||||
static const gd::String &ConvertPropertyTypeToValueType(const gd::String &propertyType);
|
||||
|
||||
/** \name Serialization
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Serialize the ParameterMetadata to the specified element
|
||||
*/
|
||||
void SerializeTo(gd::SerializerElement &element) const;
|
||||
|
||||
/**
|
||||
* \brief Load the ParameterMetadata from the specified element
|
||||
*/
|
||||
void UnserializeFrom(const gd::SerializerElement &element);
|
||||
///@}
|
||||
|
||||
private:
|
||||
gd::String name; ///< Parameter type
|
||||
gd::String supplementaryInformation; ///< Used if needed
|
||||
bool optional; ///< True if the parameter is optional
|
||||
gd::String defaultValue; ///< Used as a default value in editor or if an
|
||||
///< optional parameter is empty.
|
||||
|
||||
static const gd::String numberValueType;
|
||||
static const gd::String booleanValueType;
|
||||
static const gd::String colorValueType;
|
||||
static const gd::String choiceValueType;
|
||||
static const gd::String stringValueType;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // VALUE_TYPE_METADATA_H
|
@@ -24,14 +24,12 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
std::map<gd::String, gd::InstructionMetadata>
|
||||
PlatformExtension::badConditionsMetadata;
|
||||
std::map<gd::String, gd::InstructionMetadata>
|
||||
PlatformExtension::badActionsMetadata;
|
||||
std::map<gd::String, gd::ExpressionMetadata>
|
||||
PlatformExtension::badExpressionsMetadata;
|
||||
#endif
|
||||
|
||||
gd::InstructionMetadata& PlatformExtension::AddCondition(
|
||||
const gd::String& name,
|
||||
@@ -41,7 +39,6 @@ gd::InstructionMetadata& PlatformExtension::AddCondition(
|
||||
const gd::String& group,
|
||||
const gd::String& icon,
|
||||
const gd::String& smallicon) {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::String nameWithNamespace = GetNameSpace() + name;
|
||||
conditionsInfos[nameWithNamespace] = InstructionMetadata(GetNameSpace(),
|
||||
nameWithNamespace,
|
||||
@@ -53,7 +50,6 @@ gd::InstructionMetadata& PlatformExtension::AddCondition(
|
||||
smallicon)
|
||||
.SetHelpPath(GetHelpPath());
|
||||
return conditionsInfos[nameWithNamespace];
|
||||
#endif
|
||||
}
|
||||
|
||||
gd::InstructionMetadata& PlatformExtension::AddAction(
|
||||
@@ -64,7 +60,6 @@ gd::InstructionMetadata& PlatformExtension::AddAction(
|
||||
const gd::String& group,
|
||||
const gd::String& icon,
|
||||
const gd::String& smallicon) {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::String nameWithNamespace = GetNameSpace() + name;
|
||||
actionsInfos[nameWithNamespace] = InstructionMetadata(GetNameSpace(),
|
||||
nameWithNamespace,
|
||||
@@ -76,7 +71,6 @@ gd::InstructionMetadata& PlatformExtension::AddAction(
|
||||
smallicon)
|
||||
.SetHelpPath(GetHelpPath());
|
||||
return actionsInfos[nameWithNamespace];
|
||||
#endif
|
||||
}
|
||||
|
||||
gd::ExpressionMetadata& PlatformExtension::AddExpression(
|
||||
@@ -85,7 +79,6 @@ gd::ExpressionMetadata& PlatformExtension::AddExpression(
|
||||
const gd::String& description,
|
||||
const gd::String& group,
|
||||
const gd::String& smallicon) {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::String nameWithNamespace = GetNameSpace() + name;
|
||||
expressionsInfos[nameWithNamespace] = ExpressionMetadata("number",
|
||||
GetNameSpace(),
|
||||
@@ -96,7 +89,6 @@ gd::ExpressionMetadata& PlatformExtension::AddExpression(
|
||||
smallicon)
|
||||
.SetHelpPath(GetHelpPath());
|
||||
return expressionsInfos[nameWithNamespace];
|
||||
#endif
|
||||
}
|
||||
|
||||
gd::ExpressionMetadata& PlatformExtension::AddStrExpression(
|
||||
@@ -105,7 +97,6 @@ gd::ExpressionMetadata& PlatformExtension::AddStrExpression(
|
||||
const gd::String& description,
|
||||
const gd::String& group,
|
||||
const gd::String& smallicon) {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::String nameWithNamespace = GetNameSpace() + name;
|
||||
strExpressionsInfos[nameWithNamespace] = ExpressionMetadata("string",
|
||||
GetNameSpace(),
|
||||
@@ -116,7 +107,6 @@ gd::ExpressionMetadata& PlatformExtension::AddStrExpression(
|
||||
smallicon)
|
||||
.SetHelpPath(GetHelpPath());
|
||||
return strExpressionsInfos[nameWithNamespace];
|
||||
#endif
|
||||
}
|
||||
|
||||
gd::MultipleInstructionMetadata PlatformExtension::AddExpressionAndCondition(
|
||||
@@ -220,12 +210,10 @@ PlatformExtension::AddExpressionAndConditionAndAction(
|
||||
expression, condition, action);
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::DependencyMetadata& PlatformExtension::AddDependency() {
|
||||
extensionDependenciesMetadata.push_back(DependencyMetadata());
|
||||
return extensionDependenciesMetadata.back();
|
||||
}
|
||||
#endif
|
||||
|
||||
gd::ObjectMetadata& PlatformExtension::AddObject(
|
||||
const gd::String& name,
|
||||
@@ -317,7 +305,6 @@ gd::EventMetadata& PlatformExtension::AddEvent(
|
||||
const gd::String& group_,
|
||||
const gd::String& smallicon_,
|
||||
std::shared_ptr<gd::BaseEvent> instance_) {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::String nameWithNamespace = GetNameSpace() + name_;
|
||||
eventsInfos[nameWithNamespace] = gd::EventMetadata(nameWithNamespace,
|
||||
fullname_,
|
||||
@@ -326,7 +313,6 @@ gd::EventMetadata& PlatformExtension::AddEvent(
|
||||
smallicon_,
|
||||
instance_);
|
||||
return eventsInfos[nameWithNamespace];
|
||||
#endif
|
||||
}
|
||||
|
||||
PlatformExtension& PlatformExtension::SetExtensionInformation(
|
||||
@@ -406,8 +392,6 @@ std::vector<gd::String> PlatformExtension::GetBehaviorsTypes() const {
|
||||
return behaviors;
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
|
||||
gd::InstructionMetadata& PlatformExtension::AddDuplicatedAction(
|
||||
const gd::String& newActionName, const gd::String& copiedActionName) {
|
||||
gd::String newNameWithNamespace = GetNameSpace() + newActionName;
|
||||
@@ -586,7 +570,6 @@ gd::BaseEventSPtr PlatformExtension::CreateEvent(
|
||||
|
||||
return std::shared_ptr<gd::BaseEvent>();
|
||||
}
|
||||
#endif
|
||||
|
||||
CreateFunPtr PlatformExtension::GetObjectCreationFunctionPtr(
|
||||
const gd::String& objectType) const {
|
||||
@@ -665,7 +648,6 @@ bool PlatformExtension::IsBuiltin() const {
|
||||
builtinExtensions.end();
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
|
||||
for (std::map<gd::String, gd::InstructionMetadata>::iterator it =
|
||||
GetAllActions().begin();
|
||||
@@ -810,7 +792,40 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gd::String
|
||||
PlatformExtension::GetEventsFunctionFullType(const gd::String &extensionName,
|
||||
const gd::String &functionName) {
|
||||
const auto &separator = GetNamespaceSeparator();
|
||||
return extensionName + separator + functionName;
|
||||
}
|
||||
|
||||
gd::String PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
const gd::String &extensionName, const gd::String &behaviorName,
|
||||
const gd::String &functionName) {
|
||||
const auto &separator = GetNamespaceSeparator();
|
||||
return extensionName + separator + behaviorName + separator + functionName;
|
||||
}
|
||||
|
||||
gd::String
|
||||
PlatformExtension::GetBehaviorFullType(const gd::String &extensionName,
|
||||
const gd::String &behaviorName) {
|
||||
const auto &separator = GetNamespaceSeparator();
|
||||
return extensionName + separator + behaviorName;
|
||||
}
|
||||
|
||||
gd::String PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
const gd::String &extensionName, const gd::String &objectName,
|
||||
const gd::String &functionName) {
|
||||
const auto &separator = GetNamespaceSeparator();
|
||||
return extensionName + separator + objectName + separator + functionName;
|
||||
}
|
||||
|
||||
gd::String PlatformExtension::GetObjectFullType(const gd::String &extensionName,
|
||||
const gd::String &objectName) {
|
||||
const auto &separator = GetNamespaceSeparator();
|
||||
return extensionName + separator + objectName;
|
||||
}
|
||||
|
||||
PlatformExtension::PlatformExtension()
|
||||
: deprecated(false), category(_("General")) {}
|
||||
|
@@ -620,7 +620,26 @@ class GD_CORE_API PlatformExtension {
|
||||
*/
|
||||
static gd::String GetNamespaceSeparator() { return "::"; }
|
||||
|
||||
private:
|
||||
static gd::String GetEventsFunctionFullType(const gd::String &extensionName,
|
||||
const gd::String &functionName);
|
||||
|
||||
static gd::String
|
||||
GetBehaviorEventsFunctionFullType(const gd::String &extensionName,
|
||||
const gd::String &behaviorName,
|
||||
const gd::String &functionName);
|
||||
|
||||
static gd::String GetBehaviorFullType(const gd::String &extensionName,
|
||||
const gd::String &behaviorName);
|
||||
|
||||
static gd::String
|
||||
GetObjectEventsFunctionFullType(const gd::String &extensionName,
|
||||
const gd::String &objectName,
|
||||
const gd::String &functionName);
|
||||
|
||||
static gd::String GetObjectFullType(const gd::String &extensionName,
|
||||
const gd::String &objectName);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Set the namespace (the string all actions/conditions/expressions start
|
||||
* with).
|
||||
|
@@ -73,4 +73,54 @@ bool ArbitraryEventsWorker::VisitInstruction(gd::Instruction& instruction,
|
||||
|
||||
ArbitraryEventsWorkerWithContext::~ArbitraryEventsWorkerWithContext() {}
|
||||
|
||||
|
||||
ReadOnlyArbitraryEventsWorker::~ReadOnlyArbitraryEventsWorker() {}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitEventList(const gd::EventsList& events) {
|
||||
DoVisitEventList(events);
|
||||
|
||||
for (std::size_t i = 0; i < events.size(); ++i) {
|
||||
VisitEvent(events[i]);
|
||||
|
||||
if (events[i].CanHaveSubEvents()) {
|
||||
VisitEventList(events[i].GetSubEvents());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitEvent(const gd::BaseEvent& event) {
|
||||
DoVisitEvent(event);
|
||||
|
||||
const vector<const gd::InstructionsList*> conditionsVectors =
|
||||
event.GetAllConditionsVectors();
|
||||
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
|
||||
VisitInstructionList(*conditionsVectors[j], true);
|
||||
}
|
||||
|
||||
const vector<const gd::InstructionsList*> actionsVectors = event.GetAllActionsVectors();
|
||||
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
|
||||
VisitInstructionList(*actionsVectors[j], false);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitInstructionList(
|
||||
const gd::InstructionsList& instructions, bool areConditions) {
|
||||
DoVisitInstructionList(instructions, areConditions);
|
||||
|
||||
for (std::size_t i = 0; i < instructions.size(); ++i) {
|
||||
VisitInstruction(instructions[i], areConditions);
|
||||
if (!instructions[i].GetSubInstructions().empty()) {
|
||||
VisitInstructionList(instructions[i].GetSubInstructions(),
|
||||
areConditions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitInstruction(const gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
DoVisitInstruction(instruction, isCondition);
|
||||
}
|
||||
|
||||
ReadOnlyArbitraryEventsWorkerWithContext::~ReadOnlyArbitraryEventsWorkerWithContext() {}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -121,6 +121,101 @@ class GD_CORE_API ArbitraryEventsWorkerWithContext
|
||||
const gd::ObjectsContainer* currentObjectsContainer;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief ReadOnlyArbitraryEventsWorker is an abstract class used to browse events (and
|
||||
* instructions). It can be used to implement autocompletion for example.
|
||||
*
|
||||
* \see gd::ReadOnlyArbitraryEventsWorkerWithContext
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API ReadOnlyArbitraryEventsWorker {
|
||||
public:
|
||||
ReadOnlyArbitraryEventsWorker(){};
|
||||
virtual ~ReadOnlyArbitraryEventsWorker();
|
||||
|
||||
/**
|
||||
* \brief Launch the worker on the specified events list.
|
||||
*/
|
||||
void Launch(const gd::EventsList& events) { VisitEventList(events); };
|
||||
|
||||
private:
|
||||
void VisitEventList(const gd::EventsList& events);
|
||||
void VisitEvent(const gd::BaseEvent& event);
|
||||
void VisitInstructionList(const gd::InstructionsList& instructions,
|
||||
bool areConditions);
|
||||
void VisitInstruction(const gd::Instruction& instruction, bool isCondition);
|
||||
|
||||
/**
|
||||
* Called to do some work on an event list.
|
||||
*/
|
||||
virtual void DoVisitEventList(const gd::EventsList& events){};
|
||||
|
||||
/**
|
||||
* Called to do some work on an event
|
||||
*/
|
||||
virtual void DoVisitEvent(const gd::BaseEvent& event) {};
|
||||
|
||||
/**
|
||||
* Called to do some work on an instruction list
|
||||
*/
|
||||
virtual void DoVisitInstructionList(const gd::InstructionsList& instructions,
|
||||
bool areConditions){};
|
||||
|
||||
/**
|
||||
* Called to do some work on an instruction.
|
||||
*/
|
||||
virtual void DoVisitInstruction(const gd::Instruction& instruction,
|
||||
bool isCondition) {};
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief An events worker that will know about the context (the objects
|
||||
* container). Useful for workers working on expressions notably.
|
||||
*
|
||||
* \see gd::ReadOnlyArbitraryEventsWorker
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API ReadOnlyArbitraryEventsWorkerWithContext
|
||||
: public ReadOnlyArbitraryEventsWorker {
|
||||
public:
|
||||
ReadOnlyArbitraryEventsWorkerWithContext()
|
||||
: currentGlobalObjectsContainer(nullptr),
|
||||
currentObjectsContainer(nullptr){};
|
||||
virtual ~ReadOnlyArbitraryEventsWorkerWithContext();
|
||||
|
||||
/**
|
||||
* \brief Launch the worker on the specified events list,
|
||||
* giving the objects container on which the events are applying to.
|
||||
*/
|
||||
void Launch(const gd::EventsList& events,
|
||||
const gd::ObjectsContainer& globalObjectsContainer_,
|
||||
const gd::ObjectsContainer& objectsContainer_) {
|
||||
currentGlobalObjectsContainer = &globalObjectsContainer_;
|
||||
currentObjectsContainer = &objectsContainer_;
|
||||
ReadOnlyArbitraryEventsWorker::Launch(events);
|
||||
};
|
||||
|
||||
void Launch(gd::EventsList& events) = delete;
|
||||
|
||||
protected:
|
||||
const gd::ObjectsContainer& GetGlobalObjectsContainer() {
|
||||
// Pointers are guaranteed to be not nullptr after
|
||||
// Launch was called.
|
||||
return *currentGlobalObjectsContainer;
|
||||
};
|
||||
const gd::ObjectsContainer& GetObjectsContainer() {
|
||||
// Pointers are guaranteed to be not nullptr after
|
||||
// Launch was called.
|
||||
return *currentObjectsContainer;
|
||||
};
|
||||
|
||||
private:
|
||||
const gd::ObjectsContainer* currentGlobalObjectsContainer;
|
||||
const gd::ObjectsContainer* currentObjectsContainer;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_ARBITRARYEVENTSWORKER_H
|
||||
|
@@ -120,7 +120,7 @@ bool EventsBehaviorRenamer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
const gd::Expression& parameterValue,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName) {
|
||||
const gd::String& type = parameterMetadata.type;
|
||||
const gd::String& type = parameterMetadata.GetType();
|
||||
|
||||
if (gd::ParameterMetadata::IsBehavior(type)) {
|
||||
if (lastObjectName == objectName) {
|
||||
|
254
Core/GDCore/IDE/Events/EventsIdentifiersFinder.cpp
Normal file
254
Core/GDCore/IDE/Events/EventsIdentifiersFinder.cpp
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "EventsIdentifiersFinder.h"
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/Instruction.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/IDE/DependenciesAnalyzer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
namespace {
|
||||
/**
|
||||
* \brief Go through the nodes to search for identifier occurrences.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API IdentifierFinderExpressionNodeWorker
|
||||
: public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
IdentifierFinderExpressionNodeWorker(std::set<gd::String>& results_,
|
||||
const gd::Platform &platform_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
const gd::String& identifierType_,
|
||||
const gd::String& objectName_ = "")
|
||||
: results(results_),
|
||||
platform(platform_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
identifierType(identifierType_),
|
||||
objectName(objectName_){};
|
||||
virtual ~IdentifierFinderExpressionNodeWorker(){};
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
node.leftHandSide->Visit(*this);
|
||||
node.rightHandSide->Visit(*this);
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
node.factor->Visit(*this);
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {}
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
|
||||
bool considerFunction = objectName.empty() || node.objectName == objectName;
|
||||
|
||||
const bool isObjectFunction = !node.objectName.empty();
|
||||
const gd::ExpressionMetadata &metadata = isObjectFunction ?
|
||||
MetadataProvider::GetObjectAnyExpressionMetadata(
|
||||
platform,
|
||||
GetTypeOfObject(globalObjectsContainer, objectsContainer, objectName),
|
||||
node.functionName):
|
||||
MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName);
|
||||
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t parameterIndex = 0;
|
||||
for (size_t metadataIndex = (isObjectFunction ? 1 : 0); metadataIndex < metadata.parameters.size()
|
||||
&& parameterIndex < node.parameters.size(); ++metadataIndex) {
|
||||
auto& parameterMetadata = metadata.parameters[metadataIndex];
|
||||
if (parameterMetadata.IsCodeOnly()) {
|
||||
continue;
|
||||
}
|
||||
auto& parameterNode = node.parameters[parameterIndex];
|
||||
++parameterIndex;
|
||||
|
||||
if (considerFunction && parameterMetadata.GetType() == "identifier"
|
||||
&& parameterMetadata.GetExtraInfo() == identifierType) {
|
||||
// Store the value of the parameter
|
||||
results.insert(
|
||||
gd::ExpressionParser2NodePrinter::PrintNode(*parameterNode));
|
||||
} else {
|
||||
parameterNode->Visit(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnVisitEmptyNode(EmptyNode& node) override {}
|
||||
|
||||
private:
|
||||
const gd::Platform &platform;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
|
||||
std::set<gd::String>& results; ///< Reference to the std::set where argument
|
||||
///< values must be stored.
|
||||
gd::String identifierType; ///< The type of the parameters to be searched for.
|
||||
gd::String objectName; ///< If not empty, parameters will be taken into
|
||||
///< account only if related to this object.
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Go through the events to search for identifier occurrences.
|
||||
*/
|
||||
class GD_CORE_API IdentifierFinderEventWorker
|
||||
: public ReadOnlyArbitraryEventsWorkerWithContext {
|
||||
public:
|
||||
IdentifierFinderEventWorker(std::set<gd::String>& results_,
|
||||
const gd::Platform &platform_,
|
||||
const gd::String& identifierType_,
|
||||
const gd::String& objectName_ = "")
|
||||
: results(results_),
|
||||
platform(platform_),
|
||||
identifierType(identifierType_),
|
||||
objectName(objectName_){};
|
||||
virtual ~IdentifierFinderEventWorker(){};
|
||||
|
||||
void DoVisitInstructionList(const gd::InstructionsList& instructions,
|
||||
bool areConditions) override {
|
||||
for (std::size_t aId = 0; aId < instructions.size(); ++aId) {
|
||||
auto& instruction = instructions[aId];
|
||||
gd::String lastObjectParameter = "";
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
areConditions ? MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// The parameter has the searched type...
|
||||
if (instrInfos.parameters[pNb].GetType() == "identifier"
|
||||
&& instrInfos.parameters[pNb].GetExtraInfo() == identifierType) {
|
||||
//...remember the value of the parameter.
|
||||
if (objectName.empty() || lastObjectParameter == objectName) {
|
||||
results.insert(instruction.GetParameter(pNb).GetPlainString());
|
||||
}
|
||||
}
|
||||
// Search in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType()) ||
|
||||
ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = instruction.GetParameter(pNb).GetRootNode();
|
||||
|
||||
IdentifierFinderExpressionNodeWorker searcher(
|
||||
results,
|
||||
platform,
|
||||
GetGlobalObjectsContainer(),
|
||||
GetObjectsContainer(),
|
||||
identifierType,
|
||||
objectName);
|
||||
node->Visit(searcher);
|
||||
}
|
||||
// Remember the value of the last "object" parameter.
|
||||
else if (gd::ParameterMetadata::IsObject(
|
||||
instrInfos.parameters[pNb].GetType())) {
|
||||
lastObjectParameter =
|
||||
instruction.GetParameter(pNb).GetPlainString();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
const gd::Platform &platform;
|
||||
|
||||
std::set<gd::String>& results; ///< Reference to the std::set where argument
|
||||
///< values must be stored.
|
||||
gd::String identifierType; ///< The type of the parameters to be searched for.
|
||||
gd::String objectName; ///< If not empty, parameters will be taken into
|
||||
///< account only if related to this object.
|
||||
};
|
||||
} // namespace
|
||||
|
||||
std::set<gd::String> EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::String& identifierType,
|
||||
const gd::String& contextObjectName) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
const bool isObjectIdentifier = identifierType.find("object") == 0;
|
||||
// The object from the context is only relevent for object identifiers.
|
||||
auto& actualObjectName = isObjectIdentifier ? contextObjectName : "";
|
||||
|
||||
FindArgumentsInEventsAndDependencies(
|
||||
results,
|
||||
platform,
|
||||
project,
|
||||
layout,
|
||||
identifierType,
|
||||
actualObjectName);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
void EventsIdentifiersFinder::FindArgumentsInEventsAndDependencies(
|
||||
std::set<gd::String>& results,
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::String& identifierType,
|
||||
const gd::String& objectName) {
|
||||
IdentifierFinderEventWorker eventWorker(results,
|
||||
platform,
|
||||
identifierType,
|
||||
objectName);
|
||||
eventWorker.Launch(layout.GetEvents(), project, layout);
|
||||
|
||||
DependenciesAnalyzer dependenciesAnalyzer = DependenciesAnalyzer(project, layout);
|
||||
dependenciesAnalyzer.Analyze();
|
||||
for (const gd::String& externalEventName : dependenciesAnalyzer.GetExternalEventsDependencies()) {
|
||||
const gd::ExternalEvents& externalEvents = project.GetExternalEvents(externalEventName);
|
||||
|
||||
IdentifierFinderEventWorker eventWorker(results,
|
||||
platform,
|
||||
identifierType,
|
||||
objectName);
|
||||
eventWorker.Launch(externalEvents.GetEvents(), project, layout);
|
||||
}
|
||||
for (const gd::String& sceneName : dependenciesAnalyzer.GetScenesDependencies()) {
|
||||
const gd::Layout& dependencyLayout = project.GetLayout(sceneName);
|
||||
|
||||
IdentifierFinderEventWorker eventWorker(results,
|
||||
platform,
|
||||
identifierType,
|
||||
objectName);
|
||||
eventWorker.Launch(dependencyLayout.GetEvents(), project, dependencyLayout);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
81
Core/GDCore/IDE/Events/EventsIdentifiersFinder.h
Normal file
81
Core/GDCore/IDE/Events/EventsIdentifiersFinder.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef EVENTSIDENTIFIERSFINDER_H
|
||||
#define EVENTSIDENTIFIERSFINDER_H
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class Instruction;
|
||||
class Platform;
|
||||
class Object;
|
||||
class Project;
|
||||
class Layout;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Perform a search over a layout, searching for layout or object custom
|
||||
* identifiers.
|
||||
*
|
||||
* \todo Refactor this class using ArbitraryEventsWorker
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class EventsIdentifiersFinder {
|
||||
public:
|
||||
EventsIdentifiersFinder(){};
|
||||
virtual ~EventsIdentifiersFinder(){};
|
||||
|
||||
/**
|
||||
* Construct a list containing all the expressions for a given identifier used
|
||||
* in the layout.
|
||||
*
|
||||
* \param project The project to use.
|
||||
* \param layout The layout to use.
|
||||
* \param identifierType The identifier type to be analyzed.
|
||||
* \param objectName If not empty, parameters will be taken into account
|
||||
* only if the last object parameter is filled with
|
||||
* this value.
|
||||
* \return A std::set containing the names of all identifiers used.
|
||||
*/
|
||||
static std::set<gd::String> FindAllIdentifierExpressions(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::String& identifierType,
|
||||
const gd::String& objectName = "");
|
||||
|
||||
private:
|
||||
/**
|
||||
* Construct a list containing all the expressions for a given identifier used
|
||||
* in the layout. It searches in events dependencies.
|
||||
*
|
||||
* \param results A std::set to fill with the expressions used for all parameters of the
|
||||
* specified identifier type
|
||||
* \param platform The platform of the project
|
||||
* \param project The project to use.
|
||||
* \param layout The layout to use.
|
||||
* \param events The events to be analyzed
|
||||
* \param identifierType The identifier type to be analyzed
|
||||
* \param objectName If not empty, parameters will be taken into account
|
||||
* only if the last object parameter is filled with
|
||||
* this value.
|
||||
*/
|
||||
static void FindArgumentsInEventsAndDependencies(
|
||||
std::set<gd::String>& results,
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::String& identifierType,
|
||||
const gd::String& objectName = "");
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // EVENTSIDENTIFIERSFINDER_H
|
@@ -30,7 +30,7 @@ bool EventsLeaderboardsLister::DoVisitInstruction(gd::Instruction& instruction,
|
||||
for (int i = 0; i < instruction.GetParametersCount() &&
|
||||
i < instrInfo.GetParametersCount();
|
||||
++i)
|
||||
if (instrInfo.GetParameter(i).type == "leaderboardId") {
|
||||
if (instrInfo.GetParameter(i).GetType() == "leaderboardId") {
|
||||
leaderboardIds.insert(instruction.GetParameter(i).GetPlainString());
|
||||
}
|
||||
return false;
|
||||
|
@@ -32,7 +32,7 @@ bool EventsLeaderboardsRenamer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
++i) {
|
||||
const gd::ParameterMetadata parameter = instrInfo.GetParameter(i);
|
||||
|
||||
if (parameter.type == "leaderboardId") {
|
||||
if (parameter.GetType() == "leaderboardId") {
|
||||
const gd::String leaderboardId =
|
||||
instruction.GetParameter(i).GetPlainString();
|
||||
|
||||
|
@@ -237,12 +237,12 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// Replace object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
|
||||
actions[aId].GetParameter(pNb).GetPlainString() == oldName)
|
||||
actions[aId].SetParameter(pNb, gd::Expression(newName));
|
||||
// Replace object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, project, layout, "number", *node, oldName, newName)) {
|
||||
@@ -252,7 +252,7 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, project, layout, "string", *node, oldName, newName)) {
|
||||
@@ -291,12 +291,12 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
conditions[cId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// Replace object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
|
||||
conditions[cId].GetParameter(pNb).GetPlainString() == oldName)
|
||||
conditions[cId].SetParameter(pNb, gd::Expression(newName));
|
||||
// Replace object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, project, layout, "number", *node, oldName, newName)) {
|
||||
@@ -306,7 +306,7 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, project, layout, "string", *node, oldName, newName)) {
|
||||
@@ -425,14 +425,14 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// Find object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
|
||||
actions[aId].GetParameter(pNb).GetPlainString() == name) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
// Find object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "number", *node, name)) {
|
||||
@@ -442,7 +442,7 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
}
|
||||
// Find object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "string", *node, name)) {
|
||||
@@ -485,14 +485,14 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
conditions[cId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// Find object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
|
||||
conditions[cId].GetParameter(pNb).GetPlainString() == name) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
// Find object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "number", *node, name)) {
|
||||
@@ -502,7 +502,7 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
}
|
||||
// Find object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "string", *node, name)) {
|
||||
@@ -773,15 +773,18 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
|
||||
const gd::String& ignored_characters =
|
||||
EventsRefactorer::searchIgnoredCharacters;
|
||||
|
||||
search.replace_if(
|
||||
search.begin(),
|
||||
search.end(),
|
||||
[ignored_characters](const char& c) {
|
||||
return ignored_characters.find(c) != gd::String::npos;
|
||||
},
|
||||
"");
|
||||
search = search.LeftTrim().RightTrim();
|
||||
search.RemoveConsecutiveOccurrences(search.begin(), search.end(), ' ');
|
||||
if (inEventSentences) {
|
||||
// Remove ignored characters only when searching in event sentences.
|
||||
search.replace_if(
|
||||
search.begin(),
|
||||
search.end(),
|
||||
[ignored_characters](const char& c) {
|
||||
return ignored_characters.find(c) != gd::String::npos;
|
||||
},
|
||||
"");
|
||||
search = search.LeftTrim().RightTrim();
|
||||
search.RemoveConsecutiveOccurrences(search.begin(), search.end(), ' ');
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < events.size(); ++i) {
|
||||
bool eventAddedInResults = false;
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
@@ -22,28 +23,28 @@
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* \brief Go through the nodes and change the given object name to a new one.
|
||||
* \brief Go through the nodes to search for variable occurrences.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionParameterSearcher
|
||||
class GD_CORE_API VariableFinderExpressionNodeWorker
|
||||
: public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionParameterSearcher(const gd::Platform &platform_,
|
||||
VariableFinderExpressionNodeWorker(std::set<gd::String>& results_,
|
||||
const gd::Platform &platform_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
std::set<gd::String>& results_,
|
||||
const gd::String& parameterType_,
|
||||
const gd::String& objectName_ = "")
|
||||
: platform(platform_),
|
||||
: results(results_),
|
||||
platform(platform_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
results(results_),
|
||||
parameterType(parameterType_),
|
||||
objectName(objectName_){};
|
||||
virtual ~ExpressionParameterSearcher(){};
|
||||
virtual ~VariableFinderExpressionNodeWorker(){};
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
@@ -74,27 +75,34 @@ class GD_CORE_API ExpressionParameterSearcher
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
|
||||
bool considerFunction = objectName.empty() || node.objectName == objectName;
|
||||
|
||||
const gd::ExpressionMetadata &metadata = node.objectName.empty() ?
|
||||
MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName) :
|
||||
const bool isObjectFunction = !node.objectName.empty();
|
||||
const gd::ExpressionMetadata &metadata = isObjectFunction ?
|
||||
MetadataProvider::GetObjectAnyExpressionMetadata(
|
||||
platform,
|
||||
GetTypeOfObject(globalObjectsContainer, objectsContainer, objectName),
|
||||
node.functionName);
|
||||
node.functionName):
|
||||
MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName);
|
||||
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < node.parameters.size() &&
|
||||
i < metadata.parameters.size();
|
||||
++i) {
|
||||
auto& parameterMetadata = metadata.parameters[i];
|
||||
|
||||
size_t parameterIndex = 0;
|
||||
for (size_t metadataIndex = (isObjectFunction ? 1 : 0); metadataIndex < metadata.parameters.size()
|
||||
&& parameterIndex < node.parameters.size(); ++metadataIndex) {
|
||||
auto& parameterMetadata = metadata.parameters[metadataIndex];
|
||||
if (parameterMetadata.IsCodeOnly()) {
|
||||
continue;
|
||||
}
|
||||
auto& parameterNode = node.parameters[parameterIndex];
|
||||
++parameterIndex;
|
||||
|
||||
if (considerFunction && parameterMetadata.GetType() == parameterType) {
|
||||
// Store the value of the parameter
|
||||
results.insert(
|
||||
gd::ExpressionParser2NodePrinter::PrintNode(*node.parameters[i]));
|
||||
gd::ExpressionParser2NodePrinter::PrintNode(*parameterNode));
|
||||
} else {
|
||||
node.parameters[i]->Visit(*this);
|
||||
parameterNode->Visit(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,18 +120,87 @@ class GD_CORE_API ExpressionParameterSearcher
|
||||
///< account only if related to this object.
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Go through the events to search for variable occurrences.
|
||||
*/
|
||||
class GD_CORE_API VariableFinderEventWorker
|
||||
: public ReadOnlyArbitraryEventsWorkerWithContext {
|
||||
public:
|
||||
VariableFinderEventWorker(std::set<gd::String>& results_,
|
||||
const gd::Platform &platform_,
|
||||
const gd::String& parameterType_,
|
||||
const gd::String& objectName_ = "")
|
||||
: results(results_),
|
||||
platform(platform_),
|
||||
parameterType(parameterType_),
|
||||
objectName(objectName_){};
|
||||
virtual ~VariableFinderEventWorker(){};
|
||||
|
||||
void DoVisitInstructionList(const gd::InstructionsList& instructions,
|
||||
bool areConditions) override {
|
||||
for (std::size_t aId = 0; aId < instructions.size(); ++aId) {
|
||||
auto& instruction = instructions[aId];
|
||||
gd::String lastObjectParameter = "";
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
areConditions ? MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// The parameter has the searched type...
|
||||
if (instrInfos.parameters[pNb].GetType() == parameterType) {
|
||||
//...remember the value of the parameter.
|
||||
if (objectName.empty() || lastObjectParameter == objectName)
|
||||
results.insert(instruction.GetParameter(pNb).GetPlainString());
|
||||
}
|
||||
// Search in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType()) ||
|
||||
ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = instruction.GetParameter(pNb).GetRootNode();
|
||||
|
||||
VariableFinderExpressionNodeWorker searcher(
|
||||
results,
|
||||
platform,
|
||||
GetGlobalObjectsContainer(),
|
||||
GetObjectsContainer(),
|
||||
parameterType,
|
||||
objectName);
|
||||
node->Visit(searcher);
|
||||
}
|
||||
// Remember the value of the last "object" parameter.
|
||||
else if (gd::ParameterMetadata::IsObject(
|
||||
instrInfos.parameters[pNb].GetType())) {
|
||||
lastObjectParameter =
|
||||
instruction.GetParameter(pNb).GetPlainString();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
const gd::Platform &platform;
|
||||
|
||||
std::set<gd::String>& results; ///< Reference to the std::set where argument
|
||||
///< values must be stored.
|
||||
gd::String parameterType; ///< The type of the parameters to be searched for.
|
||||
gd::String objectName; ///< If not empty, parameters will be taken into
|
||||
///< account only if related to this object.
|
||||
};
|
||||
} // namespace
|
||||
|
||||
std::set<gd::String> EventsVariablesFinder::FindAllGlobalVariables(
|
||||
const gd::Platform& platform, const gd::Project& project) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||
std::set<gd::String> results2 =
|
||||
FindArgumentsInEventsAndDependencies(
|
||||
FindArgumentsInEventsAndDependencies(
|
||||
results,
|
||||
platform,
|
||||
project,
|
||||
project.GetLayout(i),
|
||||
"globalvar");
|
||||
results.insert(results2.begin(), results2.end());
|
||||
}
|
||||
|
||||
return results;
|
||||
@@ -135,9 +212,12 @@ std::set<gd::String> EventsVariablesFinder::FindAllLayoutVariables(
|
||||
const gd::Layout& layout) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
std::set<gd::String> results2 = FindArgumentsInEventsAndDependencies(
|
||||
platform, project, layout, "scenevar");
|
||||
results.insert(results2.begin(), results2.end());
|
||||
FindArgumentsInEventsAndDependencies(
|
||||
results,
|
||||
platform,
|
||||
project,
|
||||
layout,
|
||||
"scenevar");
|
||||
|
||||
return results;
|
||||
}
|
||||
@@ -149,159 +229,51 @@ std::set<gd::String> EventsVariablesFinder::FindAllObjectVariables(
|
||||
const gd::Object& object) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
std::set<gd::String> results2 = FindArgumentsInEventsAndDependencies(
|
||||
FindArgumentsInEventsAndDependencies(
|
||||
results,
|
||||
platform,
|
||||
project,
|
||||
layout,
|
||||
"objectvar",
|
||||
object.GetName());
|
||||
results.insert(results2.begin(), results2.end());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
std::set<gd::String> EventsVariablesFinder::FindArgumentsInInstructions(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::InstructionsList& instructions,
|
||||
bool instructionsAreConditions,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
for (std::size_t aId = 0; aId < instructions.size(); ++aId) {
|
||||
gd::String lastObjectParameter = "";
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
instructionsAreConditions ? MetadataProvider::GetConditionMetadata(
|
||||
platform, instructions[aId].GetType())
|
||||
: MetadataProvider::GetActionMetadata(
|
||||
platform, instructions[aId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// The parameter has the searched type...
|
||||
if (instrInfos.parameters[pNb].type == parameterType) {
|
||||
//...remember the value of the parameter.
|
||||
if (objectName.empty() || lastObjectParameter == objectName)
|
||||
results.insert(instructions[aId].GetParameter(pNb).GetPlainString());
|
||||
}
|
||||
// Search in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type) ||
|
||||
ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
auto node = instructions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
ExpressionParameterSearcher searcher(
|
||||
platform,
|
||||
project,
|
||||
layout,
|
||||
results,
|
||||
parameterType,
|
||||
objectName);
|
||||
node->Visit(searcher);
|
||||
}
|
||||
// Remember the value of the last "object" parameter.
|
||||
else if (gd::ParameterMetadata::IsObject(
|
||||
instrInfos.parameters[pNb].type)) {
|
||||
lastObjectParameter =
|
||||
instructions[aId].GetParameter(pNb).GetPlainString();
|
||||
}
|
||||
}
|
||||
|
||||
if (!instructions[aId].GetSubInstructions().empty())
|
||||
FindArgumentsInInstructions(platform,
|
||||
project,
|
||||
layout,
|
||||
instructions[aId].GetSubInstructions(),
|
||||
instructionsAreConditions,
|
||||
parameterType);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
std::set<gd::String> EventsVariablesFinder::FindArgumentsInEventsAndDependencies(
|
||||
void EventsVariablesFinder::FindArgumentsInEventsAndDependencies(
|
||||
std::set<gd::String>& results,
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
std::set<gd::String> results2 = FindArgumentsInEvents(
|
||||
platform, project, layout, layout.GetEvents(), parameterType, objectName);
|
||||
results.insert(results2.begin(), results2.end());
|
||||
VariableFinderEventWorker eventWorker(results,
|
||||
platform,
|
||||
parameterType,
|
||||
objectName);
|
||||
eventWorker.Launch(layout.GetEvents(), project, layout);
|
||||
|
||||
DependenciesAnalyzer dependenciesAnalyzer = DependenciesAnalyzer(project, layout);
|
||||
dependenciesAnalyzer.Analyze();
|
||||
for (const gd::String& externalEventName : dependenciesAnalyzer.GetExternalEventsDependencies()) {
|
||||
const gd::ExternalEvents& externalEvents = project.GetExternalEvents(externalEventName);
|
||||
|
||||
std::set<gd::String> results3 = FindArgumentsInEvents(
|
||||
platform, project, layout, externalEvents.GetEvents(), parameterType, objectName);
|
||||
results.insert(results3.begin(), results3.end());
|
||||
VariableFinderEventWorker eventWorker(results,
|
||||
platform,
|
||||
parameterType,
|
||||
objectName);
|
||||
eventWorker.Launch(externalEvents.GetEvents(), project, layout);
|
||||
}
|
||||
for (const gd::String& sceneName : dependenciesAnalyzer.GetScenesDependencies()) {
|
||||
const gd::Layout& dependencyLayout = project.GetLayout(sceneName);
|
||||
|
||||
std::set<gd::String> results3 = FindArgumentsInEvents(
|
||||
platform, project, dependencyLayout, dependencyLayout.GetEvents(), parameterType, objectName);
|
||||
results.insert(results3.begin(), results3.end());
|
||||
VariableFinderEventWorker eventWorker(results,
|
||||
platform,
|
||||
parameterType,
|
||||
objectName);
|
||||
eventWorker.Launch(dependencyLayout.GetEvents(), project, dependencyLayout);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
std::set<gd::String> EventsVariablesFinder::FindArgumentsInEvents(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::EventsList& events,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName) {
|
||||
std::set<gd::String> results;
|
||||
for (std::size_t i = 0; i < events.size(); ++i) {
|
||||
vector<const gd::InstructionsList*> conditionsVectors =
|
||||
events[i].GetAllConditionsVectors();
|
||||
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
|
||||
std::set<gd::String> results2 =
|
||||
FindArgumentsInInstructions(platform,
|
||||
project,
|
||||
layout,
|
||||
*conditionsVectors[j],
|
||||
/*conditions=*/true,
|
||||
parameterType,
|
||||
objectName);
|
||||
results.insert(results2.begin(), results2.end());
|
||||
}
|
||||
|
||||
vector<const gd::InstructionsList*> actionsVectors =
|
||||
events[i].GetAllActionsVectors();
|
||||
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
|
||||
std::set<gd::String> results2 =
|
||||
FindArgumentsInInstructions(platform,
|
||||
project,
|
||||
layout,
|
||||
*actionsVectors[j],
|
||||
/*conditions=*/false,
|
||||
parameterType,
|
||||
objectName);
|
||||
results.insert(results2.begin(), results2.end());
|
||||
}
|
||||
|
||||
if (events[i].CanHaveSubEvents()) {
|
||||
std::set<gd::String> results2 =
|
||||
FindArgumentsInEvents(platform,
|
||||
project,
|
||||
layout,
|
||||
events[i].GetSubEvents(),
|
||||
parameterType,
|
||||
objectName);
|
||||
results.insert(results2.begin(), results2.end());
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -23,7 +23,6 @@ namespace gd {
|
||||
* \brief Perform a search over a project or a layout, searching for layout,
|
||||
* global or object variables.
|
||||
*
|
||||
* \todo Refactor this class using ArbitraryEventsWorker
|
||||
* \todo Rework this class to return the shapes (maybe even types?) of the
|
||||
* variables (in particular for structures and arrays), so we can use this
|
||||
* for better autocompletions in the variables dialogs in the IDE.
|
||||
@@ -74,34 +73,13 @@ class EventsVariablesFinder {
|
||||
const gd::Object& object);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Construct a list of the value of the arguments for parameters of type @
|
||||
* parameterType
|
||||
*
|
||||
* \param project The project used
|
||||
* \param project The layout used
|
||||
* \param instructions The instructions to be analyzed
|
||||
* \param instructionsAreConditions True if the instructions are conditions.
|
||||
* \param parameterType The parameters type to be analyzed
|
||||
* \param objectName If not empty, parameters will be taken into account only
|
||||
* if the last object parameter is filled with this value.
|
||||
*
|
||||
* \return A std::set filled with the values used for all parameters of the
|
||||
* specified type
|
||||
*/
|
||||
static std::set<gd::String> FindArgumentsInInstructions(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::InstructionsList& instructions,
|
||||
bool instructionsAreConditions,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName = "");
|
||||
|
||||
/**
|
||||
* Construct a list of the value of the arguments for parameters of type @
|
||||
* parameterType. It searchs in events dependencies.
|
||||
* parameterType. It searches in events dependencies.
|
||||
*
|
||||
* \param results A std::set to fill with the values used for all parameters of the
|
||||
* specified type
|
||||
* \param platform The platform of the project
|
||||
* \param project The project used
|
||||
* \param layout The layout used
|
||||
@@ -110,40 +88,14 @@ class EventsVariablesFinder {
|
||||
* \param objectName If not empty, parameters will be taken into account
|
||||
* only if the last object parameter is filled with
|
||||
* this value.
|
||||
*
|
||||
* \return A std::set filled with the values used for all parameters of the
|
||||
* specified type
|
||||
*/
|
||||
static std::set<gd::String> FindArgumentsInEventsAndDependencies(
|
||||
static void FindArgumentsInEventsAndDependencies(
|
||||
std::set<gd::String>& results,
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName = "");
|
||||
|
||||
/**
|
||||
* Construct a list of the value of the arguments for parameters of type @
|
||||
* parameterType. It doesn't search in events dependencies.
|
||||
*
|
||||
* \param platform The platform of the project
|
||||
* \param project The project used
|
||||
* \param layout The layout used
|
||||
* \param events The events to be analyzed
|
||||
* \param parameterType The parameters type to be analyzed
|
||||
* \param objectName If not empty, parameters will be taken into account
|
||||
* only if the last object parameter is filled with
|
||||
* this value.
|
||||
*
|
||||
* \return A std::set filled with the values used for all parameters of the
|
||||
* specified type
|
||||
*/
|
||||
static std::set<gd::String> FindArgumentsInEvents(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::EventsList& events,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName);
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -36,7 +36,7 @@ size_t GetMinimumParametersNumber(
|
||||
size_t initialParameterIndex) {
|
||||
size_t nb = 0;
|
||||
for (std::size_t i = initialParameterIndex; i < parameters.size(); ++i) {
|
||||
if (!parameters[i].optional && !parameters[i].codeOnly) nb++;
|
||||
if (!parameters[i].IsOptional() && !parameters[i].codeOnly) nb++;
|
||||
}
|
||||
|
||||
return nb;
|
||||
|
@@ -150,7 +150,7 @@ bool ExpressionsParameterMover::DoVisitInstruction(gd::Instruction& instruction,
|
||||
for (std::size_t pNb = 0; pNb < metadata.parameters.size() &&
|
||||
pNb < instruction.GetParametersCount();
|
||||
++pNb) {
|
||||
const gd::String& type = metadata.parameters[pNb].type;
|
||||
const gd::String& type = metadata.parameters[pNb].GetType();
|
||||
const gd::Expression& expression = instruction.GetParameter(pNb);
|
||||
|
||||
auto node = expression.GetRootNode();
|
||||
|
@@ -20,6 +20,7 @@ namespace gd {
|
||||
|
||||
void EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
|
||||
const gd::Project& project,
|
||||
const gd::EventsFunctionsContainer functionContainer,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& outputGlobalObjectsContainer,
|
||||
gd::ObjectsContainer& outputObjectsContainer) {
|
||||
@@ -31,8 +32,12 @@ void EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
|
||||
// to parameters
|
||||
outputObjectsContainer.GetObjects().clear();
|
||||
outputObjectsContainer.GetObjectGroups().Clear();
|
||||
|
||||
auto ¶meters = eventsFunction.GetParametersForEvents(functionContainer);
|
||||
gd::ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
project, eventsFunction.GetParameters(), outputObjectsContainer);
|
||||
project,
|
||||
parameters,
|
||||
outputObjectsContainer);
|
||||
outputObjectsContainer.GetObjectGroups() = eventsFunction.GetObjectGroups();
|
||||
}
|
||||
|
||||
@@ -44,6 +49,7 @@ void EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
|
||||
gd::ObjectsContainer& outputObjectsContainer) {
|
||||
// The context is build the same way as free function...
|
||||
FreeEventsFunctionToObjectsContainer(project,
|
||||
eventsBasedBehavior.GetEventsFunctions(),
|
||||
eventsFunction,
|
||||
outputGlobalObjectsContainer,
|
||||
outputObjectsContainer);
|
||||
@@ -81,6 +87,7 @@ void EventsFunctionTools::ObjectEventsFunctionToObjectsContainer(
|
||||
gd::ObjectsContainer& outputObjectsContainer) {
|
||||
// The context is build the same way as free function...
|
||||
FreeEventsFunctionToObjectsContainer(project,
|
||||
eventsBasedObject.GetEventsFunctions(),
|
||||
eventsFunction,
|
||||
outputGlobalObjectsContainer,
|
||||
outputObjectsContainer);
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class Project;
|
||||
class EventsFunctionsContainer;
|
||||
class ObjectsContainer;
|
||||
class ParameterMetadata;
|
||||
class EventsFunction;
|
||||
@@ -34,6 +35,7 @@ class GD_CORE_API EventsFunctionTools {
|
||||
*/
|
||||
static void FreeEventsFunctionToObjectsContainer(
|
||||
const gd::Project& project,
|
||||
const gd::EventsFunctionsContainer functionContainer,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& outputGlobalObjectsContainer,
|
||||
gd::ObjectsContainer& outputObjectsContainer);
|
||||
|
@@ -5,6 +5,8 @@
|
||||
*/
|
||||
#include "ProjectStripper.h"
|
||||
|
||||
#include "GDCore/Project/EventsFunctionsContainer.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/Project/ExternalLayout.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
@@ -12,7 +14,7 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
void GD_CORE_API ProjectStripper::StripProjectForExport(gd::Project& project) {
|
||||
void GD_CORE_API ProjectStripper::StripProjectForExport(gd::Project &project) {
|
||||
project.GetObjectGroups().Clear();
|
||||
while (project.GetExternalEventsCount() > 0)
|
||||
project.RemoveExternalEvents(project.GetExternalEvents(0).GetName());
|
||||
@@ -22,7 +24,28 @@ void GD_CORE_API ProjectStripper::StripProjectForExport(gd::Project& project) {
|
||||
project.GetLayout(i).GetEvents().Clear();
|
||||
}
|
||||
|
||||
project.ClearEventsFunctionsExtensions();
|
||||
// Keep the EventsBasedObject object list because it's useful for the Runtime
|
||||
// to create the child-object.
|
||||
for (unsigned int extensionIndex = 0;
|
||||
extensionIndex < project.GetEventsFunctionsExtensionsCount();
|
||||
++extensionIndex) {
|
||||
auto &extension = project.GetEventsFunctionsExtension(extensionIndex);
|
||||
auto &eventsBasedObjects = extension.GetEventsBasedObjects();
|
||||
if (eventsBasedObjects.size() == 0) {
|
||||
project.RemoveEventsFunctionsExtension(extension.GetName());
|
||||
extensionIndex--;
|
||||
continue;
|
||||
}
|
||||
for (unsigned int objectIndex = 0; objectIndex < eventsBasedObjects.size();
|
||||
++objectIndex) {
|
||||
auto &eventsBasedObject = eventsBasedObjects.at(objectIndex);
|
||||
eventsBasedObject.SetFullName("");
|
||||
eventsBasedObject.SetDescription("");
|
||||
eventsBasedObject.GetEventsFunctions().GetInternalVector().clear();
|
||||
eventsBasedObject.GetPropertyDescriptors().GetInternalVector().clear();
|
||||
}
|
||||
extension.GetEventsBasedBehaviors().Clear();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
} // namespace gd
|
||||
|
301
Core/GDCore/IDE/PropertyFunctionGenerator.cpp
Normal file
301
Core/GDCore/IDE/PropertyFunctionGenerator.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2022 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "PropertyFunctionGenerator.h"
|
||||
|
||||
#include "GDCore/Events/Builtin/StandardEvent.h"
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
void PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
|
||||
gd::Project &project, gd::EventsFunctionsExtension &extension,
|
||||
gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
const gd::NamedPropertyDescriptor &property, bool isSharedProperties) {
|
||||
GenerateGetterAndSetter(project, extension, eventsBasedBehavior, property,
|
||||
eventsBasedBehavior.GetObjectType(), true,
|
||||
isSharedProperties);
|
||||
}
|
||||
|
||||
void PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
|
||||
gd::Project &project, gd::EventsFunctionsExtension &extension,
|
||||
gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::NamedPropertyDescriptor &property) {
|
||||
GenerateGetterAndSetter(project, extension, eventsBasedObject, property, "",
|
||||
false, false);
|
||||
}
|
||||
|
||||
void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
gd::Project &project, gd::EventsFunctionsExtension &extension,
|
||||
gd::AbstractEventsBasedEntity &eventsBasedEntity,
|
||||
const gd::NamedPropertyDescriptor &property, const gd::String &objectType,
|
||||
bool isBehavior, bool isSharedProperties) {
|
||||
auto &propertyName = property.GetName();
|
||||
auto &functionsContainer = eventsBasedEntity.GetEventsFunctions();
|
||||
gd::String capitalizedName = CapitalizeFirstLetter(property.GetName());
|
||||
gd::String setterName = "Set" + capitalizedName;
|
||||
|
||||
gd::String functionGroupName =
|
||||
(eventsBasedEntity.GetFullName().empty()
|
||||
? eventsBasedEntity.GetName()
|
||||
: eventsBasedEntity.GetFullName()) +
|
||||
(property.GetGroup().empty()
|
||||
? ""
|
||||
: " " + UnCapitalizeFirstLetter(property.GetGroup())) +
|
||||
" configuration";
|
||||
|
||||
gd::String propertyLabel =
|
||||
property.GetLabel().empty() ? property.GetName() : property.GetLabel();
|
||||
|
||||
gd::String descriptionSubject =
|
||||
(property.GetType() == "Boolean" ? "if " : "the ") +
|
||||
UnCapitalizeFirstLetter(propertyLabel) +
|
||||
(isSharedProperties || property.GetType() == "Boolean"
|
||||
? "."
|
||||
: " of the object.") +
|
||||
(property.GetDescription().empty() ? ""
|
||||
: " " + property.GetDescription()) +
|
||||
(isSharedProperties
|
||||
? " While an object is needed, this will apply to all "
|
||||
"objects using the behavior."
|
||||
: "");
|
||||
|
||||
gd::String propertyGetterName =
|
||||
(isSharedProperties ? "SharedProperty" : "Property") + property.GetName();
|
||||
gd::String getterType =
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
extension.GetName(), eventsBasedEntity.GetName(), propertyGetterName);
|
||||
gd::String setterType =
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
extension.GetName(), eventsBasedEntity.GetName(),
|
||||
"Set" + propertyGetterName);
|
||||
|
||||
gd::String getterName = capitalizedName;
|
||||
gd::String numberOrString =
|
||||
property.GetType() == "Number" ? "Number" : "String";
|
||||
|
||||
if (!functionsContainer.HasEventsFunctionNamed(getterName)) {
|
||||
auto &getter = functionsContainer.InsertNewEventsFunction(
|
||||
getterName, functionsContainer.GetEventsFunctionsCount());
|
||||
auto &expressionType =
|
||||
gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
property.GetType());
|
||||
// TODO Stop replacing number by expression when it"s handled by the UI
|
||||
// and released.
|
||||
auto &legacyExpressionType =
|
||||
expressionType == "number" ? "expression" : expressionType;
|
||||
getter.GetExpressionType()
|
||||
.SetName(legacyExpressionType)
|
||||
.SetExtraInfo(GetStringifiedExtraInfo(property));
|
||||
getter.SetFullName(propertyLabel).SetGroup(functionGroupName);
|
||||
if (property.GetType() == "Boolean") {
|
||||
getter.SetFunctionType(gd::EventsFunction::Condition)
|
||||
.SetDescription("Check " + descriptionSubject)
|
||||
.SetSentence("_PARAM0_ " + UnCapitalizeFirstLetter(propertyLabel));
|
||||
} else {
|
||||
getter.SetFunctionType(gd::EventsFunction::ExpressionAndCondition)
|
||||
.SetDescription(descriptionSubject)
|
||||
.SetSentence("the " + UnCapitalizeFirstLetter(propertyLabel));
|
||||
}
|
||||
|
||||
auto &event =
|
||||
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().InsertNewEvent(
|
||||
project, "BuiltinCommonInstructions::Standard", 0));
|
||||
if (property.GetType() == "Boolean") {
|
||||
gd::Instruction condition;
|
||||
condition.SetType(getterType);
|
||||
condition.AddParameter("Object");
|
||||
if (isBehavior) {
|
||||
condition.AddParameter("Behavior");
|
||||
}
|
||||
event.GetConditions().Insert(condition, 0);
|
||||
|
||||
gd::Instruction action;
|
||||
action.SetType("SetReturnBoolean");
|
||||
action.AddParameter("True");
|
||||
event.GetActions().Insert(action, 0);
|
||||
} else {
|
||||
gd::Instruction action;
|
||||
action.SetType("SetReturn" + numberOrString);
|
||||
gd::String receiver = isBehavior ? "Object.Behavior::" : "Object.";
|
||||
gd::String propertyPrefix =
|
||||
(isSharedProperties ? "SharedProperty" : "Property");
|
||||
action.AddParameter(receiver + propertyPrefix + property.GetName() +
|
||||
"()");
|
||||
event.GetActions().Insert(action, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!functionsContainer.HasEventsFunctionNamed(setterName)) {
|
||||
auto &setter = functionsContainer.InsertNewEventsFunction(
|
||||
setterName, functionsContainer.GetEventsFunctionsCount());
|
||||
if (property.GetType() == "Boolean") {
|
||||
setter.SetFunctionType(gd::EventsFunction::Action)
|
||||
.SetFullName(propertyLabel)
|
||||
.SetGroup(functionGroupName)
|
||||
.SetDescription("Change " + descriptionSubject)
|
||||
.SetSentence("_PARAM0_ " + UnCapitalizeFirstLetter(propertyLabel) +
|
||||
(isBehavior ? ": _PARAM2_" : ": _PARAM1_"));
|
||||
gd::ParameterMetadata objectParameter;
|
||||
objectParameter.SetType("object")
|
||||
.SetName("Object")
|
||||
.SetDescription("Object")
|
||||
.SetExtraInfo(objectType);
|
||||
if (!isBehavior) {
|
||||
gd::String objectFullType = gd::PlatformExtension::GetObjectFullType(
|
||||
extension.GetName(), eventsBasedEntity.GetName());
|
||||
objectParameter.SetExtraInfo(objectFullType);
|
||||
}
|
||||
setter.GetParameters().push_back(objectParameter);
|
||||
if (isBehavior) {
|
||||
gd::ParameterMetadata behaviorParameter;
|
||||
gd::String behaviorFullType =
|
||||
gd::PlatformExtension::GetBehaviorFullType(
|
||||
extension.GetName(), eventsBasedEntity.GetName());
|
||||
behaviorParameter.SetType("behavior")
|
||||
.SetName("Behavior")
|
||||
.SetDescription("Behavior")
|
||||
.SetExtraInfo(behaviorFullType);
|
||||
setter.GetParameters().push_back(behaviorParameter);
|
||||
}
|
||||
gd::ParameterMetadata valueParameter;
|
||||
valueParameter.SetType("yesorno")
|
||||
.SetName("Value")
|
||||
.SetDescription(capitalizedName)
|
||||
.SetOptional(true)
|
||||
.SetDefaultValue("yes");
|
||||
setter.GetParameters().push_back(valueParameter);
|
||||
} else {
|
||||
setter.SetFunctionType(gd::EventsFunction::ActionWithOperator);
|
||||
setter.SetGetterName(getterName);
|
||||
}
|
||||
|
||||
if (property.GetType() == "Boolean") {
|
||||
{
|
||||
auto &event =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().InsertNewEvent(
|
||||
project, "BuiltinCommonInstructions::Standard", 0));
|
||||
|
||||
gd::Instruction condition;
|
||||
condition.SetType("GetArgumentAsBoolean");
|
||||
condition.AddParameter("\"Value\"");
|
||||
event.GetConditions().Insert(condition, 0);
|
||||
|
||||
gd::Instruction action;
|
||||
action.SetType(setterType);
|
||||
action.AddParameter("Object");
|
||||
if (isBehavior) {
|
||||
action.AddParameter("Behavior");
|
||||
action.AddParameter("yes");
|
||||
} else {
|
||||
action.AddParameter("yes");
|
||||
}
|
||||
event.GetActions().Insert(action, 0);
|
||||
}
|
||||
{
|
||||
auto &event =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().InsertNewEvent(
|
||||
project, "BuiltinCommonInstructions::Standard", 0));
|
||||
|
||||
gd::Instruction condition;
|
||||
condition.SetType("GetArgumentAsBoolean");
|
||||
condition.AddParameter("\"Value\"");
|
||||
condition.SetInverted(true);
|
||||
event.GetConditions().Insert(condition, 0);
|
||||
|
||||
gd::Instruction action;
|
||||
action.SetType(setterType);
|
||||
action.AddParameter("Object");
|
||||
if (isBehavior) {
|
||||
action.AddParameter("Behavior");
|
||||
action.AddParameter("no");
|
||||
} else {
|
||||
action.AddParameter("no");
|
||||
}
|
||||
event.GetActions().Insert(action, 0);
|
||||
}
|
||||
} else {
|
||||
auto &event =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().InsertNewEvent(
|
||||
project, "BuiltinCommonInstructions::Standard", 0));
|
||||
|
||||
gd::Instruction action;
|
||||
action.SetType(setterType);
|
||||
action.AddParameter("Object");
|
||||
gd::String parameterGetterCall =
|
||||
"GetArgumentAs" + numberOrString + "(\"Value\")";
|
||||
if (isBehavior) {
|
||||
action.AddParameter("Behavior");
|
||||
action.AddParameter("=");
|
||||
action.AddParameter(parameterGetterCall);
|
||||
} else {
|
||||
action.AddParameter("=");
|
||||
action.AddParameter(parameterGetterCall);
|
||||
}
|
||||
event.GetActions().Insert(action, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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") {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto &functionsContainer = eventsBasedEntity.GetEventsFunctions();
|
||||
auto getterName = CapitalizeFirstLetter(property.GetName());
|
||||
auto setterName = "Set" + getterName;
|
||||
return !functionsContainer.HasEventsFunctionNamed(setterName) &&
|
||||
!functionsContainer.HasEventsFunctionNamed(getterName);
|
||||
};
|
||||
|
||||
gd::String PropertyFunctionGenerator::GetStringifiedExtraInfo(
|
||||
const gd::PropertyDescriptor &property) {
|
||||
if (property.GetType() == "Choice") {
|
||||
gd::String arrayString;
|
||||
arrayString += "[";
|
||||
bool isFirst = true;
|
||||
for (const gd::String &choice : property.GetExtraInfo()) {
|
||||
if (!isFirst) {
|
||||
arrayString += ",";
|
||||
}
|
||||
isFirst = false;
|
||||
arrayString += "\"" + choice + "\"";
|
||||
}
|
||||
arrayString += "]";
|
||||
return arrayString;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
gd::String
|
||||
PropertyFunctionGenerator::CapitalizeFirstLetter(const gd::String &string) {
|
||||
if (string.empty()) {
|
||||
return string;
|
||||
}
|
||||
return string.substr(0, 1).UpperCase() + string.substr(1);
|
||||
}
|
||||
|
||||
gd::String
|
||||
PropertyFunctionGenerator::UnCapitalizeFirstLetter(const gd::String &string) {
|
||||
if (string.empty()) {
|
||||
return string;
|
||||
}
|
||||
return string.substr(0, 1).LowerCase() + string.substr(1);
|
||||
}
|
||||
|
||||
} // namespace gd
|
65
Core/GDCore/IDE/PropertyFunctionGenerator.h
Normal file
65
Core/GDCore/IDE/PropertyFunctionGenerator.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2022 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_PROPERTYFUNCTIONGENERATOR_H
|
||||
#define GDCORE_PROPERTYFUNCTIONGENERATOR_H
|
||||
|
||||
namespace gd {
|
||||
class String;
|
||||
class Project;
|
||||
class EventsFunctionsExtension;
|
||||
class EventsBasedBehavior;
|
||||
class EventsBasedObject;
|
||||
class AbstractEventsBasedEntity;
|
||||
class PropertyDescriptor;
|
||||
class NamedPropertyDescriptor;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Generate a getter and a setter functions for properties.
|
||||
*/
|
||||
class GD_CORE_API PropertyFunctionGenerator {
|
||||
public:
|
||||
/**
|
||||
* \brief Generate a getter and a setter for the given behavior property.
|
||||
*/
|
||||
static void GenerateBehaviorGetterAndSetter(
|
||||
gd::Project &project, gd::EventsFunctionsExtension &extension,
|
||||
gd::EventsBasedBehavior &eventsBasedBehavior,
|
||||
const gd::NamedPropertyDescriptor &property, bool isSharedProperties);
|
||||
/**
|
||||
* \brief Generate a getter and a setter for the given object property.
|
||||
*/
|
||||
static void
|
||||
GenerateObjectGetterAndSetter(gd::Project &project,
|
||||
gd::EventsFunctionsExtension &extension,
|
||||
gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::NamedPropertyDescriptor &property);
|
||||
static bool CanGenerateGetterAndSetter(
|
||||
const gd::AbstractEventsBasedEntity &eventsBasedEntity,
|
||||
const gd::NamedPropertyDescriptor &property);
|
||||
|
||||
~PropertyFunctionGenerator();
|
||||
|
||||
private:
|
||||
static void GenerateGetterAndSetter(
|
||||
gd::Project &project, gd::EventsFunctionsExtension &extension,
|
||||
gd::AbstractEventsBasedEntity &eventsBasedEntity,
|
||||
const gd::NamedPropertyDescriptor &property, const gd::String &objectType,
|
||||
bool isBehavior, bool isSharedProperties);
|
||||
|
||||
static gd::String CapitalizeFirstLetter(const gd::String &string);
|
||||
static gd::String UnCapitalizeFirstLetter(const gd::String &string);
|
||||
static gd::String
|
||||
GetStringifiedExtraInfo(const gd::PropertyDescriptor &property);
|
||||
|
||||
PropertyFunctionGenerator();
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_PROPERTYFUNCTIONGENERATOR_H
|
@@ -35,40 +35,6 @@
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
||||
namespace {
|
||||
// These functions are doing the reverse of what is done when adding
|
||||
// instructions/expression to extension/behaviors. If needed, they could be
|
||||
// moved to gd::PlatformExtension to colocate the usage of the namespace
|
||||
// separator?
|
||||
gd::String GetEventsFunctionFullType(const gd::String& extensionName,
|
||||
const gd::String& functionName) {
|
||||
const auto& separator = gd::PlatformExtension::GetNamespaceSeparator();
|
||||
return extensionName + separator + functionName;
|
||||
}
|
||||
gd::String GetBehaviorEventsFunctionFullType(const gd::String& extensionName,
|
||||
const gd::String& behaviorName,
|
||||
const gd::String& functionName) {
|
||||
const auto& separator = gd::PlatformExtension::GetNamespaceSeparator();
|
||||
return extensionName + separator + behaviorName + separator + functionName;
|
||||
}
|
||||
gd::String GetBehaviorFullType(const gd::String& extensionName,
|
||||
const gd::String& behaviorName) {
|
||||
const auto& separator = gd::PlatformExtension::GetNamespaceSeparator();
|
||||
return extensionName + separator + behaviorName;
|
||||
}
|
||||
gd::String GetObjectEventsFunctionFullType(const gd::String& extensionName,
|
||||
const gd::String& objectName,
|
||||
const gd::String& functionName) {
|
||||
const auto& separator = gd::PlatformExtension::GetNamespaceSeparator();
|
||||
return extensionName + separator + objectName + separator + functionName;
|
||||
}
|
||||
gd::String GetObjectFullType(const gd::String& extensionName,
|
||||
const gd::String& objectName) {
|
||||
const auto& separator = gd::PlatformExtension::GetNamespaceSeparator();
|
||||
return extensionName + separator + objectName;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace gd {
|
||||
|
||||
// By convention, the first parameter of an events based behavior method is
|
||||
@@ -154,7 +120,11 @@ void WholeProjectRefactorer::ExposeProjectEvents(
|
||||
gd::ObjectsContainer globalObjectsAndGroups;
|
||||
gd::ObjectsContainer objectsAndGroups;
|
||||
gd::EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
|
||||
project, *eventsFunction, globalObjectsAndGroups, objectsAndGroups);
|
||||
project,
|
||||
eventsFunctionsExtension,
|
||||
*eventsFunction,
|
||||
globalObjectsAndGroups,
|
||||
objectsAndGroups);
|
||||
|
||||
worker.Launch(eventsFunction->GetEvents(),
|
||||
globalObjectsAndGroups,
|
||||
@@ -248,7 +218,7 @@ WholeProjectRefactorer::GetAllObjectTypesUsingEventsBasedBehavior(
|
||||
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior) {
|
||||
std::set<gd::String> allTypes;
|
||||
const gd::String behaviorType = GetBehaviorFullType(
|
||||
const gd::String behaviorType = gd::PlatformExtension::GetBehaviorFullType(
|
||||
eventsFunctionsExtension.GetName(), eventsBasedBehavior.GetName());
|
||||
|
||||
auto addTypesOfObjectsIn =
|
||||
@@ -291,7 +261,7 @@ void WholeProjectRefactorer::EnsureBehaviorEventsFunctionsProperParameters(
|
||||
.SetType("behavior")
|
||||
.SetName("Behavior")
|
||||
.SetDescription("Behavior")
|
||||
.SetExtraInfo(GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
.SetExtraInfo(gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName()));
|
||||
}
|
||||
}
|
||||
@@ -311,7 +281,7 @@ void WholeProjectRefactorer::EnsureObjectEventsFunctionsProperParameters(
|
||||
.SetType("object")
|
||||
.SetName(parentObjectParameterName)
|
||||
.SetDescription("Object")
|
||||
.SetExtraInfo(GetObjectFullType(eventsFunctionsExtension.GetName(),
|
||||
.SetExtraInfo(gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName()));
|
||||
}
|
||||
}
|
||||
@@ -326,30 +296,27 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
DoRenameEventsFunction(
|
||||
project,
|
||||
eventsFunction,
|
||||
GetEventsFunctionFullType(oldName, eventsFunction.GetName()),
|
||||
GetEventsFunctionFullType(newName, eventsFunction.GetName()));
|
||||
gd::PlatformExtension::GetEventsFunctionFullType(oldName, eventsFunction.GetName()),
|
||||
gd::PlatformExtension::GetEventsFunctionFullType(newName, eventsFunction.GetName()));
|
||||
};
|
||||
|
||||
auto renameBehaviorEventsFunction =
|
||||
[&project, &oldName, &newName](
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
const gd::EventsFunction& eventsFunction) {
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
if (eventsFunction.IsExpression()) {
|
||||
// Nothing to do, expressions are not including the extension name
|
||||
}
|
||||
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
|
||||
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(oldName,
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(oldName,
|
||||
eventsBasedBehavior.GetName(),
|
||||
eventsFunction.GetName()),
|
||||
GetBehaviorEventsFunctionFullType(newName,
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(newName,
|
||||
eventsBasedBehavior.GetName(),
|
||||
eventsFunction.GetName()));
|
||||
ExposeProjectEvents(project, renamer);
|
||||
} else if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::Expression ||
|
||||
eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
// Nothing to do, expressions are not including the extension name
|
||||
}
|
||||
};
|
||||
|
||||
@@ -359,12 +326,12 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
const gd::NamedPropertyDescriptor& property) {
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
oldName,
|
||||
eventsBasedBehavior.GetName(),
|
||||
gd::EventsBasedBehavior::GetPropertyActionName(
|
||||
property.GetName())),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
newName,
|
||||
eventsBasedBehavior.GetName(),
|
||||
gd::EventsBasedBehavior::GetPropertyActionName(
|
||||
@@ -374,12 +341,12 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
gd::InstructionsTypeRenamer conditionRenamer =
|
||||
gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
oldName,
|
||||
eventsBasedBehavior.GetName(),
|
||||
gd::EventsBasedBehavior::GetPropertyConditionName(
|
||||
property.GetName())),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
newName,
|
||||
eventsBasedBehavior.GetName(),
|
||||
gd::EventsBasedBehavior::GetPropertyConditionName(
|
||||
@@ -390,26 +357,60 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
// extension name
|
||||
};
|
||||
|
||||
auto renameBehaviorSharedPropertyFunctions =
|
||||
[&project, &oldName, &newName](
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
const gd::NamedPropertyDescriptor& property) {
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
oldName,
|
||||
eventsBasedBehavior.GetName(),
|
||||
gd::EventsBasedBehavior::GetSharedPropertyActionName(
|
||||
property.GetName())),
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
newName,
|
||||
eventsBasedBehavior.GetName(),
|
||||
gd::EventsBasedBehavior::GetSharedPropertyActionName(
|
||||
property.GetName())));
|
||||
ExposeProjectEvents(project, actionRenamer);
|
||||
|
||||
gd::InstructionsTypeRenamer conditionRenamer =
|
||||
gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
oldName,
|
||||
eventsBasedBehavior.GetName(),
|
||||
gd::EventsBasedBehavior::GetSharedPropertyConditionName(
|
||||
property.GetName())),
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
newName,
|
||||
eventsBasedBehavior.GetName(),
|
||||
gd::EventsBasedBehavior::GetSharedPropertyConditionName(
|
||||
property.GetName())));
|
||||
ExposeProjectEvents(project, conditionRenamer);
|
||||
|
||||
// Nothing to do for expressions, expressions are not including the
|
||||
// extension name
|
||||
};
|
||||
|
||||
auto renameObjectEventsFunction =
|
||||
[&project, &oldName, &newName](
|
||||
const gd::EventsBasedObject& eventsBasedObject,
|
||||
const gd::EventsFunction& eventsFunction) {
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
if (eventsFunction.IsExpression()) {
|
||||
// Nothing to do, expressions are not including the extension name
|
||||
}
|
||||
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
|
||||
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetObjectEventsFunctionFullType(oldName,
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(oldName,
|
||||
eventsBasedObject.GetName(),
|
||||
eventsFunction.GetName()),
|
||||
GetObjectEventsFunctionFullType(newName,
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(newName,
|
||||
eventsBasedObject.GetName(),
|
||||
eventsFunction.GetName()));
|
||||
ExposeProjectEvents(project, renamer);
|
||||
} else if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::Expression ||
|
||||
eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
// Nothing to do, expressions are not including the extension name
|
||||
}
|
||||
};
|
||||
|
||||
@@ -419,12 +420,12 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
const gd::NamedPropertyDescriptor& property) {
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
oldName,
|
||||
eventsBasedObject.GetName(),
|
||||
gd::EventsBasedObject::GetPropertyActionName(
|
||||
property.GetName())),
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
newName,
|
||||
eventsBasedObject.GetName(),
|
||||
gd::EventsBasedObject::GetPropertyActionName(
|
||||
@@ -434,12 +435,12 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
gd::InstructionsTypeRenamer conditionRenamer =
|
||||
gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
oldName,
|
||||
eventsBasedObject.GetName(),
|
||||
gd::EventsBasedObject::GetPropertyConditionName(
|
||||
property.GetName())),
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
newName,
|
||||
eventsBasedObject.GetName(),
|
||||
gd::EventsBasedObject::GetPropertyConditionName(
|
||||
@@ -456,9 +457,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
|
||||
// Free expressions
|
||||
for (auto&& eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
|
||||
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Expression ||
|
||||
eventsFunction->GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
if (eventsFunction->IsExpression()) {
|
||||
renameEventsFunction(*eventsFunction);
|
||||
}
|
||||
}
|
||||
@@ -467,9 +466,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
eventsFunctionsExtension.GetEventsBasedBehaviors().GetInternalVector()) {
|
||||
auto& behaviorEventsFunctions = eventsBasedBehavior->GetEventsFunctions();
|
||||
for (auto&& eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
|
||||
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Expression ||
|
||||
eventsFunction->GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
if (eventsFunction->IsExpression()) {
|
||||
renameBehaviorEventsFunction(*eventsBasedBehavior, *eventsFunction);
|
||||
}
|
||||
}
|
||||
@@ -477,8 +474,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
|
||||
// Free instructions
|
||||
for (auto&& eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
|
||||
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction->GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
|
||||
renameEventsFunction(*eventsFunction);
|
||||
}
|
||||
}
|
||||
@@ -488,21 +484,26 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
eventsFunctionsExtension.GetEventsBasedBehaviors().GetInternalVector()) {
|
||||
auto& behaviorEventsFunctions = eventsBasedBehavior->GetEventsFunctions();
|
||||
for (auto&& eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
|
||||
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction->GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
|
||||
renameBehaviorEventsFunction(*eventsBasedBehavior, *eventsFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Behavior properties
|
||||
for (auto&& eventsBasedBehavior :
|
||||
for (auto &&eventsBasedBehavior :
|
||||
eventsFunctionsExtension.GetEventsBasedBehaviors().GetInternalVector()) {
|
||||
auto& behaviorProperties = eventsBasedBehavior->GetPropertyDescriptors();
|
||||
for (auto&& propertyDescriptor : behaviorProperties.GetInternalVector()) {
|
||||
for (auto &&propertyDescriptor :
|
||||
eventsBasedBehavior->GetPropertyDescriptors().GetInternalVector()) {
|
||||
renameBehaviorPropertyFunctions(*eventsBasedBehavior,
|
||||
*propertyDescriptor);
|
||||
}
|
||||
for (auto &&propertyDescriptor :
|
||||
eventsBasedBehavior->GetSharedPropertyDescriptors()
|
||||
.GetInternalVector()) {
|
||||
renameBehaviorSharedPropertyFunctions(*eventsBasedBehavior,
|
||||
*propertyDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// Object instructions
|
||||
@@ -510,8 +511,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
|
||||
auto& objectEventsFunctions = eventsBasedObject->GetEventsFunctions();
|
||||
for (auto&& eventsFunction : objectEventsFunctions.GetInternalVector()) {
|
||||
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction->GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
|
||||
renameObjectEventsFunction(*eventsBasedObject, *eventsFunction);
|
||||
}
|
||||
}
|
||||
@@ -532,8 +532,8 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
eventsFunctionsExtension.GetEventsBasedBehaviors().GetInternalVector()) {
|
||||
DoRenameBehavior(
|
||||
project,
|
||||
GetBehaviorFullType(oldName, eventsBasedBehavior->GetName()),
|
||||
GetBehaviorFullType(newName, eventsBasedBehavior->GetName()));
|
||||
gd::PlatformExtension::GetBehaviorFullType(oldName, eventsBasedBehavior->GetName()),
|
||||
gd::PlatformExtension::GetBehaviorFullType(newName, eventsBasedBehavior->GetName()));
|
||||
}
|
||||
|
||||
// Finally, rename custom objects type
|
||||
@@ -541,8 +541,8 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
|
||||
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
|
||||
DoRenameObject(
|
||||
project,
|
||||
GetObjectFullType(oldName, eventsBasedObject->GetName()),
|
||||
GetObjectFullType(newName, eventsBasedObject->GetName()));
|
||||
gd::PlatformExtension::GetObjectFullType(oldName, eventsBasedObject->GetName()),
|
||||
gd::PlatformExtension::GetObjectFullType(newName, eventsBasedObject->GetName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,10 +559,20 @@ void WholeProjectRefactorer::RenameEventsFunction(
|
||||
DoRenameEventsFunction(
|
||||
project,
|
||||
eventsFunction,
|
||||
GetEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
gd::PlatformExtension::GetEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
oldFunctionName),
|
||||
GetEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
gd::PlatformExtension::GetEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
newFunctionName));
|
||||
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::ExpressionAndCondition) {
|
||||
for (auto&& otherFunction : eventsFunctionsExtension.GetInternalVector())
|
||||
{
|
||||
if (otherFunction->GetFunctionType() == gd::EventsFunction::ActionWithOperator &&
|
||||
otherFunction->GetGetterName() == oldFunctionName) {
|
||||
otherFunction->SetGetterName(newFunctionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::RenameBehaviorEventsFunction(
|
||||
@@ -577,30 +587,39 @@ void WholeProjectRefactorer::RenameBehaviorEventsFunction(
|
||||
const gd::EventsFunction& eventsFunction =
|
||||
eventsFunctions.GetEventsFunction(oldFunctionName);
|
||||
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
oldFunctionName),
|
||||
GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
newFunctionName));
|
||||
ExposeProjectEvents(project, renamer);
|
||||
} else if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::Expression ||
|
||||
eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
// Order is important: we first rename the expressions then the instructions,
|
||||
// to avoid being unable to fetch the metadata (the types of parameters) of
|
||||
// instructions after they are renamed.
|
||||
if (eventsFunction.IsExpression()) {
|
||||
gd::ExpressionsRenamer renamer =
|
||||
gd::ExpressionsRenamer(project.GetCurrentPlatform());
|
||||
renamer.SetReplacedBehaviorExpression(
|
||||
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName()),
|
||||
oldFunctionName,
|
||||
newFunctionName);
|
||||
ExposeProjectEvents(project, renamer);
|
||||
}
|
||||
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
|
||||
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
oldFunctionName),
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
newFunctionName));
|
||||
ExposeProjectEvents(project, renamer);
|
||||
}
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::ExpressionAndCondition) {
|
||||
for (auto&& otherFunction : eventsBasedBehavior.GetEventsFunctions().GetInternalVector())
|
||||
{
|
||||
if (otherFunction->GetFunctionType() == gd::EventsFunction::ActionWithOperator &&
|
||||
otherFunction->GetGetterName() == oldFunctionName) {
|
||||
otherFunction->SetGetterName(newFunctionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::RenameObjectEventsFunction(
|
||||
@@ -615,30 +634,36 @@ void WholeProjectRefactorer::RenameObjectEventsFunction(
|
||||
const gd::EventsFunction& eventsFunction =
|
||||
eventsFunctions.GetEventsFunction(oldFunctionName);
|
||||
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName(),
|
||||
oldFunctionName),
|
||||
GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName(),
|
||||
newFunctionName));
|
||||
ExposeProjectEvents(project, renamer);
|
||||
} else if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::Expression ||
|
||||
eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
if (eventsFunction.IsExpression()) {
|
||||
gd::ExpressionsRenamer renamer =
|
||||
gd::ExpressionsRenamer(project.GetCurrentPlatform());
|
||||
renamer.SetReplacedObjectExpression(
|
||||
GetObjectFullType(eventsFunctionsExtension.GetName(),
|
||||
gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName()),
|
||||
oldFunctionName,
|
||||
newFunctionName);
|
||||
ExposeProjectEvents(project, renamer);
|
||||
}
|
||||
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
|
||||
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName(),
|
||||
oldFunctionName),
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName(),
|
||||
newFunctionName));
|
||||
ExposeProjectEvents(project, renamer);
|
||||
}
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::ExpressionAndCondition) {
|
||||
for (auto&& otherFunction : eventsBasedObject.GetEventsFunctions().GetInternalVector())
|
||||
{
|
||||
if (otherFunction->GetFunctionType() == gd::EventsFunction::ActionWithOperator &&
|
||||
otherFunction->GetGetterName() == oldFunctionName) {
|
||||
otherFunction->SetGetterName(newFunctionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::MoveEventsFunctionParameter(
|
||||
@@ -652,24 +677,25 @@ void WholeProjectRefactorer::MoveEventsFunctionParameter(
|
||||
const gd::EventsFunction& eventsFunction =
|
||||
eventsFunctionsExtension.GetEventsFunction(functionName);
|
||||
|
||||
const gd::String& eventsFunctionType = GetEventsFunctionFullType(
|
||||
const gd::String& eventsFunctionType = gd::PlatformExtension::GetEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(), functionName);
|
||||
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
|
||||
project, eventsFunctionType, oldIndex, newIndex);
|
||||
ExposeProjectEvents(project, mover);
|
||||
} else if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::Expression ||
|
||||
eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
if (eventsFunction.IsExpression()) {
|
||||
gd::ExpressionsParameterMover mover =
|
||||
gd::ExpressionsParameterMover(project.GetCurrentPlatform());
|
||||
mover.SetFreeExpressionMovedParameter(
|
||||
eventsFunctionType, oldIndex, newIndex);
|
||||
ExposeProjectEvents(project, mover);
|
||||
}
|
||||
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
|
||||
const int operatorIndexOffset = eventsFunction.IsExpression() ? 2 : 0;
|
||||
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
|
||||
project,
|
||||
eventsFunctionType,
|
||||
oldIndex + operatorIndexOffset,
|
||||
newIndex + operatorIndexOffset);
|
||||
ExposeProjectEvents(project, mover);
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
|
||||
@@ -686,29 +712,30 @@ void WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
|
||||
eventsFunctions.GetEventsFunction(functionName);
|
||||
|
||||
const gd::String& eventsFunctionType =
|
||||
GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
functionName);
|
||||
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
|
||||
project, eventsFunctionType, oldIndex, newIndex);
|
||||
ExposeProjectEvents(project, mover);
|
||||
} else if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::Expression ||
|
||||
eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
if (eventsFunction.IsExpression()) {
|
||||
gd::ExpressionsParameterMover mover =
|
||||
gd::ExpressionsParameterMover(project.GetCurrentPlatform());
|
||||
mover.SetBehaviorExpressionMovedParameter(
|
||||
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName()),
|
||||
functionName,
|
||||
oldIndex,
|
||||
newIndex);
|
||||
ExposeProjectEvents(project, mover);
|
||||
}
|
||||
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
|
||||
const int operatorIndexOffset = eventsFunction.IsExpression() ? 2 : 0;
|
||||
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
|
||||
project,
|
||||
eventsFunctionType,
|
||||
oldIndex + operatorIndexOffset,
|
||||
newIndex + operatorIndexOffset);
|
||||
ExposeProjectEvents(project, mover);
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::MoveObjectEventsFunctionParameter(
|
||||
@@ -725,29 +752,30 @@ void WholeProjectRefactorer::MoveObjectEventsFunctionParameter(
|
||||
eventsFunctions.GetEventsFunction(functionName);
|
||||
|
||||
const gd::String& eventsFunctionType =
|
||||
GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName(),
|
||||
functionName);
|
||||
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
|
||||
project, eventsFunctionType, oldIndex, newIndex);
|
||||
ExposeProjectEvents(project, mover);
|
||||
} else if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::Expression ||
|
||||
eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
if (eventsFunction.IsExpression()) {
|
||||
gd::ExpressionsParameterMover mover =
|
||||
gd::ExpressionsParameterMover(project.GetCurrentPlatform());
|
||||
mover.SetObjectExpressionMovedParameter(
|
||||
GetObjectFullType(eventsFunctionsExtension.GetName(),
|
||||
gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName()),
|
||||
functionName,
|
||||
oldIndex,
|
||||
newIndex);
|
||||
ExposeProjectEvents(project, mover);
|
||||
}
|
||||
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
|
||||
const int operatorIndexOffset = eventsFunction.IsExpression() ? 2 : 0;
|
||||
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
|
||||
project,
|
||||
eventsFunctionType,
|
||||
oldIndex + operatorIndexOffset,
|
||||
newIndex + operatorIndexOffset);
|
||||
ExposeProjectEvents(project, mover);
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
|
||||
@@ -784,7 +812,7 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
|
||||
gd::ExpressionsRenamer expressionRenamer =
|
||||
gd::ExpressionsRenamer(project.GetCurrentPlatform());
|
||||
expressionRenamer.SetReplacedBehaviorExpression(
|
||||
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName()),
|
||||
EventsBasedBehavior::GetPropertyExpressionName(oldPropertyName),
|
||||
EventsBasedBehavior::GetPropertyExpressionName(newPropertyName));
|
||||
@@ -792,11 +820,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
|
||||
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyActionName(oldPropertyName)),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyActionName(newPropertyName)));
|
||||
@@ -804,11 +832,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
|
||||
|
||||
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyConditionName(oldPropertyName)),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyConditionName(newPropertyName)));
|
||||
@@ -816,6 +844,72 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::RenameEventsBasedBehaviorSharedProperty(
|
||||
gd::Project& project,
|
||||
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
const gd::String& oldPropertyName,
|
||||
const gd::String& newPropertyName) {
|
||||
auto& properties = eventsBasedBehavior.GetPropertyDescriptors();
|
||||
if (!properties.Has(oldPropertyName)) return;
|
||||
|
||||
if (properties.Get(oldPropertyName).GetType() == "Behavior") {
|
||||
// This is a property representing another behavior that must exist on the
|
||||
// object.
|
||||
|
||||
// This other "required behavior" uses the property name, that is about to
|
||||
// change, as its name.
|
||||
// So we must change all reference to this name in the events of the
|
||||
// behavior functions.
|
||||
gd::EventsBehaviorRenamer behaviorRenamer(project.GetCurrentPlatform(),
|
||||
behaviorObjectParameterName,
|
||||
oldPropertyName,
|
||||
newPropertyName);
|
||||
|
||||
ExposeEventsBasedBehaviorEvents(
|
||||
project, eventsBasedBehavior, behaviorRenamer);
|
||||
} else {
|
||||
// Properties that represent primitive values will be used through
|
||||
// their related actions/conditions/expressions. Rename these.
|
||||
|
||||
// Order is important: we first rename the expressions then the
|
||||
// instructions, to avoid being unable to fetch the metadata (the types of
|
||||
// parameters) of instructions after they are renamed.
|
||||
gd::ExpressionsRenamer expressionRenamer =
|
||||
gd::ExpressionsRenamer(project.GetCurrentPlatform());
|
||||
expressionRenamer.SetReplacedBehaviorExpression(
|
||||
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName()),
|
||||
EventsBasedBehavior::GetSharedPropertyExpressionName(oldPropertyName),
|
||||
EventsBasedBehavior::GetSharedPropertyExpressionName(newPropertyName));
|
||||
ExposeProjectEvents(project, expressionRenamer);
|
||||
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetSharedPropertyActionName(oldPropertyName)),
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetSharedPropertyActionName(newPropertyName)));
|
||||
ExposeProjectEvents(project, actionRenamer);
|
||||
|
||||
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetSharedPropertyConditionName(oldPropertyName)),
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetSharedPropertyConditionName(newPropertyName)));
|
||||
ExposeProjectEvents(project, conditionRenamer);
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::RenameEventsBasedObjectProperty(
|
||||
gd::Project& project,
|
||||
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
|
||||
@@ -834,7 +928,7 @@ void WholeProjectRefactorer::RenameEventsBasedObjectProperty(
|
||||
gd::ExpressionsRenamer expressionRenamer =
|
||||
gd::ExpressionsRenamer(project.GetCurrentPlatform());
|
||||
expressionRenamer.SetReplacedObjectExpression(
|
||||
GetObjectFullType(eventsFunctionsExtension.GetName(),
|
||||
gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName()),
|
||||
EventsBasedObject::GetPropertyExpressionName(oldPropertyName),
|
||||
EventsBasedObject::GetPropertyExpressionName(newPropertyName));
|
||||
@@ -842,11 +936,11 @@ void WholeProjectRefactorer::RenameEventsBasedObjectProperty(
|
||||
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName(),
|
||||
EventsBasedObject::GetPropertyActionName(oldPropertyName)),
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName(),
|
||||
EventsBasedObject::GetPropertyActionName(newPropertyName)));
|
||||
@@ -854,11 +948,11 @@ void WholeProjectRefactorer::RenameEventsBasedObjectProperty(
|
||||
|
||||
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName(),
|
||||
EventsBasedObject::GetPropertyConditionName(oldPropertyName)),
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedObject.GetName(),
|
||||
EventsBasedObject::GetPropertyConditionName(newPropertyName)));
|
||||
@@ -1088,25 +1182,22 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
|
||||
&eventsFunctionsExtension,
|
||||
&oldBehaviorName,
|
||||
&newBehaviorName](const gd::EventsFunction& eventsFunction) {
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
if (eventsFunction.IsExpression()) {
|
||||
// Nothing to do, expressions are not including the name of the
|
||||
// behavior
|
||||
}
|
||||
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
|
||||
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
oldBehaviorName,
|
||||
eventsFunction.GetName()),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
newBehaviorName,
|
||||
eventsFunction.GetName()));
|
||||
ExposeProjectEvents(project, renamer);
|
||||
} else if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::Expression ||
|
||||
eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
// Nothing to do, expressions are not including the name of the
|
||||
// behavior
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1118,11 +1209,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
|
||||
property) {
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
oldBehaviorName,
|
||||
EventsBasedBehavior::GetPropertyActionName(property.GetName())),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
newBehaviorName,
|
||||
EventsBasedBehavior::GetPropertyActionName(property.GetName())));
|
||||
@@ -1130,11 +1221,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
|
||||
|
||||
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
oldBehaviorName,
|
||||
EventsBasedBehavior::GetPropertyConditionName(property.GetName())),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
newBehaviorName,
|
||||
EventsBasedBehavior::GetPropertyConditionName(property.GetName())));
|
||||
@@ -1144,6 +1235,40 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
|
||||
// the behavior
|
||||
};
|
||||
|
||||
auto renameBehaviorSharedProperty = [&project,
|
||||
&eventsFunctionsExtension,
|
||||
&oldBehaviorName,
|
||||
&newBehaviorName](
|
||||
const gd::NamedPropertyDescriptor&
|
||||
property) {
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
oldBehaviorName,
|
||||
EventsBasedBehavior::GetSharedPropertyActionName(property.GetName())),
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
newBehaviorName,
|
||||
EventsBasedBehavior::GetSharedPropertyActionName(property.GetName())));
|
||||
ExposeProjectEvents(project, actionRenamer);
|
||||
|
||||
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
oldBehaviorName,
|
||||
EventsBasedBehavior::GetSharedPropertyConditionName(property.GetName())),
|
||||
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
newBehaviorName,
|
||||
EventsBasedBehavior::GetSharedPropertyConditionName(property.GetName())));
|
||||
ExposeProjectEvents(project, conditionRenamer);
|
||||
|
||||
// Nothing to do for expression, expressions are not including the name of
|
||||
// the behavior
|
||||
};
|
||||
|
||||
// Order is important: we first rename the expressions then the instructions,
|
||||
// to avoid being unable to fetch the metadata (the types of parameters) of
|
||||
// instructions after they are renamed.
|
||||
@@ -1151,31 +1276,30 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
|
||||
|
||||
// Behavior expressions
|
||||
for (auto&& eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
|
||||
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Expression ||
|
||||
eventsFunction->GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
if (eventsFunction->IsExpression()) {
|
||||
renameBehaviorEventsFunction(*eventsFunction);
|
||||
}
|
||||
}
|
||||
|
||||
// Behavior instructions
|
||||
for (auto&& eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
|
||||
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction->GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
|
||||
renameBehaviorEventsFunction(*eventsFunction);
|
||||
}
|
||||
}
|
||||
|
||||
// Behavior properties
|
||||
auto& properties = eventsBasedBehavior.GetPropertyDescriptors();
|
||||
for (auto&& property : properties.GetInternalVector()) {
|
||||
for (auto&& property : eventsBasedBehavior.GetPropertyDescriptors().GetInternalVector()) {
|
||||
renameBehaviorProperty(*property);
|
||||
}
|
||||
for (auto&& property : eventsBasedBehavior.GetSharedPropertyDescriptors().GetInternalVector()) {
|
||||
renameBehaviorSharedProperty(*property);
|
||||
}
|
||||
|
||||
DoRenameBehavior(
|
||||
project,
|
||||
GetBehaviorFullType(eventsFunctionsExtension.GetName(), oldBehaviorName),
|
||||
GetBehaviorFullType(eventsFunctionsExtension.GetName(), newBehaviorName));
|
||||
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(), oldBehaviorName),
|
||||
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(), newBehaviorName));
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::RenameEventsBasedObject(
|
||||
@@ -1197,25 +1321,22 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
|
||||
&eventsFunctionsExtension,
|
||||
&oldObjectName,
|
||||
&newObjectName](const gd::EventsFunction& eventsFunction) {
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
if (eventsFunction.IsExpression()) {
|
||||
// Nothing to do, expressions are not including the name of the
|
||||
// object
|
||||
}
|
||||
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
|
||||
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
oldObjectName,
|
||||
eventsFunction.GetName()),
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
newObjectName,
|
||||
eventsFunction.GetName()));
|
||||
ExposeProjectEvents(project, renamer);
|
||||
} else if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::Expression ||
|
||||
eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
// Nothing to do, expressions are not including the name of the
|
||||
// object
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1227,11 +1348,11 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
|
||||
property) {
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
oldObjectName,
|
||||
EventsBasedObject::GetPropertyActionName(property.GetName())),
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
newObjectName,
|
||||
EventsBasedObject::GetPropertyActionName(property.GetName())));
|
||||
@@ -1239,11 +1360,11 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
|
||||
|
||||
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
oldObjectName,
|
||||
EventsBasedObject::GetPropertyConditionName(property.GetName())),
|
||||
GetObjectEventsFunctionFullType(
|
||||
gd::PlatformExtension::GetObjectEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
newObjectName,
|
||||
EventsBasedObject::GetPropertyConditionName(property.GetName())));
|
||||
@@ -1260,17 +1381,14 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
|
||||
|
||||
// Object expressions
|
||||
for (auto&& eventsFunction : objectEventsFunctions.GetInternalVector()) {
|
||||
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Expression ||
|
||||
eventsFunction->GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
if (eventsFunction->IsExpression()) {
|
||||
renameObjectEventsFunction(*eventsFunction);
|
||||
}
|
||||
}
|
||||
|
||||
// Object instructions
|
||||
for (auto&& eventsFunction : objectEventsFunctions.GetInternalVector()) {
|
||||
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction->GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
|
||||
renameObjectEventsFunction(*eventsFunction);
|
||||
}
|
||||
}
|
||||
@@ -1283,8 +1401,8 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
|
||||
|
||||
DoRenameObject(
|
||||
project,
|
||||
GetObjectFullType(eventsFunctionsExtension.GetName(), oldObjectName),
|
||||
GetObjectFullType(eventsFunctionsExtension.GetName(), newObjectName));
|
||||
gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(), oldObjectName),
|
||||
gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(), newObjectName));
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::DoRenameEventsFunction(
|
||||
@@ -1292,20 +1410,20 @@ void WholeProjectRefactorer::DoRenameEventsFunction(
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
const gd::String& oldFullType,
|
||||
const gd::String& newFullType) {
|
||||
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
|
||||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
|
||||
gd::InstructionsTypeRenamer renamer =
|
||||
gd::InstructionsTypeRenamer(project, oldFullType, newFullType);
|
||||
ExposeProjectEvents(project, renamer);
|
||||
} else if (eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::Expression ||
|
||||
eventsFunction.GetFunctionType() ==
|
||||
gd::EventsFunction::StringExpression) {
|
||||
// Order is important: we first rename the expressions then the instructions,
|
||||
// to avoid being unable to fetch the metadata (the types of parameters) of
|
||||
// instructions after they are renamed.
|
||||
if (eventsFunction.IsExpression()) {
|
||||
gd::ExpressionsRenamer renamer =
|
||||
gd::ExpressionsRenamer(project.GetCurrentPlatform());
|
||||
renamer.SetReplacedFreeExpression(oldFullType, newFullType);
|
||||
ExposeProjectEvents(project, renamer);
|
||||
}
|
||||
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
|
||||
gd::InstructionsTypeRenamer renamer =
|
||||
gd::InstructionsTypeRenamer(project, oldFullType, newFullType);
|
||||
ExposeProjectEvents(project, renamer);
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::DoRenameBehavior(
|
||||
|
@@ -207,6 +207,21 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
const gd::String& oldPropertyName,
|
||||
const gd::String& newPropertyName);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **before** a shared property of a behavior is
|
||||
* renamed.
|
||||
*
|
||||
* \warning Do the renaming of the specified shared property after calling
|
||||
* this. This is because the shared property is expected to have its old name
|
||||
* for the refactoring.
|
||||
*/
|
||||
static void RenameEventsBasedBehaviorSharedProperty(
|
||||
gd::Project& project,
|
||||
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
const gd::String& oldPropertyName,
|
||||
const gd::String& newPropertyName);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **before** a property of an object is
|
||||
* renamed.
|
||||
|
@@ -10,8 +10,10 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
AbstractEventsBasedEntity::AbstractEventsBasedEntity(const gd::String& _name)
|
||||
: name(_name), fullName("") {}
|
||||
AbstractEventsBasedEntity::AbstractEventsBasedEntity(
|
||||
const gd::String& _name,
|
||||
gd::EventsFunctionsContainer::FunctionOwner functionContainerSource)
|
||||
: name(_name), fullName(""), eventsFunctionsContainer(functionContainerSource) {}
|
||||
|
||||
void AbstractEventsBasedEntity::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("description", description);
|
||||
|
@@ -29,7 +29,9 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API AbstractEventsBasedEntity {
|
||||
public:
|
||||
AbstractEventsBasedEntity(const gd::String& _name);
|
||||
AbstractEventsBasedEntity(
|
||||
const gd::String& _name,
|
||||
gd::EventsFunctionsContainer::FunctionOwner functionContainerSource);
|
||||
virtual ~AbstractEventsBasedEntity(){};
|
||||
|
||||
/**
|
||||
|
@@ -13,7 +13,8 @@ namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Base class used to represents a behavior that can be applied to an
|
||||
* object. It stores the content (i.e: the properties) of a behavior of an object.
|
||||
* object. It stores the content (i.e: the properties) of a behavior of an object
|
||||
* and forward the properties related functions to Javascript with Emscripten.
|
||||
*
|
||||
* \see gd::BehaviorsSharedData
|
||||
* \see gd::Object
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Project/CustomConfigurationHelper.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
@@ -21,52 +22,26 @@ CustomBehavior *CustomBehavior::Clone() const {
|
||||
return clone;
|
||||
}
|
||||
|
||||
void CustomBehavior::InitializeContent(gd::SerializerElement &behaviorContent) {
|
||||
if (!project.HasEventsBasedBehavior(GetTypeName())) {
|
||||
return;
|
||||
}
|
||||
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
|
||||
const auto &properties = eventsBasedBehavior.GetPropertyDescriptors();
|
||||
|
||||
gd::CustomConfigurationHelper::InitializeContent(properties, behaviorContent);
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> CustomBehavior::GetProperties(
|
||||
const gd::SerializerElement &behaviorContent) const {
|
||||
auto behaviorProperties = std::map<gd::String, gd::PropertyDescriptor>();
|
||||
if (!project.HasEventsBasedBehavior(GetTypeName())) {
|
||||
auto behaviorProperties = std::map<gd::String, gd::PropertyDescriptor>();
|
||||
return behaviorProperties;
|
||||
}
|
||||
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
|
||||
const auto &properties = eventsBasedBehavior.GetPropertyDescriptors();
|
||||
|
||||
for (auto &property : properties.GetInternalVector()) {
|
||||
const auto &propertyName = property->GetName();
|
||||
const auto &propertyType = property->GetType();
|
||||
|
||||
// TODO Move this into a PropertyDescriptor copy method.
|
||||
auto &newProperty = behaviorProperties[propertyName]
|
||||
.SetType(property->GetType())
|
||||
.SetDescription(property->GetDescription())
|
||||
.SetGroup(property->GetGroup())
|
||||
.SetLabel(property->GetLabel())
|
||||
.SetValue(property->GetValue())
|
||||
.SetHidden(property->IsHidden());
|
||||
|
||||
for (auto &extraInfo : property->GetExtraInfo()) {
|
||||
newProperty.AddExtraInfo(extraInfo);
|
||||
}
|
||||
|
||||
if (behaviorContent.HasChild(propertyName)) {
|
||||
if (propertyType == "String" || propertyType == "Choice" ||
|
||||
propertyType == "Color" || propertyType == "Behavior") {
|
||||
newProperty.SetValue(
|
||||
behaviorContent.GetChild(propertyName).GetStringValue());
|
||||
} else if (propertyType == "Number") {
|
||||
newProperty.SetValue(gd::String::From(
|
||||
behaviorContent.GetChild(propertyName).GetDoubleValue()));
|
||||
} else if (propertyType == "Boolean") {
|
||||
newProperty.SetValue(
|
||||
behaviorContent.GetChild(propertyName).GetBoolValue() ? "true"
|
||||
: "false");
|
||||
}
|
||||
} else {
|
||||
// No value was serialized for this property. `newProperty`
|
||||
// will have the default value coming from `enumeratedProperty`.
|
||||
}
|
||||
}
|
||||
|
||||
return behaviorProperties;
|
||||
return gd::CustomConfigurationHelper::GetProperties(properties, behaviorContent);
|
||||
}
|
||||
|
||||
bool CustomBehavior::UpdateProperty(gd::SerializerElement &behaviorContent,
|
||||
@@ -77,43 +52,10 @@ bool CustomBehavior::UpdateProperty(gd::SerializerElement &behaviorContent,
|
||||
}
|
||||
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
|
||||
const auto &properties = eventsBasedBehavior.GetPropertyDescriptors();
|
||||
if (!properties.Has(propertyName)) {
|
||||
return false;
|
||||
}
|
||||
const auto &property = properties.Get(propertyName);
|
||||
|
||||
auto &element = behaviorContent.AddChild(propertyName);
|
||||
const gd::String &propertyType = property.GetType();
|
||||
|
||||
if (propertyType == "String" || propertyType == "Choice" ||
|
||||
propertyType == "Color" || propertyType == "Behavior") {
|
||||
element.SetStringValue(newValue);
|
||||
} else if (propertyType == "Number") {
|
||||
element.SetDoubleValue(newValue.To<double>());
|
||||
} else if (propertyType == "Boolean") {
|
||||
element.SetBoolValue(newValue == "1");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CustomBehavior::InitializeContent(gd::SerializerElement &behaviorContent) {
|
||||
if (!project.HasEventsBasedBehavior(GetTypeName())) {
|
||||
return;
|
||||
}
|
||||
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
|
||||
const auto &properties = eventsBasedBehavior.GetPropertyDescriptors();
|
||||
for (auto &&property : properties.GetInternalVector()) {
|
||||
auto &element = behaviorContent.AddChild(property->GetName());
|
||||
auto propertyType = property->GetType();
|
||||
|
||||
if (propertyType == "String" || propertyType == "Choice" ||
|
||||
propertyType == "Color" || propertyType == "Behavior") {
|
||||
element.SetStringValue(property->GetValue());
|
||||
} else if (propertyType == "Number") {
|
||||
element.SetDoubleValue(property->GetValue().To<double>());
|
||||
} else if (propertyType == "Boolean") {
|
||||
element.SetBoolValue(property->GetValue() == "true");
|
||||
}
|
||||
}
|
||||
return gd::CustomConfigurationHelper::UpdateProperty(
|
||||
properties,
|
||||
behaviorContent,
|
||||
propertyName,
|
||||
newValue);
|
||||
}
|
||||
|
@@ -17,8 +17,7 @@ using namespace gd;
|
||||
|
||||
namespace gd {
|
||||
/**
|
||||
* \brief A gd::Behavior that stores its content in JSON and forward the
|
||||
* properties related functions to Javascript with Emscripten.
|
||||
* \brief A gd::Behavior that stores its content in JSON.
|
||||
*/
|
||||
class CustomBehavior : public gd::Behavior {
|
||||
public:
|
||||
@@ -34,13 +33,11 @@ public:
|
||||
using Behavior::UpdateProperty;
|
||||
|
||||
protected:
|
||||
virtual std::map<gd::String, gd::PropertyDescriptor>
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
GetProperties(const gd::SerializerElement &behaviorContent) const override;
|
||||
virtual bool UpdateProperty(gd::SerializerElement &behaviorContent,
|
||||
const gd::String &name,
|
||||
const gd::String &value) override;
|
||||
virtual void
|
||||
InitializeContent(gd::SerializerElement &behaviorContent) override;
|
||||
bool UpdateProperty(gd::SerializerElement &behaviorContent,
|
||||
const gd::String &name, const gd::String &value) override;
|
||||
void InitializeContent(gd::SerializerElement &behaviorContent) override;
|
||||
|
||||
private:
|
||||
const Project &project; ///< The project is used to get the
|
||||
|
61
Core/GDCore/Project/CustomBehaviorsSharedData.cpp
Normal file
61
Core/GDCore/Project/CustomBehaviorsSharedData.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "CustomBehaviorsSharedData.h"
|
||||
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Project/CustomConfigurationHelper.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
using namespace gd;
|
||||
|
||||
CustomBehaviorsSharedData *CustomBehaviorsSharedData::Clone() const {
|
||||
CustomBehaviorsSharedData *clone = new CustomBehaviorsSharedData(*this);
|
||||
return clone;
|
||||
}
|
||||
|
||||
void CustomBehaviorsSharedData::InitializeContent(gd::SerializerElement &behaviorContent) {
|
||||
if (!project.HasEventsBasedBehavior(GetTypeName())) {
|
||||
return;
|
||||
}
|
||||
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
|
||||
const auto &properties = eventsBasedBehavior.GetSharedPropertyDescriptors();
|
||||
|
||||
gd::CustomConfigurationHelper::InitializeContent(properties, behaviorContent);
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> CustomBehaviorsSharedData::GetProperties(
|
||||
const gd::SerializerElement &behaviorContent) const {
|
||||
if (!project.HasEventsBasedBehavior(GetTypeName())) {
|
||||
auto behaviorProperties = std::map<gd::String, gd::PropertyDescriptor>();
|
||||
return behaviorProperties;
|
||||
}
|
||||
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
|
||||
const auto &properties = eventsBasedBehavior.GetSharedPropertyDescriptors();
|
||||
|
||||
return gd::CustomConfigurationHelper::GetProperties(properties, behaviorContent);
|
||||
}
|
||||
|
||||
bool CustomBehaviorsSharedData::UpdateProperty(gd::SerializerElement &behaviorContent,
|
||||
const gd::String &propertyName,
|
||||
const gd::String &newValue) {
|
||||
if (!project.HasEventsBasedBehavior(GetTypeName())) {
|
||||
return false;
|
||||
}
|
||||
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
|
||||
const auto &properties = eventsBasedBehavior.GetSharedPropertyDescriptors();
|
||||
|
||||
return gd::CustomConfigurationHelper::UpdateProperty(
|
||||
properties,
|
||||
behaviorContent,
|
||||
propertyName,
|
||||
newValue);
|
||||
}
|
46
Core/GDCore/Project/CustomBehaviorsSharedData.h
Normal file
46
Core/GDCore/Project/CustomBehaviorsSharedData.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_CUSTOMBEHAVIORSSHAREDDATA_H
|
||||
#define GDCORE_CUSTOMBEHAVIORSSHAREDDATA_H
|
||||
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
using namespace gd;
|
||||
|
||||
namespace gd {
|
||||
/**
|
||||
* \brief A gd::BehaviorsSharedData that stores its content in JSON.
|
||||
*/
|
||||
class CustomBehaviorsSharedData : public gd::BehaviorsSharedData {
|
||||
public:
|
||||
CustomBehaviorsSharedData(const gd::String &name, const Project &project_,
|
||||
const gd::String &fullType)
|
||||
: BehaviorsSharedData(name, fullType), project(project_) {}
|
||||
CustomBehaviorsSharedData *Clone() const override;
|
||||
|
||||
using BehaviorsSharedData::GetProperties;
|
||||
using BehaviorsSharedData::InitializeContent;
|
||||
using BehaviorsSharedData::UpdateProperty;
|
||||
|
||||
protected:
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
GetProperties(const gd::SerializerElement &behaviorContent) const override;
|
||||
bool UpdateProperty(gd::SerializerElement &behaviorContent,
|
||||
const gd::String &name, const gd::String &value) override;
|
||||
void InitializeContent(gd::SerializerElement &behaviorContent) override;
|
||||
|
||||
private:
|
||||
const Project &project; ///< The project is used to get the
|
||||
///< EventBasedBehavior from the fullType.
|
||||
};
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_CUSTOMBEHAVIORSSHAREDDATA_H
|
104
Core/GDCore/Project/CustomConfigurationHelper.cpp
Normal file
104
Core/GDCore/Project/CustomConfigurationHelper.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "CustomConfigurationHelper.h"
|
||||
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
using namespace gd;
|
||||
|
||||
void CustomConfigurationHelper::InitializeContent(
|
||||
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
|
||||
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") {
|
||||
element.SetStringValue(property->GetValue());
|
||||
} else if (propertyType == "Number") {
|
||||
element.SetDoubleValue(property->GetValue().To<double>());
|
||||
} else if (propertyType == "Boolean") {
|
||||
element.SetBoolValue(property->GetValue() == "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> CustomConfigurationHelper::GetProperties(
|
||||
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
|
||||
const gd::SerializerElement &configurationContent) {
|
||||
auto behaviorProperties = std::map<gd::String, gd::PropertyDescriptor>();
|
||||
|
||||
for (auto &property : properties.GetInternalVector()) {
|
||||
const auto &propertyName = property->GetName();
|
||||
const auto &propertyType = property->GetType();
|
||||
|
||||
// TODO Move this into a PropertyDescriptor copy method.
|
||||
auto &newProperty = behaviorProperties[propertyName]
|
||||
.SetType(property->GetType())
|
||||
.SetDescription(property->GetDescription())
|
||||
.SetGroup(property->GetGroup())
|
||||
.SetLabel(property->GetLabel())
|
||||
.SetValue(property->GetValue())
|
||||
.SetHidden(property->IsHidden());
|
||||
|
||||
for (auto &extraInfo : property->GetExtraInfo()) {
|
||||
newProperty.AddExtraInfo(extraInfo);
|
||||
}
|
||||
|
||||
if (configurationContent.HasChild(propertyName)) {
|
||||
if (propertyType == "String" || propertyType == "Choice" ||
|
||||
propertyType == "Color" || propertyType == "Behavior") {
|
||||
newProperty.SetValue(
|
||||
configurationContent.GetChild(propertyName).GetStringValue());
|
||||
} else if (propertyType == "Number") {
|
||||
newProperty.SetValue(gd::String::From(
|
||||
configurationContent.GetChild(propertyName).GetDoubleValue()));
|
||||
} else if (propertyType == "Boolean") {
|
||||
newProperty.SetValue(
|
||||
configurationContent.GetChild(propertyName).GetBoolValue() ? "true"
|
||||
: "false");
|
||||
}
|
||||
} else {
|
||||
// No value was serialized for this property. `newProperty`
|
||||
// will have the default value coming from `enumeratedProperty`.
|
||||
}
|
||||
}
|
||||
|
||||
return behaviorProperties;
|
||||
}
|
||||
|
||||
bool CustomConfigurationHelper::UpdateProperty(
|
||||
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
|
||||
gd::SerializerElement &configurationContent,
|
||||
const gd::String &propertyName,
|
||||
const gd::String &newValue) {
|
||||
if (!properties.Has(propertyName)) {
|
||||
return false;
|
||||
}
|
||||
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") {
|
||||
element.SetStringValue(newValue);
|
||||
} else if (propertyType == "Number") {
|
||||
element.SetDoubleValue(newValue.To<double>());
|
||||
} else if (propertyType == "Boolean") {
|
||||
element.SetBoolValue(newValue == "1");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
43
Core/GDCore/Project/CustomConfigurationHelper.h
Normal file
43
Core/GDCore/Project/CustomConfigurationHelper.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_CUSTOMCONFIGURATIONHELPER_H
|
||||
#define GDCORE_CUSTOMCONFIGURATIONHELPER_H
|
||||
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
using namespace gd;
|
||||
|
||||
namespace gd {
|
||||
/**
|
||||
* \brief Helper functions that gd::CustomBehavior and gd::CustomBehaviorsSharedData use to
|
||||
* store their content in JSON.
|
||||
*/
|
||||
class CustomConfigurationHelper {
|
||||
public:
|
||||
CustomConfigurationHelper() {}
|
||||
|
||||
static void InitializeContent(
|
||||
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
|
||||
gd::SerializerElement &behaviorContent);
|
||||
|
||||
static std::map<gd::String, gd::PropertyDescriptor> GetProperties(
|
||||
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
|
||||
const gd::SerializerElement &behaviorContent);
|
||||
|
||||
static bool UpdateProperty(
|
||||
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
|
||||
gd::SerializerElement &behaviorContent,
|
||||
const gd::String &name,
|
||||
const gd::String &value);
|
||||
};
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_CUSTOMCONFIGURATIONHELPER_H
|
@@ -12,6 +12,7 @@
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
#include "GDCore/Project/CustomConfigurationHelper.h"
|
||||
|
||||
using namespace gd;
|
||||
|
||||
@@ -22,16 +23,14 @@ void CustomObjectConfiguration::Init(const gd::CustomObjectConfiguration& object
|
||||
// There is no default copy for a map of unique_ptr like childObjectConfigurations.
|
||||
childObjectConfigurations.clear();
|
||||
for (auto& it : objectConfiguration.childObjectConfigurations) {
|
||||
childObjectConfigurations[it.first] =
|
||||
gd::make_unique<gd::ObjectConfiguration>(*it.second);
|
||||
childObjectConfigurations[it.first] = it.second->Clone();
|
||||
}
|
||||
}
|
||||
|
||||
gd::ObjectConfiguration CustomObjectConfiguration::badObjectConfiguration;
|
||||
|
||||
std::unique_ptr<gd::ObjectConfiguration> CustomObjectConfiguration::Clone() const {
|
||||
CustomObjectConfiguration* clone = new CustomObjectConfiguration(*this);
|
||||
return std::unique_ptr<gd::ObjectConfiguration>(clone);
|
||||
return gd::make_unique<gd::CustomObjectConfiguration>(*this);
|
||||
}
|
||||
|
||||
gd::ObjectConfiguration &CustomObjectConfiguration::GetChildObjectConfiguration(const gd::String &objectName) {
|
||||
@@ -51,7 +50,7 @@ gd::ObjectConfiguration &CustomObjectConfiguration::GetChildObjectConfiguration(
|
||||
if (configurationPosition == childObjectConfigurations.end()) {
|
||||
childObjectConfigurations.insert(std::make_pair(
|
||||
objectName,
|
||||
project->CreateObjectConfiguration(childObject.GetType())));
|
||||
childObject.GetConfiguration().Clone()));
|
||||
return *(childObjectConfigurations[objectName]);
|
||||
}
|
||||
else {
|
||||
@@ -69,50 +68,7 @@ std::map<gd::String, gd::PropertyDescriptor> CustomObjectConfiguration::GetPrope
|
||||
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
|
||||
const auto &properties = eventsBasedObject.GetPropertyDescriptors();
|
||||
|
||||
for (auto &property : properties.GetInternalVector()) {
|
||||
const auto &propertyName = property->GetName();
|
||||
const auto &propertyType = property->GetType();
|
||||
|
||||
// TODO Move this into a PropertyDescriptor copy method.
|
||||
auto &newProperty = objectProperties[propertyName]
|
||||
.SetType(property->GetType())
|
||||
.SetDescription(property->GetDescription())
|
||||
.SetGroup(property->GetGroup())
|
||||
.SetLabel(property->GetLabel())
|
||||
.SetValue(property->GetValue())
|
||||
.SetHidden(property->IsHidden());
|
||||
|
||||
for (auto &extraInfo : property->GetExtraInfo()) {
|
||||
newProperty.AddExtraInfo(extraInfo);
|
||||
}
|
||||
|
||||
if (objectContent.HasChild(propertyName)) {
|
||||
if (
|
||||
propertyType == "String" ||
|
||||
propertyType == "Choice" ||
|
||||
propertyType == "Color"
|
||||
) {
|
||||
newProperty.SetValue(
|
||||
objectContent.GetChild(propertyName).GetStringValue()
|
||||
);
|
||||
} else if (propertyType == "Number") {
|
||||
newProperty.SetValue(
|
||||
gd::String::From(objectContent.GetChild(propertyName).GetDoubleValue())
|
||||
);
|
||||
} else if (propertyType == "Boolean") {
|
||||
newProperty.SetValue(
|
||||
objectContent.GetChild(propertyName).GetBoolValue()
|
||||
? "true"
|
||||
: "false"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// No value was serialized for this property. `newProperty`
|
||||
// will have the default value coming from `enumeratedProperty`.
|
||||
}
|
||||
}
|
||||
|
||||
return objectProperties;
|
||||
return gd::CustomConfigurationHelper::GetProperties(properties, objectContent);
|
||||
}
|
||||
|
||||
bool CustomObjectConfiguration::UpdateProperty(const gd::String& propertyName,
|
||||
@@ -122,27 +78,12 @@ bool CustomObjectConfiguration::UpdateProperty(const gd::String& propertyName,
|
||||
}
|
||||
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
|
||||
const auto &properties = eventsBasedObject.GetPropertyDescriptors();
|
||||
if (!properties.Has(propertyName)) {
|
||||
return false;
|
||||
}
|
||||
const auto &property = properties.Get(propertyName);
|
||||
|
||||
auto &element = objectContent.AddChild(propertyName);
|
||||
const gd::String &propertyType = property.GetType();
|
||||
|
||||
if (
|
||||
propertyType == "String" ||
|
||||
propertyType == "Choice" ||
|
||||
propertyType == "Color"
|
||||
) {
|
||||
element.SetStringValue(newValue);
|
||||
} else if (propertyType == "Number") {
|
||||
element.SetDoubleValue(newValue.To<double>());
|
||||
} else if (propertyType == "Boolean") {
|
||||
element.SetBoolValue(newValue == "1");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
return gd::CustomConfigurationHelper::UpdateProperty(
|
||||
properties,
|
||||
objectContent,
|
||||
propertyName,
|
||||
newValue);
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
|
@@ -110,6 +110,11 @@ class GD_CORE_API EffectsContainer {
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
|
||||
/**
|
||||
* \brief Clear all effects of the container.
|
||||
*/
|
||||
inline void Clear() { effects.clear(); }
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<gd::Effect>> effects;
|
||||
static Effect badEffect;
|
||||
|
@@ -11,17 +11,27 @@
|
||||
namespace gd {
|
||||
|
||||
EventsBasedBehavior::EventsBasedBehavior()
|
||||
: AbstractEventsBasedEntity("MyBehavior") {}
|
||||
: AbstractEventsBasedEntity(
|
||||
"MyBehavior",
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Behavior) {}
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -73,6 +73,58 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the behavior is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
bool IsPrivate() { return isPrivate; }
|
||||
|
||||
/**
|
||||
* \brief Set that the behavior is private - it can't be used outside of its
|
||||
* extension.
|
||||
*/
|
||||
EventsBasedBehavior& SetPrivate(bool _isPrivate) {
|
||||
isPrivate = _isPrivate;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the list of shared properties.
|
||||
*/
|
||||
SerializableWithNameList<NamedPropertyDescriptor>& GetSharedPropertyDescriptors() {
|
||||
return sharedPropertyDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return a const reference to the list of shared properties.
|
||||
*/
|
||||
const SerializableWithNameList<NamedPropertyDescriptor>& GetSharedPropertyDescriptors()
|
||||
const {
|
||||
return sharedPropertyDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the name of the action to change a shared property.
|
||||
*/
|
||||
static gd::String GetSharedPropertyActionName(const gd::String &propertyName) {
|
||||
return "SetSharedProperty" + propertyName;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Get the name of the condition to compare a shared property.
|
||||
*/
|
||||
static gd::String GetSharedPropertyConditionName(const gd::String &propertyName) {
|
||||
return "SharedProperty" + propertyName;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Get the name of the expression to get a shared property.
|
||||
*/
|
||||
static gd::String
|
||||
GetSharedPropertyExpressionName(const gd::String &propertyName) {
|
||||
return "SharedProperty" + propertyName;
|
||||
};
|
||||
|
||||
void SerializeTo(SerializerElement& element) const override;
|
||||
|
||||
void UnserializeFrom(gd::Project& project,
|
||||
@@ -80,6 +132,8 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
|
||||
|
||||
private:
|
||||
gd::String objectType;
|
||||
bool isPrivate = false;
|
||||
SerializableWithNameList<NamedPropertyDescriptor> sharedPropertyDescriptors;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -10,7 +10,10 @@
|
||||
namespace gd {
|
||||
|
||||
EventsBasedObject::EventsBasedObject()
|
||||
: AbstractEventsBasedEntity("MyObject"), ObjectsContainer() {
|
||||
: AbstractEventsBasedEntity(
|
||||
"MyObject",
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Object),
|
||||
ObjectsContainer() {
|
||||
}
|
||||
|
||||
EventsBasedObject::~EventsBasedObject() {}
|
||||
@@ -23,12 +26,16 @@ EventsBasedObject::EventsBasedObject(const gd::EventsBasedObject &_eventBasedObj
|
||||
}
|
||||
|
||||
void EventsBasedObject::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("defaultName", defaultName);
|
||||
|
||||
AbstractEventsBasedEntity::SerializeTo(element);
|
||||
SerializeObjectsTo(element.AddChild("objects"));
|
||||
}
|
||||
|
||||
void EventsBasedObject::UnserializeFrom(gd::Project& project,
|
||||
const SerializerElement& element) {
|
||||
defaultName = element.GetStringAttribute("defaultName");
|
||||
|
||||
AbstractEventsBasedEntity::UnserializeFrom(project, element);
|
||||
UnserializeObjectsFrom(project, element.GetChild("objects"));
|
||||
}
|
||||
|
@@ -38,6 +38,19 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public Ob
|
||||
*/
|
||||
EventsBasedObject* Clone() const { return new EventsBasedObject(*this); };
|
||||
|
||||
/**
|
||||
* \brief Get the default name for created objects.
|
||||
*/
|
||||
const gd::String& GetDefaultName() const { return defaultName; };
|
||||
|
||||
/**
|
||||
* \brief Set the default name for created objects.
|
||||
*/
|
||||
EventsBasedObject& SetDefaultName(const gd::String& defaultName_) {
|
||||
defaultName = defaultName_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
EventsBasedObject& SetDescription(const gd::String& description_) override {
|
||||
AbstractEventsBasedEntity::SetDescription(description_);
|
||||
return *this;
|
||||
@@ -65,6 +78,7 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public Ob
|
||||
const SerializerElement& element) override;
|
||||
|
||||
private:
|
||||
gd::String defaultName;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -7,29 +7,96 @@
|
||||
#include "EventsFunction.h"
|
||||
#include <vector>
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Project/EventsFunctionsContainer.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
EventsFunction::EventsFunction() : functionType(Action) {}
|
||||
EventsFunction::EventsFunction() : functionType(Action) {
|
||||
expressionType.SetName("expression");
|
||||
}
|
||||
|
||||
const std::vector<gd::ParameterMetadata>& EventsFunction::GetParametersForEvents(
|
||||
const gd::EventsFunctionsContainer& functionsContainer) const {
|
||||
if (functionType != FunctionType::ActionWithOperator) {
|
||||
// For most function types, the parameters are specified in the function.
|
||||
return parameters;
|
||||
}
|
||||
// For ActionWithOperator, the parameters are auto generated.
|
||||
actionWithOperationParameters.clear();
|
||||
if (!functionsContainer.HasEventsFunctionNamed(getterName)) {
|
||||
return actionWithOperationParameters;
|
||||
}
|
||||
const auto& expression = functionsContainer.GetEventsFunction(getterName);
|
||||
const auto& expressionParameters = expression.parameters;
|
||||
const auto functionsSource = functionsContainer.GetOwner();
|
||||
const int expressionValueParameterIndex =
|
||||
functionsSource == gd::EventsFunctionsContainer::FunctionOwner::Behavior ?
|
||||
2 :
|
||||
functionsSource == gd::EventsFunctionsContainer::FunctionOwner::Object ?
|
||||
1 :
|
||||
0;
|
||||
|
||||
for (size_t i = 0;
|
||||
i < expressionValueParameterIndex && i < expressionParameters.size();
|
||||
i++)
|
||||
{
|
||||
actionWithOperationParameters.push_back(expressionParameters[i]);
|
||||
}
|
||||
gd::ParameterMetadata parameterMetadata;
|
||||
parameterMetadata.SetName("Value").SetValueTypeMetadata(expression.expressionType);
|
||||
actionWithOperationParameters.push_back(parameterMetadata);
|
||||
for (size_t i = expressionValueParameterIndex;
|
||||
i < expressionParameters.size();
|
||||
i++)
|
||||
{
|
||||
actionWithOperationParameters.push_back(expressionParameters[i]);
|
||||
}
|
||||
|
||||
return actionWithOperationParameters;
|
||||
}
|
||||
|
||||
void EventsFunction::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("name", name);
|
||||
element.SetAttribute("fullName", fullName);
|
||||
element.SetAttribute("description", description);
|
||||
if (!description.empty()) {
|
||||
element.SetAttribute("description", description);
|
||||
}
|
||||
element.SetAttribute("sentence", sentence);
|
||||
element.SetAttribute("group", group);
|
||||
element.SetBoolAttribute("private", isPrivate);
|
||||
if (!group.empty()) {
|
||||
element.SetAttribute("group", group);
|
||||
}
|
||||
if (!getterName.empty()) {
|
||||
element.SetAttribute("getterName", getterName);
|
||||
}
|
||||
if (isPrivate) {
|
||||
element.SetBoolAttribute("private", isPrivate);
|
||||
}
|
||||
events.SerializeTo(element.AddChild("events"));
|
||||
|
||||
gd::String functionTypeStr = "Action";
|
||||
if (functionType == Condition)
|
||||
functionTypeStr = "Condition";
|
||||
else if (functionType == Expression)
|
||||
else if (functionType == Expression) {
|
||||
functionTypeStr = "Expression";
|
||||
else if (functionType == StringExpression)
|
||||
functionTypeStr = "StringExpression";
|
||||
|
||||
// Compatibility code for version 5.1.147 and older.
|
||||
// There is no longer distinction between number and string in the function
|
||||
// type directly. The expression type is now used for this.
|
||||
if (expressionType.IsString()) {
|
||||
functionTypeStr = "StringExpression";
|
||||
}
|
||||
}
|
||||
else if (functionType == ExpressionAndCondition) {
|
||||
functionTypeStr = "ExpressionAndCondition";
|
||||
}
|
||||
else if (functionType == ActionWithOperator)
|
||||
functionTypeStr = "ActionWithOperator";
|
||||
element.SetAttribute("functionType", functionTypeStr);
|
||||
|
||||
if (this->IsExpression()) {
|
||||
expressionType.SerializeTo(element.AddChild("expressionType"));
|
||||
}
|
||||
gd::SerializerElement& parametersElement = element.AddChild("parameters");
|
||||
parametersElement.ConsiderAsArrayOf("parameter");
|
||||
for (const auto& parameter : parameters) {
|
||||
@@ -46,16 +113,32 @@ void EventsFunction::UnserializeFrom(gd::Project& project,
|
||||
description = element.GetStringAttribute("description");
|
||||
sentence = element.GetStringAttribute("sentence");
|
||||
group = element.GetStringAttribute("group");
|
||||
getterName = element.GetStringAttribute("getterName");
|
||||
isPrivate = element.GetBoolAttribute("private");
|
||||
events.UnserializeFrom(project, element.GetChild("events"));
|
||||
|
||||
gd::String functionTypeStr = element.GetStringAttribute("functionType");
|
||||
|
||||
if (functionTypeStr == "Condition")
|
||||
functionType = Condition;
|
||||
else if (functionTypeStr == "Expression")
|
||||
else if (functionTypeStr == "Expression" || functionTypeStr == "StringExpression") {
|
||||
functionType = Expression;
|
||||
else if (functionTypeStr == "StringExpression")
|
||||
functionType = StringExpression;
|
||||
if (element.HasChild("expressionType")) {
|
||||
expressionType.UnserializeFrom(element.GetChild("expressionType"));
|
||||
}
|
||||
else {
|
||||
// Compatibility code for version 5.1.147 and older.
|
||||
// There is no longer distinction between number and string in the function
|
||||
// type directly. The expression type is now used for this.
|
||||
expressionType.SetName(functionTypeStr == "StringExpression" ? "string" : "expression");
|
||||
}
|
||||
}
|
||||
else if (functionTypeStr == "ExpressionAndCondition") {
|
||||
functionType = ExpressionAndCondition;
|
||||
expressionType.UnserializeFrom(element.GetChild("expressionType"));
|
||||
}
|
||||
else if (functionTypeStr == "ActionWithOperator")
|
||||
functionType = ActionWithOperator;
|
||||
else
|
||||
functionType = Action;
|
||||
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Project/ObjectGroupsContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
|
||||
// TODO: In theory (for separation of concerns between Project and
|
||||
// extensions/events), this include should be removed and gd::ParameterMetadata
|
||||
// replaced by a new gd::EventsFunctionParameter class.
|
||||
@@ -19,6 +20,7 @@
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
class Project;
|
||||
class EventsFunctionsContainer;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -115,7 +117,45 @@ class GD_CORE_API EventsFunction {
|
||||
return *this;
|
||||
}
|
||||
|
||||
enum FunctionType { Action, Condition, Expression, StringExpression };
|
||||
/**
|
||||
* \brief Get the name of the ExpressionAndCondition to use as an operand
|
||||
* that is defined in the editor.
|
||||
*/
|
||||
const gd::String& GetGetterName() const { return getterName; };
|
||||
|
||||
/**
|
||||
* \brief Set the name of the ExpressionAndCondition to use as an operand
|
||||
* that is defined in the editor.
|
||||
*/
|
||||
EventsFunction& SetGetterName(const gd::String& getterName_) {
|
||||
getterName = getterName_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the type of the expression
|
||||
*/
|
||||
EventsFunction& SetExpressionType(const gd::ValueTypeMetadata& type) {
|
||||
expressionType = type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the type of the expression
|
||||
*/
|
||||
const gd::ValueTypeMetadata& GetExpressionType() const { return expressionType; }
|
||||
|
||||
/**
|
||||
* \brief Get the type of the expression
|
||||
*/
|
||||
gd::ValueTypeMetadata& GetExpressionType() { return expressionType; }
|
||||
|
||||
enum FunctionType {
|
||||
Action,
|
||||
Condition,
|
||||
Expression,
|
||||
ExpressionAndCondition,
|
||||
ActionWithOperator };
|
||||
|
||||
/**
|
||||
* \brief Set the type of the function
|
||||
@@ -123,12 +163,40 @@ class GD_CORE_API EventsFunction {
|
||||
EventsFunction& SetFunctionType(FunctionType type) {
|
||||
functionType = type;
|
||||
return *this;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the type of the function
|
||||
*/
|
||||
FunctionType GetFunctionType() const { return functionType; };
|
||||
FunctionType GetFunctionType() const { return functionType; }
|
||||
|
||||
/**
|
||||
* \brief Return true if the function is an action.
|
||||
*/
|
||||
bool IsAction() const {
|
||||
return functionType == gd::EventsFunction::Action ||
|
||||
functionType == gd::EventsFunction::ActionWithOperator;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the function is an expression.
|
||||
*
|
||||
* Note that a function can be both an expression and a condition.
|
||||
*/
|
||||
bool IsExpression() const {
|
||||
return functionType == gd::EventsFunction::Expression ||
|
||||
functionType == gd::EventsFunction::ExpressionAndCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the function is a condition.
|
||||
*
|
||||
* Note that a function can be both an expression and a condition.
|
||||
*/
|
||||
bool IsCondition() const {
|
||||
return functionType == gd::EventsFunction::Condition ||
|
||||
functionType == gd::EventsFunction::ExpressionAndCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns true if the function is private.
|
||||
@@ -154,7 +222,20 @@ class GD_CORE_API EventsFunction {
|
||||
gd::EventsList& GetEvents() { return events; };
|
||||
|
||||
/**
|
||||
* \brief Return the parameters of the function.
|
||||
* \brief Return the parameters of the function that are used in the events.
|
||||
*
|
||||
* \note During code/extension generation, new parameters are added
|
||||
* to the generated function, like "runtimeScene" and "eventsFunctionContext".
|
||||
* This should be transparent to the user.
|
||||
*/
|
||||
const std::vector<gd::ParameterMetadata>& GetParametersForEvents(
|
||||
const gd::EventsFunctionsContainer& functionsContainer) const;
|
||||
|
||||
/**
|
||||
* \brief Return the parameters of the function that are filled in the editor.
|
||||
*
|
||||
* \note They won't be used for ActionWithOperator, but they need to be kept
|
||||
* to avoid to loose them when the function type is changed.
|
||||
*
|
||||
* \note During code/extension generation, new parameters are added
|
||||
* to the generated function, like "runtimeScene" and "eventsFunctionContext".
|
||||
@@ -202,9 +283,12 @@ class GD_CORE_API EventsFunction {
|
||||
gd::String description;
|
||||
gd::String sentence;
|
||||
gd::String group;
|
||||
gd::String getterName;
|
||||
gd::ValueTypeMetadata expressionType;
|
||||
gd::EventsList events;
|
||||
FunctionType functionType;
|
||||
std::vector<gd::ParameterMetadata> parameters;
|
||||
mutable std::vector<gd::ParameterMetadata> actionWithOperationParameters;
|
||||
gd::ObjectGroupsContainer objectGroups;
|
||||
bool isPrivate = false;
|
||||
};
|
||||
|
@@ -25,7 +25,24 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API EventsFunctionsContainer
|
||||
: private SerializableWithNameList<gd::EventsFunction> {
|
||||
public:
|
||||
public:
|
||||
enum FunctionOwner {
|
||||
Extension,
|
||||
Object,
|
||||
Behavior};
|
||||
|
||||
EventsFunctionsContainer(FunctionOwner source_) : owner(source_) {}
|
||||
|
||||
/**
|
||||
* \brief Get the source of the function container.
|
||||
*
|
||||
* \note For instance, it can be useful to handle specific parameters for
|
||||
* behaviors.
|
||||
*/
|
||||
FunctionOwner GetOwner() const {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/** \name Events Functions management
|
||||
*/
|
||||
///@{
|
||||
@@ -139,6 +156,9 @@ class GD_CORE_API EventsFunctionsContainer
|
||||
void Init(const gd::EventsFunctionsContainer& other) {
|
||||
return SerializableWithNameList<gd::EventsFunction>::Init(other);
|
||||
};
|
||||
|
||||
private:
|
||||
FunctionOwner owner;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -13,10 +13,14 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
EventsFunctionsExtension::EventsFunctionsExtension() {}
|
||||
EventsFunctionsExtension::EventsFunctionsExtension() :
|
||||
gd::EventsFunctionsContainer(
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Extension) {}
|
||||
|
||||
EventsFunctionsExtension::EventsFunctionsExtension(
|
||||
const EventsFunctionsExtension& other) {
|
||||
const EventsFunctionsExtension& other) :
|
||||
gd::EventsFunctionsContainer(
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Extension) {
|
||||
Init(other);
|
||||
}
|
||||
|
||||
@@ -50,7 +54,7 @@ void EventsFunctionsExtension::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("version", version);
|
||||
element.SetAttribute("extensionNamespace", extensionNamespace);
|
||||
element.SetAttribute("shortDescription", shortDescription);
|
||||
element.SetAttribute("description", description);
|
||||
element.AddChild("description").SetMultilineStringValue(description);
|
||||
element.SetAttribute("name", name);
|
||||
element.SetAttribute("fullName", fullName);
|
||||
element.SetAttribute("category", category);
|
||||
@@ -96,7 +100,7 @@ void EventsFunctionsExtension::UnserializeExtensionDeclarationFrom(
|
||||
version = element.GetStringAttribute("version");
|
||||
extensionNamespace = element.GetStringAttribute("extensionNamespace");
|
||||
shortDescription = element.GetStringAttribute("shortDescription");
|
||||
description = element.GetStringAttribute("description");
|
||||
description = element.GetChild("description").GetMultilineStringValue();
|
||||
name = element.GetStringAttribute("name");
|
||||
fullName = element.GetStringAttribute("fullName");
|
||||
category = element.GetStringAttribute("category");
|
||||
|
@@ -20,7 +20,9 @@ class Project;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
// TODO Remove the EventsFunctionsContainer inheritance and make it an attribute.
|
||||
// This will allow to get EventsFunctionsContainer the same way for extensions,
|
||||
// objects and behaviors.
|
||||
/**
|
||||
* \brief Hold a list of Events Functions (gd::EventsFunction) and Events Based
|
||||
* Behaviors.
|
||||
|
@@ -244,6 +244,15 @@ class GD_CORE_API HighestZOrderFinder : public gd::InitialInstanceFunctor {
|
||||
*/
|
||||
size_t GetInstancesCount() const { return instancesCount; }
|
||||
|
||||
void Reset() {
|
||||
highestZOrder = 0;
|
||||
lowestZOrder = 0;
|
||||
instancesCount = 0;
|
||||
firstCall = true;
|
||||
layerRestricted = false;
|
||||
layerName.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
int highestZOrder;
|
||||
int lowestZOrder;
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include "GDCore/IDE/SceneNameMangler.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Project/CustomBehaviorsSharedData.h"
|
||||
#include "GDCore/Project/InitialInstance.h"
|
||||
#include "GDCore/Project/Layer.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
@@ -26,6 +27,7 @@
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/PolymorphicClone.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -240,11 +242,11 @@ void Layout::UpdateBehaviorsSharedData(gd::Project& project) {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<gd::BehaviorsSharedData> Layout::CreateBehaviorsSharedData(gd::Project& project, const gd::String& name, const gd::String& behaviorsType) {
|
||||
std::unique_ptr<gd::BehaviorsSharedData> Layout::CreateBehaviorsSharedData(
|
||||
gd::Project& project, const gd::String& name, const gd::String& behaviorsType) {
|
||||
if (project.HasEventsBasedBehavior(behaviorsType)) {
|
||||
// Events based behaviors don't have shared data yet.
|
||||
auto sharedData =
|
||||
gd::make_unique<gd::BehaviorsSharedData>(name, behaviorsType);
|
||||
gd::make_unique<gd::CustomBehaviorsSharedData>(name, project, behaviorsType);
|
||||
sharedData->InitializeContent();
|
||||
return std::move(sharedData);
|
||||
}
|
||||
@@ -253,7 +255,14 @@ std::unique_ptr<gd::BehaviorsSharedData> Layout::CreateBehaviorsSharedData(gd::P
|
||||
project.GetCurrentPlatform(),
|
||||
behaviorsType);
|
||||
if (gd::MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
return nullptr;
|
||||
gd::LogWarning("Tried to create a behavior shared data with an unknown type: " +
|
||||
behaviorsType + " on object " + GetName() + "!");
|
||||
// It's probably an events-based behavior that was removed.
|
||||
// Create a custom behavior shared data to preserve the properties values.
|
||||
auto sharedData =
|
||||
gd::make_unique<gd::CustomBehaviorsSharedData>(name, project, behaviorsType);
|
||||
sharedData->InitializeContent();
|
||||
return std::move(sharedData);
|
||||
}
|
||||
|
||||
gd::BehaviorsSharedData* behaviorsSharedDataBluePrint =
|
||||
|
27
Core/GDCore/Project/MeasurementBaseUnit.cpp
Normal file
27
Core/GDCore/Project/MeasurementBaseUnit.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "MeasurementBaseUnit.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include <vector>
|
||||
|
||||
namespace gd {
|
||||
|
||||
MeasurementBaseUnit::~MeasurementBaseUnit() {}
|
||||
|
||||
const gd::MeasurementBaseUnit MeasurementBaseUnit::degreeAngle =
|
||||
MeasurementBaseUnit("degree", "deg", "");
|
||||
const gd::MeasurementBaseUnit MeasurementBaseUnit::pixel =
|
||||
MeasurementBaseUnit("pixel", "px", "distance");
|
||||
const gd::MeasurementBaseUnit MeasurementBaseUnit::meter =
|
||||
MeasurementBaseUnit("meter", "m", "distance");
|
||||
const gd::MeasurementBaseUnit MeasurementBaseUnit::second =
|
||||
MeasurementBaseUnit("second", "s", "time");
|
||||
const gd::MeasurementBaseUnit MeasurementBaseUnit::kilogram =
|
||||
MeasurementBaseUnit("kilogram", "Kg", "mass");
|
||||
|
||||
} // namespace gd
|
57
Core/GDCore/Project/MeasurementBaseUnit.h
Normal file
57
Core/GDCore/Project/MeasurementBaseUnit.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_MEASUREMENTBASEUNIT
|
||||
#define GDCORE_MEASUREMENTBASEUNIT
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief An atomic unit of measurement.
|
||||
*/
|
||||
class GD_CORE_API MeasurementBaseUnit {
|
||||
public:
|
||||
MeasurementBaseUnit(gd::String name_, gd::String symbol_,
|
||||
gd::String quantity_)
|
||||
: name(name_), symbol(symbol_), quantity(quantity_) {}
|
||||
|
||||
virtual ~MeasurementBaseUnit();
|
||||
|
||||
/**
|
||||
* \brief Return the unit name.
|
||||
*/
|
||||
const gd::String &GetName() const { return name; }
|
||||
|
||||
/**
|
||||
* \brief Return the unit symbol.
|
||||
*/
|
||||
const gd::String &GetSymbol() const { return symbol; }
|
||||
|
||||
/**
|
||||
* \brief Return the physical quantity.
|
||||
*/
|
||||
const gd::String &GetQuantity() const { return quantity; }
|
||||
|
||||
static const gd::MeasurementBaseUnit degreeAngle;
|
||||
static const gd::MeasurementBaseUnit pixel;
|
||||
static const gd::MeasurementBaseUnit meter;
|
||||
static const gd::MeasurementBaseUnit second;
|
||||
static const gd::MeasurementBaseUnit kilogram;
|
||||
|
||||
private:
|
||||
gd::String name; ///< The unit name
|
||||
gd::String symbol; ///< The unit symbol
|
||||
gd::String quantity; ///< The physical quantity
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_MEASUREMENTBASEUNIT
|
38
Core/GDCore/Project/MeasurementUnit.cpp
Normal file
38
Core/GDCore/Project/MeasurementUnit.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "MeasurementUnit.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
#include <vector>
|
||||
|
||||
namespace gd {
|
||||
|
||||
MeasurementUnit::~MeasurementUnit() {}
|
||||
|
||||
gd::MeasurementUnit MeasurementUnit::undefined = CreateUndefined();
|
||||
gd::MeasurementUnit MeasurementUnit::dimensionless = CreateDimensionless();
|
||||
gd::MeasurementUnit MeasurementUnit::degreeAngle = CreateDegreeAngle();
|
||||
gd::MeasurementUnit MeasurementUnit::second = CreateSecond();
|
||||
gd::MeasurementUnit MeasurementUnit::pixel = CreatePixel();
|
||||
gd::MeasurementUnit MeasurementUnit::pixelSpeed = CreatePixelSpeed();
|
||||
gd::MeasurementUnit MeasurementUnit::pixelAcceleration =
|
||||
CreatePixelAcceleration();
|
||||
gd::MeasurementUnit MeasurementUnit::newton = CreateNewton();
|
||||
gd::MeasurementUnit MeasurementUnit::angularSpeed = CreateAngularSpeed();
|
||||
|
||||
void MeasurementUnit::ApplyTranslation() {
|
||||
undefined = CreateUndefined();
|
||||
dimensionless = CreateDimensionless();
|
||||
degreeAngle = CreateDegreeAngle();
|
||||
second = CreateSecond();
|
||||
pixel = CreatePixel();
|
||||
pixelSpeed = CreatePixelSpeed();
|
||||
pixelAcceleration = CreatePixelAcceleration();
|
||||
newton = CreateNewton();
|
||||
angularSpeed = CreateAngularSpeed();
|
||||
}
|
||||
|
||||
} // namespace gd
|
197
Core/GDCore/Project/MeasurementUnit.h
Normal file
197
Core/GDCore/Project/MeasurementUnit.h
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_MEASUREMENTUNIT
|
||||
#define GDCORE_MEASUREMENTUNIT
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Project/MeasurementUnitElement.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
class MeasurementBaseUnit;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief A unit of measurement.
|
||||
*/
|
||||
class GD_CORE_API MeasurementUnit {
|
||||
public:
|
||||
MeasurementUnit(const std::vector<gd::MeasurementUnitElement> &elements_,
|
||||
gd::String name_, gd::String label_,
|
||||
gd::String elementsWithWords_, gd::String description_ = "")
|
||||
: elements(elements_), name(name_), label(label_),
|
||||
description(description_), elementsWithWords(elementsWithWords_) {}
|
||||
|
||||
MeasurementUnit(gd::String name_, gd::String label_,
|
||||
gd::String elementsWithWords_, gd::String description_ = "")
|
||||
: name(name_), label(label_), description(description_),
|
||||
elementsWithWords(elementsWithWords_) {}
|
||||
|
||||
virtual ~MeasurementUnit();
|
||||
|
||||
/**
|
||||
* \brief Return the unit name.
|
||||
*/
|
||||
const gd::String &GetName() const { return name; }
|
||||
|
||||
/**
|
||||
* \brief Return the unit label.
|
||||
*/
|
||||
const gd::String &GetLabel() const { return label; }
|
||||
|
||||
/**
|
||||
* \brief Return the unit description.
|
||||
*/
|
||||
const gd::String &GetDescription() const { return description; }
|
||||
|
||||
/**
|
||||
* \brief Return the unit description.
|
||||
*/
|
||||
const gd::String &GetElementsWithWords() const { return elementsWithWords; }
|
||||
|
||||
/**
|
||||
* \brief Return the unit elements.
|
||||
*/
|
||||
const std::vector<gd::MeasurementUnitElement> &GetElements() const {
|
||||
return elements;
|
||||
}
|
||||
|
||||
std::size_t GetElementsCount() const { return elements.size(); }
|
||||
|
||||
int GetElementPower(std::size_t elementIndex) const {
|
||||
return elements.at(elementIndex).GetPower();
|
||||
}
|
||||
|
||||
const gd::MeasurementBaseUnit &
|
||||
GetElementBaseUnit(std::size_t elementIndex) const {
|
||||
return elements.at(elementIndex).GetBaseUnit();
|
||||
}
|
||||
|
||||
bool IsUndefined() const { return this == &gd::MeasurementUnit::undefined; }
|
||||
|
||||
static void ApplyTranslation();
|
||||
|
||||
static gd::MeasurementUnit &GetUndefined() { return undefined; }
|
||||
|
||||
static gd::MeasurementUnit &GetDimensionless() { return dimensionless; }
|
||||
|
||||
static gd::MeasurementUnit &GetDegreeAngle() { return degreeAngle; }
|
||||
|
||||
static gd::MeasurementUnit &GetSecond() { return second; }
|
||||
|
||||
static gd::MeasurementUnit &GetPixel() { return pixel; }
|
||||
|
||||
static gd::MeasurementUnit &GetPixelSpeed() { return pixelSpeed; }
|
||||
|
||||
static gd::MeasurementUnit &GetPixelAcceleration() {
|
||||
return pixelAcceleration;
|
||||
}
|
||||
|
||||
static gd::MeasurementUnit &GetAngularSpeed() { return angularSpeed; }
|
||||
|
||||
static gd::MeasurementUnit &GetNewton() { return newton; }
|
||||
|
||||
private:
|
||||
static gd::MeasurementUnit undefined;
|
||||
static gd::MeasurementUnit dimensionless;
|
||||
static gd::MeasurementUnit degreeAngle;
|
||||
static gd::MeasurementUnit second;
|
||||
static gd::MeasurementUnit pixel;
|
||||
static gd::MeasurementUnit pixelSpeed;
|
||||
static gd::MeasurementUnit pixelAcceleration;
|
||||
static gd::MeasurementUnit newton;
|
||||
static gd::MeasurementUnit angularSpeed;
|
||||
|
||||
static gd::MeasurementUnit CreateUndefined() {
|
||||
return MeasurementUnit("Undefined", _("Undefined"), "");
|
||||
}
|
||||
|
||||
static gd::MeasurementUnit CreateDimensionless() {
|
||||
return MeasurementUnit("Dimensionless", _("Dimensionless"), "");
|
||||
}
|
||||
|
||||
static gd::MeasurementUnit CreateDegreeAngle() {
|
||||
std::vector<gd::MeasurementUnitElement> elements;
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::degreeAngle, 1));
|
||||
return MeasurementUnit(elements, "DegreeAngle", _("Angle"), _("degree"));
|
||||
}
|
||||
|
||||
static gd::MeasurementUnit CreateSecond() {
|
||||
std::vector<gd::MeasurementUnitElement> elements;
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::second, 1));
|
||||
return MeasurementUnit(elements, "Second", _("Duration"), _("second"));
|
||||
}
|
||||
|
||||
static gd::MeasurementUnit CreatePixel() {
|
||||
std::vector<gd::MeasurementUnitElement> elements;
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::pixel, 1));
|
||||
return MeasurementUnit(elements, "Pixel", _("Distance"), _("pixel"));
|
||||
}
|
||||
|
||||
static gd::MeasurementUnit CreatePixelSpeed() {
|
||||
std::vector<gd::MeasurementUnitElement> elements;
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::pixel, 1));
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::second, -1));
|
||||
return MeasurementUnit(elements, "PixelSpeed", _("Speed"),
|
||||
_("pixel per second"),
|
||||
_("How much distance is covered per second."));
|
||||
}
|
||||
|
||||
static gd::MeasurementUnit CreatePixelAcceleration() {
|
||||
std::vector<gd::MeasurementUnitElement> elements;
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::pixel, 1));
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::second, -2));
|
||||
return MeasurementUnit(elements, "PixelAcceleration", _("Acceleration"),
|
||||
_("pixel per second, per second"),
|
||||
_("How much speed is gained (or lost) per second."));
|
||||
}
|
||||
|
||||
static gd::MeasurementUnit CreateNewton() {
|
||||
std::vector<gd::MeasurementUnitElement> elements;
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::meter, 1));
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::kilogram, 1));
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::second, -2));
|
||||
return MeasurementUnit(
|
||||
elements, "Newton",
|
||||
_("Force (in Newton)"), _("meter kilogram per second, per second"),
|
||||
_("A unit to measure forces."));
|
||||
}
|
||||
|
||||
static gd::MeasurementUnit CreateAngularSpeed() {
|
||||
std::vector<gd::MeasurementUnitElement> elements;
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::degreeAngle, 1));
|
||||
elements.push_back(
|
||||
MeasurementUnitElement(gd::MeasurementBaseUnit::second, -1));
|
||||
return MeasurementUnit(elements, "AngularSpeed", _("Angular speed"),
|
||||
_("degree per second"),
|
||||
_("How much angle is covered per second."));
|
||||
}
|
||||
|
||||
gd::String name; ///< The unit name.
|
||||
gd::String label; ///< The unit label.
|
||||
gd::String description; ///< The unit description.
|
||||
gd::String elementsWithWords; ///< The unit elements put in words.
|
||||
std::vector<gd::MeasurementUnitElement> elements; ///< The unit elements.
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_MEASUREMENTUNIT
|
15
Core/GDCore/Project/MeasurementUnitElement.cpp
Normal file
15
Core/GDCore/Project/MeasurementUnitElement.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "MeasurementUnitElement.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
#include <vector>
|
||||
|
||||
namespace gd {
|
||||
|
||||
MeasurementUnitElement::~MeasurementUnitElement() {}
|
||||
|
||||
} // namespace gd
|
46
Core/GDCore/Project/MeasurementUnitElement.h
Normal file
46
Core/GDCore/Project/MeasurementUnitElement.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_MEASUREMENTUNITELEMENT
|
||||
#define GDCORE_MEASUREMENTUNITELEMENT
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Project/MeasurementBaseUnit.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief A couple of an atomic unit of measurement and its power.
|
||||
*/
|
||||
class GD_CORE_API MeasurementUnitElement {
|
||||
public:
|
||||
MeasurementUnitElement(const gd::MeasurementBaseUnit &baseUnit_, int power_)
|
||||
: baseUnit(baseUnit_), power(power_) {}
|
||||
|
||||
virtual ~MeasurementUnitElement();
|
||||
|
||||
/**
|
||||
* \brief Return the base unit.
|
||||
*/
|
||||
const gd::MeasurementBaseUnit &GetBaseUnit() const { return baseUnit; }
|
||||
|
||||
/**
|
||||
* \brief Return the power on the base unit.
|
||||
*/
|
||||
int GetPower() const { return power; }
|
||||
|
||||
private:
|
||||
gd::MeasurementBaseUnit baseUnit; ///< The base unit.
|
||||
int power; ///< The power on the base unit.
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_MEASUREMENTUNITELEMENT
|
@@ -114,7 +114,7 @@ gd::Behavior* Object::AddNewBehavior(const gd::Project& project,
|
||||
if (gd::MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
gd::LogWarning("Tried to create a behavior with an unknown type: " + type
|
||||
+ " on object " + GetName() + "!");
|
||||
// It's probably an events-based object that was removed.
|
||||
// It's probably an events-based behavior that was removed.
|
||||
// Create a custom behavior to preserve the properties values.
|
||||
return initializeAndAdd(
|
||||
gd::make_unique<CustomBehavior>(name, project, type));
|
||||
|
@@ -8,6 +8,8 @@
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Project/MeasurementUnit.h"
|
||||
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
@@ -28,12 +30,12 @@ class GD_CORE_API PropertyDescriptor {
|
||||
* \param propertyValue The value of the property.
|
||||
*/
|
||||
PropertyDescriptor(gd::String propertyValue)
|
||||
: currentValue(propertyValue), type("string"), label(""), hidden(false) {}
|
||||
: currentValue(propertyValue), type("string"), label(""), hidden(false), measurementUnit(gd::MeasurementUnit::GetUndefined()) {}
|
||||
|
||||
/**
|
||||
* \brief Empty constructor creating an empty property to be displayed.
|
||||
*/
|
||||
PropertyDescriptor() : hidden(false){};
|
||||
PropertyDescriptor() : hidden(false), measurementUnit(gd::MeasurementUnit::GetUndefined()) {};
|
||||
|
||||
/**
|
||||
* \brief Destructor
|
||||
@@ -103,12 +105,21 @@ class GD_CORE_API PropertyDescriptor {
|
||||
extraInformation.push_back(info);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Change the unit of measurement of the property value.
|
||||
*/
|
||||
PropertyDescriptor& SetMeasurementUnit(const gd::MeasurementUnit &measurementUnit_) {
|
||||
measurementUnit = measurementUnit_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const gd::String& GetValue() const { return currentValue; }
|
||||
const gd::String& GetType() const { return type; }
|
||||
const gd::String& GetLabel() const { return label; }
|
||||
const gd::String& GetDescription() const { return description; }
|
||||
const gd::String& GetGroup() const { return group; }
|
||||
const gd::MeasurementUnit& GetMeasurementUnit() const { return measurementUnit; }
|
||||
|
||||
const std::vector<gd::String>& GetExtraInfo() const {
|
||||
return extraInformation;
|
||||
@@ -168,6 +179,7 @@ class GD_CORE_API PropertyDescriptor {
|
||||
///< choices, if a property is a displayed as a combo
|
||||
///< box.
|
||||
bool hidden;
|
||||
gd::MeasurementUnit measurementUnit; //< The unit of measurement of the property vale.
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -208,8 +208,7 @@ SerializerElement& SerializerElement::GetChild(
|
||||
for (size_t i = 0; i < children.size(); ++i) {
|
||||
if (children[i].second == std::shared_ptr<SerializerElement>()) continue;
|
||||
|
||||
if (children[i].first == name ||
|
||||
(isArray && children[i].first.empty()) ||
|
||||
if (children[i].first == name || (isArray && children[i].first.empty()) ||
|
||||
(!deprecatedName.empty() && children[i].first == deprecatedName)) {
|
||||
if (index == currentIndex)
|
||||
return *children[i].second;
|
||||
@@ -242,8 +241,7 @@ std::size_t SerializerElement::GetChildrenCount(
|
||||
for (size_t i = 0; i < children.size(); ++i) {
|
||||
if (children[i].second == std::shared_ptr<SerializerElement>()) continue;
|
||||
|
||||
if (children[i].first == name ||
|
||||
(isArray && children[i].first.empty()) ||
|
||||
if (children[i].first == name || (isArray && children[i].first.empty()) ||
|
||||
(!deprecatedName.empty() && children[i].first == deprecatedName))
|
||||
currentIndex++;
|
||||
}
|
||||
@@ -291,4 +289,31 @@ void SerializerElement::Init(const gd::SerializerElement& other) {
|
||||
deprecatedArrayOf = other.deprecatedArrayOf;
|
||||
}
|
||||
|
||||
void SerializerElement::SetMultilineStringValue(const gd::String& value) {
|
||||
if (value.find('\n') == gd::String::npos) {
|
||||
SetStringValue(value);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<gd::String> lines = value.Split('\n');
|
||||
children.clear();
|
||||
ConsiderAsArrayOf("");
|
||||
for (const auto& line : lines) {
|
||||
AddChild("").SetStringValue(line);
|
||||
}
|
||||
}
|
||||
|
||||
gd::String SerializerElement::GetMultilineStringValue() {
|
||||
if (!ConsideredAsArray()) {
|
||||
return GetValue().GetString();
|
||||
}
|
||||
|
||||
gd::String value;
|
||||
for (const auto& child : children) {
|
||||
if (!value.empty()) value += "\n";
|
||||
value += child.second->GetStringValue();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Serialization/SerializerValue.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
@@ -177,6 +178,18 @@ class GD_CORE_API SerializerElement {
|
||||
* \brief Return true if no value was set for the element.
|
||||
*/
|
||||
bool IsValueUndefined() const { return valueUndefined; }
|
||||
|
||||
/**
|
||||
* \brief Save the value either as a string or as an array of strings if it
|
||||
* has line breaks.
|
||||
*/
|
||||
void SetMultilineStringValue(const gd::String &value);
|
||||
|
||||
/**
|
||||
* \brief Read the value, either represented as a string or as an array of strings,
|
||||
* into a string.
|
||||
*/
|
||||
gd::String GetMultilineStringValue();
|
||||
///@}
|
||||
|
||||
/** \name Attributes
|
||||
@@ -440,7 +453,7 @@ class GD_CORE_API SerializerElement {
|
||||
* Initialize element using another element. Used by copy-ctor and assign-op.
|
||||
* Don't forget to update me if members were changed!
|
||||
*/
|
||||
void Init(const gd::SerializerElement& other);
|
||||
void Init(const gd::SerializerElement &other);
|
||||
|
||||
bool valueUndefined; ///< If true, the element does not have a value.
|
||||
SerializerValue elementValue;
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Events/Builtin/StandardEvent.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
// TODO Remove these 2 classes and write the test with events based behaviors.
|
||||
@@ -94,6 +95,13 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
|
||||
// Don't show extension loading logs for tests (too verbose).
|
||||
platform.EnableExtensionLoadingLogs(false);
|
||||
|
||||
// Required for tests on event generation.
|
||||
std::shared_ptr<gd::PlatformExtension> commonInstructionsExtension =
|
||||
std::shared_ptr<gd::PlatformExtension>(new gd::PlatformExtension);
|
||||
commonInstructionsExtension->SetExtensionInformation(
|
||||
"BuiltinCommonInstructions", "instruction extension", "", "", "");
|
||||
commonInstructionsExtension->AddEvent("Standard", "Standard event", "", "", "", std::make_shared<gd::StandardEvent>());
|
||||
|
||||
std::shared_ptr<gd::PlatformExtension> baseObjectExtension =
|
||||
std::shared_ptr<gd::PlatformExtension>(new gd::PlatformExtension);
|
||||
|
||||
@@ -373,6 +381,7 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
|
||||
.AddUnsupportedBaseObjectCapability("effect");
|
||||
}
|
||||
|
||||
platform.AddExtension(commonInstructionsExtension);
|
||||
platform.AddExtension(baseObjectExtension);
|
||||
platform.AddExtension(extension);
|
||||
project.AddPlatform(platform);
|
||||
|
@@ -10,7 +10,8 @@
|
||||
|
||||
TEST_CASE("EventsFunctionsContainer", "[common]") {
|
||||
SECTION("Sanity checks") {
|
||||
gd::EventsFunctionsContainer eventsFunctionContainer;
|
||||
gd::EventsFunctionsContainer eventsFunctionContainer(
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Extension);
|
||||
eventsFunctionContainer.InsertNewEventsFunction("Function1", 0);
|
||||
eventsFunctionContainer.InsertNewEventsFunction("Function2", 1);
|
||||
eventsFunctionContainer.InsertNewEventsFunction("Function3", 2);
|
||||
@@ -62,7 +63,8 @@ TEST_CASE("EventsFunctionsContainer", "[common]") {
|
||||
}
|
||||
SECTION("Serialization") {
|
||||
gd::Project project;
|
||||
gd::EventsFunctionsContainer eventsFunctionContainer;
|
||||
gd::EventsFunctionsContainer eventsFunctionContainer(
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Extension);
|
||||
eventsFunctionContainer.InsertNewEventsFunction("Function1", 0);
|
||||
eventsFunctionContainer.InsertNewEventsFunction("Function2", 1);
|
||||
eventsFunctionContainer.InsertNewEventsFunction("Function3", 2);
|
||||
@@ -72,7 +74,8 @@ TEST_CASE("EventsFunctionsContainer", "[common]") {
|
||||
|
||||
eventsFunctionContainer.RemoveEventsFunction("Function2");
|
||||
|
||||
gd::EventsFunctionsContainer eventsFunctionContainer2;
|
||||
gd::EventsFunctionsContainer eventsFunctionContainer2(
|
||||
gd::EventsFunctionsContainer::FunctionOwner::Extension);
|
||||
eventsFunctionContainer2.UnserializeEventsFunctionsFrom(project, element);
|
||||
REQUIRE(eventsFunctionContainer.GetEventsFunctionsCount() == 2);
|
||||
REQUIRE(eventsFunctionContainer.GetEventsFunction(0).GetName() ==
|
||||
|
289
Core/tests/EventsIdentifiersFinder.cpp
Normal file
289
Core/tests/EventsIdentifiersFinder.cpp
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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/IDE/Events/EventsIdentifiersFinder.h"
|
||||
#include "GDCore/Events/Builtin/LinkEvent.h"
|
||||
#include "GDCore/Events/Builtin/StandardEvent.h"
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
namespace {
|
||||
const void DeclareTimerExtension(gd::Project &project, gd::Platform &platform) {
|
||||
std::shared_ptr<gd::PlatformExtension> extension =
|
||||
std::shared_ptr<gd::PlatformExtension>(new gd::PlatformExtension);
|
||||
gd::BuiltinExtensionsImplementer::ImplementsTimeExtension(*(extension.get()));
|
||||
gd::BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
*(extension.get()));
|
||||
// Add an instruction to test expressions.
|
||||
extension
|
||||
->AddAction("DoSomething", "Do something", "This does something",
|
||||
"Do something please", "", "", "")
|
||||
.AddParameter("expression", "Parameter 1 (a number)");
|
||||
platform.AddExtension(extension);
|
||||
project.AddPlatform(platform);
|
||||
}
|
||||
|
||||
const gd::StandardEvent UseSceneTimer(const gd::String &name) {
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("ResetTimer");
|
||||
instruction.SetParametersCount(2);
|
||||
instruction.SetParameter(0, gd::Expression("scene"));
|
||||
instruction.SetParameter(1, gd::Expression("\"" + name + "\""));
|
||||
event.GetActions().Insert(instruction);
|
||||
return event;
|
||||
}
|
||||
|
||||
const gd::StandardEvent UseObjectTimer(const gd::String &objectName,
|
||||
const gd::String &timerName) {
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("ResetObjectTimer");
|
||||
instruction.SetParametersCount(2);
|
||||
instruction.SetParameter(0, gd::Expression(objectName));
|
||||
instruction.SetParameter(1, gd::Expression("\"" + timerName + "\""));
|
||||
event.GetActions().Insert(instruction);
|
||||
return event;
|
||||
}
|
||||
|
||||
const gd::StandardEvent UseSceneTimerInExpression(const gd::String &name) {
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("DoSomething");
|
||||
instruction.SetParametersCount(1);
|
||||
instruction.SetParameter(
|
||||
0, gd::Expression("1 + TimerElapsedTime(\"" + name + "\")"));
|
||||
event.GetActions().Insert(instruction);
|
||||
return event;
|
||||
}
|
||||
|
||||
const gd::StandardEvent
|
||||
UseObjectTimerInExpression(const gd::String &objectName,
|
||||
const gd::String &timerName) {
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("DoSomething");
|
||||
instruction.SetParametersCount(1);
|
||||
instruction.SetParameter(0, gd::Expression("1 + " + objectName +
|
||||
".ObjectTimerElapsedTime(\"" + timerName +
|
||||
"\")"));
|
||||
event.GetActions().Insert(instruction);
|
||||
return event;
|
||||
}
|
||||
|
||||
const void UseExternalEvents(gd::Layout &layout,
|
||||
gd::ExternalEvents &externalEvents) {
|
||||
gd::LinkEvent linkEvent;
|
||||
linkEvent.SetTarget(externalEvents.GetName());
|
||||
layout.GetEvents().InsertEvent(linkEvent);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("EventsIdentifiersFinder (scene timers)", "[common]") {
|
||||
SECTION("Can find scene timers in scenes") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
layout.GetEvents().InsertEvent(UseSceneTimer("MySceneTimer"));
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
platform, project, layout, "sceneTimer");
|
||||
|
||||
REQUIRE(identifierExpressions.size() == 1);
|
||||
REQUIRE(*(identifierExpressions.begin()) == "\"MySceneTimer\"");
|
||||
}
|
||||
|
||||
SECTION("Can find scene timers in scene expressions") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
layout.GetEvents().InsertEvent(UseSceneTimerInExpression("MySceneTimer"));
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
platform, project, layout, "sceneTimer");
|
||||
|
||||
REQUIRE(identifierExpressions.size() == 1);
|
||||
REQUIRE(*(identifierExpressions.begin()) == "\"MySceneTimer\"");
|
||||
}
|
||||
|
||||
SECTION("Can find scene timers in external layouts") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(UseSceneTimer("MySceneTimer"));
|
||||
UseExternalEvents(layout, externalEvents);
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
platform, project, layout, "sceneTimer");
|
||||
|
||||
REQUIRE(identifierExpressions.size() == 1);
|
||||
REQUIRE(*(identifierExpressions.begin()) == "\"MySceneTimer\"");
|
||||
}
|
||||
|
||||
SECTION("Can find scene timers the right scene") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
layout1.GetEvents().InsertEvent(UseSceneTimer("MySceneTimerInLayout1"));
|
||||
|
||||
auto &layout2 = project.InsertNewLayout("Layout2", 0);
|
||||
layout2.GetEvents().InsertEvent(UseSceneTimer("MySceneTimerInLayout2"));
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
platform, project, layout1, "sceneTimer");
|
||||
|
||||
REQUIRE(identifierExpressions.size() == 1);
|
||||
REQUIRE(*(identifierExpressions.begin()) == "\"MySceneTimerInLayout1\"");
|
||||
}
|
||||
|
||||
SECTION("Can find scene timers in the right external layouts") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
auto &externalEvents1 =
|
||||
project.InsertNewExternalEvents("ExternalEvents1", 0);
|
||||
externalEvents1.GetEvents().InsertEvent(
|
||||
UseSceneTimer("MySceneTimerInExternalEvents1"));
|
||||
UseExternalEvents(layout1, externalEvents1);
|
||||
|
||||
auto &layout2 = project.InsertNewLayout("Layout2", 0);
|
||||
auto &externalEvents2 =
|
||||
project.InsertNewExternalEvents("ExternalEvents2", 0);
|
||||
externalEvents2.GetEvents().InsertEvent(
|
||||
UseSceneTimer("MySceneTimerInExternalEvents2"));
|
||||
UseExternalEvents(layout2, externalEvents2);
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
platform, project, layout1, "sceneTimer");
|
||||
|
||||
REQUIRE(identifierExpressions.size() == 1);
|
||||
REQUIRE(*(identifierExpressions.begin()) ==
|
||||
"\"MySceneTimerInExternalEvents1\"");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("EventsIdentifiersFinder (object timers)", "[common]") {
|
||||
SECTION("Can find object timers in scenes") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
layout.GetEvents().InsertEvent(UseObjectTimer("MyObject", "MyObjectTimer"));
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
platform, project, layout, "objectTimer", object.GetName());
|
||||
|
||||
REQUIRE(identifierExpressions.size() == 1);
|
||||
REQUIRE(*(identifierExpressions.begin()) == "\"MyObjectTimer\"");
|
||||
}
|
||||
|
||||
SECTION("Can find object timers in scene expression") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
layout.GetEvents().InsertEvent(UseObjectTimerInExpression("MyObject", "MyObjectTimer"));
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
platform, project, layout, "objectTimer", object.GetName());
|
||||
|
||||
REQUIRE(identifierExpressions.size() == 1);
|
||||
REQUIRE(*(identifierExpressions.begin()) == "\"MyObjectTimer\"");
|
||||
}
|
||||
|
||||
SECTION("Can find object timers in external layouts") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseObjectTimer("MyObject", "MyObjectTimer"));
|
||||
UseExternalEvents(layout, externalEvents);
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
platform, project, layout, "objectTimer", object.GetName());
|
||||
|
||||
REQUIRE(identifierExpressions.size() == 1);
|
||||
REQUIRE(*(identifierExpressions.begin()) == "\"MyObjectTimer\"");
|
||||
}
|
||||
|
||||
SECTION("Can find object timers in scenes for the right object") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectTimer("MyObject1", "MyObjectTimer1"));
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectTimer("MyObject2", "MyObjectTimer2"));
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
platform, project, layout, "objectTimer", object1.GetName());
|
||||
|
||||
REQUIRE(identifierExpressions.size() == 1);
|
||||
REQUIRE(*(identifierExpressions.begin()) == "\"MyObjectTimer1\"");
|
||||
}
|
||||
|
||||
SECTION("Can find object timers in external layouts for the right object") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareTimerExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseObjectTimer("MyObject1", "MyObjectTimer1"));
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseObjectTimer("MyObject2", "MyObjectTimer2"));
|
||||
UseExternalEvents(layout, externalEvents);
|
||||
|
||||
auto identifierExpressions =
|
||||
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
|
||||
platform, project, layout, "objectTimer", object1.GetName());
|
||||
|
||||
REQUIRE(identifierExpressions.size() == 1);
|
||||
REQUIRE(*(identifierExpressions.begin()) == "\"MyObjectTimer1\"");
|
||||
}
|
||||
}
|
360
Core/tests/EventsVariablesFinder.cpp
Normal file
360
Core/tests/EventsVariablesFinder.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* 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/IDE/Events/EventsVariablesFinder.h"
|
||||
#include "GDCore/Events/Builtin/LinkEvent.h"
|
||||
#include "GDCore/Events/Builtin/StandardEvent.h"
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/Variable.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
namespace {
|
||||
const void DeclareVariableExtension(gd::Project &project,
|
||||
gd::Platform &platform) {
|
||||
std::shared_ptr<gd::PlatformExtension> extension =
|
||||
std::shared_ptr<gd::PlatformExtension>(new gd::PlatformExtension);
|
||||
gd::BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
*(extension.get()));
|
||||
gd::BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
*(extension.get()));
|
||||
// Add an instruction to test expressions.
|
||||
extension
|
||||
->AddAction("DoSomething", "Do something", "This does something",
|
||||
"Do something please", "", "", "")
|
||||
.AddParameter("expression", "Parameter 1 (a number)");
|
||||
platform.AddExtension(extension);
|
||||
project.AddPlatform(platform);
|
||||
}
|
||||
|
||||
const gd::StandardEvent UseGlobalVariable(const gd::String &name) {
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("ModVarGlobal");
|
||||
instruction.SetParametersCount(2);
|
||||
instruction.SetParameter(0, gd::Expression(name));
|
||||
instruction.SetParameter(1, gd::Expression("0"));
|
||||
event.GetActions().Insert(instruction);
|
||||
return event;
|
||||
}
|
||||
|
||||
const gd::StandardEvent UseSceneVariable(const gd::String &name) {
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("ModVarScene");
|
||||
instruction.SetParametersCount(2);
|
||||
instruction.SetParameter(0, gd::Expression(name));
|
||||
instruction.SetParameter(1, gd::Expression("0"));
|
||||
event.GetActions().Insert(instruction);
|
||||
return event;
|
||||
}
|
||||
|
||||
const gd::StandardEvent UseObjectVariable(const gd::String &objectName,
|
||||
const gd::String &variableName) {
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("ModVarObjet");
|
||||
instruction.SetParametersCount(3);
|
||||
instruction.SetParameter(0, gd::Expression(objectName));
|
||||
instruction.SetParameter(1, gd::Expression(variableName));
|
||||
instruction.SetParameter(2, gd::Expression("0"));
|
||||
event.GetActions().Insert(instruction);
|
||||
return event;
|
||||
}
|
||||
|
||||
const gd::StandardEvent UseGlobalVariableInExpression(const gd::String &name) {
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("DoSomething");
|
||||
instruction.SetParametersCount(1);
|
||||
instruction.SetParameter(0,
|
||||
gd::Expression("1 + GlobalVariable(" + name + ")"));
|
||||
event.GetActions().Insert(instruction);
|
||||
return event;
|
||||
}
|
||||
|
||||
const gd::StandardEvent UseSceneVariableInExpression(const gd::String &name) {
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("DoSomething");
|
||||
instruction.SetParametersCount(1);
|
||||
instruction.SetParameter(0, gd::Expression("1 + Variable(" + name + ")"));
|
||||
event.GetActions().Insert(instruction);
|
||||
return event;
|
||||
}
|
||||
|
||||
const gd::StandardEvent
|
||||
UseObjectVariableInExpression(const gd::String &objectName,
|
||||
const gd::String &variableName) {
|
||||
gd::StandardEvent event;
|
||||
gd::Instruction instruction;
|
||||
instruction.SetType("DoSomething");
|
||||
instruction.SetParametersCount(1);
|
||||
instruction.SetParameter(
|
||||
0,
|
||||
gd::Expression("1 + " + objectName + ".Variable(" + variableName + ")"));
|
||||
event.GetActions().Insert(instruction);
|
||||
return event;
|
||||
}
|
||||
|
||||
const void UseExternalEvents(gd::Layout &layout,
|
||||
gd::ExternalEvents &externalEvents) {
|
||||
gd::LinkEvent linkEvent;
|
||||
linkEvent.SetTarget(externalEvents.GetName());
|
||||
layout.GetEvents().InsertEvent(linkEvent);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("EventsVariablesFinder (FindAllGlobalVariables)", "[common]") {
|
||||
SECTION("Can find global variables in scenes") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
layout.GetEvents().InsertEvent(UseGlobalVariable("MyGlobalVariable"));
|
||||
|
||||
auto variableNames =
|
||||
gd::EventsVariablesFinder::FindAllGlobalVariables(platform, project);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MyGlobalVariable");
|
||||
}
|
||||
|
||||
SECTION("Can find global variables in scene expressions") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseGlobalVariableInExpression("MyGlobalVariable"));
|
||||
|
||||
auto variableNames =
|
||||
gd::EventsVariablesFinder::FindAllGlobalVariables(platform, project);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MyGlobalVariable");
|
||||
}
|
||||
|
||||
SECTION("Can find global variables in external layouts") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseGlobalVariable("MyGlobalVariable"));
|
||||
UseExternalEvents(layout, externalEvents);
|
||||
|
||||
auto variableNames =
|
||||
gd::EventsVariablesFinder::FindAllGlobalVariables(platform, project);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MyGlobalVariable");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("EventsVariablesFinder (FindAllLayoutVariables)", "[common]") {
|
||||
SECTION("Can find scene variables in scenes") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
layout.GetEvents().InsertEvent(UseSceneVariable("MySceneVariable"));
|
||||
|
||||
auto variableNames = gd::EventsVariablesFinder::FindAllLayoutVariables(
|
||||
platform, project, layout);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MySceneVariable");
|
||||
}
|
||||
|
||||
SECTION("Can find scene variables in scene expressions") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseSceneVariableInExpression("MySceneVariable"));
|
||||
|
||||
auto variableNames = gd::EventsVariablesFinder::FindAllLayoutVariables(
|
||||
platform, project, layout);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MySceneVariable");
|
||||
}
|
||||
|
||||
SECTION("Can find scene variables in external layouts") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(UseSceneVariable("MySceneVariable"));
|
||||
UseExternalEvents(layout, externalEvents);
|
||||
|
||||
auto variableNames = gd::EventsVariablesFinder::FindAllLayoutVariables(
|
||||
platform, project, layout);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MySceneVariable");
|
||||
}
|
||||
|
||||
SECTION("Can find scene variables the right scene") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
layout1.GetEvents().InsertEvent(
|
||||
UseSceneVariable("MySceneVariableInLayout1"));
|
||||
|
||||
auto &layout2 = project.InsertNewLayout("Layout2", 0);
|
||||
layout2.GetEvents().InsertEvent(
|
||||
UseSceneVariable("MySceneVariableInLayout2"));
|
||||
|
||||
auto variableNames = gd::EventsVariablesFinder::FindAllLayoutVariables(
|
||||
platform, project, layout1);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MySceneVariableInLayout1");
|
||||
}
|
||||
|
||||
SECTION("Can find scene variables in the right external layouts") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout1 = project.InsertNewLayout("Layout1", 0);
|
||||
auto &externalEvents1 =
|
||||
project.InsertNewExternalEvents("ExternalEvents1", 0);
|
||||
externalEvents1.GetEvents().InsertEvent(
|
||||
UseSceneVariable("MySceneVariableInExternalEvents1"));
|
||||
UseExternalEvents(layout1, externalEvents1);
|
||||
|
||||
auto &layout2 = project.InsertNewLayout("Layout2", 0);
|
||||
auto &externalEvents2 =
|
||||
project.InsertNewExternalEvents("ExternalEvents2", 0);
|
||||
externalEvents2.GetEvents().InsertEvent(
|
||||
UseSceneVariable("MySceneVariableInExternalEvents2"));
|
||||
UseExternalEvents(layout2, externalEvents2);
|
||||
|
||||
auto variableNames = gd::EventsVariablesFinder::FindAllLayoutVariables(
|
||||
platform, project, layout1);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MySceneVariableInExternalEvents1");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("EventsVariablesFinder (FindAllObjectVariables)", "[common]") {
|
||||
SECTION("Can find object variables in scenes") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectVariable("MyObject", "MyObjectVariable"));
|
||||
|
||||
auto variableNames = gd::EventsVariablesFinder::FindAllObjectVariables(
|
||||
platform, project, layout, object);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MyObjectVariable");
|
||||
}
|
||||
|
||||
SECTION("Can find object variables in scene expressions") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectVariableInExpression("MyObject", "MyObjectVariable"));
|
||||
|
||||
auto variableNames = gd::EventsVariablesFinder::FindAllObjectVariables(
|
||||
platform, project, layout, object);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MyObjectVariable");
|
||||
}
|
||||
|
||||
SECTION("Can find object variables in external layouts") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseObjectVariable("MyObject", "MyObjectVariable"));
|
||||
UseExternalEvents(layout, externalEvents);
|
||||
|
||||
auto variableNames = gd::EventsVariablesFinder::FindAllObjectVariables(
|
||||
platform, project, layout, object);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MyObjectVariable");
|
||||
}
|
||||
|
||||
SECTION("Can find object variables in scenes for the right object") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectVariable("MyObject1", "MyObjectVariable1"));
|
||||
layout.GetEvents().InsertEvent(
|
||||
UseObjectVariable("MyObject2", "MyObjectVariable2"));
|
||||
|
||||
auto variableNames = gd::EventsVariablesFinder::FindAllObjectVariables(
|
||||
platform, project, layout, object1);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MyObjectVariable1");
|
||||
}
|
||||
|
||||
SECTION(
|
||||
"Can find object variables in external layouts for the right object") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
DeclareVariableExtension(project, platform);
|
||||
|
||||
auto &layout = project.InsertNewLayout("Layout1", 0);
|
||||
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
|
||||
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
|
||||
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseObjectVariable("MyObject1", "MyObjectVariable1"));
|
||||
externalEvents.GetEvents().InsertEvent(
|
||||
UseObjectVariable("MyObject2", "MyObjectVariable2"));
|
||||
UseExternalEvents(layout, externalEvents);
|
||||
|
||||
auto variableNames = gd::EventsVariablesFinder::FindAllObjectVariables(
|
||||
platform, project, layout, object1);
|
||||
|
||||
REQUIRE(variableNames.size() == 1);
|
||||
REQUIRE(*(variableNames.begin()) == "MyObjectVariable1");
|
||||
}
|
||||
}
|
@@ -12,11 +12,12 @@
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Serialization.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/CustomObjectConfiguration.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/Variable.h"
|
||||
@@ -29,14 +30,7 @@ using namespace gd;
|
||||
|
||||
namespace {
|
||||
|
||||
void SetupProject(gd::Project &project, gd::Platform &platform) {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
|
||||
auto &configuration = object.GetConfiguration();
|
||||
void SetupSpriteConfiguration(gd::ObjectConfiguration &configuration) {
|
||||
auto *spriteConfiguration = dynamic_cast<gd::SpriteObject *>(&configuration);
|
||||
REQUIRE(spriteConfiguration != nullptr);
|
||||
gd::Animation animation;
|
||||
@@ -44,11 +38,30 @@ void SetupProject(gd::Project &project, gd::Platform &platform) {
|
||||
spriteConfiguration->AddAnimation(animation);
|
||||
};
|
||||
|
||||
void CheckSpriteConfiguration(
|
||||
SerializerElement &objectContainerElement) {
|
||||
gd::Object &SetupProjectWithSprite(gd::Project &project,
|
||||
gd::Platform &platform) {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object =
|
||||
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
|
||||
SetupSpriteConfiguration(object.GetConfiguration());
|
||||
|
||||
return object;
|
||||
};
|
||||
|
||||
void CheckSpriteConfigurationInElement(SerializerElement &projectElement) {
|
||||
void CheckSpriteConfigurationInObjectElement(SerializerElement &objectElement) {
|
||||
REQUIRE(objectElement.HasChild("animations"));
|
||||
auto &animationsElement = objectElement.GetChild("animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation");
|
||||
REQUIRE(animationsElement.GetChildrenCount() == 1);
|
||||
auto &animationElement = animationsElement.GetChild(0);
|
||||
|
||||
REQUIRE(animationElement.GetStringAttribute("name") == "Idle");
|
||||
};
|
||||
|
||||
void CheckSpriteConfigurationInProjectElement(
|
||||
SerializerElement &projectElement) {
|
||||
auto &layoutsElement = projectElement.GetChild("layouts");
|
||||
layoutsElement.ConsiderAsArrayOf("layout");
|
||||
REQUIRE(layoutsElement.GetChildrenCount() == 1);
|
||||
@@ -64,24 +77,10 @@ void CheckSpriteConfigurationInElement(SerializerElement &projectElement) {
|
||||
|
||||
REQUIRE(objectElement.GetStringAttribute("name") == "MyObject");
|
||||
REQUIRE(objectElement.GetStringAttribute("type") == "MyExtension::Sprite");
|
||||
|
||||
REQUIRE(objectElement.HasChild("animations"));
|
||||
auto &animationsElement = objectElement.GetChild("animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation");
|
||||
REQUIRE(animationsElement.GetChildrenCount() == 1);
|
||||
auto &animationElement = animationsElement.GetChild(0);
|
||||
|
||||
REQUIRE(animationElement.GetStringAttribute("name") ==
|
||||
"Idle");
|
||||
CheckSpriteConfigurationInObjectElement(objectElement);
|
||||
};
|
||||
|
||||
void CheckSpriteConfiguration(gd::Project &project) {
|
||||
auto &layout = project.GetLayout("Scene");
|
||||
auto &object = layout.GetObject("MyObject");
|
||||
REQUIRE(object.GetName() == "MyObject");
|
||||
REQUIRE(object.GetType() == "MyExtension::Sprite");
|
||||
|
||||
auto &configuration = object.GetConfiguration();
|
||||
void CheckSpriteConfiguration(gd::ObjectConfiguration &configuration) {
|
||||
auto *spriteConfiguration = dynamic_cast<gd::SpriteObject *>(&configuration);
|
||||
REQUIRE(spriteConfiguration);
|
||||
REQUIRE(spriteConfiguration->GetAnimationsCount() == 1);
|
||||
@@ -89,6 +88,88 @@ void CheckSpriteConfiguration(gd::Project &project) {
|
||||
auto &animation = spriteConfiguration->GetAnimation(0);
|
||||
REQUIRE(animation.GetName() == "Idle");
|
||||
};
|
||||
|
||||
void CheckSpriteConfiguration(gd::Object &object) {
|
||||
REQUIRE(object.GetName() == "MyObject");
|
||||
REQUIRE(object.GetType() == "MyExtension::Sprite");
|
||||
|
||||
CheckSpriteConfiguration(object.GetConfiguration());
|
||||
};
|
||||
|
||||
void CheckSpriteConfiguration(gd::Project &project) {
|
||||
auto &layout = project.GetLayout("Scene");
|
||||
auto &object = layout.GetObject("MyObject");
|
||||
CheckSpriteConfiguration(object);
|
||||
};
|
||||
|
||||
gd::Object &SetupProjectWithCustomObject(gd::Project &project,
|
||||
gd::Platform &platform) {
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
|
||||
auto &eventsExtension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &eventsBasedObject = eventsExtension.GetEventsBasedObjects().InsertNew(
|
||||
"MyEventsBasedObject", 0);
|
||||
eventsBasedObject.SetFullName("My events based object");
|
||||
eventsBasedObject.SetDescription("An events based object for test");
|
||||
eventsBasedObject.InsertNewObject(project, "MyExtension::Sprite", "MyChild",
|
||||
0);
|
||||
|
||||
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
|
||||
gd::Object &object = layout.InsertNewObject(
|
||||
project, "MyEventsExtension::MyEventsBasedObject", "MyObject", 0);
|
||||
auto &configuration = object.GetConfiguration();
|
||||
auto *customObjectConfiguration =
|
||||
dynamic_cast<gd::CustomObjectConfiguration *>(&configuration);
|
||||
auto &spriteConfiguration =
|
||||
customObjectConfiguration->GetChildObjectConfiguration("MyChild");
|
||||
SetupSpriteConfiguration(spriteConfiguration);
|
||||
|
||||
return object;
|
||||
};
|
||||
|
||||
void CheckCustomObjectConfigurationInProjectElement(
|
||||
SerializerElement &projectElement) {
|
||||
auto &layoutsElement = projectElement.GetChild("layouts");
|
||||
layoutsElement.ConsiderAsArrayOf("layout");
|
||||
REQUIRE(layoutsElement.GetChildrenCount() == 1);
|
||||
auto &layoutElement = layoutsElement.GetChild(0);
|
||||
|
||||
REQUIRE(layoutElement.GetStringAttribute("name") == "Scene");
|
||||
REQUIRE(layoutElement.HasChild("objects"));
|
||||
|
||||
auto &objectsElement = layoutElement.GetChild("objects");
|
||||
objectsElement.ConsiderAsArrayOf("object");
|
||||
REQUIRE(objectsElement.GetChildrenCount() == 1);
|
||||
auto &objectElement = objectsElement.GetChild(0);
|
||||
|
||||
REQUIRE(objectElement.GetStringAttribute("name") == "MyObject");
|
||||
REQUIRE(objectElement.GetStringAttribute("type") ==
|
||||
"MyEventsExtension::MyEventsBasedObject");
|
||||
auto &childrenContentElement = objectElement.GetChild("childrenContent");
|
||||
|
||||
REQUIRE(childrenContentElement.HasChild("MyChild"));
|
||||
auto &childElement = childrenContentElement.GetChild("MyChild");
|
||||
CheckSpriteConfigurationInObjectElement(childElement);
|
||||
};
|
||||
|
||||
void CheckCustomObjectConfiguration(gd::Object &object) {
|
||||
REQUIRE(object.GetName() == "MyObject");
|
||||
REQUIRE(object.GetType() == "MyEventsExtension::MyEventsBasedObject");
|
||||
|
||||
auto &configuration = object.GetConfiguration();
|
||||
auto *customObjectConfiguration =
|
||||
dynamic_cast<gd::CustomObjectConfiguration *>(&configuration);
|
||||
auto &spriteConfiguration =
|
||||
customObjectConfiguration->GetChildObjectConfiguration("MyChild");
|
||||
CheckSpriteConfiguration(spriteConfiguration);
|
||||
};
|
||||
|
||||
void CheckCustomObjectConfiguration(gd::Project &project) {
|
||||
auto &layout = project.GetLayout("Scene");
|
||||
auto &object = layout.GetObject("MyObject");
|
||||
CheckCustomObjectConfiguration(object);
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("ObjectSerialization", "[common]") {
|
||||
@@ -96,16 +177,52 @@ TEST_CASE("ObjectSerialization", "[common]") {
|
||||
SECTION("Save and load a project with a sprite configuration") {
|
||||
gd::Platform platform;
|
||||
gd::Project writtenProject;
|
||||
SetupProject(writtenProject, platform);
|
||||
SetupProjectWithSprite(writtenProject, platform);
|
||||
CheckSpriteConfiguration(writtenProject);
|
||||
|
||||
SerializerElement projectElement;
|
||||
writtenProject.SerializeTo(projectElement);
|
||||
CheckSpriteConfigurationInElement(projectElement);
|
||||
CheckSpriteConfigurationInProjectElement(projectElement);
|
||||
|
||||
gd::Project readProject;
|
||||
readProject.AddPlatform(platform);
|
||||
readProject.UnserializeFrom(projectElement);
|
||||
CheckSpriteConfiguration(readProject);
|
||||
}
|
||||
|
||||
SECTION("Clone a sprite object") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
auto &object = SetupProjectWithSprite(project, platform);
|
||||
CheckSpriteConfiguration(object);
|
||||
|
||||
auto clonedObject = object.Clone();
|
||||
CheckSpriteConfiguration(*(clonedObject.get()));
|
||||
}
|
||||
|
||||
SECTION("Save and load a project with a custom object configuration") {
|
||||
gd::Platform platform;
|
||||
gd::Project writtenProject;
|
||||
SetupProjectWithCustomObject(writtenProject, platform);
|
||||
CheckCustomObjectConfiguration(writtenProject);
|
||||
|
||||
SerializerElement projectElement;
|
||||
writtenProject.SerializeTo(projectElement);
|
||||
CheckCustomObjectConfigurationInProjectElement(projectElement);
|
||||
|
||||
gd::Project readProject;
|
||||
readProject.AddPlatform(platform);
|
||||
readProject.UnserializeFrom(projectElement);
|
||||
CheckCustomObjectConfiguration(readProject);
|
||||
}
|
||||
|
||||
SECTION("Clone a custom object") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
auto &object = SetupProjectWithCustomObject(project, platform);
|
||||
CheckCustomObjectConfiguration(object);
|
||||
|
||||
auto clonedObject = object.Clone();
|
||||
CheckCustomObjectConfiguration(*(clonedObject.get()));
|
||||
}
|
||||
}
|
739
Core/tests/PropertyFunctionGenerator.cpp
Normal file
739
Core/tests/PropertyFunctionGenerator.cpp
Normal file
@@ -0,0 +1,739 @@
|
||||
/*
|
||||
* 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/IDE/PropertyFunctionGenerator.h"
|
||||
#include "DummyPlatform.h"
|
||||
#include "GDCore/Events/Builtin/StandardEvent.h"
|
||||
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "catch.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
gd::EventsBasedBehavior &
|
||||
CreateBehavior(gd::EventsFunctionsExtension &eventsExtension) {
|
||||
auto &eventsBasedBehavior =
|
||||
eventsExtension.GetEventsBasedBehaviors().InsertNew(
|
||||
"MyEventsBasedBehavior", 0);
|
||||
eventsBasedBehavior.SetFullName("My events based behavior");
|
||||
eventsBasedBehavior.SetDescription("An events based behavior for test");
|
||||
eventsBasedBehavior.SetObjectType("");
|
||||
return eventsBasedBehavior;
|
||||
};
|
||||
|
||||
gd::EventsBasedObject &
|
||||
CreateObject(gd::EventsFunctionsExtension &eventsExtension) {
|
||||
auto &eventsBasedObject = eventsExtension.GetEventsBasedObjects().InsertNew(
|
||||
"MyEventsBasedObject", 0);
|
||||
eventsBasedObject.SetFullName("My events based object");
|
||||
eventsBasedObject.SetDescription("An events based object for test");
|
||||
return eventsBasedObject;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("PropertyFunctionGenerator", "[common]") {
|
||||
SECTION("Can generate functions for a number property in a behavior") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &behavior = CreateBehavior(extension);
|
||||
|
||||
auto &property =
|
||||
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
|
||||
property.SetType("Number")
|
||||
.SetLabel("Movement angle")
|
||||
.SetDescription("The angle of the trajectory direction.")
|
||||
.SetGroup("Movement");
|
||||
|
||||
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
|
||||
project, extension, behavior, property, false);
|
||||
|
||||
REQUIRE(
|
||||
behavior.GetEventsFunctions().HasEventsFunctionNamed("MovementAngle"));
|
||||
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed(
|
||||
"SetMovementAngle"));
|
||||
{
|
||||
auto &getter =
|
||||
behavior.GetEventsFunctions().GetEventsFunction("MovementAngle");
|
||||
|
||||
REQUIRE(getter.GetFunctionType() ==
|
||||
gd::EventsFunction::ExpressionAndCondition);
|
||||
REQUIRE(getter.GetExpressionType().GetName() == "expression");
|
||||
REQUIRE(getter.GetFullName() == "Movement angle");
|
||||
REQUIRE(getter.GetGroup() ==
|
||||
"My events based behavior movement configuration");
|
||||
REQUIRE(getter.GetDescription() ==
|
||||
"the movement angle of the object. The "
|
||||
"angle of the trajectory direction.");
|
||||
REQUIRE(getter.GetSentence() == "the movement angle");
|
||||
// Object and behavior parameters are added automatically.
|
||||
REQUIRE(getter.GetParameters().size() == 0);
|
||||
|
||||
REQUIRE(getter.GetEvents().GetEventsCount() == 1);
|
||||
REQUIRE(getter.GetEvents().GetEvent(0).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
auto &getterEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().GetEvent(0));
|
||||
REQUIRE(getterEvent.GetConditions().size() == 0);
|
||||
REQUIRE(getterEvent.GetActions().size() == 1);
|
||||
auto &getterAction = getterEvent.GetActions().at(0);
|
||||
REQUIRE(getterAction.GetType() == "SetReturnNumber");
|
||||
REQUIRE(getterAction.GetParametersCount() == 1);
|
||||
REQUIRE(getterAction.GetParameter(0).GetPlainString() ==
|
||||
"Object.Behavior::PropertyMovementAngle()");
|
||||
}
|
||||
{
|
||||
auto &setter =
|
||||
behavior.GetEventsFunctions().GetEventsFunction("SetMovementAngle");
|
||||
|
||||
REQUIRE(setter.GetFunctionType() ==
|
||||
gd::EventsFunction::ActionWithOperator);
|
||||
REQUIRE(setter.GetGetterName() == "MovementAngle");
|
||||
// These fields are deducted from the getter.
|
||||
REQUIRE(setter.GetFullName() == "");
|
||||
REQUIRE(setter.GetGroup() == "");
|
||||
REQUIRE(setter.GetDescription() == "");
|
||||
REQUIRE(setter.GetSentence() == "");
|
||||
// Object and behavior parameters are added automatically.
|
||||
REQUIRE(setter.GetParameters().size() == 0);
|
||||
|
||||
REQUIRE(setter.GetEvents().GetEventsCount() == 1);
|
||||
REQUIRE(setter.GetEvents().GetEvent(0).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
auto &setterEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(0));
|
||||
REQUIRE(setterEvent.GetConditions().size() == 0);
|
||||
REQUIRE(setterEvent.GetActions().size() == 1);
|
||||
auto &setterAction = setterEvent.GetActions().at(0);
|
||||
REQUIRE(
|
||||
setterAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyMovementAngle");
|
||||
REQUIRE(setterAction.GetParametersCount() == 4);
|
||||
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterAction.GetParameter(1).GetPlainString() == "Behavior");
|
||||
REQUIRE(setterAction.GetParameter(2).GetPlainString() == "=");
|
||||
REQUIRE(setterAction.GetParameter(3).GetPlainString() ==
|
||||
"GetArgumentAsNumber(\"Value\")");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Can generate functions for a choice property in a behavior") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &behavior = CreateBehavior(extension);
|
||||
|
||||
auto &property =
|
||||
behavior.GetPropertyDescriptors().InsertNew("CollisionShape", 0);
|
||||
property.SetType("Choice")
|
||||
.SetLabel("Collision shape")
|
||||
.SetLabel("Dot shape")
|
||||
.SetDescription("The shape is used for collision.")
|
||||
.SetGroup("Movement");
|
||||
property.GetExtraInfo().push_back("Dot shape");
|
||||
property.GetExtraInfo().push_back("Bounding disk");
|
||||
|
||||
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
|
||||
project, extension, behavior, property, false);
|
||||
|
||||
REQUIRE(
|
||||
behavior.GetEventsFunctions().HasEventsFunctionNamed("CollisionShape"));
|
||||
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed(
|
||||
"SetCollisionShape"));
|
||||
|
||||
auto &getter =
|
||||
behavior.GetEventsFunctions().GetEventsFunction("CollisionShape");
|
||||
|
||||
REQUIRE(getter.GetFunctionType() ==
|
||||
gd::EventsFunction::ExpressionAndCondition);
|
||||
REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector");
|
||||
REQUIRE(getter.GetExpressionType().GetExtraInfo() ==
|
||||
"[\"Dot shape\",\"Bounding disk\"]");
|
||||
}
|
||||
|
||||
SECTION("Can generate functions for a boolean property in a behavior") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &behavior = CreateBehavior(extension);
|
||||
|
||||
auto &property = behavior.GetPropertyDescriptors().InsertNew("Rotate", 0);
|
||||
property.SetType("Boolean")
|
||||
.SetLabel("Rotate object")
|
||||
.SetDescription(
|
||||
"The rotation follows movements done by this behavior only.")
|
||||
.SetGroup("Movement");
|
||||
|
||||
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
|
||||
project, extension, behavior, property, false);
|
||||
|
||||
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed("Rotate"));
|
||||
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed("SetRotate"));
|
||||
{
|
||||
auto &getter = behavior.GetEventsFunctions().GetEventsFunction("Rotate");
|
||||
REQUIRE(getter.GetFunctionType() == gd::EventsFunction::Condition);
|
||||
REQUIRE(getter.GetExpressionType().GetName() == "boolean");
|
||||
REQUIRE(getter.GetFullName() == "Rotate object");
|
||||
REQUIRE(getter.GetGroup() ==
|
||||
"My events based behavior movement configuration");
|
||||
REQUIRE(getter.GetDescription() ==
|
||||
"Check if rotate object. The rotation follows movements done by "
|
||||
"this behavior only.");
|
||||
REQUIRE(getter.GetSentence() == "_PARAM0_ rotate object");
|
||||
// Object and behavior parameters are added automatically.
|
||||
REQUIRE(getter.GetParameters().size() == 0);
|
||||
|
||||
REQUIRE(getter.GetEvents().GetEventsCount() == 1);
|
||||
REQUIRE(getter.GetEvents().GetEvent(0).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
auto &getterEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().GetEvent(0));
|
||||
REQUIRE(getterEvent.GetConditions().size() == 1);
|
||||
REQUIRE(getterEvent.GetActions().size() == 1);
|
||||
|
||||
auto &getterCondition = getterEvent.GetConditions().at(0);
|
||||
REQUIRE(getterCondition.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedBehavior::PropertyRotate");
|
||||
REQUIRE(!getterCondition.IsInverted());
|
||||
REQUIRE(getterCondition.GetParametersCount() == 2);
|
||||
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(getterCondition.GetParameter(1).GetPlainString() == "Behavior");
|
||||
|
||||
auto &getterAction = getterEvent.GetActions().at(0);
|
||||
REQUIRE(getterAction.GetType() == "SetReturnBoolean");
|
||||
REQUIRE(getterAction.GetParametersCount() == 1);
|
||||
REQUIRE(getterAction.GetParameter(0).GetPlainString() == "True");
|
||||
}
|
||||
{
|
||||
auto &setter =
|
||||
behavior.GetEventsFunctions().GetEventsFunction("SetRotate");
|
||||
|
||||
REQUIRE(setter.GetFunctionType() == gd::EventsFunction::Action);
|
||||
REQUIRE(setter.GetFullName() == "Rotate object");
|
||||
REQUIRE(setter.GetGroup() ==
|
||||
"My events based behavior movement configuration");
|
||||
REQUIRE(setter.GetDescription() ==
|
||||
"Change if rotate object. The rotation follows movements done by "
|
||||
"this behavior only.");
|
||||
REQUIRE(setter.GetSentence() == "_PARAM0_ rotate object: _PARAM2_");
|
||||
// To generate the value parameter, object and behavior parameters has to
|
||||
// be declared too.
|
||||
REQUIRE(setter.GetParameters().size() == 3);
|
||||
auto &objectParameter = setter.GetParameters().at(0);
|
||||
REQUIRE(objectParameter.GetName() == "Object");
|
||||
REQUIRE(objectParameter.GetType() == "object");
|
||||
auto &behaviorParameter = setter.GetParameters().at(1);
|
||||
REQUIRE(behaviorParameter.GetName() == "Behavior");
|
||||
REQUIRE(behaviorParameter.GetType() == "behavior");
|
||||
REQUIRE(behaviorParameter.GetExtraInfo() ==
|
||||
"MyEventsExtension::MyEventsBasedBehavior");
|
||||
auto &valueParameter = setter.GetParameters().at(2);
|
||||
REQUIRE(valueParameter.GetName() == "Value");
|
||||
REQUIRE(valueParameter.GetType() == "yesorno");
|
||||
|
||||
REQUIRE(setter.GetEvents().GetEventsCount() == 2);
|
||||
REQUIRE(setter.GetEvents().GetEvent(0).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
REQUIRE(setter.GetEvents().GetEvent(1).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
|
||||
auto &setterNoEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(0));
|
||||
REQUIRE(setterNoEvent.GetConditions().size() == 1);
|
||||
REQUIRE(setterNoEvent.GetActions().size() == 1);
|
||||
|
||||
auto &setterNoCondition = setterNoEvent.GetConditions().at(0);
|
||||
REQUIRE(setterNoCondition.GetType() == "GetArgumentAsBoolean");
|
||||
REQUIRE(setterNoCondition.IsInverted());
|
||||
REQUIRE(setterNoCondition.GetParametersCount() == 1);
|
||||
REQUIRE(setterNoCondition.GetParameter(0).GetPlainString() ==
|
||||
"\"Value\"");
|
||||
|
||||
auto &setterNoAction = setterNoEvent.GetActions().at(0);
|
||||
REQUIRE(setterNoAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyRotate");
|
||||
REQUIRE(setterNoAction.GetParametersCount() == 3);
|
||||
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "Behavior");
|
||||
REQUIRE(setterNoAction.GetParameter(2).GetPlainString() == "no");
|
||||
|
||||
auto &setterYesEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(1));
|
||||
REQUIRE(setterYesEvent.GetConditions().size() == 1);
|
||||
REQUIRE(setterYesEvent.GetActions().size() == 1);
|
||||
|
||||
auto &setterYesCondition = setterYesEvent.GetConditions().at(0);
|
||||
REQUIRE(setterYesCondition.GetType() == "GetArgumentAsBoolean");
|
||||
REQUIRE(!setterYesCondition.IsInverted());
|
||||
REQUIRE(setterYesCondition.GetParametersCount() == 1);
|
||||
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() ==
|
||||
"\"Value\"");
|
||||
|
||||
auto &setterYesAction = setterYesEvent.GetActions().at(0);
|
||||
REQUIRE(setterYesAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyRotate");
|
||||
REQUIRE(setterYesAction.GetParametersCount() == 3);
|
||||
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "Behavior");
|
||||
REQUIRE(setterYesAction.GetParameter(2).GetPlainString() == "yes");
|
||||
}
|
||||
}
|
||||
SECTION("Can generate functions for a number property in an object") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &object = CreateObject(extension);
|
||||
|
||||
auto &property =
|
||||
object.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
|
||||
property.SetType("Number")
|
||||
.SetLabel("Movement angle")
|
||||
.SetDescription("The angle of the trajectory direction.")
|
||||
.SetGroup("Movement");
|
||||
|
||||
gd::PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
|
||||
project, extension, object, property);
|
||||
|
||||
REQUIRE(
|
||||
object.GetEventsFunctions().HasEventsFunctionNamed("MovementAngle"));
|
||||
REQUIRE(
|
||||
object.GetEventsFunctions().HasEventsFunctionNamed("SetMovementAngle"));
|
||||
{
|
||||
auto &getter =
|
||||
object.GetEventsFunctions().GetEventsFunction("MovementAngle");
|
||||
|
||||
REQUIRE(getter.GetFunctionType() ==
|
||||
gd::EventsFunction::ExpressionAndCondition);
|
||||
REQUIRE(getter.GetExpressionType().GetName() == "expression");
|
||||
REQUIRE(getter.GetFullName() == "Movement angle");
|
||||
REQUIRE(getter.GetGroup() ==
|
||||
"My events based object movement configuration");
|
||||
REQUIRE(getter.GetDescription() ==
|
||||
"the movement angle of the object. The "
|
||||
"angle of the trajectory direction.");
|
||||
REQUIRE(getter.GetSentence() == "the movement angle");
|
||||
// Object parameter is added automatically.
|
||||
REQUIRE(getter.GetParameters().size() == 0);
|
||||
|
||||
REQUIRE(getter.GetEvents().GetEventsCount() == 1);
|
||||
REQUIRE(getter.GetEvents().GetEvent(0).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
auto &getterEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().GetEvent(0));
|
||||
REQUIRE(getterEvent.GetConditions().size() == 0);
|
||||
REQUIRE(getterEvent.GetActions().size() == 1);
|
||||
auto &getterAction = getterEvent.GetActions().at(0);
|
||||
REQUIRE(getterAction.GetType() == "SetReturnNumber");
|
||||
REQUIRE(getterAction.GetParametersCount() == 1);
|
||||
REQUIRE(getterAction.GetParameter(0).GetPlainString() ==
|
||||
"Object.PropertyMovementAngle()");
|
||||
}
|
||||
{
|
||||
auto &setter =
|
||||
object.GetEventsFunctions().GetEventsFunction("SetMovementAngle");
|
||||
|
||||
REQUIRE(setter.GetFunctionType() ==
|
||||
gd::EventsFunction::ActionWithOperator);
|
||||
REQUIRE(setter.GetGetterName() == "MovementAngle");
|
||||
// These fields are deducted from the getter.
|
||||
REQUIRE(setter.GetFullName() == "");
|
||||
REQUIRE(setter.GetGroup() == "");
|
||||
REQUIRE(setter.GetDescription() == "");
|
||||
REQUIRE(setter.GetSentence() == "");
|
||||
// Object parameter is added automatically.
|
||||
REQUIRE(setter.GetParameters().size() == 0);
|
||||
|
||||
REQUIRE(setter.GetEvents().GetEventsCount() == 1);
|
||||
REQUIRE(setter.GetEvents().GetEvent(0).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
auto &setterEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(0));
|
||||
REQUIRE(setterEvent.GetConditions().size() == 0);
|
||||
REQUIRE(setterEvent.GetActions().size() == 1);
|
||||
auto &setterAction = setterEvent.GetActions().at(0);
|
||||
REQUIRE(
|
||||
setterAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedObject::SetPropertyMovementAngle");
|
||||
REQUIRE(setterAction.GetParametersCount() == 3);
|
||||
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterAction.GetParameter(1).GetPlainString() == "=");
|
||||
REQUIRE(setterAction.GetParameter(2).GetPlainString() ==
|
||||
"GetArgumentAsNumber(\"Value\")");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Can generate functions for a choice property in an object") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &object = CreateObject(extension);
|
||||
|
||||
auto &property =
|
||||
object.GetPropertyDescriptors().InsertNew("CollisionShape", 0);
|
||||
property.SetType("Choice")
|
||||
.SetLabel("Collision shape")
|
||||
.SetLabel("Dot shape")
|
||||
.SetDescription("The shape is used for collision.")
|
||||
.SetGroup("Movement");
|
||||
property.GetExtraInfo().push_back("Dot shape");
|
||||
property.GetExtraInfo().push_back("Bounding disk");
|
||||
|
||||
gd::PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
|
||||
project, extension, object, property);
|
||||
|
||||
REQUIRE(
|
||||
object.GetEventsFunctions().HasEventsFunctionNamed("CollisionShape"));
|
||||
REQUIRE(object.GetEventsFunctions().HasEventsFunctionNamed(
|
||||
"SetCollisionShape"));
|
||||
|
||||
auto &getter =
|
||||
object.GetEventsFunctions().GetEventsFunction("CollisionShape");
|
||||
|
||||
REQUIRE(getter.GetFunctionType() ==
|
||||
gd::EventsFunction::ExpressionAndCondition);
|
||||
REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector");
|
||||
REQUIRE(getter.GetExpressionType().GetExtraInfo() ==
|
||||
"[\"Dot shape\",\"Bounding disk\"]");
|
||||
}
|
||||
|
||||
SECTION("Can generate functions for a boolean property in an object") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &object = CreateObject(extension);
|
||||
|
||||
auto &property = object.GetPropertyDescriptors().InsertNew("Rotate", 0);
|
||||
property.SetType("Boolean")
|
||||
.SetLabel("Rotate object")
|
||||
.SetDescription("The rotation follows movements done by this object.")
|
||||
.SetGroup("Movement");
|
||||
|
||||
gd::PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
|
||||
project, extension, object, property);
|
||||
|
||||
REQUIRE(object.GetEventsFunctions().HasEventsFunctionNamed("Rotate"));
|
||||
REQUIRE(object.GetEventsFunctions().HasEventsFunctionNamed("SetRotate"));
|
||||
{
|
||||
auto &getter = object.GetEventsFunctions().GetEventsFunction("Rotate");
|
||||
REQUIRE(getter.GetFunctionType() == gd::EventsFunction::Condition);
|
||||
REQUIRE(getter.GetExpressionType().GetName() == "boolean");
|
||||
REQUIRE(getter.GetFullName() == "Rotate object");
|
||||
REQUIRE(getter.GetGroup() ==
|
||||
"My events based object movement configuration");
|
||||
REQUIRE(getter.GetDescription() ==
|
||||
"Check if rotate object. The rotation follows movements done by "
|
||||
"this object.");
|
||||
REQUIRE(getter.GetSentence() == "_PARAM0_ rotate object");
|
||||
// The Object parameter is added automatically.
|
||||
REQUIRE(getter.GetParameters().size() == 0);
|
||||
|
||||
REQUIRE(getter.GetEvents().GetEventsCount() == 1);
|
||||
REQUIRE(getter.GetEvents().GetEvent(0).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
auto &getterEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().GetEvent(0));
|
||||
REQUIRE(getterEvent.GetConditions().size() == 1);
|
||||
REQUIRE(getterEvent.GetActions().size() == 1);
|
||||
|
||||
auto &getterCondition = getterEvent.GetConditions().at(0);
|
||||
REQUIRE(getterCondition.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedObject::PropertyRotate");
|
||||
REQUIRE(!getterCondition.IsInverted());
|
||||
REQUIRE(getterCondition.GetParametersCount() == 1);
|
||||
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Object");
|
||||
|
||||
auto &getterAction = getterEvent.GetActions().at(0);
|
||||
REQUIRE(getterAction.GetType() == "SetReturnBoolean");
|
||||
REQUIRE(getterAction.GetParametersCount() == 1);
|
||||
REQUIRE(getterAction.GetParameter(0).GetPlainString() == "True");
|
||||
}
|
||||
{
|
||||
auto &setter = object.GetEventsFunctions().GetEventsFunction("SetRotate");
|
||||
|
||||
REQUIRE(setter.GetFunctionType() == gd::EventsFunction::Action);
|
||||
REQUIRE(setter.GetFullName() == "Rotate object");
|
||||
REQUIRE(setter.GetGroup() ==
|
||||
"My events based object movement configuration");
|
||||
REQUIRE(setter.GetDescription() ==
|
||||
"Change if rotate object. The rotation follows movements done by "
|
||||
"this object.");
|
||||
REQUIRE(setter.GetSentence() == "_PARAM0_ rotate object: _PARAM1_");
|
||||
// To generate the value parameter, the object parameter has to
|
||||
// be declared too.
|
||||
REQUIRE(setter.GetParameters().size() == 2);
|
||||
auto &objectParameter = setter.GetParameters().at(0);
|
||||
REQUIRE(objectParameter.GetName() == "Object");
|
||||
REQUIRE(objectParameter.GetType() == "object");
|
||||
REQUIRE(objectParameter.GetExtraInfo() ==
|
||||
"MyEventsExtension::MyEventsBasedObject");
|
||||
auto &valueParameter = setter.GetParameters().at(1);
|
||||
REQUIRE(valueParameter.GetName() == "Value");
|
||||
REQUIRE(valueParameter.GetType() == "yesorno");
|
||||
|
||||
REQUIRE(setter.GetEvents().GetEventsCount() == 2);
|
||||
REQUIRE(setter.GetEvents().GetEvent(0).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
REQUIRE(setter.GetEvents().GetEvent(1).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
|
||||
auto &setterNoEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(0));
|
||||
REQUIRE(setterNoEvent.GetConditions().size() == 1);
|
||||
REQUIRE(setterNoEvent.GetActions().size() == 1);
|
||||
|
||||
auto &setterNoCondition = setterNoEvent.GetConditions().at(0);
|
||||
REQUIRE(setterNoCondition.GetType() == "GetArgumentAsBoolean");
|
||||
REQUIRE(setterNoCondition.IsInverted());
|
||||
REQUIRE(setterNoCondition.GetParametersCount() == 1);
|
||||
REQUIRE(setterNoCondition.GetParameter(0).GetPlainString() ==
|
||||
"\"Value\"");
|
||||
|
||||
auto &setterNoAction = setterNoEvent.GetActions().at(0);
|
||||
REQUIRE(setterNoAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedObject::SetPropertyRotate");
|
||||
REQUIRE(setterNoAction.GetParametersCount() == 2);
|
||||
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "no");
|
||||
|
||||
auto &setterYesEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(1));
|
||||
REQUIRE(setterYesEvent.GetConditions().size() == 1);
|
||||
REQUIRE(setterYesEvent.GetActions().size() == 1);
|
||||
|
||||
auto &setterYesCondition = setterYesEvent.GetConditions().at(0);
|
||||
REQUIRE(setterYesCondition.GetType() == "GetArgumentAsBoolean");
|
||||
REQUIRE(!setterYesCondition.IsInverted());
|
||||
REQUIRE(setterYesCondition.GetParametersCount() == 1);
|
||||
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() ==
|
||||
"\"Value\"");
|
||||
|
||||
auto &setterYesAction = setterYesEvent.GetActions().at(0);
|
||||
REQUIRE(setterYesAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedObject::SetPropertyRotate");
|
||||
REQUIRE(setterYesAction.GetParametersCount() == 2);
|
||||
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Object");
|
||||
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "yes");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Can generate functions for a shared property") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &behavior = CreateBehavior(extension);
|
||||
|
||||
auto &property =
|
||||
behavior.GetSharedPropertyDescriptors().InsertNew("MovementAngle", 0);
|
||||
property.SetType("Number")
|
||||
.SetLabel("Movement angle")
|
||||
.SetDescription("The angle of the trajectory direction.")
|
||||
.SetGroup("Movement");
|
||||
|
||||
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
|
||||
project, extension, behavior, property, true);
|
||||
|
||||
REQUIRE(
|
||||
behavior.GetEventsFunctions().HasEventsFunctionNamed("MovementAngle"));
|
||||
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed(
|
||||
"SetMovementAngle"));
|
||||
{
|
||||
auto &getter =
|
||||
behavior.GetEventsFunctions().GetEventsFunction("MovementAngle");
|
||||
REQUIRE(getter.GetDescription() ==
|
||||
"the movement angle. The angle of the trajectory direction. "
|
||||
"While an object is needed, this will apply to all objects using "
|
||||
"the behavior.");
|
||||
|
||||
REQUIRE(getter.GetEvents().GetEventsCount() == 1);
|
||||
REQUIRE(getter.GetEvents().GetEvent(0).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
auto &getterEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().GetEvent(0));
|
||||
REQUIRE(getterEvent.GetConditions().size() == 0);
|
||||
REQUIRE(getterEvent.GetActions().size() == 1);
|
||||
auto &getterAction = getterEvent.GetActions().at(0);
|
||||
REQUIRE(getterAction.GetType() == "SetReturnNumber");
|
||||
REQUIRE(getterAction.GetParametersCount() == 1);
|
||||
REQUIRE(getterAction.GetParameter(0).GetPlainString() ==
|
||||
"Object.Behavior::SharedPropertyMovementAngle()");
|
||||
}
|
||||
{
|
||||
auto &setter =
|
||||
behavior.GetEventsFunctions().GetEventsFunction("SetMovementAngle");
|
||||
|
||||
REQUIRE(setter.GetEvents().GetEventsCount() == 1);
|
||||
REQUIRE(setter.GetEvents().GetEvent(0).GetType() ==
|
||||
"BuiltinCommonInstructions::Standard");
|
||||
auto &setterEvent =
|
||||
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(0));
|
||||
REQUIRE(setterEvent.GetConditions().size() == 0);
|
||||
REQUIRE(setterEvent.GetActions().size() == 1);
|
||||
auto &setterAction = setterEvent.GetActions().at(0);
|
||||
REQUIRE(setterAction.GetType() ==
|
||||
"MyEventsExtension::MyEventsBasedBehavior::"
|
||||
"SetSharedPropertyMovementAngle");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Allow functions generation when there is no setter") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &behavior = CreateBehavior(extension);
|
||||
|
||||
auto &property =
|
||||
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
|
||||
property.SetType("Number")
|
||||
.SetLabel("Movement angle")
|
||||
.SetDescription("The angle of the trajectory direction.")
|
||||
.SetGroup("Movement");
|
||||
|
||||
REQUIRE(gd::PropertyFunctionGenerator::CanGenerateGetterAndSetter(
|
||||
behavior, property));
|
||||
}
|
||||
|
||||
SECTION("Forbid functions generation when a getter exists") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &behavior = CreateBehavior(extension);
|
||||
|
||||
auto &property =
|
||||
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
|
||||
property.SetType("Number")
|
||||
.SetLabel("Movement angle")
|
||||
.SetDescription("The angle of the trajectory direction.")
|
||||
.SetGroup("Movement");
|
||||
|
||||
behavior.GetEventsFunctions().InsertNewEventsFunction("MovementAngle", 0);
|
||||
|
||||
REQUIRE(!gd::PropertyFunctionGenerator::CanGenerateGetterAndSetter(
|
||||
behavior, property));
|
||||
}
|
||||
|
||||
SECTION("Forbid functions generation when a setter exists") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &behavior = CreateBehavior(extension);
|
||||
|
||||
auto &property =
|
||||
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
|
||||
property.SetType("Number")
|
||||
.SetLabel("Movement angle")
|
||||
.SetDescription("The angle of the trajectory direction.")
|
||||
.SetGroup("Movement");
|
||||
|
||||
behavior.GetEventsFunctions().InsertNewEventsFunction("SetMovementAngle",
|
||||
0);
|
||||
|
||||
REQUIRE(!gd::PropertyFunctionGenerator::CanGenerateGetterAndSetter(
|
||||
behavior, property));
|
||||
}
|
||||
|
||||
SECTION("Forbid functions generation when both setter and getter exist") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &behavior = CreateBehavior(extension);
|
||||
|
||||
auto &property =
|
||||
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
|
||||
property.SetType("Number")
|
||||
.SetLabel("Movement angle")
|
||||
.SetDescription("The angle of the trajectory direction.")
|
||||
.SetGroup("Movement");
|
||||
|
||||
behavior.GetEventsFunctions().InsertNewEventsFunction("MovementAngle", 0);
|
||||
behavior.GetEventsFunctions().InsertNewEventsFunction("SetMovementAngle",
|
||||
0);
|
||||
|
||||
REQUIRE(!gd::PropertyFunctionGenerator::CanGenerateGetterAndSetter(
|
||||
behavior, property));
|
||||
}
|
||||
|
||||
SECTION("Forbid functions generation for required behavior properties") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &behavior = CreateBehavior(extension);
|
||||
|
||||
auto &property =
|
||||
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
|
||||
property.SetType("Behavior")
|
||||
.SetLabel("Pathfinding behavior")
|
||||
.SetDescription("A required behavior.")
|
||||
.SetGroup("Movement")
|
||||
.GetExtraInfo()
|
||||
.push_back("PlatformBehavior::PlatformerObjectBehavior");
|
||||
|
||||
REQUIRE(!gd::PropertyFunctionGenerator::CanGenerateGetterAndSetter(
|
||||
behavior, property));
|
||||
}
|
||||
|
||||
SECTION("Can generate functions when only the property name is filled") {
|
||||
gd::Platform platform;
|
||||
gd::Project project;
|
||||
SetupProjectWithDummyPlatform(project, platform);
|
||||
auto &extension =
|
||||
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
|
||||
auto &behavior = CreateBehavior(extension);
|
||||
|
||||
auto &property =
|
||||
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
|
||||
property.SetType("Number");
|
||||
|
||||
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
|
||||
project, extension, behavior, property, false);
|
||||
|
||||
REQUIRE(
|
||||
behavior.GetEventsFunctions().HasEventsFunctionNamed("MovementAngle"));
|
||||
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed(
|
||||
"SetMovementAngle"));
|
||||
|
||||
auto &getter =
|
||||
behavior.GetEventsFunctions().GetEventsFunction("MovementAngle");
|
||||
|
||||
REQUIRE(getter.GetFunctionType() ==
|
||||
gd::EventsFunction::ExpressionAndCondition);
|
||||
REQUIRE(getter.GetExpressionType().GetName() == "expression");
|
||||
REQUIRE(getter.GetFullName() == "MovementAngle");
|
||||
REQUIRE(getter.GetGroup() == "My events based behavior configuration");
|
||||
REQUIRE(getter.GetDescription() == "the movementAngle of the object.");
|
||||
REQUIRE(getter.GetSentence() == "the movementAngle");
|
||||
}
|
||||
}
|
@@ -81,6 +81,30 @@ TEST_CASE("SerializerElement", "[common]") {
|
||||
REQUIRE(element.GetChild(2).GetDoubleValue() == 45.6);
|
||||
}
|
||||
|
||||
SECTION("Multiline strings") {
|
||||
SerializerElement element;
|
||||
|
||||
// A single line is saved as a string.
|
||||
element.SetMultilineStringValue("test");
|
||||
REQUIRE(element.GetMultilineStringValue() == "test");
|
||||
REQUIRE(element.GetStringValue() == "test");
|
||||
|
||||
// A string can be read.
|
||||
element.SetStringValue("test of\nsomething\nsaved as a string");
|
||||
REQUIRE(element.GetMultilineStringValue() == "test of\nsomething\nsaved as a string");
|
||||
|
||||
// A multi lines string is saved as an array.
|
||||
element.SetMultilineStringValue("test\nwith\nmultiple lines.");
|
||||
REQUIRE(element.ConsideredAsArray() == true);
|
||||
REQUIRE(element.GetChildrenCount() == 3);
|
||||
REQUIRE(element.GetMultilineStringValue() == "test\nwith\nmultiple lines.");
|
||||
|
||||
element.SetMultilineStringValue("test\n\nwith\n\nmultiple lines.\n");
|
||||
REQUIRE(element.ConsideredAsArray() == true);
|
||||
REQUIRE(element.GetChildrenCount() == 6);
|
||||
REQUIRE(element.GetMultilineStringValue() == "test\n\nwith\n\nmultiple lines.\n");
|
||||
}
|
||||
|
||||
SECTION("(Deprecated) attributes") {
|
||||
SerializerElement element;
|
||||
element.AddChild("child1").SetStringValue("value123");
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,7 @@ module.exports = {
|
||||
'Arthur Pacaud (arthuro555)',
|
||||
'MIT'
|
||||
)
|
||||
.setCategory('Device');
|
||||
.setCategory('User interface');
|
||||
extension
|
||||
.addInstructionOrExpressionGroupMetadata(_('Advanced window management'))
|
||||
.setIcon('res/actions/window24.png');
|
||||
|
@@ -105,9 +105,9 @@ std::map<gd::String, gd::PropertyDescriptor> AnchorBehavior::GetProperties(
|
||||
|
||||
properties[("useLegacyBottomAndRightAnchors")]
|
||||
.SetLabel(_(
|
||||
"Stretch object when anchoring right or bottom ledge (deprecated, "
|
||||
"it's recommended to let this unchecked and anchor both sides if you "
|
||||
"want Sprite to stretch instead.)"))
|
||||
"Stretch object when anchoring right or bottom edge (deprecated, "
|
||||
"it's recommended to leave this unchecked and anchor both sides if "
|
||||
"you want Sprite to stretch instead.)"))
|
||||
.SetGroup(_("Deprecated options (advanced)"))
|
||||
.SetValue(behaviorContent.GetBoolAttribute(
|
||||
"useLegacyBottomAndRightAnchors", true)
|
||||
|
@@ -17,6 +17,7 @@ void DeclareAnchorBehaviorExtension(gd::PlatformExtension& extension) {
|
||||
_("Anchor objects to the window's bounds."),
|
||||
"Victor Levasseur",
|
||||
"Open source (MIT License)")
|
||||
.SetCategory("User interface")
|
||||
.SetExtensionHelpPath("/behaviors/anchor");
|
||||
|
||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
||||
|
@@ -17,8 +17,12 @@ namespace gdjs {
|
||||
_bottomEdgeDistance: number = 0;
|
||||
_useLegacyBottomAndRightAnchors: boolean = false;
|
||||
|
||||
constructor(runtimeScene, behaviorData, owner) {
|
||||
super(runtimeScene, behaviorData, owner);
|
||||
constructor(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
behaviorData,
|
||||
owner: gdjs.RuntimeObject
|
||||
) {
|
||||
super(instanceContainer, behaviorData, owner);
|
||||
this._relativeToOriginalWindowSize = !!behaviorData.relativeToOriginalWindowSize;
|
||||
this._leftEdgeAnchor = behaviorData.leftEdgeAnchor;
|
||||
this._rightEdgeAnchor = behaviorData.rightEdgeAnchor;
|
||||
@@ -65,11 +69,15 @@ namespace gdjs {
|
||||
this._invalidDistances = true;
|
||||
}
|
||||
|
||||
doStepPreEvents(runtimeScene) {
|
||||
const game = runtimeScene.getGame();
|
||||
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
|
||||
const workingPoint: FloatPoint = gdjs.staticArray(
|
||||
gdjs.AnchorRuntimeBehavior.prototype.doStepPreEvents
|
||||
) as FloatPoint;
|
||||
// TODO EBO Make it work with event based objects or hide this behavior for them.
|
||||
const game = instanceContainer.getGame();
|
||||
let rendererWidth = game.getGameResolutionWidth();
|
||||
let rendererHeight = game.getGameResolutionHeight();
|
||||
const layer = runtimeScene.getLayer(this.owner.getLayer());
|
||||
const layer = instanceContainer.getLayer(this.owner.getLayer());
|
||||
if (this._invalidDistances) {
|
||||
if (this._relativeToOriginalWindowSize) {
|
||||
rendererWidth = game.getOriginalWidth();
|
||||
@@ -79,7 +87,9 @@ namespace gdjs {
|
||||
//Calculate the distances from the window's bounds.
|
||||
const topLeftPixel = layer.convertCoords(
|
||||
this.owner.getDrawableX(),
|
||||
this.owner.getDrawableY()
|
||||
this.owner.getDrawableY(),
|
||||
0,
|
||||
workingPoint
|
||||
);
|
||||
|
||||
//Left edge
|
||||
@@ -125,9 +135,12 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
}
|
||||
// It's fine to reuse workingPoint as topLeftPixel is no longer used.
|
||||
const bottomRightPixel = layer.convertCoords(
|
||||
this.owner.getDrawableX() + this.owner.getWidth(),
|
||||
this.owner.getDrawableY() + this.owner.getHeight()
|
||||
this.owner.getDrawableY() + this.owner.getHeight(),
|
||||
0,
|
||||
workingPoint
|
||||
);
|
||||
|
||||
//Right edge
|
||||
@@ -268,11 +281,24 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
}
|
||||
const topLeftCoord = layer.convertInverseCoords(leftPixel, topPixel);
|
||||
// It's fine to reuse workingPoint as topLeftPixel is no longer used.
|
||||
const topLeftCoord = layer.convertInverseCoords(
|
||||
leftPixel,
|
||||
topPixel,
|
||||
0,
|
||||
workingPoint
|
||||
);
|
||||
const left = topLeftCoord[0];
|
||||
const top = topLeftCoord[1];
|
||||
|
||||
const bottomRightCoord = layer.convertInverseCoords(
|
||||
rightPixel,
|
||||
bottomPixel
|
||||
bottomPixel,
|
||||
0,
|
||||
workingPoint
|
||||
);
|
||||
const right = bottomRightCoord[0];
|
||||
const bottom = bottomRightCoord[1];
|
||||
|
||||
// Compatibility with GD <= 5.0.133
|
||||
if (this._useLegacyBottomAndRightAnchors) {
|
||||
@@ -281,25 +307,25 @@ namespace gdjs {
|
||||
this._rightEdgeAnchor !==
|
||||
AnchorRuntimeBehavior.HorizontalAnchor.NONE
|
||||
) {
|
||||
this.owner.setWidth(bottomRightCoord[0] - topLeftCoord[0]);
|
||||
this.owner.setWidth(right - left);
|
||||
}
|
||||
if (
|
||||
this._bottomEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
|
||||
) {
|
||||
this.owner.setHeight(bottomRightCoord[1] - topLeftCoord[1]);
|
||||
this.owner.setHeight(bottom - top);
|
||||
}
|
||||
if (
|
||||
this._leftEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
|
||||
) {
|
||||
this.owner.setX(
|
||||
topLeftCoord[0] + this.owner.getX() - this.owner.getDrawableX()
|
||||
left + this.owner.getX() - this.owner.getDrawableX()
|
||||
);
|
||||
}
|
||||
if (
|
||||
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
|
||||
) {
|
||||
this.owner.setY(
|
||||
topLeftCoord[1] + this.owner.getY() - this.owner.getDrawableY()
|
||||
top + this.owner.getY() - this.owner.getDrawableY()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -311,15 +337,15 @@ namespace gdjs {
|
||||
AnchorRuntimeBehavior.HorizontalAnchor.NONE &&
|
||||
this._leftEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
|
||||
) {
|
||||
this.owner.setWidth(bottomRightCoord[0] - topLeftCoord[0]);
|
||||
this.owner.setX(topLeftCoord[0]);
|
||||
this.owner.setWidth(right - left);
|
||||
this.owner.setX(left);
|
||||
} else {
|
||||
if (
|
||||
this._leftEdgeAnchor !==
|
||||
AnchorRuntimeBehavior.HorizontalAnchor.NONE
|
||||
) {
|
||||
this.owner.setX(
|
||||
topLeftCoord[0] + this.owner.getX() - this.owner.getDrawableX()
|
||||
left + this.owner.getX() - this.owner.getDrawableX()
|
||||
);
|
||||
}
|
||||
if (
|
||||
@@ -327,7 +353,7 @@ namespace gdjs {
|
||||
AnchorRuntimeBehavior.HorizontalAnchor.NONE
|
||||
) {
|
||||
this.owner.setX(
|
||||
bottomRightCoord[0] +
|
||||
right +
|
||||
this.owner.getX() -
|
||||
this.owner.getDrawableX() -
|
||||
this.owner.getWidth()
|
||||
@@ -340,14 +366,14 @@ namespace gdjs {
|
||||
AnchorRuntimeBehavior.VerticalAnchor.NONE &&
|
||||
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
|
||||
) {
|
||||
this.owner.setHeight(bottomRightCoord[1] - topLeftCoord[1]);
|
||||
this.owner.setY(topLeftCoord[1]);
|
||||
this.owner.setHeight(bottom - top);
|
||||
this.owner.setY(top);
|
||||
} else {
|
||||
if (
|
||||
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
|
||||
) {
|
||||
this.owner.setY(
|
||||
topLeftCoord[1] + this.owner.getY() - this.owner.getDrawableY()
|
||||
top + this.owner.getY() - this.owner.getDrawableY()
|
||||
);
|
||||
}
|
||||
if (
|
||||
@@ -355,7 +381,7 @@ namespace gdjs {
|
||||
AnchorRuntimeBehavior.VerticalAnchor.NONE
|
||||
) {
|
||||
this.owner.setY(
|
||||
bottomRightCoord[1] +
|
||||
bottom +
|
||||
this.owner.getY() -
|
||||
this.owner.getDrawableY() -
|
||||
this.owner.getHeight()
|
||||
@@ -366,7 +392,7 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
doStepPostEvents(runtimeScene) {}
|
||||
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {}
|
||||
|
||||
static HorizontalAnchor = {
|
||||
NONE: 0,
|
||||
|
@@ -62,16 +62,6 @@ describe('gdjs.AnchorRuntimeBehavior', function () {
|
||||
return object;
|
||||
}
|
||||
|
||||
function getAnchorBehavior(object) {
|
||||
const behavior = object.getBehavior(anchorBehaviorName);
|
||||
if (!(behavior instanceof gdjs.AnchorRuntimeBehavior)) {
|
||||
throw new Error(
|
||||
'Expected behavior to be an instance of gdjs.AnchorBehavior'
|
||||
);
|
||||
}
|
||||
return behavior;
|
||||
}
|
||||
|
||||
describe('(anchor horizontal edge)', function () {
|
||||
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
|
||||
it(`anchors the ${objectEdge} edge of object to window left (fixed)`, function () {
|
||||
|
@@ -33,7 +33,10 @@ module.exports = {
|
||||
'Todor Imreorov',
|
||||
'Open source (MIT License)'
|
||||
)
|
||||
.setExtensionHelpPath('/objects/bbtext');
|
||||
.setExtensionHelpPath('/objects/bbtext')
|
||||
.setCategory('User interface');
|
||||
extension.addInstructionOrExpressionGroupMetadata(_("BBCode Text Object"))
|
||||
.setIcon("JsPlatform/Extensions/bbcode32.png");
|
||||
|
||||
var objectBBText = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError
|
||||
@@ -168,7 +171,7 @@ module.exports = {
|
||||
.addIncludeFile(
|
||||
'Extensions/BBText/pixi-multistyle-text/dist/pixi-multistyle-text.umd.js'
|
||||
)
|
||||
.setCategoryFullName(_('Texts'));
|
||||
.setCategoryFullName(_('User interface'));
|
||||
|
||||
/**
|
||||
* Utility function to add both a setter and a getter to a property from a list.
|
||||
@@ -498,7 +501,7 @@ module.exports = {
|
||||
RenderedBBTextInstance.getThumbnail = function (
|
||||
project,
|
||||
resourcesLoader,
|
||||
object
|
||||
objectConfiguration
|
||||
) {
|
||||
return 'JsPlatform/Extensions/bbcode24.png';
|
||||
};
|
||||
|
@@ -10,11 +10,11 @@ namespace gdjs {
|
||||
|
||||
/**
|
||||
* @param runtimeObject The object to render
|
||||
* @param runtimeScene The gdjs.RuntimeScene in which the object is
|
||||
* @param instanceContainer The gdjs.RuntimeInstanceContainer in which the object is
|
||||
*/
|
||||
constructor(
|
||||
runtimeObject: gdjs.BBTextRuntimeObject,
|
||||
runtimeScene: gdjs.RuntimeScene
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer
|
||||
) {
|
||||
this._object = runtimeObject;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace gdjs {
|
||||
if (this._pixiObject === undefined) {
|
||||
this._pixiObject = new MultiStyleText(runtimeObject._text, {
|
||||
default: {
|
||||
fontFamily: runtimeScene
|
||||
fontFamily: instanceContainer
|
||||
.getGame()
|
||||
.getFontManager()
|
||||
.getFontFamily(runtimeObject._fontFamily),
|
||||
@@ -44,7 +44,7 @@ namespace gdjs {
|
||||
this.updateFontFamily();
|
||||
this.updateFontSize();
|
||||
}
|
||||
runtimeScene
|
||||
instanceContainer
|
||||
.getLayer('')
|
||||
.getRenderer()
|
||||
.addRendererObject(this._pixiObject, runtimeObject.getZOrder());
|
||||
@@ -95,7 +95,8 @@ namespace gdjs {
|
||||
}
|
||||
|
||||
updateFontFamily(): void {
|
||||
this._pixiObject.textStyles.default.fontFamily = this._object._runtimeScene
|
||||
this._pixiObject.textStyles.default.fontFamily = this._object
|
||||
.getInstanceContainer()
|
||||
.getGame()
|
||||
.getFontManager()
|
||||
.getFontFamily(this._object._fontFamily);
|
||||
|
@@ -48,11 +48,14 @@ namespace gdjs {
|
||||
hidden: boolean;
|
||||
|
||||
/**
|
||||
* @param runtimeScene The scene the object belongs to.
|
||||
* @param instanceContainer The container the object belongs to.
|
||||
* @param objectData The object data used to initialize the object
|
||||
*/
|
||||
constructor(runtimeScene: gdjs.RuntimeScene, objectData: BBTextObjectData) {
|
||||
super(runtimeScene, objectData);
|
||||
constructor(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
objectData: BBTextObjectData
|
||||
) {
|
||||
super(instanceContainer, objectData);
|
||||
// @ts-ignore - parseFloat should not be required, but GDevelop 5.0 beta 92 and below were storing it as a string.
|
||||
this._opacity = parseFloat(objectData.content.opacity);
|
||||
this._text = objectData.content.text;
|
||||
@@ -62,7 +65,10 @@ namespace gdjs {
|
||||
this._fontSize = parseFloat(objectData.content.fontSize);
|
||||
this._wordWrap = objectData.content.wordWrap;
|
||||
this._align = objectData.content.align;
|
||||
this._renderer = new gdjs.BBTextRuntimeObjectRenderer(this, runtimeScene);
|
||||
this._renderer = new gdjs.BBTextRuntimeObjectRenderer(
|
||||
this,
|
||||
instanceContainer
|
||||
);
|
||||
this.hidden = !objectData.content.visible;
|
||||
|
||||
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
|
||||
@@ -122,8 +128,8 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
onDestroyFromScene(runtimeScene): void {
|
||||
super.onDestroyFromScene(runtimeScene);
|
||||
onDestroyFromScene(instanceContainer: gdjs.RuntimeInstanceContainer): void {
|
||||
super.onDestroyFromScene(instanceContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,7 +245,7 @@ namespace gdjs {
|
||||
|
||||
this._wrappingWidth = width;
|
||||
this._renderer.updateWrappingWidth();
|
||||
this.hitBoxesDirty = true;
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,7 +260,7 @@ namespace gdjs {
|
||||
|
||||
this._wordWrap = wordWrap;
|
||||
this._renderer.updateWordWrap();
|
||||
this.hitBoxesDirty = true;
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
|
||||
getWordWrap() {
|
||||
|
@@ -35,7 +35,10 @@ module.exports = {
|
||||
'Aurélien Vivet',
|
||||
'Open source (MIT License)'
|
||||
)
|
||||
.setExtensionHelpPath('/objects/bitmap_text');
|
||||
.setExtensionHelpPath('/objects/bitmap_text')
|
||||
.setCategory('User interface');
|
||||
extension.addInstructionOrExpressionGroupMetadata(_("Bitmap Text"))
|
||||
.setIcon("JsPlatform/Extensions/bitmapfont32.png");
|
||||
|
||||
const bitmapTextObject = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError
|
||||
@@ -171,7 +174,7 @@ module.exports = {
|
||||
.addIncludeFile(
|
||||
'Extensions/BitmapText/bitmaptextruntimeobject-pixi-renderer.js'
|
||||
)
|
||||
.setCategoryFullName(_('Texts'));
|
||||
.setCategoryFullName(_('User interface'));
|
||||
|
||||
object
|
||||
.addExpressionAndConditionAndAction(
|
||||
@@ -627,7 +630,7 @@ module.exports = {
|
||||
RenderedBitmapTextInstance.getThumbnail = function (
|
||||
project,
|
||||
resourcesLoader,
|
||||
object
|
||||
objectConfiguration
|
||||
) {
|
||||
return 'JsPlatform/Extensions/bitmapfont24.png';
|
||||
};
|
||||
|
@@ -10,16 +10,16 @@ namespace gdjs {
|
||||
|
||||
/**
|
||||
* @param runtimeObject The object to render
|
||||
* @param runtimeScene The gdjs.RuntimeScene in which the object is
|
||||
* @param instanceContainer The container in which the object is
|
||||
*/
|
||||
constructor(
|
||||
runtimeObject: gdjs.BitmapTextRuntimeObject,
|
||||
runtimeScene: gdjs.RuntimeScene
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer
|
||||
) {
|
||||
this._object = runtimeObject;
|
||||
|
||||
// Obtain the bitmap font to use in the object.
|
||||
const bitmapFont = runtimeScene
|
||||
const bitmapFont = instanceContainer
|
||||
.getGame()
|
||||
.getBitmapFontManager()
|
||||
.obtainBitmapFont(
|
||||
@@ -32,7 +32,7 @@ namespace gdjs {
|
||||
});
|
||||
|
||||
// Set the object on the scene
|
||||
runtimeScene
|
||||
instanceContainer
|
||||
.getLayer('')
|
||||
.getRenderer()
|
||||
.addRendererObject(this._pixiObject, runtimeObject.getZOrder());
|
||||
@@ -59,7 +59,8 @@ namespace gdjs {
|
||||
|
||||
onDestroy() {
|
||||
// Mark the font from the object as not used anymore.
|
||||
this._object._runtimeScene
|
||||
this._object
|
||||
.getInstanceContainer()
|
||||
.getGame()
|
||||
.getBitmapFontManager()
|
||||
.releaseBitmapFont(this._pixiObject.fontName);
|
||||
@@ -73,7 +74,8 @@ namespace gdjs {
|
||||
|
||||
updateFont(): void {
|
||||
// Get the new bitmap font to use
|
||||
const bitmapFont = this._object._runtimeScene
|
||||
const bitmapFont = this._object
|
||||
.getInstanceContainer()
|
||||
.getGame()
|
||||
.getBitmapFontManager()
|
||||
.obtainBitmapFont(
|
||||
@@ -82,7 +84,8 @@ namespace gdjs {
|
||||
);
|
||||
|
||||
// Mark the old font as not used anymore
|
||||
this._object._runtimeScene
|
||||
this._object
|
||||
.getInstanceContainer()
|
||||
.getGame()
|
||||
.getBitmapFontManager()
|
||||
.releaseBitmapFont(this._pixiObject.fontName);
|
||||
|
@@ -50,14 +50,14 @@ namespace gdjs {
|
||||
_renderer: gdjs.BitmapTextRuntimeObjectPixiRenderer;
|
||||
|
||||
/**
|
||||
* @param runtimeScene The scene the object belongs to.
|
||||
* @param instanceContainer The container the object belongs to.
|
||||
* @param objectData The object data used to initialize the object
|
||||
*/
|
||||
constructor(
|
||||
runtimeScene: gdjs.RuntimeScene,
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
objectData: BitmapTextObjectData
|
||||
) {
|
||||
super(runtimeScene, objectData);
|
||||
super(instanceContainer, objectData);
|
||||
|
||||
this._opacity = objectData.content.opacity;
|
||||
this._text = objectData.content.text;
|
||||
@@ -73,7 +73,7 @@ namespace gdjs {
|
||||
|
||||
this._renderer = new gdjs.BitmapTextRuntimeObjectRenderer(
|
||||
this,
|
||||
runtimeScene
|
||||
instanceContainer
|
||||
);
|
||||
|
||||
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
|
||||
@@ -137,8 +137,8 @@ namespace gdjs {
|
||||
}
|
||||
}
|
||||
|
||||
onDestroyFromScene(runtimeScene: gdjs.RuntimeScene): void {
|
||||
super.onDestroyFromScene(runtimeScene);
|
||||
onDestroyFromScene(instanceContainer: gdjs.RuntimeInstanceContainer): void {
|
||||
super.onDestroyFromScene(instanceContainer);
|
||||
this._renderer.onDestroy();
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace gdjs {
|
||||
setText(text: string): void {
|
||||
this._text = text;
|
||||
this._renderer.updateTextContent();
|
||||
this.hitBoxesDirty = true;
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +170,7 @@ namespace gdjs {
|
||||
setScale(scale: float): void {
|
||||
this._scale = scale;
|
||||
this._renderer.updateScale();
|
||||
this.hitBoxesDirty = true;
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
|
||||
getScale(): float {
|
||||
@@ -276,7 +276,7 @@ namespace gdjs {
|
||||
setWrappingWidth(width: float): void {
|
||||
this._wrappingWidth = width;
|
||||
this._renderer.updateWrappingWidth();
|
||||
this.hitBoxesDirty = true;
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,7 +289,7 @@ namespace gdjs {
|
||||
setWordWrap(wordWrap: boolean): void {
|
||||
this._wordWrap = wordWrap;
|
||||
this._renderer.updateWrappingWidth();
|
||||
this.hitBoxesDirty = true;
|
||||
this.invalidateHitboxes();
|
||||
}
|
||||
|
||||
getWordWrap(): boolean {
|
||||
|
@@ -7,10 +7,12 @@ namespace gdjs {
|
||||
export namespace debuggerTools {
|
||||
/**
|
||||
* Stop the game execution.
|
||||
* @param runtimeScene - The current scene.
|
||||
* @param instanceContainer - The current container.
|
||||
*/
|
||||
export const pause = function (runtimeScene: gdjs.RuntimeScene) {
|
||||
runtimeScene.getGame().pause(true);
|
||||
export const pause = function (
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer
|
||||
) {
|
||||
instanceContainer.getGame().pause(true);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -29,20 +31,20 @@ namespace gdjs {
|
||||
|
||||
/**
|
||||
* Enable or disable the debug draw.
|
||||
* @param runtimeScene - The current scene.
|
||||
* @param instanceContainer - The current container.
|
||||
* @param enableDebugDraw - true to enable the debug draw, false to disable it.
|
||||
* @param showHiddenInstances - true to apply the debug draw to hidden objects.
|
||||
* @param showPointsNames - true to show point names.
|
||||
* @param showCustomPoints - true to show custom points of Sprite objects.
|
||||
*/
|
||||
export const enableDebugDraw = function (
|
||||
runtimeScene: gdjs.RuntimeScene,
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
enableDebugDraw: boolean,
|
||||
showHiddenInstances: boolean,
|
||||
showPointsNames: boolean,
|
||||
showCustomPoints: boolean
|
||||
) {
|
||||
runtimeScene.enableDebugDraw(
|
||||
instanceContainer.enableDebugDraw(
|
||||
enableDebugDraw,
|
||||
showHiddenInstances,
|
||||
showPointsNames,
|
||||
|
@@ -25,6 +25,7 @@ DestroyOutsideBehavior::GetProperties(
|
||||
.SetValue(gd::String::From(
|
||||
behaviorContent.GetDoubleAttribute("extraBorder", 0)))
|
||||
.SetType("Number")
|
||||
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
|
||||
.SetLabel(_("Margin before deleting the object, in pixels"));
|
||||
|
||||
return properties;
|
||||
|
@@ -20,6 +20,7 @@ void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension) {
|
||||
"or other short-lived objects."),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetCategory("Game mechanic")
|
||||
.SetExtensionHelpPath("/behaviors/destroyoutside");
|
||||
|
||||
gd::BehaviorMetadata& aut =
|
||||
|
@@ -11,8 +11,12 @@ namespace gdjs {
|
||||
export class DestroyOutsideRuntimeBehavior extends gdjs.RuntimeBehavior {
|
||||
_extraBorder: any;
|
||||
|
||||
constructor(runtimeScene, behaviorData, owner) {
|
||||
super(runtimeScene, behaviorData, owner);
|
||||
constructor(
|
||||
instanceContainer: gdjs.RuntimeInstanceContainer,
|
||||
behaviorData,
|
||||
owner
|
||||
) {
|
||||
super(instanceContainer, behaviorData, owner);
|
||||
this._extraBorder = behaviorData.extraBorder || 0;
|
||||
}
|
||||
|
||||
@@ -23,14 +27,14 @@ namespace gdjs {
|
||||
return true;
|
||||
}
|
||||
|
||||
doStepPostEvents(runtimeScene) {
|
||||
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
|
||||
// TODO: This would better be done using the object AABB (getAABB), as (`getCenterX`;`getCenterY`) point
|
||||
// is not necessarily in the middle of the object (for sprites for example).
|
||||
const ow = this.owner.getWidth();
|
||||
const oh = this.owner.getHeight();
|
||||
const ocx = this.owner.getDrawableX() + this.owner.getCenterX();
|
||||
const ocy = this.owner.getDrawableY() + this.owner.getCenterY();
|
||||
const layer = runtimeScene.getLayer(this.owner.getLayer());
|
||||
const layer = instanceContainer.getLayer(this.owner.getLayer());
|
||||
const boundingCircleRadius = Math.sqrt(ow * ow + oh * oh) / 2.0;
|
||||
if (
|
||||
ocx + boundingCircleRadius + this._extraBorder <
|
||||
@@ -43,7 +47,7 @@ namespace gdjs {
|
||||
layer.getCameraY() + layer.getCameraHeight() / 2
|
||||
) {
|
||||
//We are outside the camera area.
|
||||
this.owner.deleteFromScene(runtimeScene);
|
||||
this.owner.deleteFromScene(instanceContainer);
|
||||
}
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user