Notice: I have pivoted the idea to one of improving UNDO speed and efficiency. Please read the replies below.
Hi all. In the latest build of Blender 2.8, Undo follows the global order in which actions were done. This means that if I am working on an object having previously worked on another object, but wish to undo an action done on the previous object, I have to undo all the actions done to the current object too. I have done some research on Right Click Select and UI Papercut, and noticed that this is a pain point for some Blender users too. https://blender.community/c/rightclickselect/VLcbbc/
I wish to propose a refactor of the Undo system so that it retains the ability to perform traditional undo as well as my proposed per data-block undo. This involves storing actions at data-block level. If user clicks on a mesh data-block in the outliner, Ctrl-Z will perform traditional undo (following global order) while Ctrl-Alt-Z will perform per data-block undo (for the selected mesh). In addition, I intend to create a new Undo panel for undo management.
If our active editor is 3D view port and we are in edit mode, upon translating a vertex of object A, this action will be recorded under object A’s mesh data-block.
If our active editor is 3D view port and we are in object mode, upon translating object A, this action will be recorded under object A’s data-block.
If our active editor is Properties and we are in material panel, upon modify the diffused color, this action will be recorded under object A’s material data-block.
If an action on one data-block strictly requires that an action on another data-block has been completed, then my proposed Undo mechanism may not be viable because if we were to undo the dependent action, the other action will become invalid.
If all Blender actions are unrestricted and have its own inverse (i.e. translate (0, 0, 1) and translate (0, 0, -1)), then my concern is unfounded. But if there are actions in Blender that maybe active/ inactive based on some conditions (restricted action), then my concern is valid.
Thank you for looking through my gSOC project ideation. I would love to receive some feedback regarding the meaningfulness of this project, viability of this project, general ideas and suggestions. Is it a pain point for many users? Could this be a good gSOC project on its own?
I’m afraid the situation is really quite complicated and there are dependencies between datablocks in many situations that make per-datablock undo problematic. Bugs and unexpected behavior due to this is exactly why we moved away from it, even if it can be useful in some cases.
In the right click select request, note also that the request is to decouple undo of layers and drawing, which are both edits to the same datablock.
I don’t want to interfere… but the main UNDO problem is speed in medium to large scenes, just moving an object and doing an UNDO of that movement can take several seconds, even minutes!
Just in case this helps you out to your ideas for the GSOC, IMHO try to do something useful, “small” but important and then it could probably even be included in master after GSOC (it depends on you and the devs… but if it’s simple, useful and stable… why not?)
It’s great to see a dev or potential dev interested in improving the UNDO system.
Right, optimizing undo could be a project. It touches quite some core code so needs to be done very carefully, but if enough time is taking to test well it would work. Some ideas for that are here: https://developer.blender.org/T60695
Thank you for your advise. I think so too, to have my work included in master would be icing on the cake.
I don’t deal with complex scene in Blender often enough, so thanks for sharing a potential project idea! It reminds me of my not so good experience creating fur using particle system for the first time.
When a datablock changes, it is tagged for updated in the dependency graph. The dependency graph will then do things like evaluation modifiers or animation for that datablock and any datablocks depending on it.
I suggest to start from blenkernel/intern/blender_undo.c and follow the function calls. That file contains the two functions that perform the global undo push and load.
A suggestion: this might seem obvious, but it might be a good idea to download the demo files. https://www.blender.org/download/demo-files/ Some of these are pretty slow to undo/redo. You could use them as a standard benchmark for your improvements (as they are already used to benchmark CPU/GPU performance in Open Data).
Hi Brecht, I am in the process of writing my project proposal and would like to clarify my understanding of the relevant Blender’s code.
At the high level, in blenkernel/intern/blender_undo.c, BKE_memfile_undo_decode calls BKE_blendfile_read_from_memfile, which does the actual reading from MemFile (undo buffer) and updates bContext. I presume bContext contains all the states for a Blender program. Hence, having updated bContext, the UNDO operation has completed.
Is this correct in so far as this project is concerned?
Thank you! I would like to clarify my understanding of the relevant Blender’s code further and seek feedback for my analysis of the UNDO task.
Following the function calls, BKE_blendfile_read_from_memfile calls BLO_read_from_memfile and setup_app_data.
BLO_read_from_memfile in turn calls the following functions:
blo_filedata_from_memfile: Creates a catalog of DNA-structuresdocumentation and returns FileData.
blo_make_image_pointer_map & related calls: ? I presume this is the reason render results remains after UNDO.
blo_read_file_internal: Reads from MemFile and returns BlendFileData.
setup_app_data updates Main through bContext and pushes updates to the UI.
/* Even though directly used libs have been already moved to new main, indirect ones have not.
* This is a bit annoying, but we have no choice but to keep them all for now - means some now unused
* data may remain in memory, but think we'll have to live with it. */
Question: What do directly and indirectly used library refer to? Am I right thus far? (": ?" can be ignored unless it is important)
Referring to the bullet point “Read only changed datablocks” of this task that you shared, I presume that BLO_read_from_memfile needs to be modified so that all datablocks remains as it is from old Main. blo_read_file_internal function needs to be modified so that changed datablocks are read from MemFile. We will also need to deal with added/ removed datablocks. Idea is to start off from the current state, find datablocks that has changed, read those datablocks from MemFile into BlendFileData.
setup_app_data should not need much modification if any at all.
blo_read_file_internal is used for loading of .blend files as well and therefore needs extra care.
Question: Where in the code are links between datablocks reestablished? Is my analysis of the UNDO task reasonably correct? Could I have misunderstood the task or the code?
I don’t want to muddy this discussion with non-relevant posts, but improving undo speed on complex scenes would be absolutely amazing. These types of unglamorous, utilitarian changes often go untouched, but know that you will make a lot users very happy if the speed improves.