diff --git a/Core/GDCore/Events/CodeGeneration/EventsCodeGenerator.h b/Core/GDCore/Events/CodeGeneration/EventsCodeGenerator.h index 79f3c8ce04d4..e5ddafd15eaa 100644 --- a/Core/GDCore/Events/CodeGeneration/EventsCodeGenerator.h +++ b/Core/GDCore/Events/CodeGeneration/EventsCodeGenerator.h @@ -467,7 +467,14 @@ class GD_CORE_API EventsCodeGenerator { */ virtual gd::String GetCodeNamespace() { return ""; }; - enum VariableScope { LAYOUT_VARIABLE = 0, PROJECT_VARIABLE, OBJECT_VARIABLE, ANY_VARIABLE }; + enum VariableScope { + LAYOUT_VARIABLE = 0, + PROJECT_VARIABLE, + OBJECT_VARIABLE, + ANY_VARIABLE, + VARIABLE_OR_PROPERTY, + VARIABLE_OR_PROPERTY_OR_PARAMETER + }; /** * Generate a single unique number for the specified instruction. @@ -579,7 +586,9 @@ class GD_CORE_API EventsCodeGenerator { } else if (scope == PROJECT_VARIABLE) { return "getProjectVariable(" + variableName + ")"; - } else if (scope == ANY_VARIABLE) { + } else if (scope == ANY_VARIABLE || scope == VARIABLE_OR_PROPERTY || + scope == VARIABLE_OR_PROPERTY_OR_PARAMETER) { + // TODO Split the 3 cases to make tests stronger. return "getAnyVariable(" + variableName + ")"; } diff --git a/Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.cpp b/Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.cpp index 9ec8b8a155b6..86aca52b5fc7 100644 --- a/Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.cpp +++ b/Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.cpp @@ -133,9 +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 == "variableOrProperty" || - type == "variableOrPropertyOrParameter" + type == "variable" ? gd::EventsCodeGenerator::ANY_VARIABLE + : type == "variableOrProperty" + ? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY + : type == "variableOrPropertyOrParameter" + ? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY_OR_PARAMETER : type == "globalvar" ? gd::EventsCodeGenerator::PROJECT_VARIABLE : type == "scenevar" ? gd::EventsCodeGenerator::LAYOUT_VARIABLE : gd::EventsCodeGenerator::OBJECT_VARIABLE; @@ -223,9 +226,12 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) { codeGenerator.GenerateObject(node.identifierName, type, context); } else if (gd::ParameterMetadata::IsExpression("variable", type)) { EventsCodeGenerator::VariableScope scope = - type == "variable" || type == "variableOrProperty" || - type == "variableOrPropertyOrParameter" + type == "variable" ? gd::EventsCodeGenerator::ANY_VARIABLE + : type == "variableOrProperty" + ? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY + : type == "variableOrPropertyOrParameter" + ? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY_OR_PARAMETER : type == "globalvar" ? gd::EventsCodeGenerator::PROJECT_VARIABLE : type == "scenevar" ? gd::EventsCodeGenerator::LAYOUT_VARIABLE : gd::EventsCodeGenerator::OBJECT_VARIABLE; @@ -254,7 +260,7 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) { output += codeGenerator.GenerateVariableValueAs(type); }, [&]() { output += codeGenerator.GenerateGetVariable( - node.identifierName, gd::EventsCodeGenerator::ANY_VARIABLE, context, + node.identifierName, gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY_OR_PARAMETER, context, "", !node.childIdentifierName.empty()); if (!node.childIdentifierName.empty()) { output += codeGenerator.GenerateVariableAccessor(node.childIdentifierName); diff --git a/Core/GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.cpp b/Core/GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.cpp index a580c70cc4e4..de6e4864747a 100644 --- a/Core/GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.cpp +++ b/Core/GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.cpp @@ -71,13 +71,18 @@ bool EventsVariableInstructionTypeSwitcher::DoVisitInstruction(gd::Instruction& .GetObjectsContainersList() .GetObjectOrGroupVariablesContainer(lastObjectName); } + } else if (type == "variableOrProperty") { + variablesContainer = + &GetProjectScopedContainers() + .GetVariablesContainersList() + .GetVariablesContainerFromVariableOrPropertyName(variableName); } else { if (GetProjectScopedContainers().GetVariablesContainersList().Has( variableName)) { variablesContainer = &GetProjectScopedContainers() .GetVariablesContainersList() - .GetVariablesContainerFromVariableName(variableName); + .GetVariablesContainerFromVariableOrPropertyOrParameterName(variableName); } } diff --git a/Core/GDCore/IDE/Events/EventsVariableReplacer.cpp b/Core/GDCore/IDE/Events/EventsVariableReplacer.cpp index 966d2159fcc8..b51620848ad9 100644 --- a/Core/GDCore/IDE/Events/EventsVariableReplacer.cpp +++ b/Core/GDCore/IDE/Events/EventsVariableReplacer.cpp @@ -122,7 +122,7 @@ class GD_CORE_API ExpressionVariableReplacer [&]() { // This is a variable. if (&projectScopedContainers.GetVariablesContainersList() - .GetVariablesContainerFromVariableName(node.name) == + .GetVariablesContainerFromVariableOrPropertyOrParameterName(node.name) == &targetVariablesContainer) { // The node represents a variable, that can come from the target // (because the target is in the scope), replace or remove it: @@ -235,7 +235,7 @@ class GD_CORE_API ExpressionVariableReplacer [&]() { // This is a variable. if (&projectScopedContainers.GetVariablesContainersList() - .GetVariablesContainerFromVariableName( + .GetVariablesContainerFromVariableOrPropertyOrParameterName( node.identifierName) == &targetVariablesContainer) { // The node represents a variable, that can come from the target // (because the target is in the scope), replace or remove it: diff --git a/Core/GDCore/IDE/Events/ExpressionCompletionFinder.h b/Core/GDCore/IDE/Events/ExpressionCompletionFinder.h index 6e79568f6a2a..7cbd53e941ce 100644 --- a/Core/GDCore/IDE/Events/ExpressionCompletionFinder.h +++ b/Core/GDCore/IDE/Events/ExpressionCompletionFinder.h @@ -1034,7 +1034,7 @@ class GD_CORE_API ExpressionCompletionFinder description.SetVariableType(variable.GetType()); description.SetVariableScope( projectScopedContainers.GetVariablesContainersList() - .GetVariablesContainerFromVariableName(variableName) + .GetVariablesContainerFromVariableOrPropertyOrParameterName(variableName) .GetSourceType()); completions.push_back(description); @@ -1086,7 +1086,7 @@ class GD_CORE_API ExpressionCompletionFinder description.SetVariableType(variable.GetType()); description.SetVariableScope( projectScopedContainers.GetVariablesContainersList() - .GetVariablesContainerFromVariableName(variableName) + .GetVariablesContainerFromVariableOrPropertyOrParameterName(variableName) .GetSourceType()); completions.push_back(description); diff --git a/Core/GDCore/IDE/Events/ExpressionVariablePathFinder.h b/Core/GDCore/IDE/Events/ExpressionVariablePathFinder.h index 36ed811a960d..5299bd54918c 100644 --- a/Core/GDCore/IDE/Events/ExpressionVariablePathFinder.h +++ b/Core/GDCore/IDE/Events/ExpressionVariablePathFinder.h @@ -215,7 +215,7 @@ class GD_CORE_API ExpressionVariablePathFinder if (projectScopedContainers.GetVariablesContainersList().Has(identifier)) { variablesContainer = &(projectScopedContainers.GetVariablesContainersList() - .GetVariablesContainerFromVariableName(identifier)); + .GetVariablesContainerFromVariableOrPropertyOrParameterName(identifier)); variableName = identifier; if (childIdentifier) { childVariableNames.push_back(*childIdentifier); @@ -229,7 +229,7 @@ class GD_CORE_API ExpressionVariablePathFinder identifier)) { variablesContainer = &(projectScopedContainers.GetVariablesContainersList() - .GetVariablesContainerFromVariableName(identifier)); + .GetVariablesContainerFromVariableOrPropertyOrParameterName(identifier)); variableName = identifier; // There is no support for "children" of properties. } @@ -241,7 +241,7 @@ class GD_CORE_API ExpressionVariablePathFinder identifier)) { variablesContainer = &(projectScopedContainers.GetVariablesContainersList() - .GetVariablesContainerFromVariableName(identifier)); + .GetVariablesContainerFromVariableOrPropertyOrParameterName(identifier)); variableName = identifier; // There is no support for "children" of parameters. } diff --git a/Core/GDCore/Project/ProjectScopedContainers.h b/Core/GDCore/Project/ProjectScopedContainers.h index 3cb77988e02b..ba1419b9b6df 100644 --- a/Core/GDCore/Project/ProjectScopedContainers.h +++ b/Core/GDCore/Project/ProjectScopedContainers.h @@ -131,7 +131,7 @@ class ProjectScopedContainers { return objectCallback(); else if (variablesContainersList.Has(name)) { const auto &variablesContainer = - variablesContainersList.GetVariablesContainerFromVariableName(name); + variablesContainersList.GetVariablesContainerFromVariableOrPropertyOrParameterName(name); const auto sourceType = variablesContainer.GetSourceType(); if (sourceType == gd::VariablesContainer::SourceType::Properties) { return propertyCallback(); diff --git a/Core/GDCore/Project/VariablesContainersList.cpp b/Core/GDCore/Project/VariablesContainersList.cpp index 683663ae7405..bbe4b9bf7d15 100644 --- a/Core/GDCore/Project/VariablesContainersList.cpp +++ b/Core/GDCore/Project/VariablesContainersList.cpp @@ -147,7 +147,7 @@ const Variable& VariablesContainersList::Get(const gd::String& name) const { } const VariablesContainer & -VariablesContainersList::GetVariablesContainerFromVariableName( +VariablesContainersList::GetVariablesContainerFromVariableOrPropertyOrParameterName( const gd::String &variableName) const { for (auto it = variablesContainers.rbegin(); it != variablesContainers.rend(); ++it) { @@ -157,6 +157,34 @@ VariablesContainersList::GetVariablesContainerFromVariableName( return badVariablesContainer; } +const VariablesContainer &VariablesContainersList:: + GetVariablesContainerFromVariableOrPropertyName( + const gd::String &variableName) const { + for (auto it = variablesContainers.rbegin(); it != variablesContainers.rend(); + ++it) { + if ((*it)->GetSourceType() != + gd::VariablesContainer::SourceType::Parameters && + (*it)->Has(variableName)) + return **it; + } + return badVariablesContainer; +} + +const VariablesContainer &VariablesContainersList:: + GetVariablesContainerFromVariableNameOnly( + const gd::String &variableName) const { + for (auto it = variablesContainers.rbegin(); it != variablesContainers.rend(); + ++it) { + if ((*it)->GetSourceType() != + gd::VariablesContainer::SourceType::Parameters && + (*it)->GetSourceType() != + gd::VariablesContainer::SourceType::Properties && + (*it)->Has(variableName)) + return **it; + } + return badVariablesContainer; +} + std::size_t VariablesContainersList::GetVariablesContainerPositionFromVariableName( const gd::String &variableName) const { diff --git a/Core/GDCore/Project/VariablesContainersList.h b/Core/GDCore/Project/VariablesContainersList.h index 0b481eea7b6d..d9f196e22cc2 100644 --- a/Core/GDCore/Project/VariablesContainersList.h +++ b/Core/GDCore/Project/VariablesContainersList.h @@ -114,11 +114,23 @@ class GD_CORE_API VariablesContainersList { return variablesContainers.at(firstLocalVariableContainerIndex - 1); } + /** + * Get the variables container for a given variable or property or parameter. + */ + const VariablesContainer & + GetVariablesContainerFromVariableOrPropertyOrParameterName(const gd::String &variableName) const; + + /** + * Get the variables container for a given variable or property. + */ + const VariablesContainer & + GetVariablesContainerFromVariableOrPropertyName(const gd::String &variableName) const; + /** * Get the variables container for a given variable. */ const VariablesContainer & - GetVariablesContainerFromVariableName(const gd::String &variableName) const; + GetVariablesContainerFromVariableNameOnly(const gd::String &variableName) const; /** * Get the variables container index for a given variable. diff --git a/Core/tests/WholeProjectRefactorer-ApplyRefactoringForVariablesContainer.cpp b/Core/tests/WholeProjectRefactorer-ApplyRefactoringForVariablesContainer.cpp index 4d9e87e8dd86..738f184a1087 100644 --- a/Core/tests/WholeProjectRefactorer-ApplyRefactoringForVariablesContainer.cpp +++ b/Core/tests/WholeProjectRefactorer-ApplyRefactoringForVariablesContainer.cpp @@ -1540,7 +1540,7 @@ TEST_CASE("WholeProjectRefactorer::ApplyRefactoringForVariablesContainer", auto projectScopedContainers = gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, scene); REQUIRE(&projectScopedContainers.GetVariablesContainersList() - .GetVariablesContainerFromVariableName("MyVariable") == &scene.GetVariables()); + .GetVariablesContainerFromVariableOrPropertyOrParameterName("MyVariable") == &scene.GetVariables()); // Do the changes and launch the refactoring. scene.GetVariables().ResetPersistentUuid(); diff --git a/GDJS/GDJS/Events/CodeGeneration/EventsCodeGenerator.cpp b/GDJS/GDJS/Events/CodeGeneration/EventsCodeGenerator.cpp index bd062712b344..bf16087e3d19 100644 --- a/GDJS/GDJS/Events/CodeGeneration/EventsCodeGenerator.cpp +++ b/GDJS/GDJS/Events/CodeGeneration/EventsCodeGenerator.cpp @@ -1363,12 +1363,21 @@ gd::String EventsCodeGenerator::GenerateGetVariable( bool hasChild) { gd::String output; const gd::VariablesContainer* variables = NULL; - if (scope == ANY_VARIABLE) { + if (scope == ANY_VARIABLE || scope == VARIABLE_OR_PROPERTY || + scope == VARIABLE_OR_PROPERTY_OR_PARAMETER) { const auto variablesContainersList = GetProjectScopedContainers().GetVariablesContainersList(); - const auto& variablesContainer = - variablesContainersList.GetVariablesContainerFromVariableName( - variableName); + const auto &variablesContainer = + scope == VARIABLE_OR_PROPERTY_OR_PARAMETER + ? variablesContainersList.GetVariablesContainerFromVariableOrPropertyOrParameterName( + variableName) + : scope == VARIABLE_OR_PROPERTY + ? variablesContainersList + .GetVariablesContainerFromVariableOrPropertyName( + variableName) + : variablesContainersList + .GetVariablesContainerFromVariableNameOnly( + variableName); const auto sourceType = variablesContainer.GetSourceType(); if (sourceType == gd::VariablesContainer::SourceType::Scene) { variables = &variablesContainer; diff --git a/GDJS/GDJS/Extensions/Builtin/VariablesExtension.cpp b/GDJS/GDJS/Extensions/Builtin/VariablesExtension.cpp index 0cdf7082a819..ce99698bac4a 100644 --- a/GDJS/GDJS/Extensions/Builtin/VariablesExtension.cpp +++ b/GDJS/GDJS/Extensions/Builtin/VariablesExtension.cpp @@ -44,7 +44,7 @@ VariablesExtension::VariablesExtension() { const auto variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList(); const auto& variablesContainer = - variablesContainersList.GetVariablesContainerFromVariableName( + variablesContainersList.GetVariablesContainerFromVariableOrPropertyOrParameterName( variableName); const auto sourceType = variablesContainer.GetSourceType(); if (sourceType != gd::VariablesContainer::SourceType::Properties && @@ -75,7 +75,7 @@ VariablesExtension::VariablesExtension() { const auto variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList(); const auto& variablesContainer = - variablesContainersList.GetVariablesContainerFromVariableName( + variablesContainersList.GetVariablesContainerFromVariableOrPropertyOrParameterName( variableName); const auto sourceType = variablesContainer.GetSourceType(); if (sourceType != gd::VariablesContainer::SourceType::Properties && @@ -107,7 +107,7 @@ VariablesExtension::VariablesExtension() { const auto variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList(); const auto& variablesContainer = - variablesContainersList.GetVariablesContainerFromVariableName( + variablesContainersList.GetVariablesContainerFromVariableOrPropertyOrParameterName( variableName); const auto sourceType = variablesContainer.GetSourceType(); if (sourceType != gd::VariablesContainer::SourceType::Properties && @@ -181,7 +181,7 @@ VariablesExtension::VariablesExtension() { const auto variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList(); const auto& variablesContainer = - variablesContainersList.GetVariablesContainerFromVariableName( + variablesContainersList.GetVariablesContainerFromVariableOrPropertyName( variableName); const auto sourceType = variablesContainer.GetSourceType(); if (sourceType == gd::VariablesContainer::SourceType::Properties) { @@ -244,7 +244,7 @@ VariablesExtension::VariablesExtension() { const auto variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList(); const auto& variablesContainer = - variablesContainersList.GetVariablesContainerFromVariableName( + variablesContainersList.GetVariablesContainerFromVariableOrPropertyName( variableName); const auto sourceType = variablesContainer.GetSourceType(); if (sourceType == gd::VariablesContainer::SourceType::Properties) { @@ -304,7 +304,7 @@ VariablesExtension::VariablesExtension() { const auto variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList(); const auto& variablesContainer = - variablesContainersList.GetVariablesContainerFromVariableName( + variablesContainersList.GetVariablesContainerFromVariableOrPropertyName( variableName); const auto sourceType = variablesContainer.GetSourceType(); if (sourceType == gd::VariablesContainer::SourceType::Properties) { diff --git a/GDevelop.js/Bindings/Bindings.idl b/GDevelop.js/Bindings/Bindings.idl index 845cc7eb43d8..b015d46aa01c 100644 --- a/GDevelop.js/Bindings/Bindings.idl +++ b/GDevelop.js/Bindings/Bindings.idl @@ -341,7 +341,9 @@ interface VariablesContainer { interface VariablesContainersList { boolean Has([Const] DOMString name); [Const, Ref] Variable Get([Const] DOMString name); - [Const, Ref] VariablesContainer GetVariablesContainerFromVariableName([Const] DOMString variableName); + [Const, Ref] VariablesContainer GetVariablesContainerFromVariableOrPropertyOrParameterName([Const] DOMString variableName); + [Const, Ref] VariablesContainer GetVariablesContainerFromVariableOrPropertyName([Const] DOMString variableName); + [Const, Ref] VariablesContainer GetVariablesContainerFromVariableNameOnly([Const] DOMString variableName); [Const, Ref] VariablesContainer GetVariablesContainer(unsigned long index); unsigned long GetVariablesContainersCount(); diff --git a/GDevelop.js/__tests__/GDJSBehaviorCodeGenerationIntegrationTests.js b/GDevelop.js/__tests__/GDJSBehaviorCodeGenerationIntegrationTests.js index e957c5c12fea..4ff6eef70edf 100644 --- a/GDevelop.js/__tests__/GDJSBehaviorCodeGenerationIntegrationTests.js +++ b/GDevelop.js/__tests__/GDJSBehaviorCodeGenerationIntegrationTests.js @@ -260,6 +260,71 @@ describe('libGD.js - GDJS Behavior Code Generation integration tests', function expect(behavior._getMyProperty()).toBe(456); }); + it('Can use a property in a variable action when a parameter with the same name exits', () => { + const project = new gd.ProjectHelper.createNewGDJSProject(); + const eventsFunctionsExtension = project.insertNewEventsFunctionsExtension( + 'MyExtension', + 0 + ); + const eventsBasedBehavior = eventsFunctionsExtension + .getEventsBasedBehaviors() + .insertNew('MyBehavior', 0); + + eventsBasedBehavior + .getPropertyDescriptors() + .insertNew('MyIdentifier', 0) + .setValue('123') + .setType('Number'); + + const eventsSerializerElement = gd.Serializer.fromJSObject([ + { + type: 'BuiltinCommonInstructions::Standard', + conditions: [], + actions: [ + { + type: { value: 'SetNumberVariable' }, + parameters: ['MyIdentifier', '=', '456'], + }, + ], + }, + ]); + eventsBasedBehavior + .getEventsFunctions() + .insertNewEventsFunction('MyFunction', 0) + .getEvents() + .unserializeFrom(project, eventsSerializerElement); + gd.WholeProjectRefactorer.ensureBehaviorEventsFunctionsProperParameters( + eventsFunctionsExtension, + eventsBasedBehavior + ); + // Add a parameter with the same name as the property. + // It won't be used as SetNumberVariable has a variableOrProperty parameter. + const eventsFunction = eventsBasedBehavior + .getEventsFunctions() + .insertNewEventsFunction('MyFunction', 0); + const parameter = eventsFunction + .getParameters() + .insertNewParameter( + 'MyIdentifier', + eventsFunction.getParameters().getParametersCount() + ); + parameter.setType('number'); + + const { runtimeScene, behavior } = generatedBehavior( + gd, + project, + eventsFunctionsExtension, + eventsBasedBehavior, + { logCode: false } + ); + + // Check the default value is set. + expect(behavior._getMyIdentifier()).toBe(123); + + behavior.MyFunction(222); + expect(behavior._getMyIdentifier()).toBe(456); + }); + it('Can use a property in a variable condition', () => { const project = new gd.ProjectHelper.createNewGDJSProject(); const scene = project.insertNewLayout('MyScene', 0); diff --git a/GDevelop.js/types.d.ts b/GDevelop.js/types.d.ts index 6c480b6921d1..527760e82a7a 100644 --- a/GDevelop.js/types.d.ts +++ b/GDevelop.js/types.d.ts @@ -361,7 +361,9 @@ export class VariablesContainer extends EmscriptenObject { export class VariablesContainersList extends EmscriptenObject { has(name: string): boolean; get(name: string): Variable; - getVariablesContainerFromVariableName(variableName: string): VariablesContainer; + getVariablesContainerFromVariableOrPropertyOrParameterName(variableName: string): VariablesContainer; + getVariablesContainerFromVariableOrPropertyName(variableName: string): VariablesContainer; + getVariablesContainerFromVariableNameOnly(variableName: string): VariablesContainer; getVariablesContainer(index: number): VariablesContainer; getVariablesContainersCount(): number; } diff --git a/GDevelop.js/types/gdvariablescontainerslist.js b/GDevelop.js/types/gdvariablescontainerslist.js index c6666e3f30dd..8087c5d3c1be 100644 --- a/GDevelop.js/types/gdvariablescontainerslist.js +++ b/GDevelop.js/types/gdvariablescontainerslist.js @@ -2,7 +2,9 @@ declare class gdVariablesContainersList { has(name: string): boolean; get(name: string): gdVariable; - getVariablesContainerFromVariableName(variableName: string): gdVariablesContainer; + getVariablesContainerFromVariableOrPropertyOrParameterName(variableName: string): gdVariablesContainer; + getVariablesContainerFromVariableOrPropertyName(variableName: string): gdVariablesContainer; + getVariablesContainerFromVariableNameOnly(variableName: string): gdVariablesContainer; getVariablesContainer(index: number): gdVariablesContainer; getVariablesContainersCount(): number; delete(): void; diff --git a/newIDE/app/src/EventsSheet/EventsTree/Renderers/ForEachChildVariableEvent.js b/newIDE/app/src/EventsSheet/EventsTree/Renderers/ForEachChildVariableEvent.js index 2bd7332de53d..a05e5b9d8731 100644 --- a/newIDE/app/src/EventsSheet/EventsTree/Renderers/ForEachChildVariableEvent.js +++ b/newIDE/app/src/EventsSheet/EventsTree/Renderers/ForEachChildVariableEvent.js @@ -14,10 +14,9 @@ import { } from '../ClassNames'; import InlinePopover from '../../InlinePopover'; import AnyVariableField from '../../ParameterFields/AnyVariableField'; -import { - getVariableSourceIcon, - getVariablesContainerSourceType, -} from '../../ParameterFields/VariableField'; +import { getVariableSourceIcon } from '../../ParameterFields/VariableField'; +import { getVariableSourceFromIdentifier } from '../../ParameterFields/AnyVariableField'; + import { type ParameterFieldInterface } from '../../ParameterFields/ParameterFieldCommons'; import { type EventRendererProps } from './EventRenderer'; import ConditionsActionsColumns from '../ConditionsActionsColumns'; @@ -31,9 +30,9 @@ export const getVariableSourceOrSceneIcon = ( projectScopedContainersAccessor: ProjectScopedContainersAccessor, variableName: string ) => { - const variablesContainerSourceType = getVariablesContainerSourceType( - projectScopedContainersAccessor, - variableName + const variablesContainerSourceType = getVariableSourceFromIdentifier( + variableName, + projectScopedContainersAccessor.get() ); return getVariableSourceIcon( variablesContainerSourceType === gd.VariablesContainer.Unknown diff --git a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableField.js b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableField.js index a4093362d300..2c2147d19566 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableField.js @@ -121,6 +121,7 @@ export default React.forwardRef( : undefined } onInstructionTypeChanged={onInstructionTypeChanged} + getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} /> {editorOpen && ( ( } ); +export const getVariableSourceFromIdentifier = ( + variableName: string, + projectScopedContainers: gdProjectScopedContainers +): VariablesContainer_SourceType => { + const rootVariableName = getRootVariableName(variableName); + const variablesContainersList = projectScopedContainers.getVariablesContainersList(); + return variablesContainersList.has(rootVariableName) + ? variablesContainersList + .getVariablesContainerFromVariableNameOnly(rootVariableName) + .getSourceType() + : gd.VariablesContainer.Unknown; +}; + export const renderInlineAnyVariable = (props: ParameterInlineRendererProps) => - renderVariableWithIcon(props, 'variable'); + renderVariableWithIcon(props, 'variable', getVariableSourceFromIdentifier); diff --git a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyField.js b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyField.js index a352d2a27a3a..3f3cce7dcf58 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyField.js @@ -119,6 +119,7 @@ export default React.forwardRef( : undefined } onInstructionTypeChanged={onInstructionTypeChanged} + getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} /> {editorOpen && ( ( } ); +export const getVariableSourceFromIdentifier = ( + variableName: string, + projectScopedContainers: gdProjectScopedContainers +): VariablesContainer_SourceType => { + const rootVariableName = getRootVariableName(variableName); + const variablesContainersList = projectScopedContainers.getVariablesContainersList(); + return variablesContainersList.has(rootVariableName) + ? variablesContainersList + .getVariablesContainerFromVariableOrPropertyName(rootVariableName) + .getSourceType() + : gd.VariablesContainer.Unknown; +}; + export const renderInlineAnyVariableOrProperty = ( props: ParameterInlineRendererProps -) => renderVariableWithIcon(props, 'variable'); +) => renderVariableWithIcon(props, 'variable', getVariableSourceFromIdentifier); diff --git a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyOrParameterField.js b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyOrParameterField.js index 2eae9458a193..f38c6268723a 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyOrParameterField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/AnyVariableOrPropertyOrParameterField.js @@ -16,6 +16,8 @@ import { import { enumerateVariablesOrPropertiesOrParametersOfContainersList } from './EnumerateVariables'; import { mapFor } from '../../Utils/MapFor'; +const gd: libGDevelop = global.gd; + export default React.forwardRef( function AnyVariableField(props: ParameterFieldProps, ref) { const field = React.useRef(null); @@ -113,6 +115,7 @@ export default React.forwardRef( : undefined } onInstructionTypeChanged={onInstructionTypeChanged} + getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} /> {editorOpen && ( ( } ); +export const getVariableSourceFromIdentifier = ( + variableName: string, + projectScopedContainers: gdProjectScopedContainers +): VariablesContainer_SourceType => { + const rootVariableName = getRootVariableName(variableName); + const variablesContainersList = projectScopedContainers.getVariablesContainersList(); + return variablesContainersList.has(rootVariableName) + ? variablesContainersList + .getVariablesContainerFromVariableOrPropertyOrParameterName( + rootVariableName + ) + .getSourceType() + : gd.VariablesContainer.Unknown; +}; + export const renderInlineAnyVariableOrPropertyOrParameter = ( props: ParameterInlineRendererProps -) => renderVariableWithIcon(props, 'variable'); +) => renderVariableWithIcon(props, 'variable', getVariableSourceFromIdentifier); diff --git a/newIDE/app/src/EventsSheet/ParameterFields/GlobalVariableField.js b/newIDE/app/src/EventsSheet/ParameterFields/GlobalVariableField.js index 020ae7b57936..097e278b1b0c 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/GlobalVariableField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/GlobalVariableField.js @@ -13,7 +13,8 @@ import { type FieldFocusFunction, } from './ParameterFieldCommons'; import { enumerateVariables } from './EnumerateVariables'; -import GlobalVariableIcon from '../../UI/CustomSvgIcons/GlobalVariable'; + +const gd: libGDevelop = global.gd; export default React.forwardRef( function GlobalVariableField(props: ParameterFieldProps, ref) { @@ -63,6 +64,7 @@ export default React.forwardRef( objectsContainer={props.objectsContainer} projectScopedContainersAccessor={projectScopedContainersAccessor} scope={scope} + getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} /> {editorOpen && project && ( ( } ); +const getVariableSourceFromIdentifier = ( + variableName: string, + projectScopedContainers: gdProjectScopedContainers +): VariablesContainer_SourceType => gd.VariablesContainer.Global; + export const renderInlineGlobalVariable = ( props: ParameterInlineRendererProps -) => renderVariableWithIcon(props, 'global variable', GlobalVariableIcon); +) => + renderVariableWithIcon( + props, + 'global variable', + getVariableSourceFromIdentifier + ); diff --git a/newIDE/app/src/EventsSheet/ParameterFields/ObjectVariableField.js b/newIDE/app/src/EventsSheet/ParameterFields/ObjectVariableField.js index 42e40f29a8fd..66aa4afb467e 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/ObjectVariableField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/ObjectVariableField.js @@ -16,7 +16,6 @@ import { import { getLastObjectParameterValue } from './ParameterMetadataTools'; import getObjectByName from '../../Utils/GetObjectByName'; import getObjectGroupByName from '../../Utils/GetObjectGroupByName'; -import ObjectVariableIcon from '../../UI/CustomSvgIcons/ObjectVariable'; import { enumerateVariables } from './EnumerateVariables'; import { intersectionBy } from 'lodash'; import EventsRootVariablesFinder from '../../Utils/EventsRootVariablesFinder'; @@ -205,6 +204,7 @@ export default React.forwardRef( : undefined } onInstructionTypeChanged={onInstructionTypeChanged} + getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} /> {editorOpen && project && @@ -248,6 +248,16 @@ export default React.forwardRef( } ); +const getVariableSourceFromIdentifier = ( + identifier: string, + projectScopedContainers: gdProjectScopedContainers +): VariablesContainer_SourceType => gd.VariablesContainer.Object; + export const renderInlineObjectVariable = ( props: ParameterInlineRendererProps -) => renderVariableWithIcon(props, 'object variable', ObjectVariableIcon); +) => + renderVariableWithIcon( + props, + 'object variable', + getVariableSourceFromIdentifier + ); diff --git a/newIDE/app/src/EventsSheet/ParameterFields/SceneVariableField.js b/newIDE/app/src/EventsSheet/ParameterFields/SceneVariableField.js index 1e1ae02950a5..8fa8a628b72a 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/SceneVariableField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/SceneVariableField.js @@ -13,9 +13,10 @@ import { type FieldFocusFunction, } from './ParameterFieldCommons'; import { enumerateVariables } from './EnumerateVariables'; -import SceneVariableIcon from '../../UI/CustomSvgIcons/SceneVariable'; import GlobalAndSceneVariablesDialog from '../../VariablesList/GlobalAndSceneVariablesDialog'; +const gd: libGDevelop = global.gd; + export default React.forwardRef( function SceneVariableField(props: ParameterFieldProps, ref) { const field = React.useRef(null); @@ -95,6 +96,7 @@ export default React.forwardRef( ? `parameter-${props.parameterIndex}-scene-variable-field` : undefined } + getVariableSourceFromIdentifier={getVariableSourceFromIdentifier} /> {editorOpen && layout && project && ( ( } ); +const getVariableSourceFromIdentifier = ( + identifier: string, + projectScopedContainers: gdProjectScopedContainers +): VariablesContainer_SourceType => gd.VariablesContainer.Scene; + export const renderInlineSceneVariable = ( props: ParameterInlineRendererProps -) => renderVariableWithIcon(props, 'scene variable', SceneVariableIcon); +) => + renderVariableWithIcon( + props, + 'scene variable', + getVariableSourceFromIdentifier + ); diff --git a/newIDE/app/src/EventsSheet/ParameterFields/VariableField.js b/newIDE/app/src/EventsSheet/ParameterFields/VariableField.js index e210dccafb53..fa583e443bd8 100644 --- a/newIDE/app/src/EventsSheet/ParameterFields/VariableField.js +++ b/newIDE/app/src/EventsSheet/ParameterFields/VariableField.js @@ -22,7 +22,6 @@ import SemiControlledAutoComplete, { import { TextFieldWithButtonLayout } from '../../UI/Layout'; import { type ParameterInlineRendererProps } from './ParameterInlineRenderer.flow'; import ShareExternal from '../../UI/CustomSvgIcons/ShareExternal'; -import SvgIcon, { type SvgIconProps } from '@material-ui/core/SvgIcon'; import SelectField from '../../UI/SelectField'; import SelectOption from '../../UI/SelectOption'; import { ColumnStackLayout } from '../../UI/Layout'; @@ -55,6 +54,10 @@ type Props = { ...ParameterFieldProps, isObjectVariable: boolean, variablesContainers: Array, + getVariableSourceFromIdentifier: ( + identifier: string, + projectScopedContainers: gdProjectScopedContainers + ) => VariablesContainer_SourceType, enumerateVariables: () => Array, forceDeclaration?: boolean, onOpenDialog: (VariableDialogOpeningProps => void) | null, @@ -99,6 +102,10 @@ export const getRootVariableName = (name: string): string => { export const quicklyAnalyzeVariableName = ( name: string, variablesContainers?: Array, + getVariableSourceFromIdentifier?: ( + identifier: string, + projectScopedContainers: gdProjectScopedContainers + ) => VariablesContainer_SourceType | null, projectScopedContainersAccessor?: ProjectScopedContainersAccessor, isObjectVariable: boolean = false ): VariableNameQuickAnalyzeResult => { @@ -150,21 +157,20 @@ export const quicklyAnalyzeVariableName = ( return VariableNameQuickAnalyzeResults.NAME_COLLISION_WITH_OBJECT; } - if (name.length !== rootVariableName.length) { - const variablesContainer = projectScopedContainers - .getVariablesContainersList() - .getVariablesContainerFromVariableName(rootVariableName); - if ( - variablesContainers && - variablesContainers.includes(variablesContainer) - ) { - const variableSource = variablesContainer.getSourceType(); - if (variableSource === gd.VariablesContainer.Parameters) { - return VariableNameQuickAnalyzeResults.PARAMETER_WITH_CHILD; - } - if (variableSource === gd.VariablesContainer.Properties) { - return VariableNameQuickAnalyzeResults.PROPERTY_WITH_CHILD; - } + if ( + name.length !== rootVariableName.length && + getVariableSourceFromIdentifier + ) { + const variableSource = getVariableSourceFromIdentifier( + rootVariableName, + projectScopedContainers + ); + + if (variableSource === gd.VariablesContainer.Parameters) { + return VariableNameQuickAnalyzeResults.PARAMETER_WITH_CHILD; + } + if (variableSource === gd.VariablesContainer.Properties) { + return VariableNameQuickAnalyzeResults.PROPERTY_WITH_CHILD; } } @@ -230,6 +236,7 @@ export default React.forwardRef( id, onInstructionTypeChanged, isObjectVariable, + getVariableSourceFromIdentifier, } = props; const field = React.useRef(null); @@ -321,6 +328,7 @@ export default React.forwardRef( const quicklyAnalysisResult = quicklyAnalyzeVariableName( value, variablesContainers, + getVariableSourceFromIdentifier, projectScopedContainersAccessor, isObjectVariable ); @@ -496,21 +504,6 @@ export default React.forwardRef( } ); -export const getVariablesContainerSourceType = ( - projectScopedContainersAccessor: ProjectScopedContainersAccessor, - variableName: string -) => { - const rootVariableName = getRootVariableName(variableName); - const variablesContainersList = projectScopedContainersAccessor - .get() - .getVariablesContainersList(); - return variablesContainersList.has(rootVariableName) - ? variablesContainersList - .getVariablesContainerFromVariableName(rootVariableName) - .getSourceType() - : gd.VariablesContainer.Unknown; -}; - export const renderVariableWithIcon = ( { value, @@ -521,16 +514,20 @@ export const renderVariableWithIcon = ( projectScopedContainersAccessor, }: ParameterInlineRendererProps, tooltip: string, - ForcedVariableIcon?: SvgIconProps => React.Element + getVariableSourceFromIdentifier: ( + variableName: string, + projectScopedContainers: gdProjectScopedContainers + ) => VariablesContainer_SourceType ) => { if (!value && !parameterMetadata.isOptional()) { return ; } - const VariableIcon = - ForcedVariableIcon || - getVariableSourceIcon( - getVariablesContainerSourceType(projectScopedContainersAccessor, value) - ); + const VariableIcon = getVariableSourceIcon( + getVariableSourceFromIdentifier( + value, + projectScopedContainersAccessor.get() + ) + ); const IconAndNameContainer = expressionIsValid ? React.Fragment