-
-
Notifications
You must be signed in to change notification settings - Fork 22k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a way to know when a TileMapLayer
's cell is modified
#96078
Conversation
I think this does make sense as a callback. There's certain types of automation tools which automatically place relevant tiles based on the context of surrounding tiles, but such tools require a callback like this. |
We lightly discussed in the past (@groud), and we generally agreed that it's not a good idea as is. This will be emitted every time any tile change occurs. However, to make it brief, emitting the signal multiple times for many, many changes adds up, even if the signal is not connected to anything. Tile maps are not exactly known for their performance as they are now, either. Despite the concerns, this feature is very much desired. I myself would need this, as I heavily relied on overriding
One alternative is to make this signal only available in the editor. It can be argued that while editing the TileMap the performance hit is pretty minor. Another alternative is to find a way to toggle the emission of this signal but... I wouldn't know how to feel about that. |
The issue raised with overloading the signal does seem valid, yes. It's tricky to handle this in a way that won't seem like overengineering things, but a batched solution like you suggested might be desirable. Another potential suggestion I'll offer is that you could make it so that emitting a signal dependent on whether an explicit mode is set in the TileMapLayer, hopefully removing any unwanted overhead for users who don't require such a callback. While not a signal, there is some precedent in the engine already with NOTIFICATION_TRANFORM_CHANGED which requires the explicit calling of set_notify_transform(), which removes the overhead when its not needed as opposed to making it an explicit editor vs not-editor thing. |
Indeed. And that is not a signal for... roughly the same reasons. Maybe demoting this to a virtual function would be enough, but the risk of excessive overhead is still there. Some benchmark tests could be nice. |
Mmh.. Right, I do agree, having the signal here is not a great idea. I understaind how trying to emit the signal would impact performance negatively, and the function actually seems to be called a few times per cell on init. If we add to that the fact that modifying the tile that has just been changed through the signal would require it to be called once more, that is probably a bit much. A batched solution would definitly be better, as it solves most of the issues. Such a signal/callback would still be called multiple times if tile modifications are made within it. Would it be better to have the solution inside the Was there a particular reason why #27500 was not kept in 4.0 ? |
Actually, this would cause a feedback loop and crash the application, unless it is checked manually. It also happens when handling
It's a good suggestion, although TileMapLayerEditor is not exposed to scripting languages so it may not matter too much. Though I can see the desire in having this work at run-time, as well.
Being able to override non-virtual methods has always been quirky. Whether it actually works as imagined depends purely on whether the internal code calls the method directly (with pointers), or through |
It is not that bad because it is checked internally (for what I assume are performance reasons). So as long as the tile that the user wants to place does not change between calls, there should not be any feedback loop. However, if the user ever decide to use randomness in the setting of the tile (to make use of tile alternatives for example), there is a chance of a feedback loop crashing godot.
I think you did, thanks :). Maybe there could be two functions to set a cell then: a "checked" and an "unchecked" one. This would work both in editor and at runtime because the user can call the "checked" version if they want. And as a (small) bonus, it would still be possible to call the "unchecked" version from a script if needed for performance. |
Hi, thanks for the contribution. We could add this to the editor, but it might not be easy to do, as there are likely several places where this is called, and it does not handle use cases for in-game situations. That being said, I think one thing that could be done is adding a callback in the TileMapLayer when cells are updated. Updated are deferred (to avoid too many updates), and they work with a "group of cells to update" being provided. So we could have a virtual method called: |
Alright, good to know ! I think it makes sense as well.
Yup, that could work. It would still be called mutliple times when trying to use
If I'm not mistaken, this would not have any of the issues raised so far, as it is called before any modification to the tilemap. In addition, the new function would be called only by the Should I try some of the ideas and see what sticks ? They don't seem to require a lot of work to have in a working state, so that might help decide on what is best. |
No. This function is guaranteed to be only run once per frame. So if you call As a side note, I'd really avoid making the API more complex than it is right now. I'd rather avoid adding more argument to set_cell, or new functions it's hard to understand what they do at a glance. |
You pushed your branch in such a way that it cleared any changes, which automatically closes the PR, to reset use |
I'd suggest opening a new PR with a separate branch so you avoid issues with the |
Ok, thanks ! |
This is how I use it |
Hi !
This PR adds the signal
cell_changed
to theTileMapLayer
. It allows for making tools that react to modifications to theTileMapLayer
's cells.This feature was discussed in godotengine/godot-proposals#668. Back in godot 3.2, #27500 made so the
TileMapEditor
calledTileMap.set_cell
throughObject.call
, this allowed the function to be overridden in GDScript or C# in@tool
scripts. However with the tile map reworks, this was removed.I decided not to reimplement the fix from #27500 as having a signal seemed simpler while having the same capabilities.