gdcore-tools 1.0.8 → 1.0.9
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/examples/create-objects-from-json/index.js +50 -50
- package/examples/export-game/game.json +204 -204
- package/examples/export-game/index.js +13 -13
- package/package.json +1 -1
- package/src/EventsFunctionsExtensionsLoader/index.js +130 -123
- package/src/EventsFunctionsExtensionsLoader/legacy.js +451 -0
- package/src/WrappedGD.js +4 -1
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
const loadGD = require("../..");
|
|
2
|
-
const list = require("./mylist.json");
|
|
3
|
-
|
|
4
|
-
let gdTools;
|
|
5
|
-
loadGD()
|
|
6
|
-
.then((_gdTools) => {
|
|
7
|
-
gdTools = _gdTools;
|
|
8
|
-
// Load the project file
|
|
9
|
-
return gdTools.loadProject("./game.json");
|
|
10
|
-
})
|
|
11
|
-
.then((project) => {
|
|
12
|
-
// Get the scene and add the objects and instances from the list
|
|
13
|
-
const scene = project.getLayout(/* Scene name: */ "MyScene");
|
|
14
|
-
const instances = scene.getInitialInstances();
|
|
15
|
-
let offset = 1;
|
|
16
|
-
list.forEach((item) => {
|
|
17
|
-
const textObjectName = "MyListItem_" + item;
|
|
18
|
-
const object = gdTools.gd.asTextObject(
|
|
19
|
-
scene.insertNewObject(
|
|
20
|
-
/* Project: */ project,
|
|
21
|
-
/* Object type: */ "TextObject::Text",
|
|
22
|
-
/* Object name: */ textObjectName,
|
|
23
|
-
/* Position where to insert: */ scene.getObjectsCount()
|
|
24
|
-
)
|
|
25
|
-
);
|
|
26
|
-
object.setString(item);
|
|
27
|
-
object.setColor(
|
|
28
|
-
Math.random() * 255,
|
|
29
|
-
Math.random() * 255,
|
|
30
|
-
Math.random() * 255
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
const textObjectInstance = instances.insertNewInitialInstance();
|
|
34
|
-
const spriteObjectInstance = instances.insertNewInitialInstance();
|
|
35
|
-
textObjectInstance.setObjectName(textObjectName);
|
|
36
|
-
spriteObjectInstance.setObjectName("Button");
|
|
37
|
-
textObjectInstance.setX(50);
|
|
38
|
-
spriteObjectInstance.setX(40);
|
|
39
|
-
textObjectInstance.setY(70 * offset + 15);
|
|
40
|
-
spriteObjectInstance.setY(70 * offset++);
|
|
41
|
-
textObjectInstance.setZOrder(1);
|
|
42
|
-
spriteObjectInstance.setZOrder(0);
|
|
43
|
-
|
|
44
|
-
spriteObjectInstance.setHasCustomSize(true);
|
|
45
|
-
spriteObjectInstance.setCustomHeight(48);
|
|
46
|
-
spriteObjectInstance.setCustomWidth(96);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
return gdTools.saveProject(project, "new_game.json");
|
|
50
|
-
});
|
|
1
|
+
const loadGD = require("../..");
|
|
2
|
+
const list = require("./mylist.json");
|
|
3
|
+
|
|
4
|
+
let gdTools;
|
|
5
|
+
loadGD()
|
|
6
|
+
.then((_gdTools) => {
|
|
7
|
+
gdTools = _gdTools;
|
|
8
|
+
// Load the project file
|
|
9
|
+
return gdTools.loadProject("./game.json");
|
|
10
|
+
})
|
|
11
|
+
.then((project) => {
|
|
12
|
+
// Get the scene and add the objects and instances from the list
|
|
13
|
+
const scene = project.getLayout(/* Scene name: */ "MyScene");
|
|
14
|
+
const instances = scene.getInitialInstances();
|
|
15
|
+
let offset = 1;
|
|
16
|
+
list.forEach((item) => {
|
|
17
|
+
const textObjectName = "MyListItem_" + item;
|
|
18
|
+
const object = gdTools.gd.asTextObject(
|
|
19
|
+
scene.insertNewObject(
|
|
20
|
+
/* Project: */ project,
|
|
21
|
+
/* Object type: */ "TextObject::Text",
|
|
22
|
+
/* Object name: */ textObjectName,
|
|
23
|
+
/* Position where to insert: */ scene.getObjectsCount()
|
|
24
|
+
)
|
|
25
|
+
);
|
|
26
|
+
object.setString(item);
|
|
27
|
+
object.setColor(
|
|
28
|
+
Math.random() * 255,
|
|
29
|
+
Math.random() * 255,
|
|
30
|
+
Math.random() * 255
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const textObjectInstance = instances.insertNewInitialInstance();
|
|
34
|
+
const spriteObjectInstance = instances.insertNewInitialInstance();
|
|
35
|
+
textObjectInstance.setObjectName(textObjectName);
|
|
36
|
+
spriteObjectInstance.setObjectName("Button");
|
|
37
|
+
textObjectInstance.setX(50);
|
|
38
|
+
spriteObjectInstance.setX(40);
|
|
39
|
+
textObjectInstance.setY(70 * offset + 15);
|
|
40
|
+
spriteObjectInstance.setY(70 * offset++);
|
|
41
|
+
textObjectInstance.setZOrder(1);
|
|
42
|
+
spriteObjectInstance.setZOrder(0);
|
|
43
|
+
|
|
44
|
+
spriteObjectInstance.setHasCustomSize(true);
|
|
45
|
+
spriteObjectInstance.setCustomHeight(48);
|
|
46
|
+
spriteObjectInstance.setCustomWidth(96);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return gdTools.saveProject(project, "new_game.json");
|
|
50
|
+
});
|
|
@@ -1,205 +1,205 @@
|
|
|
1
|
-
{
|
|
2
|
-
"firstLayout": "",
|
|
3
|
-
"gdVersion": {
|
|
4
|
-
"build": 99,
|
|
5
|
-
"major": 4,
|
|
6
|
-
"minor": 0,
|
|
7
|
-
"revision": 0
|
|
8
|
-
},
|
|
9
|
-
"properties": {
|
|
10
|
-
"adaptGameResolutionAtRuntime": true,
|
|
11
|
-
"folderProject": false,
|
|
12
|
-
"orientation": "landscape",
|
|
13
|
-
"packageName": "com.example.gamename",
|
|
14
|
-
"projectUuid": "b0ec0124-f3d9-4225-bfb5-60645a43b358",
|
|
15
|
-
"scaleMode": "linear",
|
|
16
|
-
"sizeOnStartupMode": "",
|
|
17
|
-
"useExternalSourceFiles": false,
|
|
18
|
-
"version": "1.0.0",
|
|
19
|
-
"name": "Project",
|
|
20
|
-
"author": "",
|
|
21
|
-
"windowWidth": 800,
|
|
22
|
-
"windowHeight": 600,
|
|
23
|
-
"latestCompilationDirectory": "",
|
|
24
|
-
"maxFPS": 60,
|
|
25
|
-
"minFPS": 20,
|
|
26
|
-
"verticalSync": false,
|
|
27
|
-
"platformSpecificAssets": {},
|
|
28
|
-
"loadingScreen": {
|
|
29
|
-
"showGDevelopSplash": true
|
|
30
|
-
},
|
|
31
|
-
"extensionProperties": [],
|
|
32
|
-
"extensions": [
|
|
33
|
-
{
|
|
34
|
-
"name": "BuiltinObject"
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"name": "BuiltinAudio"
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
"name": "BuiltinVariables"
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"name": "BuiltinTime"
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
"name": "BuiltinMouse"
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"name": "BuiltinKeyboard"
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
"name": "BuiltinJoystick"
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
"name": "BuiltinCamera"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
"name": "BuiltinWindow"
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
"name": "BuiltinFile"
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
"name": "BuiltinNetwork"
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
"name": "BuiltinScene"
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"name": "BuiltinAdvanced"
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"name": "Sprite"
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
"name": "BuiltinCommonInstructions"
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
"name": "BuiltinCommonConversions"
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
"name": "BuiltinStringInstructions"
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
"name": "BuiltinMathematicalTools"
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
"name": "BuiltinExternalLayouts"
|
|
89
|
-
}
|
|
90
|
-
],
|
|
91
|
-
"platforms": [
|
|
92
|
-
{
|
|
93
|
-
"name": "GDevelop JS platform"
|
|
94
|
-
}
|
|
95
|
-
],
|
|
96
|
-
"currentPlatform": "GDevelop JS platform"
|
|
97
|
-
},
|
|
98
|
-
"resources": {
|
|
99
|
-
"resources": [],
|
|
100
|
-
"resourceFolders": []
|
|
101
|
-
},
|
|
102
|
-
"objects": [],
|
|
103
|
-
"objectsGroups": [],
|
|
104
|
-
"variables": [],
|
|
105
|
-
"layouts": [
|
|
106
|
-
{
|
|
107
|
-
"b": 209,
|
|
108
|
-
"disableInputWhenNotFocused": true,
|
|
109
|
-
"mangledName": "New_32scene",
|
|
110
|
-
"name": "New scene",
|
|
111
|
-
"oglFOV": 90,
|
|
112
|
-
"oglZFar": 500,
|
|
113
|
-
"oglZNear": 1,
|
|
114
|
-
"r": 209,
|
|
115
|
-
"standardSortMethod": true,
|
|
116
|
-
"stopSoundsOnStartup": true,
|
|
117
|
-
"title": "",
|
|
118
|
-
"v": 209,
|
|
119
|
-
"uiSettings": {
|
|
120
|
-
"grid": false,
|
|
121
|
-
"gridB": 255,
|
|
122
|
-
"gridG": 180,
|
|
123
|
-
"gridHeight": 32,
|
|
124
|
-
"gridOffsetX": 0,
|
|
125
|
-
"gridOffsetY": 0,
|
|
126
|
-
"gridR": 158,
|
|
127
|
-
"gridWidth": 32,
|
|
128
|
-
"snap": true,
|
|
129
|
-
"windowMask": false,
|
|
130
|
-
"zoomFactor": 0.7662
|
|
131
|
-
},
|
|
132
|
-
"objectsGroups": [],
|
|
133
|
-
"variables": [],
|
|
134
|
-
"instances": [
|
|
135
|
-
{
|
|
136
|
-
"angle": 0,
|
|
137
|
-
"customSize": false,
|
|
138
|
-
"height": 0,
|
|
139
|
-
"layer": "",
|
|
140
|
-
"locked": false,
|
|
141
|
-
"name": "Test",
|
|
142
|
-
"persistentUuid": "f65d2b44-652d-4fdf-a603-05e48a9cf5ef",
|
|
143
|
-
"width": 0,
|
|
144
|
-
"x": 247,
|
|
145
|
-
"y": 279,
|
|
146
|
-
"zOrder": 1,
|
|
147
|
-
"numberProperties": [],
|
|
148
|
-
"stringProperties": [],
|
|
149
|
-
"initialVariables": []
|
|
150
|
-
}
|
|
151
|
-
],
|
|
152
|
-
"objects": [
|
|
153
|
-
{
|
|
154
|
-
"bold": false,
|
|
155
|
-
"italic": false,
|
|
156
|
-
"name": "Test",
|
|
157
|
-
"smoothed": true,
|
|
158
|
-
"tags": "",
|
|
159
|
-
"type": "TextObject::Text",
|
|
160
|
-
"underlined": false,
|
|
161
|
-
"variables": [],
|
|
162
|
-
"behaviors": [],
|
|
163
|
-
"string": "Test exporting via gdcore-tools",
|
|
164
|
-
"font": "",
|
|
165
|
-
"characterSize": 20,
|
|
166
|
-
"color": {
|
|
167
|
-
"b": 0,
|
|
168
|
-
"g": 0,
|
|
169
|
-
"r": 0
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
],
|
|
173
|
-
"events": [],
|
|
174
|
-
"layers": [
|
|
175
|
-
{
|
|
176
|
-
"ambientLightColorB": 16,
|
|
177
|
-
"ambientLightColorG": 0,
|
|
178
|
-
"ambientLightColorR": 0,
|
|
179
|
-
"followBaseLayerCamera": false,
|
|
180
|
-
"isLightingLayer": false,
|
|
181
|
-
"name": "",
|
|
182
|
-
"visibility": true,
|
|
183
|
-
"cameras": [
|
|
184
|
-
{
|
|
185
|
-
"defaultSize": true,
|
|
186
|
-
"defaultViewport": true,
|
|
187
|
-
"height": 0,
|
|
188
|
-
"viewportBottom": 1,
|
|
189
|
-
"viewportLeft": 0,
|
|
190
|
-
"viewportRight": 1,
|
|
191
|
-
"viewportTop": 0,
|
|
192
|
-
"width": 0
|
|
193
|
-
}
|
|
194
|
-
],
|
|
195
|
-
"effects": []
|
|
196
|
-
}
|
|
197
|
-
],
|
|
198
|
-
"behaviorsSharedData": []
|
|
199
|
-
}
|
|
200
|
-
],
|
|
201
|
-
"externalEvents": [],
|
|
202
|
-
"eventsFunctionsExtensions": [],
|
|
203
|
-
"externalLayouts": [],
|
|
204
|
-
"externalSourceFiles": []
|
|
1
|
+
{
|
|
2
|
+
"firstLayout": "",
|
|
3
|
+
"gdVersion": {
|
|
4
|
+
"build": 99,
|
|
5
|
+
"major": 4,
|
|
6
|
+
"minor": 0,
|
|
7
|
+
"revision": 0
|
|
8
|
+
},
|
|
9
|
+
"properties": {
|
|
10
|
+
"adaptGameResolutionAtRuntime": true,
|
|
11
|
+
"folderProject": false,
|
|
12
|
+
"orientation": "landscape",
|
|
13
|
+
"packageName": "com.example.gamename",
|
|
14
|
+
"projectUuid": "b0ec0124-f3d9-4225-bfb5-60645a43b358",
|
|
15
|
+
"scaleMode": "linear",
|
|
16
|
+
"sizeOnStartupMode": "",
|
|
17
|
+
"useExternalSourceFiles": false,
|
|
18
|
+
"version": "1.0.0",
|
|
19
|
+
"name": "Project",
|
|
20
|
+
"author": "",
|
|
21
|
+
"windowWidth": 800,
|
|
22
|
+
"windowHeight": 600,
|
|
23
|
+
"latestCompilationDirectory": "",
|
|
24
|
+
"maxFPS": 60,
|
|
25
|
+
"minFPS": 20,
|
|
26
|
+
"verticalSync": false,
|
|
27
|
+
"platformSpecificAssets": {},
|
|
28
|
+
"loadingScreen": {
|
|
29
|
+
"showGDevelopSplash": true
|
|
30
|
+
},
|
|
31
|
+
"extensionProperties": [],
|
|
32
|
+
"extensions": [
|
|
33
|
+
{
|
|
34
|
+
"name": "BuiltinObject"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "BuiltinAudio"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "BuiltinVariables"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "BuiltinTime"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "BuiltinMouse"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "BuiltinKeyboard"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "BuiltinJoystick"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "BuiltinCamera"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"name": "BuiltinWindow"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "BuiltinFile"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "BuiltinNetwork"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "BuiltinScene"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"name": "BuiltinAdvanced"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "Sprite"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "BuiltinCommonInstructions"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "BuiltinCommonConversions"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"name": "BuiltinStringInstructions"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "BuiltinMathematicalTools"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"name": "BuiltinExternalLayouts"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"platforms": [
|
|
92
|
+
{
|
|
93
|
+
"name": "GDevelop JS platform"
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"currentPlatform": "GDevelop JS platform"
|
|
97
|
+
},
|
|
98
|
+
"resources": {
|
|
99
|
+
"resources": [],
|
|
100
|
+
"resourceFolders": []
|
|
101
|
+
},
|
|
102
|
+
"objects": [],
|
|
103
|
+
"objectsGroups": [],
|
|
104
|
+
"variables": [],
|
|
105
|
+
"layouts": [
|
|
106
|
+
{
|
|
107
|
+
"b": 209,
|
|
108
|
+
"disableInputWhenNotFocused": true,
|
|
109
|
+
"mangledName": "New_32scene",
|
|
110
|
+
"name": "New scene",
|
|
111
|
+
"oglFOV": 90,
|
|
112
|
+
"oglZFar": 500,
|
|
113
|
+
"oglZNear": 1,
|
|
114
|
+
"r": 209,
|
|
115
|
+
"standardSortMethod": true,
|
|
116
|
+
"stopSoundsOnStartup": true,
|
|
117
|
+
"title": "",
|
|
118
|
+
"v": 209,
|
|
119
|
+
"uiSettings": {
|
|
120
|
+
"grid": false,
|
|
121
|
+
"gridB": 255,
|
|
122
|
+
"gridG": 180,
|
|
123
|
+
"gridHeight": 32,
|
|
124
|
+
"gridOffsetX": 0,
|
|
125
|
+
"gridOffsetY": 0,
|
|
126
|
+
"gridR": 158,
|
|
127
|
+
"gridWidth": 32,
|
|
128
|
+
"snap": true,
|
|
129
|
+
"windowMask": false,
|
|
130
|
+
"zoomFactor": 0.7662
|
|
131
|
+
},
|
|
132
|
+
"objectsGroups": [],
|
|
133
|
+
"variables": [],
|
|
134
|
+
"instances": [
|
|
135
|
+
{
|
|
136
|
+
"angle": 0,
|
|
137
|
+
"customSize": false,
|
|
138
|
+
"height": 0,
|
|
139
|
+
"layer": "",
|
|
140
|
+
"locked": false,
|
|
141
|
+
"name": "Test",
|
|
142
|
+
"persistentUuid": "f65d2b44-652d-4fdf-a603-05e48a9cf5ef",
|
|
143
|
+
"width": 0,
|
|
144
|
+
"x": 247,
|
|
145
|
+
"y": 279,
|
|
146
|
+
"zOrder": 1,
|
|
147
|
+
"numberProperties": [],
|
|
148
|
+
"stringProperties": [],
|
|
149
|
+
"initialVariables": []
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
"objects": [
|
|
153
|
+
{
|
|
154
|
+
"bold": false,
|
|
155
|
+
"italic": false,
|
|
156
|
+
"name": "Test",
|
|
157
|
+
"smoothed": true,
|
|
158
|
+
"tags": "",
|
|
159
|
+
"type": "TextObject::Text",
|
|
160
|
+
"underlined": false,
|
|
161
|
+
"variables": [],
|
|
162
|
+
"behaviors": [],
|
|
163
|
+
"string": "Test exporting via gdcore-tools",
|
|
164
|
+
"font": "",
|
|
165
|
+
"characterSize": 20,
|
|
166
|
+
"color": {
|
|
167
|
+
"b": 0,
|
|
168
|
+
"g": 0,
|
|
169
|
+
"r": 0
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
"events": [],
|
|
174
|
+
"layers": [
|
|
175
|
+
{
|
|
176
|
+
"ambientLightColorB": 16,
|
|
177
|
+
"ambientLightColorG": 0,
|
|
178
|
+
"ambientLightColorR": 0,
|
|
179
|
+
"followBaseLayerCamera": false,
|
|
180
|
+
"isLightingLayer": false,
|
|
181
|
+
"name": "",
|
|
182
|
+
"visibility": true,
|
|
183
|
+
"cameras": [
|
|
184
|
+
{
|
|
185
|
+
"defaultSize": true,
|
|
186
|
+
"defaultViewport": true,
|
|
187
|
+
"height": 0,
|
|
188
|
+
"viewportBottom": 1,
|
|
189
|
+
"viewportLeft": 0,
|
|
190
|
+
"viewportRight": 1,
|
|
191
|
+
"viewportTop": 0,
|
|
192
|
+
"width": 0
|
|
193
|
+
}
|
|
194
|
+
],
|
|
195
|
+
"effects": []
|
|
196
|
+
}
|
|
197
|
+
],
|
|
198
|
+
"behaviorsSharedData": []
|
|
199
|
+
}
|
|
200
|
+
],
|
|
201
|
+
"externalEvents": [],
|
|
202
|
+
"eventsFunctionsExtensions": [],
|
|
203
|
+
"externalLayouts": [],
|
|
204
|
+
"externalSourceFiles": []
|
|
205
205
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
// Note: for exporting games programatically, look into GDExporter.
|
|
2
|
-
// https://github.com/arthuro555/gdexporter
|
|
3
|
-
|
|
4
|
-
const loadGD = require("../..");
|
|
5
|
-
|
|
6
|
-
let gdTools;
|
|
7
|
-
loadGD()
|
|
8
|
-
.then((_gdTools) => {
|
|
9
|
-
gdTools = _gdTools;
|
|
10
|
-
// Load the project file
|
|
11
|
-
return gdTools.loadProject("./game.json");
|
|
12
|
-
})
|
|
13
|
-
.then((project) => gdTools.exportProject(project, "GameExport"));
|
|
1
|
+
// Note: for exporting games programatically, look into GDExporter.
|
|
2
|
+
// https://github.com/arthuro555/gdexporter
|
|
3
|
+
|
|
4
|
+
const loadGD = require("../..");
|
|
5
|
+
|
|
6
|
+
let gdTools;
|
|
7
|
+
loadGD()
|
|
8
|
+
.then((_gdTools) => {
|
|
9
|
+
gdTools = _gdTools;
|
|
10
|
+
// Load the project file
|
|
11
|
+
return gdTools.loadProject("./game.json");
|
|
12
|
+
})
|
|
13
|
+
.then((project) => gdTools.exportProject(project, "GameExport"));
|
package/package.json
CHANGED
|
@@ -27,16 +27,8 @@ const getObjectFunctionCodeNamespace = (
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
module.exports.makeLoader = (gd) => {
|
|
30
|
-
const {
|
|
31
|
-
|
|
32
|
-
declareBehaviorInstructionOrExpressionMetadata,
|
|
33
|
-
declareEventsFunctionParameters,
|
|
34
|
-
declareBehaviorMetadata,
|
|
35
|
-
declareExtension,
|
|
36
|
-
isBehaviorLifecycleEventsFunction,
|
|
37
|
-
isExtensionLifecycleEventsFunction,
|
|
38
|
-
declareBehaviorPropertiesInstructionAndExpressions,
|
|
39
|
-
} = require("./MetadataDeclarationHelpers")(gd);
|
|
30
|
+
const { isExtensionLifecycleEventsFunction } =
|
|
31
|
+
require("./MetadataDeclarationHelpers")(gd);
|
|
40
32
|
|
|
41
33
|
const loader = {};
|
|
42
34
|
|
|
@@ -135,7 +127,10 @@ module.exports.makeLoader = (gd) => {
|
|
|
135
127
|
options
|
|
136
128
|
) => {
|
|
137
129
|
const extension = new gd.PlatformExtension();
|
|
138
|
-
declareExtension(
|
|
130
|
+
gd.MetadataDeclarationHelper.declareExtension(
|
|
131
|
+
extension,
|
|
132
|
+
eventsFunctionsExtension
|
|
133
|
+
);
|
|
139
134
|
|
|
140
135
|
const codeNamespacePrefix =
|
|
141
136
|
"gdjs.evtsExt__" + mangleName(eventsFunctionsExtension.getName());
|
|
@@ -168,24 +163,22 @@ module.exports.makeLoader = (gd) => {
|
|
|
168
163
|
)
|
|
169
164
|
)
|
|
170
165
|
.then(() =>
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
)
|
|
188
|
-
)
|
|
166
|
+
// Generate all objects and their functions
|
|
167
|
+
Promise.all(
|
|
168
|
+
mapVector(
|
|
169
|
+
eventsFunctionsExtension.getEventsBasedObjects(),
|
|
170
|
+
(eventsBasedObject) => {
|
|
171
|
+
return generateObject(
|
|
172
|
+
project,
|
|
173
|
+
extension,
|
|
174
|
+
eventsFunctionsExtension,
|
|
175
|
+
eventsBasedObject,
|
|
176
|
+
options,
|
|
177
|
+
codeGenerationContext
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
)
|
|
181
|
+
)
|
|
189
182
|
)
|
|
190
183
|
.then(() =>
|
|
191
184
|
// Generate all free functions
|
|
@@ -204,7 +197,9 @@ module.exports.makeLoader = (gd) => {
|
|
|
204
197
|
})
|
|
205
198
|
)
|
|
206
199
|
)
|
|
207
|
-
.then(() =>
|
|
200
|
+
.then((functionInfos) => {
|
|
201
|
+
return extension;
|
|
202
|
+
});
|
|
208
203
|
};
|
|
209
204
|
|
|
210
205
|
const generateFreeFunction = (
|
|
@@ -215,46 +210,28 @@ module.exports.makeLoader = (gd) => {
|
|
|
215
210
|
options,
|
|
216
211
|
codeGenerationContext
|
|
217
212
|
) => {
|
|
218
|
-
const
|
|
213
|
+
const metadataDeclarationHelper = new gd.MetadataDeclarationHelper();
|
|
214
|
+
const { functionMetadata } = generateFreeFunctionMetadata(
|
|
215
|
+
project,
|
|
219
216
|
extension,
|
|
220
217
|
eventsFunctionsExtension,
|
|
221
|
-
eventsFunction
|
|
222
|
-
);
|
|
223
|
-
// By convention, first parameter is always the Runtime Scene.
|
|
224
|
-
instructionOrExpression.addCodeOnlyParameter("currentScene", "");
|
|
225
|
-
declareEventsFunctionParameters(eventsFunction, instructionOrExpression);
|
|
226
|
-
|
|
227
|
-
// Hide "lifecycle" functions as they are called automatically by
|
|
228
|
-
// the game engine.
|
|
229
|
-
if (isExtensionLifecycleEventsFunction(eventsFunction.getName())) {
|
|
230
|
-
instructionOrExpression.setHidden();
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const codeNamespace = getFreeFunctionCodeNamespace(
|
|
234
218
|
eventsFunction,
|
|
235
|
-
|
|
219
|
+
options,
|
|
220
|
+
codeGenerationContext,
|
|
221
|
+
metadataDeclarationHelper
|
|
236
222
|
);
|
|
237
|
-
const functionName = codeNamespace + ".func";
|
|
238
|
-
|
|
239
|
-
const codeExtraInformation =
|
|
240
|
-
instructionOrExpression.getCodeExtraInformation();
|
|
241
|
-
codeExtraInformation
|
|
242
|
-
.setIncludeFile(
|
|
243
|
-
options.eventsFunctionCodeWriter.getIncludeFileFor(functionName)
|
|
244
|
-
)
|
|
245
|
-
.setFunctionName(functionName);
|
|
246
|
-
|
|
247
|
-
// Always include the extension include files when using a free function.
|
|
248
|
-
codeGenerationContext.extensionIncludeFiles.forEach((includeFile) => {
|
|
249
|
-
codeExtraInformation.addIncludeFile(includeFile);
|
|
250
|
-
});
|
|
251
223
|
|
|
252
224
|
if (!options.skipCodeGeneration) {
|
|
253
225
|
const includeFiles = new gd.SetString();
|
|
254
226
|
const eventsFunctionsExtensionCodeGenerator =
|
|
255
227
|
new gd.EventsFunctionsExtensionCodeGenerator(project);
|
|
228
|
+
const codeNamespace = getFreeFunctionCodeNamespace(
|
|
229
|
+
eventsFunction,
|
|
230
|
+
codeGenerationContext.codeNamespacePrefix
|
|
231
|
+
);
|
|
256
232
|
const code =
|
|
257
233
|
eventsFunctionsExtensionCodeGenerator.generateFreeEventsFunctionCompleteCode(
|
|
234
|
+
eventsFunctionsExtension,
|
|
258
235
|
eventsFunction,
|
|
259
236
|
codeNamespace,
|
|
260
237
|
includeFiles,
|
|
@@ -271,15 +248,18 @@ module.exports.makeLoader = (gd) => {
|
|
|
271
248
|
.toNewVectorString()
|
|
272
249
|
.toJSArray()
|
|
273
250
|
.forEach((includeFile) => {
|
|
274
|
-
|
|
251
|
+
functionMetadata.addIncludeFile(includeFile);
|
|
275
252
|
});
|
|
276
253
|
|
|
277
254
|
includeFiles.delete();
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
255
|
+
eventsFunctionsExtensionCodeGenerator.delete();
|
|
256
|
+
metadataDeclarationHelper.delete();
|
|
257
|
+
|
|
258
|
+
// TODO Implement an helper function for free function names.
|
|
259
|
+
const functionName = codeNamespace + ".func";
|
|
260
|
+
return options.eventsFunctionCodeWriter
|
|
261
|
+
.writeFunctionCode(functionName, code)
|
|
262
|
+
.then(() => {});
|
|
283
263
|
} else {
|
|
284
264
|
// Skip code generation if no events function writer is provided.
|
|
285
265
|
// This is the case during the "first pass", where all events functions extensions
|
|
@@ -289,79 +269,71 @@ module.exports.makeLoader = (gd) => {
|
|
|
289
269
|
}
|
|
290
270
|
};
|
|
291
271
|
|
|
292
|
-
|
|
272
|
+
const generateFreeFunctionMetadata = (
|
|
293
273
|
project,
|
|
294
274
|
extension,
|
|
295
275
|
eventsFunctionsExtension,
|
|
296
|
-
|
|
276
|
+
eventsFunction,
|
|
297
277
|
options,
|
|
298
|
-
codeGenerationContext
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
278
|
+
codeGenerationContext,
|
|
279
|
+
metadataDeclarationHelper
|
|
280
|
+
) => {
|
|
281
|
+
const instructionOrExpression =
|
|
282
|
+
metadataDeclarationHelper.generateFreeFunctionMetadata(
|
|
283
|
+
project,
|
|
284
|
+
extension,
|
|
285
|
+
eventsFunctionsExtension,
|
|
286
|
+
eventsFunction
|
|
287
|
+
);
|
|
288
|
+
const functionName = gd.MetadataDeclarationHelper.getFreeFunctionCodeName(
|
|
289
|
+
eventsFunctionsExtension,
|
|
290
|
+
eventsFunction
|
|
303
291
|
);
|
|
292
|
+
const functionFile =
|
|
293
|
+
options.eventsFunctionCodeWriter.getIncludeFileFor(functionName);
|
|
294
|
+
instructionOrExpression.setIncludeFile(functionFile);
|
|
304
295
|
|
|
305
|
-
|
|
306
|
-
const codeNamespace = getBehaviorFunctionCodeNamespace(
|
|
307
|
-
eventsBasedBehavior,
|
|
308
|
-
codeGenerationContext.codeNamespacePrefix
|
|
309
|
-
);
|
|
310
|
-
const includeFile =
|
|
311
|
-
options.eventsFunctionCodeWriter.getIncludeFileFor(codeNamespace);
|
|
312
|
-
|
|
313
|
-
behaviorMetadata.setIncludeFile(includeFile);
|
|
314
|
-
|
|
315
|
-
// Always include the extension include files when using a behavior.
|
|
296
|
+
// Always include the extension include files when using a free function.
|
|
316
297
|
codeGenerationContext.extensionIncludeFiles.forEach((includeFile) => {
|
|
317
|
-
|
|
298
|
+
instructionOrExpression.addIncludeFile(includeFile);
|
|
318
299
|
});
|
|
319
300
|
|
|
301
|
+
// Skip code generation if no events function writer is provided.
|
|
302
|
+
// This is the case during the "first pass", where all events functions extensions
|
|
303
|
+
// are loaded as extensions but not code generated, as events in functions could
|
|
304
|
+
// themselves be using functions that are not yet available in extensions.
|
|
305
|
+
return {
|
|
306
|
+
functionFile: functionFile,
|
|
307
|
+
functionMetadata: instructionOrExpression,
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
function generateBehavior(
|
|
312
|
+
project,
|
|
313
|
+
extension,
|
|
314
|
+
eventsFunctionsExtension,
|
|
315
|
+
eventsBasedBehavior,
|
|
316
|
+
options,
|
|
317
|
+
codeGenerationContext
|
|
318
|
+
) {
|
|
320
319
|
return Promise.resolve().then(() => {
|
|
321
320
|
const behaviorMethodMangledNames = new gd.MapStringString();
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
eventsBasedBehavior
|
|
321
|
+
const behaviorMetadata = generateBehaviorMetadata(
|
|
322
|
+
project,
|
|
323
|
+
extension,
|
|
324
|
+
eventsFunctionsExtension,
|
|
325
|
+
eventsBasedBehavior,
|
|
326
|
+
options,
|
|
327
|
+
codeGenerationContext,
|
|
328
|
+
behaviorMethodMangledNames
|
|
327
329
|
);
|
|
328
330
|
|
|
329
|
-
// Declare all the behavior functions
|
|
330
|
-
mapFor(0, eventsFunctionsContainer.getEventsFunctionsCount(), (i) => {
|
|
331
|
-
const eventsFunction = eventsFunctionsContainer.getEventsFunctionAt(i);
|
|
332
|
-
|
|
333
|
-
const eventsFunctionMangledName = mangleName(eventsFunction.getName());
|
|
334
|
-
behaviorMethodMangledNames.set(
|
|
335
|
-
eventsFunction.getName(),
|
|
336
|
-
eventsFunctionMangledName
|
|
337
|
-
);
|
|
338
|
-
|
|
339
|
-
const instructionOrExpression =
|
|
340
|
-
declareBehaviorInstructionOrExpressionMetadata(
|
|
341
|
-
behaviorMetadata,
|
|
342
|
-
eventsBasedBehavior,
|
|
343
|
-
eventsFunction
|
|
344
|
-
);
|
|
345
|
-
declareEventsFunctionParameters(
|
|
346
|
-
eventsFunction,
|
|
347
|
-
instructionOrExpression
|
|
348
|
-
);
|
|
349
|
-
|
|
350
|
-
// Hide "lifecycle" methods as they are called automatically by
|
|
351
|
-
// the game engine.
|
|
352
|
-
if (isBehaviorLifecycleEventsFunction(eventsFunction.getName())) {
|
|
353
|
-
instructionOrExpression.setHidden();
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
const codeExtraInformation =
|
|
357
|
-
instructionOrExpression.getCodeExtraInformation();
|
|
358
|
-
codeExtraInformation
|
|
359
|
-
.setIncludeFile(includeFile)
|
|
360
|
-
.setFunctionName(eventsFunctionMangledName);
|
|
361
|
-
});
|
|
362
|
-
|
|
363
331
|
// Generate code for the behavior and its methods
|
|
364
332
|
if (!options.skipCodeGeneration) {
|
|
333
|
+
const codeNamespace = getBehaviorFunctionCodeNamespace(
|
|
334
|
+
eventsBasedBehavior,
|
|
335
|
+
codeGenerationContext.codeNamespacePrefix
|
|
336
|
+
);
|
|
365
337
|
const includeFiles = new gd.SetString();
|
|
366
338
|
const behaviorCodeGenerator = new gd.BehaviorCodeGenerator(project);
|
|
367
339
|
const code = behaviorCodeGenerator.generateRuntimeBehaviorCompleteCode(
|
|
@@ -403,6 +375,41 @@ module.exports.makeLoader = (gd) => {
|
|
|
403
375
|
});
|
|
404
376
|
}
|
|
405
377
|
|
|
378
|
+
function generateBehaviorMetadata(
|
|
379
|
+
project,
|
|
380
|
+
extension,
|
|
381
|
+
eventsFunctionsExtension,
|
|
382
|
+
eventsBasedBehavior,
|
|
383
|
+
options,
|
|
384
|
+
codeGenerationContext,
|
|
385
|
+
behaviorMethodMangledNames
|
|
386
|
+
) {
|
|
387
|
+
const behaviorMetadata =
|
|
388
|
+
gd.MetadataDeclarationHelper.generateBehaviorMetadata(
|
|
389
|
+
project,
|
|
390
|
+
extension,
|
|
391
|
+
eventsFunctionsExtension,
|
|
392
|
+
eventsBasedBehavior,
|
|
393
|
+
behaviorMethodMangledNames
|
|
394
|
+
);
|
|
395
|
+
|
|
396
|
+
const codeNamespace = getBehaviorFunctionCodeNamespace(
|
|
397
|
+
eventsBasedBehavior,
|
|
398
|
+
codeGenerationContext.codeNamespacePrefix
|
|
399
|
+
);
|
|
400
|
+
const includeFile =
|
|
401
|
+
options.eventsFunctionCodeWriter.getIncludeFileFor(codeNamespace);
|
|
402
|
+
|
|
403
|
+
behaviorMetadata.setIncludeFile(includeFile);
|
|
404
|
+
|
|
405
|
+
// Always include the extension include files when using a behavior.
|
|
406
|
+
codeGenerationContext.extensionIncludeFiles.forEach((includeFile) => {
|
|
407
|
+
behaviorMetadata.addIncludeFile(includeFile);
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
return behaviorMetadata;
|
|
411
|
+
}
|
|
412
|
+
|
|
406
413
|
function generateObject(
|
|
407
414
|
project,
|
|
408
415
|
extension,
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
const { mapVector, mapFor } = require("../MapFor");
|
|
2
|
+
const { caseSensitiveSlug } = require("../CaseSensitiveSlug");
|
|
3
|
+
|
|
4
|
+
const mangleName = (name) => {
|
|
5
|
+
return caseSensitiveSlug(name, "_", []);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/** Generate the namespace for a free function. */
|
|
9
|
+
const getFreeFunctionCodeNamespace = (eventsFunction, codeNamespacePrefix) => {
|
|
10
|
+
return codeNamespacePrefix + "__" + mangleName(eventsFunction.getName());
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/** Generate the namespace for a behavior function. */
|
|
14
|
+
const getBehaviorFunctionCodeNamespace = (
|
|
15
|
+
eventsBasedBehavior,
|
|
16
|
+
codeNamespacePrefix
|
|
17
|
+
) => {
|
|
18
|
+
return codeNamespacePrefix + "__" + mangleName(eventsBasedBehavior.getName());
|
|
19
|
+
};
|
|
20
|
+
|
|
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.
|
|
47
|
+
mapFor(0, project.getEventsFunctionsExtensionsCount(), (i) => {
|
|
48
|
+
return loadProjectEventsFunctionsExtension(
|
|
49
|
+
project,
|
|
50
|
+
project.getEventsFunctionsExtensionAt(i),
|
|
51
|
+
{ skipCodeGeneration: true, eventsFunctionCodeWriter }
|
|
52
|
+
);
|
|
53
|
+
})
|
|
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;
|
|
72
|
+
|
|
73
|
+
const loadProjectEventsFunctionsExtension = (
|
|
74
|
+
project,
|
|
75
|
+
eventsFunctionsExtension,
|
|
76
|
+
options
|
|
77
|
+
) => {
|
|
78
|
+
return generateEventsFunctionExtension(
|
|
79
|
+
project,
|
|
80
|
+
eventsFunctionsExtension,
|
|
81
|
+
options
|
|
82
|
+
).then((extension) => {
|
|
83
|
+
gd.JsPlatform.get().addNewExtension(extension);
|
|
84
|
+
extension.delete();
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Get the list of mandatory include files when using the
|
|
90
|
+
* extension.
|
|
91
|
+
*/
|
|
92
|
+
const getExtensionIncludeFiles = (
|
|
93
|
+
project,
|
|
94
|
+
eventsFunctionsExtension,
|
|
95
|
+
options,
|
|
96
|
+
codeNamespacePrefix
|
|
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
|
|
110
|
+
|
|
111
|
+
return options.eventsFunctionCodeWriter.getIncludeFileFor(
|
|
112
|
+
functionName
|
|
113
|
+
);
|
|
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(
|
|
152
|
+
project,
|
|
153
|
+
extension,
|
|
154
|
+
eventsFunctionsExtension,
|
|
155
|
+
eventsBasedBehavior,
|
|
156
|
+
options,
|
|
157
|
+
codeGenerationContext
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
)
|
|
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
|
+
};
|
|
181
|
+
|
|
182
|
+
const generateFreeFunction = (
|
|
183
|
+
project,
|
|
184
|
+
extension,
|
|
185
|
+
eventsFunctionsExtension,
|
|
186
|
+
eventsFunction,
|
|
187
|
+
options,
|
|
188
|
+
codeGenerationContext
|
|
189
|
+
) => {
|
|
190
|
+
const instructionOrExpression = declareInstructionOrExpressionMetadata(
|
|
191
|
+
extension,
|
|
192
|
+
eventsFunctionsExtension,
|
|
193
|
+
eventsFunction
|
|
194
|
+
);
|
|
195
|
+
// By convention, first parameter is always the Runtime Scene.
|
|
196
|
+
instructionOrExpression.addCodeOnlyParameter("currentScene", "");
|
|
197
|
+
declareEventsFunctionParameters(eventsFunction, instructionOrExpression);
|
|
198
|
+
|
|
199
|
+
// Hide "lifecycle" functions as they are called automatically by
|
|
200
|
+
// the game engine.
|
|
201
|
+
if (isExtensionLifecycleEventsFunction(eventsFunction.getName())) {
|
|
202
|
+
instructionOrExpression.setHidden();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const codeNamespace = getFreeFunctionCodeNamespace(
|
|
206
|
+
eventsFunction,
|
|
207
|
+
codeGenerationContext.codeNamespacePrefix
|
|
208
|
+
);
|
|
209
|
+
const functionName = codeNamespace + ".func";
|
|
210
|
+
|
|
211
|
+
const codeExtraInformation =
|
|
212
|
+
instructionOrExpression.getCodeExtraInformation();
|
|
213
|
+
codeExtraInformation
|
|
214
|
+
.setIncludeFile(
|
|
215
|
+
options.eventsFunctionCodeWriter.getIncludeFileFor(functionName)
|
|
216
|
+
)
|
|
217
|
+
.setFunctionName(functionName);
|
|
218
|
+
|
|
219
|
+
// Always include the extension include files when using a free function.
|
|
220
|
+
codeGenerationContext.extensionIncludeFiles.forEach((includeFile) => {
|
|
221
|
+
codeExtraInformation.addIncludeFile(includeFile);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
if (!options.skipCodeGeneration) {
|
|
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
|
+
);
|
|
238
|
+
|
|
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"
|
|
241
|
+
// are transitively included).
|
|
242
|
+
includeFiles
|
|
243
|
+
.toNewVectorString()
|
|
244
|
+
.toJSArray()
|
|
245
|
+
.forEach((includeFile) => {
|
|
246
|
+
codeExtraInformation.addIncludeFile(includeFile);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
includeFiles.delete();
|
|
250
|
+
|
|
251
|
+
return options.eventsFunctionCodeWriter.writeFunctionCode(
|
|
252
|
+
functionName,
|
|
253
|
+
code
|
|
254
|
+
);
|
|
255
|
+
} else {
|
|
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.
|
|
260
|
+
return Promise.resolve();
|
|
261
|
+
}
|
|
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
|
|
299
|
+
);
|
|
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
|
+
|
|
421
|
+
return {
|
|
422
|
+
name: parts[parts.length - 1],
|
|
423
|
+
behaviorName: parts.length > 2 ? parts[1] : undefined,
|
|
424
|
+
extensionName: parts[0],
|
|
425
|
+
};
|
|
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;
|
|
451
|
+
};
|
package/src/WrappedGD.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const EventEmitter = require("events");
|
|
2
2
|
const loadExtensions = require("./JsExtensionsLoader/LocalJsExtensionsLoader");
|
|
3
3
|
const projectLoader = require("./LocalProjectOpener");
|
|
4
|
+
const { makeLoader: makeLegacyLoader } = require("./EventsFunctionsExtensionsLoader/legacy");
|
|
4
5
|
const { makeLoader } = require("./EventsFunctionsExtensionsLoader/index");
|
|
5
6
|
const {
|
|
6
7
|
makeLocalEventsFunctionCodeWriter,
|
|
@@ -59,7 +60,9 @@ class WrappedGD extends EventEmitter {
|
|
|
59
60
|
})
|
|
60
61
|
.then(() => {
|
|
61
62
|
this.fs = assignIn(new this.gd.AbstractFileSystemJS(), makeFS(this.gd));
|
|
62
|
-
|
|
63
|
+
|
|
64
|
+
const makeLoaderFunc = (!this.gd.MetadataDeclarationHelper) ? makeLegacyLoader : makeLoader;
|
|
65
|
+
this.eventsFunctionsLoader = makeLoaderFunc(
|
|
63
66
|
this.gd
|
|
64
67
|
).loadProjectEventsFunctionsExtensions;
|
|
65
68
|
})
|