gdcore-tools 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/package.json +1 -1
- package/src/EventsFunctionsExtensionsLoader/MetadataDeclarationHelpers.js +442 -449
- package/src/EventsFunctionsExtensionsLoader/index.js +373 -354
- package/src/LocalFileSystem.js +39 -39
- package/src/WrappedGD.js +138 -0
- package/src/downloadGD.js +40 -29
- package/src/index.js +10 -118
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
const { mapVector, mapFor } = require("../MapFor");
|
|
2
2
|
const { caseSensitiveSlug } = require("../CaseSensitiveSlug");
|
|
3
|
-
const {
|
|
4
|
-
declareInstructionOrExpressionMetadata,
|
|
5
|
-
declareBehaviorInstructionOrExpressionMetadata,
|
|
6
|
-
declareEventsFunctionParameters,
|
|
7
|
-
declareBehaviorMetadata,
|
|
8
|
-
declareExtension,
|
|
9
|
-
isBehaviorLifecycleEventsFunction,
|
|
10
|
-
isExtensionLifecycleEventsFunction,
|
|
11
|
-
declareBehaviorPropertiesInstructionAndExpressions,
|
|
12
|
-
} = require("./MetadataDeclarationHelpers");
|
|
13
3
|
|
|
14
4
|
const mangleName = (name) => {
|
|
15
5
|
return caseSensitiveSlug(name, "_", []);
|
|
@@ -28,405 +18,434 @@ const getBehaviorFunctionCodeNamespace = (
|
|
|
28
18
|
return codeNamespacePrefix + "__" + mangleName(eventsBasedBehavior.getName());
|
|
29
19
|
};
|
|
30
20
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
21
|
+
module.exports.makeLoader = (gd) => {
|
|
22
|
+
const {
|
|
23
|
+
declareInstructionOrExpressionMetadata,
|
|
24
|
+
declareBehaviorInstructionOrExpressionMetadata,
|
|
25
|
+
declareEventsFunctionParameters,
|
|
26
|
+
declareBehaviorMetadata,
|
|
27
|
+
declareExtension,
|
|
28
|
+
isBehaviorLifecycleEventsFunction,
|
|
29
|
+
isExtensionLifecycleEventsFunction,
|
|
30
|
+
declareBehaviorPropertiesInstructionAndExpressions,
|
|
31
|
+
} = require("./MetadataDeclarationHelpers")(gd);
|
|
32
|
+
|
|
33
|
+
const loader = {};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Load all events functions of a project in extensions
|
|
37
|
+
*/
|
|
38
|
+
const loadProjectEventsFunctionsExtensions = (
|
|
39
|
+
project,
|
|
40
|
+
eventsFunctionCodeWriter
|
|
41
|
+
) => {
|
|
42
|
+
return Promise.all(
|
|
43
|
+
// First pass: generate extensions from the events functions extensions,
|
|
44
|
+
// without writing code for the functions. This is useful as events in functions
|
|
45
|
+
// could be using other functions, which would not yet be available as
|
|
46
|
+
// extensions.
|
|
53
47
|
mapFor(0, project.getEventsFunctionsExtensionsCount(), (i) => {
|
|
54
48
|
return loadProjectEventsFunctionsExtension(
|
|
55
49
|
project,
|
|
56
50
|
project.getEventsFunctionsExtensionAt(i),
|
|
57
|
-
{
|
|
58
|
-
skipCodeGeneration: false,
|
|
59
|
-
eventsFunctionCodeWriter,
|
|
60
|
-
}
|
|
51
|
+
{ skipCodeGeneration: true, eventsFunctionCodeWriter }
|
|
61
52
|
);
|
|
62
53
|
})
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
).then(() =>
|
|
55
|
+
Promise.all(
|
|
56
|
+
// Second pass: generate extensions, including code.
|
|
57
|
+
mapFor(0, project.getEventsFunctionsExtensionsCount(), (i) => {
|
|
58
|
+
return loadProjectEventsFunctionsExtension(
|
|
59
|
+
project,
|
|
60
|
+
project.getEventsFunctionsExtensionAt(i),
|
|
61
|
+
{
|
|
62
|
+
skipCodeGeneration: false,
|
|
63
|
+
eventsFunctionCodeWriter,
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
})
|
|
67
|
+
)
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
loader.loadProjectEventsFunctionsExtensions =
|
|
71
|
+
loadProjectEventsFunctionsExtensions;
|
|
67
72
|
|
|
68
|
-
const loadProjectEventsFunctionsExtension = (
|
|
69
|
-
project,
|
|
70
|
-
eventsFunctionsExtension,
|
|
71
|
-
options
|
|
72
|
-
) => {
|
|
73
|
-
return generateEventsFunctionExtension(
|
|
73
|
+
const loadProjectEventsFunctionsExtension = (
|
|
74
74
|
project,
|
|
75
75
|
eventsFunctionsExtension,
|
|
76
76
|
options
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const getExtensionIncludeFiles = (
|
|
88
|
-
project,
|
|
89
|
-
eventsFunctionsExtension,
|
|
90
|
-
options,
|
|
91
|
-
codeNamespacePrefix
|
|
92
|
-
) => {
|
|
93
|
-
return mapFor(0, eventsFunctionsExtension.getEventsFunctionsCount(), (i) => {
|
|
94
|
-
const eventsFunction = eventsFunctionsExtension.getEventsFunctionAt(i);
|
|
95
|
-
|
|
96
|
-
if (isExtensionLifecycleEventsFunction(eventsFunction.getName())) {
|
|
97
|
-
const codeNamespace = getFreeFunctionCodeNamespace(
|
|
98
|
-
eventsFunction,
|
|
99
|
-
codeNamespacePrefix
|
|
100
|
-
);
|
|
101
|
-
const functionName = codeNamespace + ".func"; // TODO
|
|
102
|
-
|
|
103
|
-
return options.eventsFunctionCodeWriter.getIncludeFileFor(functionName);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return null;
|
|
107
|
-
}).filter(Boolean);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Generate the code for the events based extension
|
|
112
|
-
*/
|
|
113
|
-
const generateEventsFunctionExtension = (
|
|
114
|
-
project,
|
|
115
|
-
eventsFunctionsExtension,
|
|
116
|
-
options
|
|
117
|
-
) => {
|
|
118
|
-
const extension = new _GD.PlatformExtension();
|
|
119
|
-
declareExtension(extension, eventsFunctionsExtension);
|
|
120
|
-
|
|
121
|
-
const codeNamespacePrefix =
|
|
122
|
-
"gdjs.evtsExt__" + mangleName(eventsFunctionsExtension.getName());
|
|
77
|
+
) => {
|
|
78
|
+
return generateEventsFunctionExtension(
|
|
79
|
+
project,
|
|
80
|
+
eventsFunctionsExtension,
|
|
81
|
+
options
|
|
82
|
+
).then((extension) => {
|
|
83
|
+
gd.JsPlatform.get().addNewExtension(extension);
|
|
84
|
+
extension.delete();
|
|
85
|
+
});
|
|
86
|
+
};
|
|
123
87
|
|
|
124
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Get the list of mandatory include files when using the
|
|
90
|
+
* extension.
|
|
91
|
+
*/
|
|
92
|
+
const getExtensionIncludeFiles = (
|
|
125
93
|
project,
|
|
126
94
|
eventsFunctionsExtension,
|
|
127
95
|
options,
|
|
128
96
|
codeNamespacePrefix
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
97
|
+
) => {
|
|
98
|
+
return mapFor(
|
|
99
|
+
0,
|
|
100
|
+
eventsFunctionsExtension.getEventsFunctionsCount(),
|
|
101
|
+
(i) => {
|
|
102
|
+
const eventsFunction = eventsFunctionsExtension.getEventsFunctionAt(i);
|
|
103
|
+
|
|
104
|
+
if (isExtensionLifecycleEventsFunction(eventsFunction.getName())) {
|
|
105
|
+
const codeNamespace = getFreeFunctionCodeNamespace(
|
|
106
|
+
eventsFunction,
|
|
107
|
+
codeNamespacePrefix
|
|
108
|
+
);
|
|
109
|
+
const functionName = codeNamespace + ".func"; // TODO
|
|
134
110
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
mapVector(
|
|
138
|
-
eventsFunctionsExtension.getEventsBasedBehaviors(),
|
|
139
|
-
(eventsBasedBehavior) => {
|
|
140
|
-
return generateBehavior(
|
|
141
|
-
project,
|
|
142
|
-
extension,
|
|
143
|
-
eventsFunctionsExtension,
|
|
144
|
-
eventsBasedBehavior,
|
|
145
|
-
options,
|
|
146
|
-
codeGenerationContext
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
)
|
|
150
|
-
)
|
|
151
|
-
.then(() =>
|
|
152
|
-
// Generate all free functions
|
|
153
|
-
Promise.all(
|
|
154
|
-
mapFor(0, eventsFunctionsExtension.getEventsFunctionsCount(), (i) => {
|
|
155
|
-
const eventsFunction = eventsFunctionsExtension.getEventsFunctionAt(
|
|
156
|
-
i
|
|
111
|
+
return options.eventsFunctionCodeWriter.getIncludeFileFor(
|
|
112
|
+
functionName
|
|
157
113
|
);
|
|
158
|
-
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
).filter(Boolean);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Generate the code for the events based extension
|
|
123
|
+
*/
|
|
124
|
+
const generateEventsFunctionExtension = (
|
|
125
|
+
project,
|
|
126
|
+
eventsFunctionsExtension,
|
|
127
|
+
options
|
|
128
|
+
) => {
|
|
129
|
+
const extension = new gd.PlatformExtension();
|
|
130
|
+
declareExtension(extension, eventsFunctionsExtension);
|
|
131
|
+
|
|
132
|
+
const codeNamespacePrefix =
|
|
133
|
+
"gdjs.evtsExt__" + mangleName(eventsFunctionsExtension.getName());
|
|
134
|
+
|
|
135
|
+
const extensionIncludeFiles = getExtensionIncludeFiles(
|
|
136
|
+
project,
|
|
137
|
+
eventsFunctionsExtension,
|
|
138
|
+
options,
|
|
139
|
+
codeNamespacePrefix
|
|
140
|
+
);
|
|
141
|
+
const codeGenerationContext = {
|
|
142
|
+
codeNamespacePrefix,
|
|
143
|
+
extensionIncludeFiles,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return Promise.all(
|
|
147
|
+
// Generate all behaviors and their functions
|
|
148
|
+
mapVector(
|
|
149
|
+
eventsFunctionsExtension.getEventsBasedBehaviors(),
|
|
150
|
+
(eventsBasedBehavior) => {
|
|
151
|
+
return generateBehavior(
|
|
159
152
|
project,
|
|
160
153
|
extension,
|
|
161
154
|
eventsFunctionsExtension,
|
|
162
|
-
|
|
155
|
+
eventsBasedBehavior,
|
|
163
156
|
options,
|
|
164
157
|
codeGenerationContext
|
|
165
158
|
);
|
|
166
|
-
}
|
|
159
|
+
}
|
|
167
160
|
)
|
|
168
161
|
)
|
|
169
|
-
|
|
170
|
-
|
|
162
|
+
.then(() =>
|
|
163
|
+
// Generate all free functions
|
|
164
|
+
Promise.all(
|
|
165
|
+
mapFor(0, eventsFunctionsExtension.getEventsFunctionsCount(), (i) => {
|
|
166
|
+
const eventsFunction =
|
|
167
|
+
eventsFunctionsExtension.getEventsFunctionAt(i);
|
|
168
|
+
return generateFreeFunction(
|
|
169
|
+
project,
|
|
170
|
+
extension,
|
|
171
|
+
eventsFunctionsExtension,
|
|
172
|
+
eventsFunction,
|
|
173
|
+
options,
|
|
174
|
+
codeGenerationContext
|
|
175
|
+
);
|
|
176
|
+
})
|
|
177
|
+
)
|
|
178
|
+
)
|
|
179
|
+
.then(() => extension);
|
|
180
|
+
};
|
|
171
181
|
|
|
172
|
-
const generateFreeFunction = (
|
|
173
|
-
|
|
174
|
-
extension,
|
|
175
|
-
eventsFunctionsExtension,
|
|
176
|
-
eventsFunction,
|
|
177
|
-
options,
|
|
178
|
-
codeGenerationContext
|
|
179
|
-
) => {
|
|
180
|
-
const instructionOrExpression = declareInstructionOrExpressionMetadata(
|
|
182
|
+
const generateFreeFunction = (
|
|
183
|
+
project,
|
|
181
184
|
extension,
|
|
182
185
|
eventsFunctionsExtension,
|
|
183
|
-
eventsFunction
|
|
184
|
-
);
|
|
185
|
-
// By convention, first parameter is always the Runtime Scene.
|
|
186
|
-
instructionOrExpression.addCodeOnlyParameter("currentScene", "");
|
|
187
|
-
declareEventsFunctionParameters(eventsFunction, instructionOrExpression);
|
|
188
|
-
|
|
189
|
-
// Hide "lifecycle" functions as they are called automatically by
|
|
190
|
-
// the game engine.
|
|
191
|
-
if (isExtensionLifecycleEventsFunction(eventsFunction.getName())) {
|
|
192
|
-
instructionOrExpression.setHidden();
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const codeNamespace = getFreeFunctionCodeNamespace(
|
|
196
186
|
eventsFunction,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
options.eventsFunctionCodeWriter.getIncludeFileFor(functionName)
|
|
205
|
-
)
|
|
206
|
-
.setFunctionName(functionName);
|
|
207
|
-
|
|
208
|
-
// Always include the extension include files when using a free function.
|
|
209
|
-
codeGenerationContext.extensionIncludeFiles.forEach((includeFile) => {
|
|
210
|
-
codeExtraInformation.addIncludeFile(includeFile);
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
if (!options.skipCodeGeneration) {
|
|
214
|
-
const includeFiles = new _GD.SetString();
|
|
215
|
-
const eventsFunctionsExtensionCodeGenerator = new _GD.EventsFunctionsExtensionCodeGenerator(
|
|
216
|
-
project
|
|
217
|
-
);
|
|
218
|
-
const code = eventsFunctionsExtensionCodeGenerator.generateFreeEventsFunctionCompleteCode(
|
|
219
|
-
eventsFunction,
|
|
220
|
-
codeNamespace,
|
|
221
|
-
includeFiles,
|
|
222
|
-
// For now, always generate functions for runtime (this disables
|
|
223
|
-
// generation of profiling for groups (see EventsCodeGenerator))
|
|
224
|
-
// as extensions generated can be used either for preview or export.
|
|
225
|
-
true
|
|
226
|
-
);
|
|
227
|
-
|
|
228
|
-
// Add any include file required by the function to the list
|
|
229
|
-
// of include files for this function (so that when used, the "dependencies"
|
|
230
|
-
// are transitively included).
|
|
231
|
-
includeFiles
|
|
232
|
-
.toNewVectorString()
|
|
233
|
-
.toJSArray()
|
|
234
|
-
.forEach((includeFile) => {
|
|
235
|
-
codeExtraInformation.addIncludeFile(includeFile);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
includeFiles.delete();
|
|
239
|
-
|
|
240
|
-
return options.eventsFunctionCodeWriter.writeFunctionCode(
|
|
241
|
-
functionName,
|
|
242
|
-
code
|
|
187
|
+
options,
|
|
188
|
+
codeGenerationContext
|
|
189
|
+
) => {
|
|
190
|
+
const instructionOrExpression = declareInstructionOrExpressionMetadata(
|
|
191
|
+
extension,
|
|
192
|
+
eventsFunctionsExtension,
|
|
193
|
+
eventsFunction
|
|
243
194
|
);
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// are loaded as extensions but not code generated, as events in functions could
|
|
248
|
-
// themselves be using functions that are not yet available in extensions.
|
|
249
|
-
return Promise.resolve();
|
|
250
|
-
}
|
|
251
|
-
};
|
|
195
|
+
// By convention, first parameter is always the Runtime Scene.
|
|
196
|
+
instructionOrExpression.addCodeOnlyParameter("currentScene", "");
|
|
197
|
+
declareEventsFunctionParameters(eventsFunction, instructionOrExpression);
|
|
252
198
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
options,
|
|
259
|
-
codeGenerationContext
|
|
260
|
-
) {
|
|
261
|
-
const behaviorMetadata = declareBehaviorMetadata(
|
|
262
|
-
extension,
|
|
263
|
-
eventsBasedBehavior
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
const eventsFunctionsContainer = eventsBasedBehavior.getEventsFunctions();
|
|
267
|
-
const codeNamespace = getBehaviorFunctionCodeNamespace(
|
|
268
|
-
eventsBasedBehavior,
|
|
269
|
-
codeGenerationContext.codeNamespacePrefix
|
|
270
|
-
);
|
|
271
|
-
const includeFile = options.eventsFunctionCodeWriter.getIncludeFileFor(
|
|
272
|
-
codeNamespace
|
|
273
|
-
);
|
|
274
|
-
|
|
275
|
-
behaviorMetadata.setIncludeFile(includeFile);
|
|
276
|
-
|
|
277
|
-
// Always include the extension include files when using a behavior.
|
|
278
|
-
codeGenerationContext.extensionIncludeFiles.forEach((includeFile) => {
|
|
279
|
-
behaviorMetadata.addIncludeFile(includeFile);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
return Promise.resolve().then(() => {
|
|
283
|
-
const behaviorMethodMangledNames = new _GD.MapStringString();
|
|
199
|
+
// Hide "lifecycle" functions as they are called automatically by
|
|
200
|
+
// the game engine.
|
|
201
|
+
if (isExtensionLifecycleEventsFunction(eventsFunction.getName())) {
|
|
202
|
+
instructionOrExpression.setHidden();
|
|
203
|
+
}
|
|
284
204
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
eventsBasedBehavior
|
|
205
|
+
const codeNamespace = getFreeFunctionCodeNamespace(
|
|
206
|
+
eventsFunction,
|
|
207
|
+
codeGenerationContext.codeNamespacePrefix
|
|
289
208
|
);
|
|
209
|
+
const functionName = codeNamespace + ".func";
|
|
290
210
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
eventsFunctionMangledName
|
|
299
|
-
);
|
|
300
|
-
|
|
301
|
-
const instructionOrExpression = declareBehaviorInstructionOrExpressionMetadata(
|
|
302
|
-
behaviorMetadata,
|
|
303
|
-
eventsBasedBehavior,
|
|
304
|
-
eventsFunction
|
|
305
|
-
);
|
|
306
|
-
declareEventsFunctionParameters(eventsFunction, instructionOrExpression);
|
|
307
|
-
|
|
308
|
-
// Hide "lifecycle" methods as they are called automatically by
|
|
309
|
-
// the game engine.
|
|
310
|
-
if (isBehaviorLifecycleEventsFunction(eventsFunction.getName())) {
|
|
311
|
-
instructionOrExpression.setHidden();
|
|
312
|
-
}
|
|
211
|
+
const codeExtraInformation =
|
|
212
|
+
instructionOrExpression.getCodeExtraInformation();
|
|
213
|
+
codeExtraInformation
|
|
214
|
+
.setIncludeFile(
|
|
215
|
+
options.eventsFunctionCodeWriter.getIncludeFileFor(functionName)
|
|
216
|
+
)
|
|
217
|
+
.setFunctionName(functionName);
|
|
313
218
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
.setFunctionName(eventsFunctionMangledName);
|
|
219
|
+
// Always include the extension include files when using a free function.
|
|
220
|
+
codeGenerationContext.extensionIncludeFiles.forEach((includeFile) => {
|
|
221
|
+
codeExtraInformation.addIncludeFile(includeFile);
|
|
318
222
|
});
|
|
319
223
|
|
|
320
|
-
// Generate code for the behavior and its methods
|
|
321
224
|
if (!options.skipCodeGeneration) {
|
|
322
|
-
const includeFiles = new
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
);
|
|
336
|
-
behaviorCodeGenerator.delete();
|
|
337
|
-
behaviorMethodMangledNames.delete();
|
|
225
|
+
const includeFiles = new gd.SetString();
|
|
226
|
+
const eventsFunctionsExtensionCodeGenerator =
|
|
227
|
+
new gd.EventsFunctionsExtensionCodeGenerator(project);
|
|
228
|
+
const code =
|
|
229
|
+
eventsFunctionsExtensionCodeGenerator.generateFreeEventsFunctionCompleteCode(
|
|
230
|
+
eventsFunction,
|
|
231
|
+
codeNamespace,
|
|
232
|
+
includeFiles,
|
|
233
|
+
// For now, always generate functions for runtime (this disables
|
|
234
|
+
// generation of profiling for groups (see EventsCodeGenerator))
|
|
235
|
+
// as extensions generated can be used either for preview or export.
|
|
236
|
+
true
|
|
237
|
+
);
|
|
338
238
|
|
|
339
|
-
// Add any include file required by the
|
|
340
|
-
// of include files for this
|
|
239
|
+
// Add any include file required by the function to the list
|
|
240
|
+
// of include files for this function (so that when used, the "dependencies"
|
|
341
241
|
// are transitively included).
|
|
342
242
|
includeFiles
|
|
343
243
|
.toNewVectorString()
|
|
344
244
|
.toJSArray()
|
|
345
245
|
.forEach((includeFile) => {
|
|
346
|
-
|
|
246
|
+
codeExtraInformation.addIncludeFile(includeFile);
|
|
347
247
|
});
|
|
348
248
|
|
|
349
249
|
includeFiles.delete();
|
|
350
250
|
|
|
351
|
-
return options.eventsFunctionCodeWriter.
|
|
352
|
-
|
|
251
|
+
return options.eventsFunctionCodeWriter.writeFunctionCode(
|
|
252
|
+
functionName,
|
|
353
253
|
code
|
|
354
254
|
);
|
|
355
255
|
} else {
|
|
356
|
-
// Skip code generation
|
|
357
|
-
|
|
256
|
+
// Skip code generation if no events function writer is provided.
|
|
257
|
+
// This is the case during the "first pass", where all events functions extensions
|
|
258
|
+
// are loaded as extensions but not code generated, as events in functions could
|
|
259
|
+
// themselves be using functions that are not yet available in extensions.
|
|
358
260
|
return Promise.resolve();
|
|
359
261
|
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
function generateBehavior(
|
|
265
|
+
project,
|
|
266
|
+
extension,
|
|
267
|
+
eventsFunctionsExtension,
|
|
268
|
+
eventsBasedBehavior,
|
|
269
|
+
options,
|
|
270
|
+
codeGenerationContext
|
|
271
|
+
) {
|
|
272
|
+
const behaviorMetadata = declareBehaviorMetadata(
|
|
273
|
+
extension,
|
|
274
|
+
eventsBasedBehavior
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
const eventsFunctionsContainer = eventsBasedBehavior.getEventsFunctions();
|
|
278
|
+
const codeNamespace = getBehaviorFunctionCodeNamespace(
|
|
279
|
+
eventsBasedBehavior,
|
|
280
|
+
codeGenerationContext.codeNamespacePrefix
|
|
281
|
+
);
|
|
282
|
+
const includeFile =
|
|
283
|
+
options.eventsFunctionCodeWriter.getIncludeFileFor(codeNamespace);
|
|
284
|
+
|
|
285
|
+
behaviorMetadata.setIncludeFile(includeFile);
|
|
286
|
+
|
|
287
|
+
// Always include the extension include files when using a behavior.
|
|
288
|
+
codeGenerationContext.extensionIncludeFiles.forEach((includeFile) => {
|
|
289
|
+
behaviorMetadata.addIncludeFile(includeFile);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
return Promise.resolve().then(() => {
|
|
293
|
+
const behaviorMethodMangledNames = new gd.MapStringString();
|
|
294
|
+
|
|
295
|
+
// Declare the instructions/expressions for properties
|
|
296
|
+
declareBehaviorPropertiesInstructionAndExpressions(
|
|
297
|
+
behaviorMetadata,
|
|
298
|
+
eventsBasedBehavior
|
|
371
299
|
);
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
300
|
+
|
|
301
|
+
// Declare all the behavior functions
|
|
302
|
+
mapFor(0, eventsFunctionsContainer.getEventsFunctionsCount(), (i) => {
|
|
303
|
+
const eventsFunction = eventsFunctionsContainer.getEventsFunctionAt(i);
|
|
304
|
+
|
|
305
|
+
const eventsFunctionMangledName = mangleName(eventsFunction.getName());
|
|
306
|
+
behaviorMethodMangledNames.set(
|
|
307
|
+
eventsFunction.getName(),
|
|
308
|
+
eventsFunctionMangledName
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
const instructionOrExpression =
|
|
312
|
+
declareBehaviorInstructionOrExpressionMetadata(
|
|
313
|
+
behaviorMetadata,
|
|
314
|
+
eventsBasedBehavior,
|
|
315
|
+
eventsFunction
|
|
316
|
+
);
|
|
317
|
+
declareEventsFunctionParameters(
|
|
318
|
+
eventsFunction,
|
|
319
|
+
instructionOrExpression
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
// Hide "lifecycle" methods as they are called automatically by
|
|
323
|
+
// the game engine.
|
|
324
|
+
if (isBehaviorLifecycleEventsFunction(eventsFunction.getName())) {
|
|
325
|
+
instructionOrExpression.setHidden();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const codeExtraInformation =
|
|
329
|
+
instructionOrExpression.getCodeExtraInformation();
|
|
330
|
+
codeExtraInformation
|
|
331
|
+
.setIncludeFile(includeFile)
|
|
332
|
+
.setFunctionName(eventsFunctionMangledName);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Generate code for the behavior and its methods
|
|
336
|
+
if (!options.skipCodeGeneration) {
|
|
337
|
+
const includeFiles = new gd.SetString();
|
|
338
|
+
const behaviorCodeGenerator = new gd.BehaviorCodeGenerator(project);
|
|
339
|
+
const code = behaviorCodeGenerator.generateRuntimeBehaviorCompleteCode(
|
|
340
|
+
eventsFunctionsExtension.getName(),
|
|
341
|
+
eventsBasedBehavior,
|
|
342
|
+
codeNamespace,
|
|
343
|
+
behaviorMethodMangledNames,
|
|
344
|
+
includeFiles,
|
|
345
|
+
|
|
346
|
+
// For now, always generate functions for runtime (this disables
|
|
347
|
+
// generation of profiling for groups (see EventsCodeGenerator))
|
|
348
|
+
// as extensions generated can be used either for preview or export.
|
|
349
|
+
true
|
|
350
|
+
);
|
|
351
|
+
behaviorCodeGenerator.delete();
|
|
352
|
+
behaviorMethodMangledNames.delete();
|
|
353
|
+
|
|
354
|
+
// Add any include file required by the functions to the list
|
|
355
|
+
// of include files for this behavior (so that when used, the "dependencies"
|
|
356
|
+
// are transitively included).
|
|
357
|
+
includeFiles
|
|
358
|
+
.toNewVectorString()
|
|
359
|
+
.toJSArray()
|
|
360
|
+
.forEach((includeFile) => {
|
|
361
|
+
behaviorMetadata.addIncludeFile(includeFile);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
includeFiles.delete();
|
|
365
|
+
|
|
366
|
+
return options.eventsFunctionCodeWriter.writeBehaviorCode(
|
|
367
|
+
codeNamespace,
|
|
368
|
+
code
|
|
369
|
+
);
|
|
370
|
+
} else {
|
|
371
|
+
// Skip code generation
|
|
372
|
+
behaviorMethodMangledNames.delete();
|
|
373
|
+
return Promise.resolve();
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Unload all extensions providing events functions of a project
|
|
380
|
+
*/
|
|
381
|
+
const unloadProjectEventsFunctionsExtensions = (project) => {
|
|
382
|
+
return Promise.all(
|
|
383
|
+
mapFor(0, project.getEventsFunctionsExtensionsCount(), (i) => {
|
|
384
|
+
gd.JsPlatform.get().removeExtension(
|
|
385
|
+
project.getEventsFunctionsExtensionAt(i).getName()
|
|
386
|
+
);
|
|
387
|
+
})
|
|
388
|
+
);
|
|
389
|
+
};
|
|
390
|
+
loader.unloadProjectEventsFunctionsExtensions =
|
|
391
|
+
unloadProjectEventsFunctionsExtensions;
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Given metadata about an instruction or an expression, tells if this was created
|
|
395
|
+
* from an event function.
|
|
396
|
+
*/
|
|
397
|
+
const isAnEventFunctionMetadata = (instructionOrExpression) => {
|
|
398
|
+
const parametersCount = instructionOrExpression.getParametersCount();
|
|
399
|
+
if (parametersCount <= 0) return false;
|
|
400
|
+
|
|
401
|
+
return (
|
|
402
|
+
instructionOrExpression.getParameter(parametersCount - 1).getType() ===
|
|
403
|
+
"eventsFunctionContext"
|
|
404
|
+
);
|
|
405
|
+
};
|
|
406
|
+
loader.isAnEventFunctionMetadata = isAnEventFunctionMetadata;
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Get back the name a function from its type.
|
|
410
|
+
* See also getFreeEventsFunctionType for the reverse operation.
|
|
411
|
+
*/
|
|
412
|
+
const getFunctionNameFromType = (type) => {
|
|
413
|
+
const parts = type.split("::");
|
|
414
|
+
if (!parts.length)
|
|
415
|
+
return {
|
|
416
|
+
name: "",
|
|
417
|
+
behaviorName: "",
|
|
418
|
+
extensionName: "",
|
|
419
|
+
};
|
|
420
|
+
|
|
399
421
|
return {
|
|
400
|
-
name:
|
|
401
|
-
behaviorName:
|
|
402
|
-
extensionName:
|
|
422
|
+
name: parts[parts.length - 1],
|
|
423
|
+
behaviorName: parts.length > 2 ? parts[1] : undefined,
|
|
424
|
+
extensionName: parts[0],
|
|
403
425
|
};
|
|
404
|
-
|
|
405
|
-
return {
|
|
406
|
-
name: parts[parts.length - 1],
|
|
407
|
-
behaviorName: parts.length > 2 ? parts[1] : undefined,
|
|
408
|
-
extensionName: parts[0],
|
|
409
426
|
};
|
|
427
|
+
loader.getFunctionNameFromType = getFunctionNameFromType;
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Get the type of a Events Function.
|
|
431
|
+
* See also getFunctionNameFromType for the reverse operation.
|
|
432
|
+
*/
|
|
433
|
+
const getFreeEventsFunctionType = (extensionName, eventsFunction) => {
|
|
434
|
+
return extensionName + "::" + eventsFunction.getName();
|
|
435
|
+
};
|
|
436
|
+
loader.getFreeEventsFunctionType = getFreeEventsFunctionType;
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Return the index of the first parameter to be shown to the user:
|
|
440
|
+
* * 0 for a behavior "method",
|
|
441
|
+
* * 1 for a free function (as the first parameter is by convention the runtimeScene).
|
|
442
|
+
*/
|
|
443
|
+
const getParametersIndexOffset = (isEventsBasedBehaviorMethod) => {
|
|
444
|
+
return isEventsBasedBehaviorMethod
|
|
445
|
+
? 0 /*In the case of a behavior events function, the first two parameters are by convention the "Object" and "Behavior" */
|
|
446
|
+
: 1; /*In the case of a free events function (i.e: not tied to a behavior), the first parameter is by convention the current scene and is not shown.*/
|
|
447
|
+
};
|
|
448
|
+
loader.getParametersIndexOffset = getParametersIndexOffset;
|
|
449
|
+
|
|
450
|
+
return loader;
|
|
410
451
|
};
|
|
411
|
-
module.exports.getFunctionNameFromType = getFunctionNameFromType;
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Get the type of a Events Function.
|
|
415
|
-
* See also getFunctionNameFromType for the reverse operation.
|
|
416
|
-
*/
|
|
417
|
-
const getFreeEventsFunctionType = (extensionName, eventsFunction) => {
|
|
418
|
-
return extensionName + "::" + eventsFunction.getName();
|
|
419
|
-
};
|
|
420
|
-
module.exports.getFreeEventsFunctionType = getFreeEventsFunctionType;
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Return the index of the first parameter to be shown to the user:
|
|
424
|
-
* * 0 for a behavior "method",
|
|
425
|
-
* * 1 for a free function (as the first parameter is by convention the runtimeScene).
|
|
426
|
-
*/
|
|
427
|
-
const getParametersIndexOffset = (isEventsBasedBehaviorMethod) => {
|
|
428
|
-
return isEventsBasedBehaviorMethod
|
|
429
|
-
? 0 /*In the case of a behavior events function, the first two parameters are by convention the "Object" and "Behavior" */
|
|
430
|
-
: 1; /*In the case of a free events function (i.e: not tied to a behavior), the first parameter is by convention the current scene and is not shown.*/
|
|
431
|
-
};
|
|
432
|
-
module.exports.getParametersIndexOffset = getParametersIndexOffset;
|