PhaserEditor2D / PhaserEditor

A friendly IDE to develop HTML5 games based on the Phaser framework.
https://phasereditor2d.com
Eclipse Public License 1.0
330 stars 45 forks source link

Prefabs: constructor ordering of custom definition props and START-USER-CTR-CODE #158

Closed jrabek closed 3 years ago

jrabek commented 3 years ago

Description

Note that while technically this is a bug, it is more about a bigger issue of the data update model in prefabs.

This came about due to a related change in https://github.com/PhaserEditor2D/PhaserEditor2D-v3/issues/132#issuecomment-876707383.

Currently in the constructor the ordering of data init is: 1) codegen of Phaser objects created in the editor 2) custom definition of props 3) USER-CTR-CODE

The issue is that any custom objects (i.e. ones that Phaser Editor does not have a representation for) are created in the USER-CTR-CODE section which means that props with setters will not be applied to custom objects. It also means that every custom setter must have guard code to check if the custom objects have been created yet just to handle the constructor sequencing since the custom objects will be defined after the constructor returns.

Possible solution

There are a couple possible solutions: 1) Have two sections of prop definitions in the constructor: One before the USER-CTR-CODE and one after. The one before is for props that do not have custom setters and can be used in custom object init, and the other will be for props with custom setters that may apply to the custom objects.

2) A single section of custom definition props that appears after USER-CTR-CODE. That way the custom setter can apply values to the custom objects. This is simpler than (1) since the custom setters must apply the values anyway so easier to just assume that the values get set in the setter rather than in the custom object init.

The application of props without custom definitions would need to happen in a start method that can be triggered via a generated event handler.

this.scene.events.once(Phaser.Scenes.Events.UPDATE, this.start, this);

Bigger discussion

There are currently components-awake and prefab-awake events that are fired in the prefab's editor generated create handler. There are a few issues with this approach.

1) Pollution of scene with 3 lines per each prefab in the scene. Double that if the prefab has components. For a scene with even a modest number of prefabs (i.e. ~20) the majority of the scene becomes event emitter lines.

2) prefab-awake encourages a polling data model

prefab-awake was added so that custom props can be applied to objects. The problem is that if the properties change later there is no way to know unless a previous value is checked or if they are updated in every single update call. Neither is efficient.

It would be better to eliminate the prefab-awake and force the use of setters. Note that phaser itself does this so that property updates are properly reflected in the objects (e.g. https://github.com/photonstorm/phaser/blob/5c8ecbcf999e6f328d21884e877c9e5935d2d350/src/gameobjects/text/Text.js#L1321).

Some properties like position are handled during the render cycle and don't need immediate update, but many property updates trigger a one time change in the object. Either can be handled by a custom setter.

Question about components

It seems component-awake should be handled entirely within the component itself. In the component constructor an event handler can be added so that the code currently in awake would be executed there instead.

The component already has a reference to the gameObject which has a reference to the scene so the following can be placed in the constructor:

this.gameObject.scene.events.once(Phaser.Scenes.Events.UPDATE, this.start, this);
jrabek commented 3 years ago

Accidentally filed in wrong project. Update https://github.com/PhaserEditor2D/PhaserEditor2D-v3/issues/136