GDevelop icon indicating copy to clipboard operation
GDevelop copied to clipboard

Return objects from events based extensions

Open arthuro555 opened this issue 3 years ago • 10 comments

This adds an action to return objects from an events based extension. This will set the return value to true and pick the currently picked instances of the object back to where the function is used.

Example: pick.zip

arthuro555 avatar Oct 10 '21 10:10 arthuro555

Finally getting to this! Very interesting! Is this supporting a few interesting use cases like objects created in the function, can you return them?

4ian avatar Oct 12 '21 16:10 4ian

Yep! You can test it with this project file: pikk.zip

arthuro555 avatar Oct 12 '21 16:10 arthuro555

I've identified multiple edge cases. This is not an easy problem, this can be very powerful but we must be sure that we handle everything properly and be 100% correct so that we don't discover later issues when using groups/passing groups/passing multiple objects/calling this action multiple times :)

I think the key is being very clear about what is inside the object lists.

4ian avatar Oct 12 '21 21:10 4ian

Whoops! While I indeed tested passing groups, I did not test for those edge cases. I fixed the first and second one, though I am not sure I understand the last one. If the object is passed twice, shouldn't modifying its picked objects still be fine? The only other alternative would be to not pick them but that sounds more confusing.

arthuro555 avatar Oct 13 '21 22:10 arthuro555

I think I understand now what you meant with that last edge case (what if i am using a group in the function that consists of two times the same object that was passed?), and my current implementation while being a little slower on that edge case should be resilient against this (e.g. it will not duplicate objects in the list, since even if it fills it a second time it will clear it before doing so).

As the edge cases seem fixed, I am removing the draft.

arthuro555 avatar Oct 23 '21 21:10 arthuro555

Ping!

arthuro555 avatar Nov 13 '21 15:11 arthuro555

Ping!

arthuro555 avatar Nov 24 '21 11:11 arthuro555

Sorry about the delay on this, it's hard to review because I'm not sure if we're missing a case or not. Can we somehow create a few exhaustive "test cases"? I'm thinking either of testing in GDJSCodeGenerationIntegrationTests or "just" a game that would use this in multiple settings:

  • With a group or not at the scene level
  • With groups or not inside the function
  • Passing groups with multiple times the same object
  • Maybe a final test case where a function calls another functions, and both use the action (to ensure picked objects can traverse 2 layers of functions? And that there is no problem of naming, especially because we're pushing objects using their names in the object lists).

4ian avatar Nov 25 '21 17:11 4ian

I added some cases in the example project: https://www.dropbox.com/s/4gk4gpzcho2ohve/PickTest.zip?dl=0

I observed that:

  • It doesn't feel intuitive with behavior functions When this action is used in a behavior function, it will be called for each owner instance. The last instance executed will decide what is picked. Most of the time, extension users will surround the behavior action with a for each to handle the picked instances with knowledge of the behavior owner. But, in case they don't need to, the function will seem broken.

  • An event-based condition A that call another event-based B won't work because the condition B doesn't find the object lists.

  • Maybe not related to this PR: when an object is created in the picked instances are reset One use-case is the bullet extension. It kind of warp a create action and I guess users will expect it to work the same. This means adding the picked object to the picking list and keeping objects that were already picked.

D8H avatar Jul 23 '22 18:07 D8H

To answer my younger self:

  • It doesn't feel intuitive with behavior functions When this action is used in a behavior function, it will be called for each owner instance. The last instance executed will decide what is picked. Most of the time, extension users will surround the behavior action with a for each to handle the picked instances with knowledge of the behavior owner. But, in case they don't need to, the function will seem broken.

This is actually not a real use-case because behavior Object picking is handled by the generated code according to returned boolean from the condition already. The UI should just hide the "Return object" action from within behaviors.

  • An event-based condition A that call another event-based B won't work because the condition B doesn't find the object lists.

The issue was the use of object.getName() which gives the object name in the scene but it didn't work if the event-function caller is not a scene event. I tried a different implementation to fix this issue:

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

It will work for simple picking but the events may need to use imbricated "for each instance" to check some conditions on each object tuples. It won't be possible with just this new action.

Maybe, it could require a new concept like named picking list:

  • An action Add Object to the object list "MyPickingList"
  • An action Remove Object from the object list "MyPickingList"
  • A condition Pick all Object from the object list "MyPickingList"

The idea would be to build an object list in "for each instance" loops and use the condition to get the result and give it to the "Return" action. Something like this:

Clear the object list "MyPickingList"
for each instance of Player
  for each instance of Obstacle
    A condition on Player and Obstacle --> Add Object to the object list "MyPickingList"
                                       --> Add Obstacle to the object list "MyPickingList"
Pick all Player from the object list "MyPickingList" --> Set objects to return to Player
Pick all Obstacle from the object list "MyPickingList" --> Set objects to return to Obstacle

Though, it would be better if we can found a simpler solution.

D8H avatar Oct 22 '23 19:10 D8H