GDevelop
GDevelop copied to clipboard
Fix the "create" action to do picking in functions
Context - Instance picking by actions that create instances
- Users wants to apply actions to created instances.
- Users can create instances using the built-in the "create" action.
- Users can create instances using actions from event-based extensions.
- Event-based extensions use the built-in the "create" action to create instances.
Case 1 - when some instances were already picked
Expected
- Created instances should be added to the picked list.
Actual
- All good.
Case 2 - when no instance picking was done before
Expected
- Only the created instances should be picked.
Actual
- The "create" action works as expected (when no action or "pick all" is used on the same object before it).
- Extension actions add the created instances to the picking list and it looks as if no picking happened because all instances are picked.
Technical context
How object parameters work
-
Object parameters that are passed to instructions can be:
-
objectList
a map containing lists of objects which are specified by the object name in another parameter.- This one is usually used by conditions because it allows to filter which instances are picked.
- It's a map because instances can be from different objects because of object groups.
-
objectPtr
a reference to the object specified by the object name in another parameter.- The loop on the picked instances is done outside of the instruction function.
-
-
Event functions always declare their object parameters as
objectList
because they loop on instances internally.- Copies of the
objectList
are flatten and they are used like scene events use the list of all instance in the scene
- Copies of the
Challenge - Detecting the "no picking done" case
- There is no way to tell from a
ObjectList
alone if it contains all instances because conditions picked them all or if no picking was done.
Solution A - Add a flag to the picking list to know if a picking was done
- Add a
isPicked
boolean to differentiate these 2 cases. - The generated code will set this boolean to
true
as soon as a function asking for anObjectList
was called. - As event-functions may not actually do picking, tag the object parameters that are read-only by analyzing their events for:
- "create" actions
- instructions with not ready-only object parameters
- and maybe JS events that use
ObjectList
Note: considering that actions that creates instances are often 1st, a 1st version could still work without doing the event analysis and consider every event-function as not read-only.
Drawback
- The flag needs changes in the code generation.
Solution B - Use a special object parameter type to give empty instance list when no picking has happened
The "create" action actually use a special parameter type:
-
objectListOrEmptyIfJustDeclared
is the same asobjectList
but it doesn't pick object if they are not already picked. -
This avoids to copy all the instances when the function will only pick the created instance.
-
It makes the action works as it only adds created instances without caring if some picking happened before or not.
Something similar could be done for event-functions that are creating instances:
- no instances would be passed to them when no picking has happened before
- the created instances will be added to the picking list as usual
It could be done:
- automatically, this will require, like for the solution A, to scan functions for "create" actions recursively.
- manually, it would require extension creator to choose a special object parameter type.
Drawbacks
Some extension like "Spawner" uses conditions on the instance count to decide when to create an instance. It means that the automatic solution would need to ensure compatibility with old extensions by using a new parameter type.
- In both cases, this solution will need 2 object parameter types. Once a parameter type is in the wild, there is no coming back.
PR of the "solution B"
- https://github.com/4ian/GDevelop/pull/5239