-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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 TileSetAtlasSource::TileAnimationMode
options and allow to shuffle tile animations
#77257
Conversation
That position in list of tile properties was arbitrary and maybe not best spot? Not sure I understand the merge error: I need to run doctool locally? Naw I did not do that last time I changed docs for tween? Thanks for help. |
The class reference is automatically alphabetically sorted. You cannot influence this order; it's here by design to make diffs easier to read 🙂 |
Doctool is built into the executable. You just do |
I think the checkbox should be at the bottom. |
ab85835
to
3a1dc40
Compare
scene/2d/tile_map.cpp
Outdated
bool sync = atlas_source->get_tile_animation_sync(p_atlas_coords); | ||
int frames_count = atlas_source->get_tile_animation_frames_count(p_atlas_coords); | ||
int start_frame = sync ? 0 : rand() % frames_count; | ||
real_t time = 0.0; | ||
for (int frame = 0; frame < atlas_source->get_tile_animation_frames_count(p_atlas_coords); frame++) { | ||
real_t frame_duration = atlas_source->get_tile_animation_frame_duration(p_atlas_coords, frame) / speed; | ||
for (int frame = 0; frame < frames_count; frame++) { | ||
int current_frame = (frame + start_frame) % frames_count; | ||
real_t frame_duration = atlas_source->get_tile_animation_frame_duration(p_atlas_coords, current_frame) / speed; | ||
RenderingServer::get_singleton()->canvas_item_add_animation_slice(p_canvas_item, animation_duration, time, time + frame_duration, 0.0); | ||
|
||
Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, frame); | ||
Rect2i source_rect = atlas_source->get_runtime_tile_texture_region(p_atlas_coords, current_frame); | ||
tex->draw_rect_region(p_canvas_item, dest_rect, source_rect, modulate, transpose, p_tile_set->is_uv_clipping()); | ||
|
||
time += frame_duration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently what's being randomized is only the starting frame, which I don't think is the way to go. Like e.g. for an animation with 2 frames with durations 1 and 100 respectively it would still pick each frame with ~50% probabiility. I suggest changing it to be time based.
For this you could do (more or less) something like real_t animation_offset = sync ? 0.0 : randf() * animation_duration;
and keep the loop as it was before, changing only the last argument of canvas_item_add_animation_slice
to be such animation_offset
.
Besides that, such animation_offset
would need to be stored per cell, instead of choosing a new random offset each time such cell is being redrawn (by calling draw_tile
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was originally intending to use the probability
values that are already stored and set per tile, like in TileMapEditorTilesPlugin::_pick_random_tile
? Perhaps that would be better? Otherwise, probability
exists but is meaningless for animation tiles. (PreBug)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for my mistake, not available for all animation tiles, because cannot select all, and already used by Place Random Tile.
I wonder if adding just a "sync" bool is the way to go. Instead of allowing only synced/random options, it could probably make sense to provide a way to manually set animation offsets for each cell, so e.g. creating animated patterns at will would be possible. Not fully sure about the implementation though, would such offsets need to be stored in the |
292aaee
to
01e83bf
Compare
I think the feature is good and simple enough to be added. I have a few remarks:
I would thus suggest to replace the bool by an enum called "animation_mode" (or something like that), with two values:
It would require a dedicated callback, as the animation frame is not stored in the TileData object. |
01e83bf
to
80ef323
Compare
One small issue I noticed is a kind of flickering when setting lots of random tiles.
Thanks. |
4e3a594
to
810b5a7
Compare
I've mentioned this in #77257 (comment):
Whenever To be clear: it's not editor only issue, as tiles can be placed / changed on runtime too (which would triggers qudrant redrawing / reissuing draw commands). Hence this needs to be solved now, when adding the feature. So the question is how/where such animation offsets should be stored (and whether they should be serialized?:thinking:). |
a63ff16
to
2ba4f05
Compare
Thanks, I changed to an enum and added a |
9b11e05
to
f3959c9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This look quite good already, but I am quite concerned by the performance impact the offset cache will have. Using a hashmap is quite memory inefficient and can easily become slow.
What I would suggest to replace that is to make the offset fixed per cell. Basically, that mean that each cell would be assigned a fixed random value, but that would depend only the tile's coordinates (and maybe the TileMap's pointer address, or something like that (basically the this
pointer ?).
Basically, you could do something like this (haven't tested):
Array to_hash;
to_hash.push_back(p_position);
to_hash.push_back(int(this));
animation_offset = RandomPCG(to_hash.hash()).randf();
This would ensure a random value, unique for each tile, but that would stay consistent between each call. This should be enough to avoid using a HashMap.
Thanks. I tried it and it does work but:
I am not even sure it needs to be fixed. Since we are basically just dealing with noise, it is maybe not AS important that every tile has a 'special' number? Just that they all look generally different and preserve that difference through drawing interference? It is maybe not worth it to "duplicate" the random noise for each tileMap when there is no visible difference? not really special or associated noise... just noise? I foresee a similar issue for times when the cache 'needs to be regenerated' but luckily it is just noise and cannot even notice it is using an old cache? so those bugs will never be discovered. I was gonna say the same thing about changing from frame to time but not sure it is the same... maybe noticeable with long delays idk Is it a bug or is it visual trickery / optimization? :) Thanks |
Ah you are right. The static part is the problem and I did not realize that So the cleanest solution to me then is to add an optional argument
I think it might be visible in some cases, where you have multiple tiles on top of each other on the same layer. So I think it should probably be dependent on the TileMap pointer or something.
Hashing is pretty fast, while the time to access a bin in a hashmap takes a time that is dependent on how big the map is. For big tilemap it might be a problem. |
d4e01ec
to
c49e64c
Compare
Thanks. You are right. I was easily able to see dupes / no dupes just by adding lots to multiple layers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A small nitpick on a variable name, but aside from that, looks good!
- to tile animation properties - when "Default" each animation starts at time 0. - when "Random Start Times" each animation starts at random time.
c49e64c
to
6dbae30
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks!
One thing I am curious about is if there is a better way do these casts:
Nothing else seems to be using Thanks. |
TileSetAtlasSource::TileAnimationMode::TILE_ANIMATION_MODE_RANDOM_START_TIMES
enum to shuffle tile animations.
I don't think there is a significantly better way. Most of the time we only deal with enums represented as integers, so conversion is straightforward. Here we have a variant, so it needs extra work. So this seems appropriate. |
TileSetAtlasSource::TileAnimationMode::TILE_ANIMATION_MODE_RANDOM_START_TIMES
enum to shuffle tile animations.TileSetAtlasSource::TileAnimationMode
options and allow to shuffle tile animations
Thanks! |
sorry i accidentally merged and/or messed up that branch somehow ok to make a new request? sorry. thanks.
replaces: #77255
this adds a sync option that is on by default just above separation
if turned off all animations of that type will start at random frame instead of 0
to address my recent issue and proposal
godotengine/godot-proposals#6856
#57677
thanks.
Bugsquad edit: This closes godotengine/godot-proposals#6856.