mirror of
https://github.com/Heretek-AI/GDevelop.git
synced 2026-07-22 10:05:37 -04:00
7597dbe0d1
* Add `PickedInstancesCount` and `SceneInstancesCount` expressions, to replace `Count`. These expressions don't do any "picking" of instances, so they are safe to use anywhere without "weird" side effects. * Equivalent conditions are available for all objects. These conditions allow to check at any point in your events the number of instances living on the scene or picked by actions/conditions. * This is useful to check if enough objects are picked by a condition before launching an action. * Because this condition does not change the already picked objects, it's safe to use anywhere without any side effect. Only show the rest in the developer changelog: * Allow to read events missing some fields (like `disabled`, `folded`). * Reduce the useless information stored in project JSON files by not storing the fields if they have their default value.
166 lines
4.8 KiB
JavaScript
166 lines
4.8 KiB
JavaScript
const initializeGDevelopJs = require('../../Binaries/embuild/GDevelop.js/libGD.js');
|
|
const { makeMinimalGDJSMock } = require('../TestUtils/GDJSMocks');
|
|
|
|
describe('libGD.js - GDJS Behavior Code Generation integration tests', function () {
|
|
let gd = null;
|
|
beforeAll((done) =>
|
|
initializeGDevelopJs().then((module) => {
|
|
gd = module;
|
|
done();
|
|
})
|
|
);
|
|
|
|
it('generates a working empty behavior', function () {
|
|
// Create an empty behavior
|
|
const project = new gd.ProjectHelper.createNewGDJSProject();
|
|
const eventsBasedBehavior = new gd.EventsBasedBehavior();
|
|
eventsBasedBehavior.setName('MyBehavior');
|
|
eventsBasedBehavior.setFullName('My descriptive name');
|
|
eventsBasedBehavior.setDescription('My description');
|
|
|
|
const makeCompiledRuntimeBehavior = generateCompiledRuntimeBehaviorMaker(
|
|
gd,
|
|
project,
|
|
eventsBasedBehavior
|
|
);
|
|
eventsBasedBehavior.delete();
|
|
project.delete();
|
|
|
|
// Instanciate the behavior
|
|
const { gdjs, runtimeScene } = makeMinimalGDJSMock();
|
|
const CompiledRuntimeBehavior = makeCompiledRuntimeBehavior(gdjs);
|
|
const behaviorData = {};
|
|
const ownerRuntimeObject = {};
|
|
const behavior = new CompiledRuntimeBehavior(
|
|
runtimeScene,
|
|
behaviorData,
|
|
ownerRuntimeObject
|
|
);
|
|
|
|
// Check that doStepPreEvents is always defined
|
|
expect(behavior.doStepPreEvents).not.toBeUndefined();
|
|
});
|
|
|
|
it('generates a working behavior with doStepPreEvents using "Trigger Once" condition', function () {
|
|
// Create a new behavior with events in doStepPreEvents
|
|
const project = new gd.ProjectHelper.createNewGDJSProject();
|
|
const eventsBasedBehavior = new gd.EventsBasedBehavior();
|
|
eventsBasedBehavior.setName('MyBehavior');
|
|
eventsBasedBehavior.setFullName('My descriptive name');
|
|
eventsBasedBehavior.setDescription('My description');
|
|
|
|
const eventsSerializerElement = gd.Serializer.fromJSObject([
|
|
{
|
|
type: 'BuiltinCommonInstructions::Standard',
|
|
conditions: [
|
|
{
|
|
type: {
|
|
value: 'BuiltinCommonInstructions::Once',
|
|
},
|
|
parameters: [],
|
|
},
|
|
],
|
|
actions: [
|
|
{
|
|
type: { value: 'ModVarScene' },
|
|
parameters: ['SuccessVariable', '+', '1'],
|
|
},
|
|
],
|
|
},
|
|
]);
|
|
eventsBasedBehavior
|
|
.getEventsFunctions()
|
|
.insertNewEventsFunction('doStepPreEvents', 0)
|
|
.getEvents()
|
|
.unserializeFrom(project, eventsSerializerElement);
|
|
|
|
// Instanciate the behavior twice
|
|
const makeCompiledRuntimeBehavior = generateCompiledRuntimeBehaviorMaker(
|
|
gd,
|
|
project,
|
|
eventsBasedBehavior
|
|
);
|
|
eventsBasedBehavior.delete();
|
|
project.delete();
|
|
|
|
const { gdjs, runtimeScene } = makeMinimalGDJSMock();
|
|
const CompiledRuntimeBehavior = makeCompiledRuntimeBehavior(gdjs);
|
|
const behaviorData = {};
|
|
const ownerRuntimeObject = {};
|
|
const behavior = new CompiledRuntimeBehavior(
|
|
runtimeScene,
|
|
behaviorData,
|
|
ownerRuntimeObject
|
|
);
|
|
const behavior2 = new CompiledRuntimeBehavior(
|
|
runtimeScene,
|
|
behaviorData,
|
|
ownerRuntimeObject
|
|
);
|
|
|
|
// Check that Trigger once is working, separately handled by each behavior instance:
|
|
expect(behavior.doStepPreEvents).not.toBeUndefined();
|
|
behavior.doStepPreEvents();
|
|
behavior2.doStepPreEvents();
|
|
expect(runtimeScene.getVariables().has('SuccessVariable')).toBe(true);
|
|
expect(
|
|
runtimeScene.getVariables().get('SuccessVariable').getAsNumber()
|
|
).toBe(2);
|
|
|
|
behavior.doStepPreEvents();
|
|
behavior2.doStepPreEvents();
|
|
expect(
|
|
runtimeScene.getVariables().get('SuccessVariable').getAsNumber()
|
|
).toBe(2);
|
|
});
|
|
});
|
|
|
|
function generateCompiledRuntimeBehaviorMaker(
|
|
gd,
|
|
project,
|
|
eventsBasedBehavior
|
|
) {
|
|
const includeFiles = new gd.SetString();
|
|
|
|
const codeNamespace = 'behaviorNamespace';
|
|
const behaviorCodeGenerator = new gd.BehaviorCodeGenerator(project);
|
|
|
|
// Generate "mangled names" as required by the code generation
|
|
const behaviorMethodMangledNames = new gd.MapStringString();
|
|
for (
|
|
let i = 0;
|
|
i < eventsBasedBehavior.getEventsFunctions().getEventsFunctionsCount();
|
|
i++
|
|
) {
|
|
const eventsFunction = eventsBasedBehavior
|
|
.getEventsFunctions()
|
|
.getEventsFunctionAt(i);
|
|
behaviorMethodMangledNames.set(
|
|
eventsFunction.getName(),
|
|
eventsFunction.getName()
|
|
);
|
|
}
|
|
|
|
const code = behaviorCodeGenerator.generateRuntimeBehaviorCompleteCode(
|
|
'MyExtension',
|
|
eventsBasedBehavior,
|
|
codeNamespace,
|
|
behaviorMethodMangledNames,
|
|
includeFiles,
|
|
true
|
|
);
|
|
|
|
// Create a function with the generated behavior.
|
|
const makeCompiledBehavior = new Function(
|
|
'gdjs',
|
|
`let behaviorNamespace = {};
|
|
let Hashtable = gdjs.Hashtable;
|
|
${code}
|
|
return behaviorNamespace.MyBehavior;`
|
|
);
|
|
|
|
includeFiles.delete();
|
|
|
|
return makeCompiledBehavior;
|
|
}
|