Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to use parameters and properties in the variable action and condition #7124

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
18 changes: 18 additions & 0 deletions Core/GDCore/Events/CodeGeneration/EventsCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1358,12 +1358,30 @@ gd::String EventsCodeGenerator::GeneratePropertyGetter(const gd::PropertiesConta
return "getProperty" + property.GetName() + "As" + type + "()";
}

gd::String EventsCodeGenerator::GeneratePropertyGetterWithoutCasting(
const gd::PropertiesContainer &propertiesContainer,
const gd::NamedPropertyDescriptor &property) {
return "getProperty" + property.GetName() + "()";
}

gd::String EventsCodeGenerator::GeneratePropertySetterWithoutCasting(
const gd::PropertiesContainer &propertiesContainer,
const gd::NamedPropertyDescriptor &property,
const gd::String &operandCode) {
return "setProperty" + property.GetName() + "(" + operandCode + ")";
}

gd::String EventsCodeGenerator::GenerateParameterGetter(const gd::ParameterMetadata& parameter,
const gd::String& type,
gd::EventsCodeGenerationContext& context) {
return "getParameter" + parameter.GetName() + "As" + type + "()";
}

gd::String EventsCodeGenerator::GenerateParameterGetterWithoutCasting(
const gd::ParameterMetadata &parameter) {
return "getParameter" + parameter.GetName() + "()";
}

EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
const gd::Layout& layout,
const gd::Platform& platform_)
Expand Down
12 changes: 12 additions & 0 deletions Core/GDCore/Events/CodeGeneration/EventsCodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,11 @@ class GD_CORE_API EventsCodeGenerator {
GenerateAnyOrSceneVariableGetter(const gd::Expression &variableExpression,
EventsCodeGenerationContext &context);

virtual gd::String GeneratePropertySetterWithoutCasting(
const gd::PropertiesContainer &propertiesContainer,
const gd::NamedPropertyDescriptor &property,
const gd::String &operandCode);

protected:
virtual const gd::String GenerateRelationalOperatorCodes(
const gd::String& operatorString);
Expand Down Expand Up @@ -627,11 +632,18 @@ class GD_CORE_API EventsCodeGenerator {
const gd::String& type,
gd::EventsCodeGenerationContext& context);

virtual gd::String GeneratePropertyGetterWithoutCasting(
const gd::PropertiesContainer &propertiesContainer,
const gd::NamedPropertyDescriptor &property);

virtual gd::String GenerateParameterGetter(
const gd::ParameterMetadata& parameter,
const gd::String& type,
gd::EventsCodeGenerationContext& context);

virtual gd::String
GenerateParameterGetterWithoutCasting(const gd::ParameterMetadata &parameter);

/**
* \brief Generate the code to reference an object which is
* in an empty/null state.
Expand Down
42 changes: 20 additions & 22 deletions Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,12 @@ void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) {
if (gd::ParameterMetadata::IsExpression("variable", type)) {
// The node is a variable inside an expression waiting for a *variable* to be returned, not its value.
EventsCodeGenerator::VariableScope scope =
type == "variable"
type == "variable" || type == "variableOrProperty" ||
type == "variableOrPropertyOrParameter"
? gd::EventsCodeGenerator::ANY_VARIABLE
: type == "globalvar"
? gd::EventsCodeGenerator::PROJECT_VARIABLE
: type == "scenevar"
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
: gd::EventsCodeGenerator::OBJECT_VARIABLE;
: type == "globalvar" ? gd::EventsCodeGenerator::PROJECT_VARIABLE
: type == "scenevar" ? gd::EventsCodeGenerator::LAYOUT_VARIABLE
: gd::EventsCodeGenerator::OBJECT_VARIABLE;

auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
codeGenerator.GetObjectsContainersList(),
Expand Down Expand Up @@ -222,23 +221,22 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
output +=
codeGenerator.GenerateObject(node.identifierName, type, context);
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
EventsCodeGenerator::VariableScope scope =
type == "variable"
EventsCodeGenerator::VariableScope scope =
type == "variable" || type == "variableOrProperty" ||
type == "variableOrPropertyOrParameter"
? gd::EventsCodeGenerator::ANY_VARIABLE
: type == "globalvar"
? gd::EventsCodeGenerator::PROJECT_VARIABLE
: type == "scenevar"
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
: gd::EventsCodeGenerator::OBJECT_VARIABLE;

auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
codeGenerator.GetObjectsContainersList(),
rootObjectName,
node);
output += codeGenerator.GenerateGetVariable(
node.identifierName, scope, context, objectName);
if (!node.childIdentifierName.empty()) {
output += codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
: type == "globalvar" ? gd::EventsCodeGenerator::PROJECT_VARIABLE
: type == "scenevar" ? gd::EventsCodeGenerator::LAYOUT_VARIABLE
: gd::EventsCodeGenerator::OBJECT_VARIABLE;

auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(
codeGenerator.GetPlatform(), codeGenerator.GetObjectsContainersList(),
rootObjectName, node);
output += codeGenerator.GenerateGetVariable(node.identifierName, scope,
context, objectName);
if (!node.childIdentifierName.empty()) {
output +=
codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
}
} else {
const auto& variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList();
Expand Down
12 changes: 6 additions & 6 deletions Core/GDCore/Extensions/Builtin/VariablesExtension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"",
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("variable", _("Variable"))
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions());

Expand All @@ -45,7 +45,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"",
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("variable", _("Variable"))
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions());

Expand All @@ -58,7 +58,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"",
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("variable", _("Variable"))
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
.AddParameter("trueorfalse", _("Check if the value is"))
.SetDefaultValue("true")
// This parameter allows to keep the operand expression
Expand All @@ -73,7 +73,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"",
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Variable"))
.AddParameter("variableOrProperty", _("Variable"))
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions());

Expand All @@ -85,7 +85,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"",
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Variable"))
.AddParameter("variableOrProperty", _("Variable"))
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions());

Expand All @@ -98,7 +98,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"",
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("variable", _("Variable"))
.AddParameter("variableOrProperty", _("Variable"))
.AddParameter("operator", _("Value"), "boolean")
// This parameter allows to keep the operand expression
// when the editor switch between variable instructions.
Expand Down
5 changes: 3 additions & 2 deletions Core/GDCore/Extensions/Metadata/ParameterMetadataTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ void ParameterMetadataTools::ParametersToObjectsContainer(
const auto& parameter = parameters.GetParameter(i);
if (parameter.GetName().empty()) continue;

if (gd::ParameterMetadata::IsObject(parameter.GetType())) {
auto &valueTypeMetadata = parameter.GetValueTypeMetadata();
if (valueTypeMetadata.IsObject()) {
outputObjectsContainer.InsertNewObject(
project,
parameter.GetExtraInfo(),
Expand All @@ -43,7 +44,7 @@ void ParameterMetadataTools::ParametersToObjectsContainer(
// Search "lastObjectName" in the codebase for other place where this
// convention is enforced.
lastObjectName = parameter.GetName();
} else if (gd::ParameterMetadata::IsBehavior(parameter.GetType())) {
} else if (valueTypeMetadata.IsBehavior()) {
if (!lastObjectName.empty()) {
if (outputObjectsContainer.HasObjectNamed(lastObjectName)) {
const gd::Object& object =
Expand Down
11 changes: 7 additions & 4 deletions Core/GDCore/Extensions/Metadata/ValueTypeMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,13 @@ class GD_CORE_API ValueTypeMetadata {
return parameterType == "yesorno" || parameterType == "trueorfalse";
} else if (type == "variable") {
return
parameterType == "variable" || // Any variable.
// Old, "pre-scoped" variables:
parameterType == "objectvar" || parameterType == "globalvar" ||
parameterType == "scenevar";
// Any variable.
parameterType == "variable" ||
parameterType == "variableOrProperty" ||
parameterType == "variableOrPropertyOrParameter" ||
// Old, "pre-scoped" variables:
parameterType == "objectvar" || parameterType == "globalvar" ||
parameterType == "scenevar";
} else if (type == "resource") {
return parameterType == "fontResource" ||
parameterType == "audioResource" ||
Expand Down
9 changes: 7 additions & 2 deletions Core/GDCore/IDE/Events/ExpressionValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ const gd::String& ExpressionValidator::TypeToString(Type type) {
case Type::NumberOrString:
return numberOrStringTypeString;
case Type::Variable:
case Type::VariableOrProperty:
case Type::VariableOrPropertyOrParameter:
return variableTypeString;
case Type::LegacyVariable:
// This function is only used to display error.
Expand Down Expand Up @@ -493,8 +495,11 @@ ExpressionValidator::Type ExpressionValidator::StringToType(
ExpressionValidator::variableTypeString, type)) {
if (gd::ValueTypeMetadata::IsTypeLegacyPreScopedVariable(type)) {
return Type::LegacyVariable;
}
else {
} else if (type == "variableOrProperty") {
return Type::VariableOrProperty;
} else if (type == "variableOrPropertyOrParameter") {
return Type::VariableOrPropertyOrParameter;
} else {
return Type::Variable;
}
}
Expand Down
54 changes: 36 additions & 18 deletions Core/GDCore/IDE/Events/ExpressionValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,9 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
void OnVisitVariableNode(VariableNode& node) override {
ReportAnyError(node);

if (parentType == Type::Variable) {
if (parentType == Type::Variable ||
parentType == Type::VariableOrProperty ||
parentType == Type::VariableOrPropertyOrParameter) {
childType = parentType;

CheckVariableExistence(node.location, node.name);
Expand All @@ -216,7 +218,8 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
if (node.child) {
node.child->Visit(*this);
}
} else if (parentType == Type::String || parentType == Type::Number || parentType == Type::NumberOrString) {
} else if (parentType == Type::String || parentType == Type::Number ||
parentType == Type::NumberOrString) {
// The node represents a variable or an object variable in an expression waiting for its *value* to be returned.
childType = parentType;

Expand Down Expand Up @@ -336,11 +339,12 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
_("You must enter a number or a text, wrapped inside double quotes (example: \"Hello world\"), or a variable name."),
node.location);
}
}
else if (parentType == Type::Variable) {
} else if (parentType == Type::Variable ||
parentType == Type::VariableOrProperty ||
parentType == Type::VariableOrPropertyOrParameter) {
CheckVariableExistence(node.location, node.identifierName);
}
else if (parentType != Type::Object && parentType != Type::LegacyVariable) {
} else if (parentType != Type::Object &&
parentType != Type::LegacyVariable) {
// It can't happen.
RaiseTypeError(
_("You've entered a name, but this type was expected:") + " " + TypeToString(parentType),
Expand Down Expand Up @@ -376,8 +380,19 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
childType = Type::Empty;
}

private:
enum Type {Unknown = 0, Number, String, NumberOrString, Variable, LegacyVariable, Object, Empty};
private:
enum Type {
Unknown = 0,
Number,
String,
NumberOrString,
Variable,
LegacyVariable,
Object,
Empty,
VariableOrProperty,
VariableOrPropertyOrParameter
};
Type ValidateFunction(const gd::FunctionCallNode& function);
bool ValidateObjectVariableOrVariableOrProperty(const gd::IdentifierNode& identifier);
bool ValidateObjectVariableOrVariableOrProperty(
Expand All @@ -402,19 +417,22 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
},
[&]() {
// This is a property.
// This error won't happen unless the priority is changed.
RaiseVariableNameCollisionError(
_("This variable has the same name as a property. Consider "
"renaming one or the other."),
location, name);
if (parentType != Type::VariableOrProperty &&
parentType != Type::VariableOrPropertyOrParameter) {
RaiseVariableNameCollisionError(
_("This variable has the same name as a property. Consider "
"renaming one or the other."),
location, name);
}
},
[&]() {
// This is a parameter.
// This error won't happen unless the priority is changed.
RaiseVariableNameCollisionError(
_("This variable has the same name as a parameter. Consider "
"renaming one or the other."),
location, name);
if (parentType != Type::VariableOrPropertyOrParameter) {
RaiseVariableNameCollisionError(
_("This variable has the same name as a parameter. Consider "
"renaming one or the other."),
location, name);
}
},
[&]() {
// This is something else.
Expand Down
24 changes: 20 additions & 4 deletions Core/GDCore/IDE/Events/ExpressionVariablePathFinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,28 @@ class GD_CORE_API ExpressionVariablePathFinder
}
},
[&]() {
// Ignore properties here.
// There is no support for "children" of properties.
// This is a property.
if (parameterType != "objectvar" &&
projectScopedContainers.GetVariablesContainersList().Has(
identifier)) {
variablesContainer =
&(projectScopedContainers.GetVariablesContainersList()
.GetVariablesContainerFromVariableName(identifier));
variableName = identifier;
// There is no support for "children" of properties.
}
},
[&]() {
// Ignore parameters here.
// There is no support for "children" of parameters.
// This is a parameter.
if (parameterType != "objectvar" &&
projectScopedContainers.GetVariablesContainersList().Has(
identifier)) {
variablesContainer =
&(projectScopedContainers.GetVariablesContainersList()
.GetVariablesContainerFromVariableName(identifier));
variableName = identifier;
// There is no support for "children" of parameters.
}
},
[&]() {
// Ignore unrecognised identifiers here.
Expand Down
Loading
Loading