GDevelop icon indicating copy to clipboard operation
GDevelop copied to clipboard

Fix the "create" action to do picking in functions

Open D8H opened this issue 1 year ago • 1 comments

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

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 an ObjectList 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 as objectList 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.

D8H avatar Mar 31 '23 11:03 D8H

PR of the "solution B"

  • https://github.com/4ian/GDevelop/pull/5239

D8H avatar Apr 17 '23 08:04 D8H