mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-07-21 09:35:27 -04:00
a51c223c9c
* Still to do:
* Properly handle effects (disable 3D effects) for layers
* Handle hot reloading properly
* Avoid duplicating the configuration of the custom object inside each object created from it. Instead, only store the modified values.
* Add a "Extract as a custom object ("prefab")" when selecting instances in a scene.
* Add a dialog to give choice between 2D or 3D object when creating one.
* Make sure "behavior shared data" are properly handled (physics, pathfinding...)
* Check if we need to give an expression to translate coordinates from the parent to the local custom object.
* Ensure a deleted custom object does not break the editor
Co-authored-by: Davy Hélard <davy.helard@gmail.com>
208 lines
7.5 KiB
JavaScript
208 lines
7.5 KiB
JavaScript
const initializeGDevelopJs = require('../../Binaries/embuild/GDevelop.js/libGD.js');
|
|
const { makeMinimalGDJSMock } = require('../TestUtils/GDJSMocks.js');
|
|
const {
|
|
generateCompiledEventsForLayout,
|
|
} = require('../TestUtils/CodeGenerationHelpers.js');
|
|
|
|
describe('libGD.js - GDJS Scene Code Generation integration tests', function () {
|
|
let gd = null;
|
|
beforeAll(async () => {
|
|
gd = await initializeGDevelopJs();
|
|
});
|
|
|
|
describe('(Scene) variable code generation', () => {
|
|
let project = null;
|
|
let scene = null;
|
|
beforeEach(() => {
|
|
project = new gd.ProjectHelper.createNewGDJSProject();
|
|
scene = project.insertNewLayout('Scene', 0);
|
|
scene.getObjects().insertNewObject(project, '', 'MyObject', 0);
|
|
|
|
// These variables are "simple" and their type will be known at code generation.
|
|
scene.getVariables().insertNew('MyNumberVariable', 0).setValue(123);
|
|
scene.getVariables().insertNew('MyStringVariable', 1).setString('Test');
|
|
scene
|
|
.getVariables()
|
|
.insertNew('MyOtherStringVariable', 1)
|
|
.setString('SomeChild');
|
|
|
|
// Use a variable that has a value deep inside a structure - so code generation
|
|
// does not know its type and will issue a `getAsNumberOrString`.
|
|
scene
|
|
.getVariables()
|
|
.insertNew('MyOtherStructureVariable', 1)
|
|
.getChild('Child')
|
|
.getChild('SubChild')
|
|
.setString('SomeOtherChild');
|
|
const structureVariable = scene
|
|
.getVariables()
|
|
.insertNew('MyStructureVariable', 2);
|
|
|
|
// Make a structure that we will address using other variables.
|
|
structureVariable.getChild('Test').setValue(1);
|
|
structureVariable.getChild('123').setValue(2);
|
|
structureVariable.getChild('42').setValue(4);
|
|
structureVariable.getChild('MyObject').setValue(8);
|
|
structureVariable.getChild('SomeChild').getChild('Test').setValue(16);
|
|
structureVariable.getChild('SomeChild').getChild('123').setValue(32);
|
|
structureVariable.getChild('SomeChild').getChild('42').setValue(64);
|
|
structureVariable
|
|
.getChild('SomeChild')
|
|
.getChild('MyObject')
|
|
.setValue(128);
|
|
structureVariable
|
|
.getChild('SomeChild')
|
|
.getChild('SomeOtherChild')
|
|
.getChild('Test')
|
|
.setValue(256);
|
|
structureVariable
|
|
.getChild('SomeChild')
|
|
.getChild('SomeOtherChild')
|
|
.getChild('123')
|
|
.setValue(512);
|
|
structureVariable
|
|
.getChild('SomeChild')
|
|
.getChild('SomeOtherChild')
|
|
.getChild('42')
|
|
.setValue(1024);
|
|
structureVariable
|
|
.getChild('SomeChild')
|
|
.getChild('SomeOtherChild')
|
|
.getChild('MyObject')
|
|
.setValue(2048);
|
|
});
|
|
afterEach(() => {
|
|
project.delete();
|
|
});
|
|
|
|
it('generates code for structure variables accessed by another variable (1 level)', function () {
|
|
const serializedLayoutEvents = gd.Serializer.fromJSObject([
|
|
{
|
|
type: 'BuiltinCommonInstructions::Standard',
|
|
conditions: [],
|
|
actions: [
|
|
{
|
|
type: { value: 'ModVarScene' },
|
|
parameters: [
|
|
'Counter',
|
|
'+',
|
|
'MyStructureVariable[MyStringVariable] + MyStructureVariable[MyNumberVariable] + MyStructureVariable[MyObject.X()] + MyStructureVariable[MyObject.ObjectName()]',
|
|
],
|
|
},
|
|
],
|
|
events: [],
|
|
},
|
|
]);
|
|
scene.getEvents().unserializeFrom(project, serializedLayoutEvents);
|
|
|
|
const runCompiledEvents = generateCompiledEventsForLayout(
|
|
gd,
|
|
project,
|
|
scene
|
|
);
|
|
|
|
const serializedSceneElement = new gd.SerializerElement();
|
|
scene.serializeTo(serializedSceneElement);
|
|
|
|
const { gdjs, runtimeScene } = makeMinimalGDJSMock({
|
|
sceneData: JSON.parse(gd.Serializer.toJSON(serializedSceneElement)),
|
|
});
|
|
serializedSceneElement.delete();
|
|
const myObjectInstance = runtimeScene.createObject('MyObject');
|
|
myObjectInstance.setX(42);
|
|
runCompiledEvents(gdjs, runtimeScene);
|
|
|
|
expect(runtimeScene.getVariables().has('Counter')).toBe(true);
|
|
expect(runtimeScene.getVariables().get('Counter').getAsNumber()).toBe(
|
|
1 + 2 + 4 + 8
|
|
);
|
|
});
|
|
|
|
it('generates code for structure variables accessed by another variable (2 levels)', function () {
|
|
const serializedLayoutEvents = gd.Serializer.fromJSObject([
|
|
{
|
|
type: 'BuiltinCommonInstructions::Standard',
|
|
conditions: [],
|
|
actions: [
|
|
{
|
|
type: { value: 'ModVarScene' },
|
|
parameters: [
|
|
'Counter',
|
|
'+',
|
|
'MyStructureVariable.SomeChild[MyStringVariable] + MyStructureVariable.SomeChild[MyNumberVariable] + MyStructureVariable.SomeChild[MyObject.X()] + MyStructureVariable.SomeChild[MyObject.ObjectName()]',
|
|
],
|
|
},
|
|
],
|
|
events: [],
|
|
},
|
|
]);
|
|
scene.getEvents().unserializeFrom(project, serializedLayoutEvents);
|
|
|
|
const runCompiledEvents = generateCompiledEventsForLayout(
|
|
gd,
|
|
project,
|
|
scene
|
|
);
|
|
|
|
const serializedSceneElement = new gd.SerializerElement();
|
|
scene.serializeTo(serializedSceneElement);
|
|
|
|
const { gdjs, runtimeScene } = makeMinimalGDJSMock({
|
|
sceneData: JSON.parse(gd.Serializer.toJSON(serializedSceneElement)),
|
|
});
|
|
serializedSceneElement.delete();
|
|
const myObjectInstance = runtimeScene.createObject('MyObject');
|
|
myObjectInstance.setX(42);
|
|
runCompiledEvents(gdjs, runtimeScene);
|
|
|
|
expect(runtimeScene.getVariables().has('Counter')).toBe(true);
|
|
expect(runtimeScene.getVariables().get('Counter').getAsNumber()).toBe(
|
|
16 + 32 + 64 + 128
|
|
);
|
|
});
|
|
|
|
it('generates code for structure variables accessed by another variable (3 levels)', function () {
|
|
const serializedLayoutEvents = gd.Serializer.fromJSObject([
|
|
{
|
|
type: 'BuiltinCommonInstructions::Standard',
|
|
conditions: [],
|
|
actions: [
|
|
{
|
|
type: { value: 'ModVarScene' },
|
|
parameters: [
|
|
'Counter',
|
|
'+',
|
|
'MyStructureVariable[MyOtherStringVariable][MyOtherStructureVariable.Child.SubChild][MyStringVariable] +MyStructureVariable[MyOtherStringVariable][MyOtherStructureVariable.Child.SubChild][MyNumberVariable] + MyStructureVariable[MyOtherStringVariable][MyOtherStructureVariable.Child.SubChild][MyObject.X()] + MyStructureVariable[MyOtherStringVariable][MyOtherStructureVariable.Child.SubChild][MyObject.ObjectName()]',
|
|
],
|
|
},
|
|
],
|
|
events: [],
|
|
},
|
|
]);
|
|
scene.getEvents().unserializeFrom(project, serializedLayoutEvents);
|
|
|
|
const runCompiledEvents = generateCompiledEventsForLayout(
|
|
gd,
|
|
project,
|
|
scene
|
|
);
|
|
|
|
const serializedSceneElement = new gd.SerializerElement();
|
|
scene.serializeTo(serializedSceneElement);
|
|
|
|
const { gdjs, runtimeScene } = makeMinimalGDJSMock({
|
|
sceneData: JSON.parse(gd.Serializer.toJSON(serializedSceneElement)),
|
|
});
|
|
serializedSceneElement.delete();
|
|
const myObjectInstance = runtimeScene.createObject('MyObject');
|
|
myObjectInstance.setX(42);
|
|
runCompiledEvents(gdjs, runtimeScene);
|
|
|
|
expect(runtimeScene.getVariables().has('Counter')).toBe(true);
|
|
expect(runtimeScene.getVariables().get('Counter').getAsNumber()).toBe(
|
|
256 + 512 + 1024 + 2048
|
|
);
|
|
});
|
|
});
|
|
});
|