Skip to content

Commit

Permalink
Allow any variables in for each child loops (#6585)
Browse files Browse the repository at this point in the history
- Don't show in changelog
  • Loading branch information
D8H committed May 23, 2024
1 parent e3cc01e commit 231d92a
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 49 deletions.
6 changes: 4 additions & 2 deletions Core/GDCore/Events/Builtin/ForEachChildVariableEvent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ vector<pair<gd::Expression*, gd::ParameterMetadata> >
ForEachChildVariableEvent::GetAllExpressionsWithMetadata() {
vector<pair<gd::Expression*, gd::ParameterMetadata> >
allExpressionsWithMetadata;
auto metadata = gd::ParameterMetadata().SetType("scenevar");
auto metadata = gd::ParameterMetadata().SetType("variable");
metadata.SetExtraInfo("AllowUndeclaredVariable");
allExpressionsWithMetadata.push_back(
std::make_pair(&iterableVariableName, metadata));
allExpressionsWithMetadata.push_back(
Expand All @@ -63,7 +64,8 @@ vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
ForEachChildVariableEvent::GetAllExpressionsWithMetadata() const {
vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
allExpressionsWithMetadata;
auto metadata = gd::ParameterMetadata().SetType("scenevar");
auto metadata = gd::ParameterMetadata().SetType("variable");
metadata.SetExtraInfo("AllowUndeclaredVariable");
allExpressionsWithMetadata.push_back(
std::make_pair(&iterableVariableName, metadata));
allExpressionsWithMetadata.push_back(
Expand Down
18 changes: 18 additions & 0 deletions Core/GDCore/Events/CodeGeneration/EventsCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/Events/ExpressionVariableNameFinder.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/ObjectsContainersList.h"
Expand Down Expand Up @@ -633,6 +634,23 @@ gd::String EventsCodeGenerator::GenerateLocalVariablesStackAccessor() {
".localVariables";
}

gd::String EventsCodeGenerator::GenerateAnyOrSceneVariableGetter(
const gd::Expression &variableExpression,
EventsCodeGenerationContext &context) {
const auto variableName = gd::ExpressionVariableNameFinder::GetVariableName(
*variableExpression.GetRootNode());

gd::String variableParameterType =
GetProjectScopedContainers().GetVariablesContainersList().Has(
variableName)
? "variable"
: "scenevar";

return gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, variableParameterType,
variableExpression.GetPlainString(), "", "AllowUndeclaredVariable");
}

const EventsCodeGenerator::CallbackDescriptor
EventsCodeGenerator::GenerateCallback(
const gd::String& callbackID,
Expand Down
10 changes: 9 additions & 1 deletion Core/GDCore/Events/CodeGeneration/EventsCodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,15 @@ class GD_CORE_API EventsCodeGenerator {
*/
virtual gd::String GenerateLocalVariablesStackAccessor();

protected:
/**
* \brief Generate an any variable getter that fallbacks on scene variable for
* compatibility reason.
*/
gd::String
GenerateAnyOrSceneVariableGetter(const gd::Expression &variableExpression,
EventsCodeGenerationContext &context);

protected:
virtual const gd::String GenerateRelationalOperatorCodes(
const gd::String& operatorString);

Expand Down
16 changes: 7 additions & 9 deletions GDJS/GDJS/Extensions/Builtin/CommonInstructionsExtension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,9 +539,8 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
outputCode
.FindAndReplace(
"$VALUE_ITERATOR_VARIABLE_ACCESSOR",
gd::ExpressionCodeGenerator::GenerateExpressionCode(
codeGenerator, context, "scenevar",
event.GetValueIteratorVariableName()))
codeGenerator.GenerateAnyOrSceneVariableGetter(
event.GetValueIteratorVariableName(), context))
.FindAndReplace("$VALUE_ITERATOR_REFERENCE",
iteratorReferenceVariableName);
}
Expand All @@ -554,22 +553,21 @@ CommonInstructionsExtension::CommonInstructionsExtension() {
outputCode
.FindAndReplace(
"$KEY_ITERATOR_VARIABLE_ACCESSOR",
gd::ExpressionCodeGenerator::GenerateExpressionCode(
codeGenerator, context, "scenevar",
event.GetKeyIteratorVariableName()))
codeGenerator.GenerateAnyOrSceneVariableGetter(
event.GetKeyIteratorVariableName(), context))
.FindAndReplace("$KEY_ITERATOR_REFERENCE",
iteratorReferenceVariableName);
}

return outputCode
.FindAndReplace("$ITERATOR_KEY", iteratorKeyVariableName)
.FindAndReplace("$STRUCTURE_CHILD_VARIABLE",
structureChildVariableName)
.FindAndReplace("$ITERABLE_REFERENCE",
iterableReferenceVariableName)
.FindAndReplace("$ITERABLE_VARIABLE_ACCESSOR",
gd::ExpressionCodeGenerator::GenerateExpressionCode(
codeGenerator, context, "scenevar",
event.GetIterableVariableName()));
codeGenerator.GenerateAnyOrSceneVariableGetter(
event.GetIterableVariableName(), context));
});

GetAllEvents()["BuiltinCommonInstructions::Repeat"].SetCodeGenerator(
Expand Down
25 changes: 6 additions & 19 deletions GDJS/GDJS/Extensions/Builtin/VariablesExtension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,14 @@ VariablesExtension::VariablesExtension() {
"gdjs.evtTools.variable.getLastVariableNumber");

GetAllExpressions()["VariableChildCount"].SetCustomCodeGenerator(
[](const std::vector<gd::Expression> &parameters, gd::EventsCodeGenerator &codeGenerator,
[](const std::vector<gd::Expression> &parameters,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context) {
auto &variableExpression = parameters[0];
const auto variableName =
gd::ExpressionVariableNameFinder::GetVariableName(
*variableExpression.GetRootNode());

// This expression used to be declared with a scenevar parameter.
gd::String variableParameterType =
codeGenerator.GetProjectScopedContainers()
.GetVariablesContainersList()
.Has(variableName)
? "variable"
: "scenevar";

gd::String varGetter =
gd::ExpressionCodeGenerator::GenerateExpressionCode(
codeGenerator, context, variableParameterType,
variableExpression.GetPlainString(), "", "AllowUndeclaredVariable");

return "gdjs.evtTools.variable.getVariableChildCount(" + varGetter + ")";
return "gdjs.evtTools.variable.getVariableChildCount(" +
codeGenerator.GenerateAnyOrSceneVariableGetter(parameters[0],
context) +
")";
});
GetAllConditions()["VariableChildCount"].SetFunctionName(
"gdjs.evtTools.variable.getVariableChildCount");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,35 @@ import {
icon,
} from '../ClassNames';
import InlinePopover from '../../InlinePopover';
import SceneVariableField from '../../ParameterFields/SceneVariableField';
import AnyVariableField from '../../ParameterFields/AnyVariableField';
import {
getVariableSourceIcon,
getVariablesContainerSourceType,
} from '../../ParameterFields/VariableField';
import { type ParameterFieldInterface } from '../../ParameterFields/ParameterFieldCommons';
import { type EventRendererProps } from './EventRenderer';
import ConditionsActionsColumns from '../ConditionsActionsColumns';
import { Trans } from '@lingui/macro';
import { shouldActivate } from '../../../UI/KeyboardShortcuts/InteractionKeys';
import { ProjectScopedContainersAccessor } from '../../../InstructionOrExpression/EventsScope.flow';

const gd: libGDevelop = global.gd;

export const getVariableSourceOrSceneIcon = (
projectScopedContainersAccessor: ProjectScopedContainersAccessor,
variableName: string
) => {
const variablesContainerSourceType = getVariablesContainerSourceType(
projectScopedContainersAccessor,
variableName
);
return getVariableSourceIcon(
variablesContainerSourceType === gd.VariablesContainer.Unknown
? gd.VariablesContainer.Scene
: variablesContainerSourceType
);
};

const styles = {
container: {
display: 'flex',
Expand Down Expand Up @@ -165,6 +186,21 @@ export default class ForEachChildVariableEvent extends React.Component<
const keyIteratorName = forEachChildVariableEvent.getKeyIteratorVariableName();
const iterableName = forEachChildVariableEvent.getIterableVariableName();

const ValueIteratorVariableIcon = getVariableSourceOrSceneIcon(
this.props.projectScopedContainersAccessor,
valueIteratorName
);

const KeyIteratorVariableIcon = getVariableSourceOrSceneIcon(
this.props.projectScopedContainersAccessor,
keyIteratorName
);

const IterableVariableIcon = getVariableSourceOrSceneIcon(
this.props.projectScopedContainersAccessor,
iterableName
);

return (
<div
style={styles.container}
Expand Down Expand Up @@ -198,10 +234,10 @@ export default class ForEachChildVariableEvent extends React.Component<
}}
tabIndex={0}
>
<img
className={icon}
src="res/types/scenevar.png"
alt="Scene variable"
<IterableVariableIcon
className={classNames({
[icon]: true,
})}
/>
{iterableName.length !== 0 ? (
<span>{iterableName}</span>
Expand All @@ -228,10 +264,10 @@ export default class ForEachChildVariableEvent extends React.Component<
}}
tabIndex={0}
>
<img
className={icon}
src="res/types/scenevar.png"
alt="Scene variable"
<ValueIteratorVariableIcon
className={classNames({
[icon]: true,
})}
/>
{valueIteratorName.length !== 0 ? (
<span>{valueIteratorName}</span>
Expand All @@ -258,10 +294,10 @@ export default class ForEachChildVariableEvent extends React.Component<
}}
tabIndex={0}
>
<img
className={icon}
src="res/types/scenevar.png"
alt="Scene variable"
<KeyIteratorVariableIcon
className={classNames({
[icon]: true,
})}
/>
{keyIteratorName.length !== 0 ? (
<span>{keyIteratorName}</span>
Expand Down Expand Up @@ -355,7 +391,7 @@ export default class ForEachChildVariableEvent extends React.Component<
onRequestClose={this.cancelEditing}
onApply={this.endEditing}
>
<SceneVariableField
<AnyVariableField
project={this.props.project}
scope={this.props.scope}
globalObjectsContainer={this.props.globalObjectsContainer}
Expand All @@ -380,7 +416,7 @@ export default class ForEachChildVariableEvent extends React.Component<
onRequestClose={this.cancelEditing}
onApply={this.endEditing}
>
<SceneVariableField
<AnyVariableField
project={this.props.project}
scope={this.props.scope}
globalObjectsContainer={this.props.globalObjectsContainer}
Expand All @@ -405,7 +441,7 @@ export default class ForEachChildVariableEvent extends React.Component<
onRequestClose={this.cancelEditing}
onApply={this.endEditing}
>
<SceneVariableField
<AnyVariableField
project={this.props.project}
scope={this.props.scope}
globalObjectsContainer={this.props.globalObjectsContainer}
Expand Down
4 changes: 2 additions & 2 deletions newIDE/app/src/EventsSheet/ParameterFields/VariableField.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export const quicklyAnalyzeVariableName = (
return VariableNameQuickAnalyzeResults.OK;
};

const getVariableSourceIcon = (
export const getVariableSourceIcon = (
variableSourceType: VariablesContainer_SourceType
) => {
switch (variableSourceType) {
Expand Down Expand Up @@ -382,7 +382,7 @@ export default React.forwardRef<Props, VariableFieldInterface>(
}
);

const getVariablesContainerSourceType = (
export const getVariablesContainerSourceType = (
projectScopedContainersAccessor: ProjectScopedContainersAccessor,
variableName: string
) => {
Expand Down

0 comments on commit 231d92a

Please sign in to comment.