Skip to content

Commit 50ebf6e

Browse files
committed
Add support for creating objects in JS extensions + example
1 parent cbe33d2 commit 50ebf6e

File tree

15 files changed

+550
-84
lines changed

15 files changed

+550
-84
lines changed

Extensions/ExampleJsExtension/JsExtension.js

Lines changed: 126 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ module.exports = {
262262
};
263263
dummyObject.setRawJSONContent(
264264
JSON.stringify({
265-
property1: "Initial value",
265+
property1: "Hello world",
266266
property2: true,
267267
property3: 123
268268
})
@@ -311,24 +311,29 @@ module.exports = {
311311
return instanceProperties;
312312
};
313313

314-
extension.addObject(
315-
"DummyObject",
316-
t("Dummy object for testing"),
317-
t("This dummy object does nothing"),
318-
"CppPlatform/Extensions/topdownmovementicon.png",
319-
dummyObject
320-
);
314+
extension
315+
.addObject(
316+
"DummyObject",
317+
t("Dummy object for testing"),
318+
t("This dummy object does nothing"),
319+
"CppPlatform/Extensions/topdownmovementicon.png",
320+
dummyObject
321+
)
322+
.setIncludeFile("Extensions/ExampleJsExtension/dummyruntimeobject.js")
323+
.addIncludeFile(
324+
"Extensions/ExampleJsExtension/dummyruntimeobject-pixi-renderer.js"
325+
);
321326

322327
return extension;
323328
},
324329
/**
325330
* You can optionally add sanity tests that will check the basic working
326331
* of your extension behaviors/objects by instanciating behaviors/objects
327332
* and setting the property to a given value.
328-
*
333+
*
329334
* If you don't have any tests, you can simply return an empty array like this:
330335
* `runExtensionSanityTests: function(gd, extension) { return []; }`
331-
*
336+
*
332337
* But it is recommended to create tests for the behaviors/objects properties you created
333338
* to avoid mistakes.
334339
*/
@@ -351,5 +356,116 @@ module.exports = {
351356
"Testing value"
352357
)
353358
];
359+
},
360+
/**
361+
* Register editors for objects.
362+
*
363+
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
364+
*/
365+
registerEditorConfigurations: function(objectsEditorService) {
366+
objectsEditorService.registerEditorConfiguration(
367+
"MyDummyExtension::DummyObject",
368+
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor()
369+
);
370+
},
371+
/**
372+
* Register renderers for instance of objects on the scene editor.
373+
*
374+
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
375+
*/
376+
registerInstanceRenderers: function(objectsRenderingService) {
377+
const RenderedInstance = objectsRenderingService.RenderedInstance;
378+
const PIXI = objectsRenderingService.PIXI;
379+
380+
/**
381+
* Renderer for instances of DummyObject inside the IDE.
382+
*
383+
* @extends RenderedInstance
384+
* @class RenderedDummyObjectInstance
385+
* @constructor
386+
*/
387+
function RenderedDummyObjectInstance(
388+
project,
389+
layout,
390+
instance,
391+
associatedObject,
392+
pixiContainer,
393+
pixiResourcesLoader
394+
) {
395+
RenderedInstance.call(
396+
this,
397+
project,
398+
layout,
399+
instance,
400+
associatedObject,
401+
pixiContainer,
402+
pixiResourcesLoader
403+
);
404+
405+
//Setup the PIXI object:
406+
this._pixiObject = new PIXI.Text("This is a dummy object", {
407+
align: "left"
408+
});
409+
this._pixiObject.anchor.x = 0.5;
410+
this._pixiObject.anchor.y = 0.5;
411+
this._pixiContainer.addChild(this._pixiObject);
412+
this.update();
413+
}
414+
RenderedDummyObjectInstance.prototype = Object.create(
415+
RenderedInstance.prototype
416+
);
417+
418+
/**
419+
* Return the path to the thumbnail of the specified object.
420+
*/
421+
RenderedDummyObjectInstance.getThumbnail = function(
422+
project,
423+
resourcesLoader,
424+
object
425+
) {
426+
return "CppPlatform/Extensions/texticon24.png";
427+
};
428+
429+
/**
430+
* This is called to update the PIXI object on the scene editor
431+
*/
432+
RenderedDummyObjectInstance.prototype.update = function() {
433+
// Read a property from the object
434+
const property1Value = this._associatedObject
435+
.getProperties(this.project)
436+
.get("My first property")
437+
.getValue();
438+
this._pixiObject.text = property1Value;
439+
440+
// Read position and angle from the instance
441+
this._pixiObject.position.x =
442+
this._instance.getX() + this._pixiObject.width / 2;
443+
this._pixiObject.position.y =
444+
this._instance.getY() + this._pixiObject.height / 2;
445+
this._pixiObject.rotation = RenderedInstance.toRad(
446+
this._instance.getAngle()
447+
);
448+
// Custom size can be read in instance.getCustomWidth() and
449+
// instance.getCustomHeight()
450+
};
451+
452+
/**
453+
* Return the width of the instance, when it's not resized.
454+
*/
455+
RenderedDummyObjectInstance.prototype.getDefaultWidth = function() {
456+
return this._pixiObject.width;
457+
};
458+
459+
/**
460+
* Return the height of the instance, when it's not resized.
461+
*/
462+
RenderedDummyObjectInstance.prototype.getDefaultHeight = function() {
463+
return this._pixiObject.height;
464+
};
465+
466+
objectsRenderingService.registerInstanceRenderer(
467+
"MyDummyExtension::DummyObject",
468+
RenderedDummyObjectInstance
469+
);
354470
}
355471
};
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* The PIXI.js renderer for the DummyRuntimeObject.
3+
*
4+
* @class DummyRuntimeObjectPixiRenderer
5+
* @constructor
6+
* @param {gdjs.DummyRuntimeObject} runtimeObject The object to render
7+
* @param {gdjs.RuntimeScene} runtimeScene The gdjs.RuntimeScene in which the object is
8+
*/
9+
gdjs.DummyRuntimeObjectPixiRenderer = function(runtimeObject, runtimeScene)
10+
{
11+
this._object = runtimeObject; // Keep a reference to the object to read from it later.
12+
13+
// Here we're going to create a dummy text as an example.
14+
if ( this._text === undefined ) {
15+
this._text = new PIXI.Text(runtimeObject.getText(), {align:"left"});
16+
}
17+
18+
// You can also create a PIXI sprite or other PIXI object
19+
// this._imageManager = runtimeScene.getGame().getImageManager();
20+
// if ( this._sprite === undefined )
21+
// this._sprite = new PIXI.Sprite(this._imageManager.getInvalidPIXITexture());
22+
23+
this._text.anchor.x = 0.5;
24+
this._text.anchor.y = 0.5;
25+
runtimeScene.getLayer("").getRenderer().addRendererObject(this._text, runtimeObject.getZOrder());
26+
27+
this.updatePosition();
28+
};
29+
30+
gdjs.DummyRuntimeObjectRenderer = gdjs.DummyRuntimeObjectPixiRenderer; //Register the class to let the engine use it.
31+
32+
gdjs.DummyRuntimeObjectPixiRenderer.prototype.getRendererObject = function() {
33+
// Mandatory, return the internal PIXI object used for your object:
34+
return this._text;
35+
};
36+
37+
gdjs.DummyRuntimeObjectPixiRenderer.prototype.ensureUpToDate = function() {
38+
this.updatePosition();
39+
};
40+
41+
gdjs.DummyRuntimeObjectPixiRenderer.prototype.updatePosition = function() {
42+
this._text.position.x = this._object.x+this._text.width/2;
43+
this._text.position.y = this._object.y+this._text.height/2;
44+
};
45+
46+
gdjs.DummyRuntimeObjectPixiRenderer.prototype.updateAngle = function() {
47+
this._text.rotation = gdjs.toRad(this._object.angle);
48+
};
49+
50+
gdjs.DummyRuntimeObjectPixiRenderer.prototype.updateOpacity = function() {
51+
this._text.alpha = this._object.opacity / 255;
52+
};
53+
54+
gdjs.DummyRuntimeObjectPixiRenderer.prototype.getWidth = function() {
55+
return this._text.width;
56+
};
57+
58+
gdjs.DummyRuntimeObjectPixiRenderer.prototype.getHeight = function() {
59+
return this._text.height;
60+
};
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**
2+
* A dummy object doing showing a text on screen
3+
*
4+
* @memberof gdjs
5+
* @class DummyRuntimeObject
6+
* @extends RuntimeObject
7+
*/
8+
gdjs.DummyRuntimeObject = function(runtimeScene, objectData) {
9+
// Always call the base gdjs.RuntimeObject constructor.
10+
gdjs.RuntimeObject.call(this, runtimeScene, objectData);
11+
12+
// Load any required data from the object properties.
13+
this._property1 = objectData.content.property1;
14+
15+
// Create the renderer (see dummyruntimeobject-pixi-renderer.js)
16+
if (this._renderer)
17+
gdjs.DummyRuntimeObjectRenderer.call(this._renderer, this, runtimeScene);
18+
else this._renderer = new gdjs.DummyRuntimeObjectRenderer(this, runtimeScene);
19+
};
20+
21+
gdjs.DummyRuntimeObject.prototype = Object.create(gdjs.RuntimeObject.prototype);
22+
gdjs.DummyRuntimeObject.thisIsARuntimeObjectConstructor =
23+
"MyDummyExtension::DummyObject"; //Replace by your extension + object name.
24+
25+
gdjs.DummyRuntimeObject.prototype.getRendererObject = function() {
26+
return this._renderer.getRendererObject();
27+
};
28+
29+
/**
30+
* Called once during the game loop, before events and rendering.
31+
* @param {gdjs.RuntimeScene} runtimeScene The gdjs.RuntimeScene the object belongs to.
32+
*/
33+
gdjs.DummyRuntimeObject.prototype.update = function(runtimeScene) {
34+
// This is an example: typically you want to make sure the renderer
35+
// is up to date with the object.
36+
this._renderer.ensureUpToDate();
37+
};
38+
39+
/**
40+
* Initialize the extra parameters that could be set for an instance.
41+
* @private
42+
*/
43+
gdjs.DummyRuntimeObject.prototype.extraInitializationFromInitialInstance = function(
44+
initialInstanceData
45+
) {
46+
// For example:
47+
// this.setSomething(initialInstanceData.something);
48+
};
49+
50+
/**
51+
* Update the object position.
52+
* @private
53+
*/
54+
gdjs.DummyRuntimeObject.prototype._updatePosition = function() {
55+
// This is an example: typically you want to tell the renderer to update
56+
// the position of the object.
57+
this._renderer.updatePosition();
58+
};
59+
60+
/**
61+
* Set object position on X axis.
62+
*/
63+
gdjs.DummyRuntimeObject.prototype.setX = function(x) {
64+
gdjs.RuntimeObject.prototype.setX.call(this, x); // Always call the parent method first.
65+
this._updatePosition();
66+
};
67+
68+
/**
69+
* Set object position on Y axis.
70+
*/
71+
gdjs.DummyRuntimeObject.prototype.setY = function(y) {
72+
gdjs.RuntimeObject.prototype.setY.call(this, y); // Always call the parent method first.
73+
this._updatePosition();
74+
};
75+
76+
/**
77+
* Set the angle of the object.
78+
* @param {number} angle The new angle of the object
79+
*/
80+
gdjs.DummyRuntimeObject.prototype.setAngle = function(angle) {
81+
gdjs.RuntimeObject.prototype.setAngle.call(this, angle); // Always call the parent method first.
82+
this._renderer.updateAngle(); // Tell the renderer to update the rendered object
83+
};
84+
85+
/**
86+
* Set object opacity.
87+
*/
88+
gdjs.DummyRuntimeObject.prototype.setOpacity = function(opacity) {
89+
if (opacity < 0) opacity = 0;
90+
if (opacity > 255) opacity = 255;
91+
92+
this.opacity = opacity;
93+
this._renderer.updateOpacity(); // Tell the renderer to update the rendered object
94+
};
95+
96+
/**
97+
* Get object opacity.
98+
*/
99+
gdjs.DummyRuntimeObject.prototype.getOpacity = function() {
100+
return this.opacity;
101+
};
102+
103+
/**
104+
* Get the text that must be displayed by the dummy object.
105+
*/
106+
gdjs.DummyRuntimeObject.prototype.getText = function() {
107+
return this._property1;
108+
};

0 commit comments

Comments
 (0)