-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Stacks of items on the ground render either the last-dropped favorite item or the largest item. #72153
Conversation
@@ -472,7 +472,7 @@ void tileset_cache::loader::create_textures_from_tile_atlas( const SDL_Surface_P | |||
for( tiles_pixel_color_entry &entry : tile_values_data ) { | |||
std::vector<texture> *tile_values = std::get<0>( entry ); | |||
color_pixel_function_pointer color_pixel_function = get_color_pixel_function( std::get<1> | |||
( entry ) ); | |||
( entry ) ); |
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.
[JSON & C++ formatters] reported by reviewdog 🐶
( entry ) ); | |
( entry ) ); |
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.
Note: You can accept all the bot is suggesting here in a single commit, (then squish that commit into yours locally, if you want, then force push).
std::remove_if( | ||
v.obj.begin(), | ||
v.obj.end(), |
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.
[JSON & C++ formatters] reported by reviewdog 🐶
std::remove_if( | |
v.obj.begin(), | |
v.obj.end(), | |
std::remove_if( | |
v.obj.begin(), | |
v.obj.end(), |
[&]( int id ) { | ||
return id >= offset || id < 0; | ||
} ), | ||
v.obj.end() | ||
); | ||
); |
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.
[JSON & C++ formatters] reported by reviewdog 🐶
); | |
); |
std::remove_if( | ||
vs.begin(), | ||
vs.end(), |
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.
[JSON & C++ formatters] reported by reviewdog 🐶
std::remove_if( | |
vs.begin(), | |
vs.end(), | |
std::remove_if( | |
vs.begin(), | |
vs.end(), |
[&]( const weighted_object<int, std::vector<int>> &o ) { | ||
return o.obj.empty(); | ||
} | ||
), | ||
), |
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.
[JSON & C++ formatters] reported by reviewdog 🐶
), | |
), |
@@ -3579,7 +3578,7 @@ | |||
auto field_at = [&]( const tripoint & q, const bool invis ) -> field_type_id { | |||
const auto it = field_override.find( q ); | |||
return it != field_override.end() ? it->second : | |||
( !fld_overridden || !invis ) ? here.field_at( q ).displayed_field_type() : fd_null; | |||
( !fld_overridden || !invis ) ? here.field_at( q ).displayed_field_type() : fd_null; |
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.
[JSON & C++ formatters] reported by reviewdog 🐶
( !fld_overridden || !invis ) ? here.field_at( q ).displayed_field_type() : fd_null; | |
( !fld_overridden || !invis ) ? here.field_at( q ).displayed_field_type() : fd_null; |
player_to_screen( iD + point( direction_offset, 0 ) ), | ||
formatted_text( sText, FG, direction ) ); |
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.
[JSON & C++ formatters] reported by reviewdog 🐶
player_to_screen( iD + point( direction_offset, 0 ) ), | |
formatted_text( sText, FG, direction ) ); | |
player_to_screen( iD + point( direction_offset, 0 ) ), | |
formatted_text( sText, FG, direction ) ); |
@@ -4818,7 +4819,7 @@ | |||
const auto ter = [&]( const tripoint & q, const bool invis ) -> ter_id { | |||
const auto override = ter_override.find( q ); | |||
return override != ter_override.end() ? override->second : | |||
( !overridden || !invis ) ? here.ter( q ) : t_null; | |||
( !overridden || !invis ) ? here.ter( q ) : t_null; |
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.
[JSON & C++ formatters] reported by reviewdog 🐶
( !overridden || !invis ) ? here.ter( q ) : t_null; | |
( !overridden || !invis ) ? here.ter( q ) : t_null; |
@@ -5238,7 +5239,7 @@ | |||
|
|||
std::vector<map_extra_id> map_extra_ids = MapExtras::get_all_function_names(); | |||
map_extra_ids.erase( | |||
std::remove_if( map_extra_ids.begin(), map_extra_ids.end(), | |||
std::remove_if( map_extra_ids.begin(), map_extra_ids.end(), |
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.
[JSON & C++ formatters] reported by reviewdog 🐶
std::remove_if( map_extra_ids.begin(), map_extra_ids.end(), | |
std::remove_if( map_extra_ids.begin(), map_extra_ids.end(), |
* | ||
* Assumes there is at least one item. | ||
* Used to decide which item to render. | ||
* TODO: might be slow enough to justify storing the most visible item for each 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.
[JSON & C++ formatters] reported by reviewdog 🐶
* TODO: might be slow enough to justify storing the most visible item for each tile? | |
* TODO: might be slow enough to justify storing the most visible item for each tile? |
* | ||
* Assumes there is at least one item. | ||
* Used to decide which item to render. | ||
* TODO: might be slow enough to justify storing the most visible item for each 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.
You can (and should!) check this yourself.
Spawn a ton of items and see if the game is still playable before and after your changes.
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 actually did test it ingame, spawned a bunch of items, I mentioned that in the PR but didn't update the comment in the code, mb
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 am not sure if this is viable, but if it is, the merger will want these to be fixed.
units::volume biggest_volume = 0_ml; | ||
|
||
// uppermost item is at end of the list, so iterate backwards so uppermost item is preferred | ||
auto items = get_items(); |
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.
Avoid using auto
auto items = get_items(); | ||
// unsigned int i = get_items().size(); | ||
for( auto it = items.rbegin(); it != items.rend(); it++ ) { | ||
const auto &item = *it; |
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.
Avoid using auto
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.
It's generally acceptable for more complex types such as iterators, though. So only the one inside the loop needs to be changed, in case that wasn't clear.
@@ -418,6 +418,35 @@ class maptile_impl | |||
return *std::prev( sm->get_items( pos() ).cend() ); | |||
} | |||
|
|||
/** Returns the uppermost favorite item if there is a favorite item. Otherwise, returns the item with the greatest volume. | |||
* | |||
* Assumes there is at least one item. |
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.
You should check it in the code instead of silently returning nullptr. Throw some cata error (not sure how from the top of my head).
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 put that there because get_uppermost_item() made that assumption, so I figured I could too. I'll change it though.
* Used to decide which item to render. | ||
* TODO: might be slow enough to justify storing the most visible item for each tile? | ||
*/ | ||
const item &get_most_visible_item() const { |
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.
The implementation of this size should be in the .cpp
file, not the .h
file.
Btw this will improve the compilation time (when changing only the implementation) enormously, as you only recompile one file.
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 realized that - I was again just basing it off what get_uppermost_item() did, and assumed that there was some reason that other functions in the same file were implemented in the header. I'll fix that.
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.
It's based on simplicity of the function. One liners can be in .h files. But anything in .h means drastically more recompile time on change.
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.
oh wait, actually it's all in a header because it's a method of a template class.
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.
Oh, you might be right. I don't know enough about template stuff splitting, Feel free to mark this as resolved.
I like the idea of showing a favourite item if it can be done fast. I believe this is not fast. But you can prove me wrong by testing it. I don't care for showing the largest item. |
Would you like to test its performance impact? |
I got an error when playing with your changes. Steps to reproduce:
Specifically, Cataclysm-DDA/src/cata_tiles.cpp Line 3720 in faf0ed7
The same happens when I try to debug spawn 10000 plastic chunks. |
In case you are not aware, you can press "V" to list all items around the player. And it's quite easy to locate whatever you're looking for, especially if you add the item to your favorite. Either scroll down the list or press "/" to search to filter the list. |
I did not mean to push just now, I am still making changes. Now I know what that button does. |
Alright, I fixed those crashes. After doing some profiling, I've found that it does make the game run slightly slower, which isn't great, so I'm making submaps store the most visible item on each tile so it only needs to be recalculated when an item is added (just compare new item to current most visible, O(1)) or when the most visible item is removed (O(N), but this isn't going to happen very often and worst case it's iterating through 4096 items in contiguous memory). |
On further examination, that might not actually be possible since apparently there's a method used throughout the code that just gives people a read-write reference to the items, meaning there's no way to know when an item is added/removed. I'll see if I can find a clever workaround for performance, though. If I can't, I'll just make it ignore volume when deciding what to render, since calling base_volume() was the main slowdown in get_most_visible_item(), and make it just prioritize favorite items. |
After more performance testing with ~300,000 dropped items on the ground, I found that this just won't work performance wise, even if it ignores volume and just tries to prioritize favorite items. Given that it's just a small QOL feature it's definitely not worth the performance hit, so I'm gonna close this. Sad. |
Better luck next time. Sorry things didn't work out. |
Summary
Interface "Instead of rendering the last-dropped item on the ground, it renders the last-dropped favorite items on the ground, or the biggest item if no such favorite item."
Purpose of change
Addresses #71637
Once, I lost my backpack in a lab and spent like an hour trying to find it because after dropping my backpack on a tile, I noticed I also had some broken glass in my pockets and decided to drop that too. Because the game rendered the glass instead of the backpack. it was a huge pain to find it.
In general, it makes much more sense for bigger items to display in favor of smaller ones, and for favorite items to display in favor of non-favorite ones, and will prevent stuff like bullet casings covering up actually important items.
Describe the solution
In the code that renders dropped items, I replaced the calls to submap::get_uppermost_item() with a call to a new function, submap::get_most_visible_item(), which iterates through the items on that tile and returns the first (and therefore last dropped) favorite item or, failing that, the biggest item.
Describe alternatives you've considered
Marking the item as favorite and enabling creation of notes when a favorite item is dropped helps, but it doesn't give its exact position as well, and it doesn't change the fact that it's really weird/potentially deceptive for the last dropped item to render, even when you drop something tiny on something big.
Testing
I walked around in a new game picking up and dropping various items in various orders, and strolling through the city. Worked as expected, and I did not notice any performance issues, even with thousands of items on the same tile.
I also ran all tests locally and saw no related issues.
Additional context
If this leads to performance issues with item rendering (given the O(n items on tile) time complexity), it would be pretty simple to just cache the most visible item on each tile, but I can't imagine this being an issue unless there are literally >1,000,000 items in view, in which case there are most likely already other performance issues.