Skip to content

Commit 51a171e

Browse files
authored
Merge pull request #1627 from pau-tomas/feat/wait-event-variables
Add support for value field to Wait event
2 parents 32a3856 + 901abfc commit 51a171e

File tree

8 files changed

+250
-59
lines changed

8 files changed

+250
-59
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3434
- Improved collision handling for ladders and one-way platforms in the Platformer scene type. Ladders now use the player's bottom edge for anchoring, and one-way platforms no longer snap the player to the platform when colliding from below [@Steinbeuge](https://github.com/Steinbeuge)
3535
- Ladder collision tile now only visible on Platform scenes by default, edit `engine.json` to add per scene collision tile types
3636
- New instances of prefabs use prefab's name by default
37+
- Update "Wait" event to support using variable values for wait time [@pau-tomas](https://github.com/pau-tomas))
3738
- Updated Polish localisation. [@ReptiIe](https://github.com/ReptiIe)
3839
- Updated Japanese localisation. [@tomo666](https://github.com/tomo666)
3940

src/components/forms/ValueSelect.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import ScriptEventFormMathArea from "components/script/ScriptEventFormMatharea";
4545
import { ActorDirection } from "shared/lib/entities/entitiesTypes";
4646
import {
4747
castEventToBool,
48+
castEventToFloat,
4849
castEventToInt,
4950
} from "renderer/lib/helpers/castEventValue";
5051
import l10n, { L10NKey } from "shared/lib/lang/l10n";
@@ -944,7 +945,10 @@ const ValueSelect = ({
944945
onChange={(e) => {
945946
onChange({
946947
type: "number",
947-
value: castEventToInt(e, 0),
948+
value:
949+
(step ?? 1) % 1 === 0
950+
? castEventToInt(e, 0)
951+
: castEventToFloat(e, 0),
948952
});
949953
}}
950954
onKeyDown={onKeyDown}

src/lib/compiler/scriptBuilder.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
ScriptEvent,
1717
CustomEvent,
1818
SoundData,
19+
TimeUnitType,
1920
} from "shared/lib/entities/entitiesTypes";
2021
import type { EngineFieldSchema } from "store/features/engine/engineState";
2122
import type { SettingsState } from "store/features/settings/settingsState";
@@ -3952,6 +3953,40 @@ extern void __mute_mask_${symbol};
39523953
this._addNL();
39533954
};
39543955

3956+
waitScriptValue = (duration: ScriptValue, units: TimeUnitType) => {
3957+
const waitArgsRef = this._declareLocal("wait_args", 1, true);
3958+
const stackPtr = this.stackPtr;
3959+
const [rpnOps, fetchOps] = precompileScriptValue(
3960+
optimiseScriptValue(duration)
3961+
);
3962+
if (rpnOps.length === 1 && rpnOps[0].type === "number") {
3963+
const frames =
3964+
units === "time" ? Math.ceil(rpnOps[0].value * 60) : rpnOps[0].value;
3965+
this._addComment(`Wait ${frames} frames`);
3966+
if (frames < 5) {
3967+
for (let i = 0; i < frames; i++) {
3968+
this._idle();
3969+
}
3970+
} else {
3971+
this._setConst(waitArgsRef, Math.round(frames));
3972+
this._invoke("wait_frames", 0, waitArgsRef);
3973+
}
3974+
} else {
3975+
this._addComment(`Wait frames ${units}`);
3976+
const localsLookup = this._performFetchOperations(fetchOps);
3977+
const rpn = this._rpn();
3978+
this._performValueRPN(rpn, rpnOps, localsLookup);
3979+
if (units === "time") {
3980+
rpn.int16(60);
3981+
rpn.operator(".MUL");
3982+
}
3983+
rpn.refSetVariable(waitArgsRef).stop();
3984+
this._invoke("wait_frames", 0, waitArgsRef);
3985+
}
3986+
this._assertStackNeutral(stackPtr);
3987+
this._addNL();
3988+
};
3989+
39553990
// --------------------------------------------------------------------------
39563991
// UI
39573992

src/lib/events/eventWait.js

Lines changed: 41 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,62 +18,56 @@ const autoLabel = (fetchArg, input) => {
1818

1919
const fields = [
2020
{
21-
type: "group",
22-
fields: [
21+
key: "time",
22+
label: l10n("FIELD_DURATION"),
23+
description: l10n("FIELD_DURATION_WAIT_DESC"),
24+
type: "value",
25+
min: 0,
26+
max: 60,
27+
step: 0.1,
28+
unitsField: "units",
29+
unitsDefault: "time",
30+
unitsAllowed: ["time", "frames"],
31+
defaultValue: {
32+
type: "number",
33+
value: 0.5,
34+
},
35+
conditions: [
2336
{
24-
key: "time",
25-
type: "number",
26-
label: l10n("FIELD_DURATION"),
27-
description: l10n("FIELD_DURATION_WAIT_DESC"),
28-
min: 0,
29-
max: 60,
30-
step: 0.1,
31-
defaultValue: 0.5,
32-
unitsField: "units",
33-
unitsDefault: "time",
34-
unitsAllowed: ["time", "frames"],
35-
conditions: [
36-
{
37-
key: "units",
38-
ne: "frames",
39-
},
40-
],
37+
key: "units",
38+
ne: "frames",
4139
},
40+
],
41+
},
42+
{
43+
key: "frames",
44+
label: l10n("FIELD_DURATION"),
45+
description: l10n("FIELD_DURATION_WAIT_DESC"),
46+
type: "value",
47+
min: 0,
48+
max: 3600,
49+
width: "50%",
50+
unitsField: "units",
51+
unitsDefault: "time",
52+
unitsAllowed: ["time", "frames"],
53+
defaultValue: {
54+
type: "number",
55+
value: 1,
56+
},
57+
conditions: [
4258
{
43-
key: "frames",
44-
label: l10n("FIELD_DURATION"),
45-
description: l10n("FIELD_DURATION_WAIT_DESC"),
46-
type: "number",
47-
min: 0,
48-
max: 3600,
49-
width: "50%",
50-
defaultValue: 30,
51-
unitsField: "units",
52-
unitsDefault: "time",
53-
unitsAllowed: ["time", "frames"],
54-
conditions: [
55-
{
56-
key: "units",
57-
eq: "frames",
58-
},
59-
],
59+
key: "units",
60+
eq: "frames",
6061
},
6162
],
6263
},
6364
];
6465

6566
const compile = (input, helpers) => {
66-
const { wait } = helpers;
67-
let frames = 0;
68-
if (input.units === "frames") {
69-
frames = typeof input.frames === "number" ? input.frames : 30;
70-
} else {
71-
const seconds = typeof input.time === "number" ? input.time : 0.5;
72-
frames = Math.ceil(seconds * 60);
73-
}
74-
if (frames > 0) {
75-
wait(frames);
76-
}
67+
const { waitScriptValue } = helpers;
68+
const duration =
69+
input.units === "frames" ? input.frames ?? 1 : input.time ?? 0.5;
70+
waitScriptValue(duration, input.units ?? "time");
7771
};
7872

7973
module.exports = {

src/lib/project/migration/migrateProjectResources.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import {
33
ProjectResourcesMigration,
44
applyProjectResourcesMigration,
55
} from "./helpers";
6-
import { migrate410r1To420r1 } from "./versions/410to420";
6+
import { migrate410r1To420r1, migrate420r1To420r2 } from "./versions/410to420";
77

88
const migrations: ProjectResourcesMigration[] = [
99
// 4.1.0 to 4.2.0
1010
migrate410r1To420r1,
11+
migrate420r1To420r2,
1112
];
1213

1314
const lastMigration = migrations[migrations.length - 1];

src/lib/project/migration/versions/410to420.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,32 @@ export const migrate410r1To420r1: ProjectResourcesMigration = {
3434
to: { version: "4.2.0", release: "1" },
3535
migrationFn: createScriptEventsMigrator(migrateFrom410r1To420r1Event),
3636
};
37+
38+
export const migrateFrom420r1To420r2Event: ScriptEventMigrationFn = (
39+
scriptEvent
40+
) => {
41+
if (scriptEvent.args && scriptEvent.command === "EVENT_WAIT") {
42+
const args: Record<string, unknown> = { ...scriptEvent.args };
43+
// Convert to constvalue
44+
args["frames"] = {
45+
type: "number",
46+
value: typeof args["frames"] === "number" ? args["frames"] : 30,
47+
};
48+
args["time"] = {
49+
type: "number",
50+
value: typeof args["time"] === "number" ? args["time"] : 0.5,
51+
};
52+
53+
return {
54+
...scriptEvent,
55+
args,
56+
};
57+
}
58+
return scriptEvent;
59+
};
60+
61+
export const migrate420r1To420r2: ProjectResourcesMigration = {
62+
from: { version: "4.2.0", release: "1" },
63+
to: { version: "4.2.0", release: "2" },
64+
migrationFn: createScriptEventsMigrator(migrateFrom420r1To420r2Event),
65+
};

test/events/eventWait.test.js

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,52 @@
11
import { compile } from "../../src/lib/events/eventWait";
22

33
test("Should be able to wait for a second", () => {
4-
const mockWait = jest.fn();
4+
const mockWaitScriptValues = jest.fn();
55
compile(
66
{
77
time: 1,
88
},
99
{
10-
wait: mockWait,
10+
waitScriptValue: mockWaitScriptValues,
1111
}
1212
);
13-
expect(mockWait).toBeCalledWith(60);
13+
expect(mockWaitScriptValues).toBeCalledWith(1, "time");
1414
});
1515

1616
test("Should wait for half a second if time not set", () => {
17-
const mockWait = jest.fn();
17+
const mockWaitScriptValues = jest.fn();
1818
compile(
1919
{},
2020
{
21-
wait: mockWait,
21+
waitScriptValue: mockWaitScriptValues,
2222
}
2323
);
24-
expect(mockWait).toBeCalledWith(30);
24+
expect(mockWaitScriptValues).toBeCalledWith(0.5, "time");
2525
});
2626

2727
test("Should be able to wait for one and a half seconds", () => {
28-
const mockWait = jest.fn();
28+
const mockWaitScriptValues = jest.fn();
2929
compile(
3030
{
3131
time: 1.5,
3232
},
3333
{
34-
wait: mockWait,
34+
waitScriptValue: mockWaitScriptValues,
3535
}
3636
);
37-
expect(mockWait).toBeCalledWith(90);
37+
expect(mockWaitScriptValues).toBeCalledWith(1.5, "time");
38+
});
39+
40+
test("Should be able to wait for one frame", () => {
41+
const mockWaitScriptValues = jest.fn();
42+
compile(
43+
{
44+
frames: 1,
45+
units: "frames",
46+
},
47+
{
48+
waitScriptValue: mockWaitScriptValues,
49+
}
50+
);
51+
expect(mockWaitScriptValues).toBeCalledWith(1, "frames");
3852
});

0 commit comments

Comments
 (0)