-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Group created values in IdTypeMap by a shared Id that can later be used to remove them in bulk. #5827
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
base: main
Are you sure you want to change the base?
Group created values in IdTypeMap by a shared Id that can later be used to remove them in bulk. #5827
Conversation
…ed to remove them in bulk.
I agree that this is a problem, but I'm not sure if this is the best way of fixing this. I think it'd be neat if there was some way to automatically clean up data that e.g. wasn't accessed last frame or for the last N frames or seconds. Would that also fix things for your usecase? |
Preview available at https://egui-pr-preview.github.io/pr/5827-dataidfortypeidmap |
No, last n frames/seconds is not a good fix for me because I also hide stuff temporarily and later show it again. Your suggestion would remove this hidden stuff aswell, which is not desired. An example of what my app has to do: Id prefer it if I could manually choose when to discard. Sidenote: |
@lucasmerlin I am having massive problems with your check script. cargo check --quiet -p eframe --no-default-features --features glow I will fix the cargo fmt issue and hope for the best. |
Have you looked at |
@emilk That appeared to only works for persistet type. I dont have any persistence so its all temp values. I couldnt see how this setting affects the temp values. I will double check this later. Even if it worked I again would like this level of fine control as mentioned removing the "oldest" or oldest unused value is not the correct behavior I desire. |
@lucasmerlin |
Hello @lucasmerlin @emilk I really need this feature for my use case and would prefer to not have to maintain this as a patch that I constantly have to rebase onto all your changes. Is there anything you still want me to do? If you do not want to merge this then Sincerely |
@AlexanderSchuetz97 Can It is very suitable for storing values that will be automatically cleared when they are not needed. // You can customize the types of keys and values.
type MyPublisher = egui::cache::FramePublisher<String, u32>;
fn foo(ui: &mut egui::Ui) {
let key = String::from("random id");
// In this use case, the first frame is `None`, and every subsequent frame is `Some(0)`.
// If the set method is not called in the future, the stored data will be automatically cleared in the next frame.
let prev_value = ui.ctx().memory_mut(|m| m.caches.cache::<MyPublisher>().get(&key).copied());
// some other code
// Manually set the values that need to be saved to the next frame.
ui.ctx().memory_mut(|m| m.caches.cache::<MyPublisher>().set(key, 0));
} |
@zhatuokun no it can not. As mentioned previously I have to hide a ui (i.e. its not drawn!) for significant amount of time and it later becomes visible again and should have the same properties. (For example positioning of a panel that was manually resized by the user) I dont manually set ANY data into the ctx.memory map its the Side Panel for example or a scroll pane that does so. |
Oh, I'm sorry, I ignored your answer above. I have done similar things before, when I chose to create a new struct and manage it manually. |
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 think this is the wrong solution.
If you want fine control over when data is retained/removed I suggest you either store it outside of IdTypeMap
, or we add add retain
functions to IdTypeMap
, and you can store the extra state inside of the type itself:
impl IdTypeMap {
/// For each temp value of the given type, only retain it if the predicate is `true`.
pub fn retain_temp<T>(&mut self, keep: impl Fn(&mut T)) {
}
}
EDIT: Or do you need this to work for types you don't have control for too, e.g. CollapsingHeader
?
@emilk |
I'm hesitant to add complexity to egui to support this somewhat niche use case. However, we're in the process of adding a lookup-map for Id:s in this PR: Theoretically we could use this map to look up all ancestor Id:s from some Id (e.g. that of a top-level panel), and then you could write code for "remove data for these Id"s. WDYT? |
That would work were if the typeids were not included in the hashes. Sadly they are. the ids are also a problem but predicting the typeids is harder or even impossible as you seem to feed private types into the map. If you dont want to expose as much api bandwidth as this change proposes, expose the raw keys to the map u64? or wrap them in a type thats eq, clone and hash and allow me to iterate over all raw keys and remove by them.Then I could track the garbage on my end. I already mentioned this in a comment above. I discussed this with @lucasmerlin in discord and we came to the conclusion that the original solution i proposed is probably best. If you want I can remove the changes from the context.rs and we can only keep the changes to the typeidmap. It wouldnt look as nice but it would still work and thats all I care about. |
Hello,
this is my first PR to this repository.
I hope it meets your requirements on how a PR is supposed to be filed.
It is a small change that allows me to remove temporary values stored in the TypeIdMap created by a part of the ui that is obsolete.
What is the problem?
I have a very generic UI that changes drastically based on data/state and user actions.
It is impossible for me to uniquely id many of my widgets that require an id.
I have therefore opted to assign semi random id's together with the state.
This works great, however sometimes user action or data/state changes cause parts of the ui
to disappear and different stuff to be added.
Over a long time this causes the TypeIdMap to bloat with temporary values.
To print the count I used
In my update loop. This value never decreased. (Memory Leak)
How does this PR help me?
This pr adds a fn to Context that I can call to assign a id to all elements inserted
into the TypeIdMap during the execution of a closure. (Similar to ui::push_id)
The "group" id is determined at the time of insertion into the TypeIdMap.
During this closure I will update my UI. (For example update/create a nested left or right Panel and all elements in it).
This allows me to logically group my elements so that I can later remove all temporary values associated to the elements once
I desire them to become obsolete.
What alternatives have I considered?
I was unable to individually remove all the elements from the TypeIdMap because
I was not able to correctly deduce the TypeId which is part of the Key Hash.
Calling TypeIdMap::clear() is also not workable for me because it makes the entire UI jerk back to default settings,
undoing any resizing the user may have done to still relevant panels.
Naming/Bikeshedding
I am not at all attached to the function name "push_data_id" or the name "data_id"
I gave this name group id explained above which is stored for every value in the TypeIdMap.
As you are probably aware naming things is not trivial.
If you want me to change the name to something else then tell me and I will gladly change it.
Since this is quite a technical PR I don't think adding any screenshots provides value.
If you want me to make a simple app demonstrating my problem (by printing the number) and making a button that appears/disappears a panel each time with a new id then I can do so. But once again since this is a technical issue I think such an app would be boring to look at?
I would be delighted if this could be merged.
Sincerely
Alexander Schütz