I want to get my entire session's undo history back when I load a Blender file. This would allow me to undo as far as would have been possible, had I not closed Blender.
Can any in-built feature or plugin support this?
I want to get my entire session's undo history back when I load a Blender file. This would allow me to undo as far as would have been possible, had I not closed Blender.
Can any in-built feature or plugin support this?
as you mentioned there is a limitation. this test shows you how many steps you can undo. In my pc I can undo only 32 steps:
import bpy
for i in range(0,100):
bpy.ops.mesh.primitive_cube_add(enter_editmode=False, align='WORLD', location=(i, 0, 0))
bpy.ops.ed.undo_push(message="Add Cube")
for i in range(0,100):
bpy.ops.ed.undo()
I decompiled undo script
void ED_undo_push(bContext *C, const char *str)
{
CLOG_INFO(&LOG, 1, "name='%s'", str);
WM_file_tag_modified();
wmWindowManager *wm = CTX_wm_manager(C);
int steps = U.undosteps;
/* Ensure steps that have been initialized are always pushed,
- even when undo steps are zero.
- Note that some modes (paint, sculpt) initialize an undo step before an action runs,
- then accumulate changes there, or restore data from it in the case of 2D painting.
- For this reason we need to handle the undo step even when undo steps is set to zero.
*/
if ((steps <= 0) && wm->undo_stack->step_init != NULL) {
steps = 1;
}
if (steps <= 0) {
return;
}
/* Only apply limit if this is the last undo step. */
if (wm->undo_stack->step_active && (wm->undo_stack->step_active->next == NULL)) {
BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, steps - 1, 0);
}
BKE_undosys_step_push(wm->undo_stack, C, str);
if (U.undomemory != 0) {
const size_t memory_limit = (size_t)U.undomemory * 1024 * 1024;
BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, -1, memory_limit);
}
if (CLOG_CHECK(&LOG, 1)) {
BKE_undosys_print(wm->undo_stack);
}
}
you can see how limitation calculated:
const size_t memory_limit = (size_t)U.undomemory * 1024 * 1024;
as @Jachym Michal said in comments increasing this limitation is not recommended
I suggest you use Git.you can easily undo (checkout) by git commands
Git is a distributed version control system for tracking changes in source code during software development.
but if you like the automatic way you can commit after each change:
import subprocess
from subprocess import Popen, PIPE, STDOUT
import re
undo step
step = 0
repository path
repoDir = 'C:/Users/Kamali/Desktop/Test'
def gitCommit(message):
global step
step += 1
cmd = 'git add . && git commit -am '+message
p = subprocess.Popen(cmd, cwd=repoDir)
p.wait()
def undo():
global step
step -= 1
checkoutTo(step)
check out to specific step
def checkoutTo(Index):
cmd = 'git checkout ' + getStepRevision()
p = subprocess.Popen(cmd, cwd=repoDir)
p.wait()
get specific revision from git log history 546bece2c66acb454878500689e3017b92c43d28
def getStepRevision():
cmd = 'powershell.exe git show HEAD~'+str(step)+' --pretty=oneline --no-patch'
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True, cwd=repoDir)
output = p.stdout.read()
p.wait()
revision = re.search('(.*?)\s',output.decode('utf-8')).group(1)
print(revision)
if you don't know git commands you can use git extension
after you undo (check out) you have to close and reopen blender to refresh but these lines of code help you to reload it easy
import bpy
bpy.ops.wm.open_mainfile(filepath=bpy.data.filepath)
run this code and see what happened!!!
import subprocess
from subprocess import Popen, PIPE, STDOUT
import bpy
repoDir = 'C:/Users/Kamali/Desktop/New folder'
for i in range(0,100):
bpy.ops.mesh.primitive_cube_add(enter_editmode=False, align='WORLD', location=(i, 0, 0))
bpy.ops.ed.undo_push(message="Add Cube")
def gitCommit(message):
bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
add = 'git add .'
p = subprocess.Popen(add, cwd=repoDir)
p.wait()
commit = 'git commit -m ' + message
p = subprocess.Popen(commit, cwd=repoDir)
p.wait()
I could commit 100 steps with code