4
$\begingroup$

I have a for loop that each time it will move or rotate several objects randomly, if some conditions not satisfied, it will undo all operations.

for obj in group_obj.objects:
            move_rotate(obj, T, T_0)

            accessableArea(obj)
        
        new_c = total_cost(group_obj)
        if i == 0:
            old_c = c_0
        if Metropolis(old_c, new_c):
            old_c = new_c
        else:
            for i in range(len(group_obj.objects)):
                bpy.ops.ed.undo()

This is move & rotate function

def move_rotate(object, T, T_0):
"""
Description:move and rotate object randomly

"""
if len(object.name.split("_")) < 3:

    std = math.sqrt(T/10)
    m = np.random.normal(0, std, 1)
    if np.random.randint(2):
        object.location.x += m
    else:
        object.location.y += m
    # rootate
    std = math.pi * (T/T_0)
    r = np.random.normal(0, std, 1)
    object.rotation_euler.z += r

It will report this error

RuntimeError: Operator bpy.ops.ed.undo.poll() failed, context is incorrect

Another question is, it seems blneder considered all operations down by script as one operation, Each time I run over the script press undo the sence will return to origin instead of last step.

Update: Based on @X Y's answer, I made some improvement:

while T > T_F:
    for i in range(num):
        count = 0
        for obj in group.objects:
            bpy.ops.ed.undo_push()
            # repeat move&rotate until it won't cross the wall
            while True:
                
                move_rotate(obj, T, T_0)

                if check_if_cross_wall(obj):
                    bpy.ops.ed.undo()
                    continue

                break
                

            count += 1
            accessableArea(obj)
        
        new_c = total_cost(group)
        if i == 0:
            old_c = c_0
        if Metropolis(old_c, new_c):
            old_c = new_c
        else:
            bpy.ops.ed.undo()

    T = T * alpha

move & rotate function keep it as is. before running script

error message

after running script

report StructRNA of type Object has been removed.

$\endgroup$
6
  • $\begingroup$ Run bpy.ops.ed.undo_push() before you do some action. $\endgroup$
    – X Y
    Commented Jul 9, 2022 at 2:48
  • 2
    $\begingroup$ That's because Run Script operation is a bpy.ops operation in itself so the undo would reverse everything done by the Run Script action. You can see this action as Run Script under menu Edit > Undo History $\endgroup$
    – Harry McKenzie
    Commented Jul 9, 2022 at 3:17
  • $\begingroup$ So this would push current state into stack and if I need reverse to a history state just need to use bpy.ops.ed.undo_history(i)? $\endgroup$
    – P. Scotty
    Commented Jul 9, 2022 at 3:49
  • $\begingroup$ If no restore point to get backwards, It will cause the Error: Operator bpy.ops.ed.undo.poll() failed, context is incorrect $\endgroup$
    – X Y
    Commented Jul 9, 2022 at 22:17
  • $\begingroup$ when you access the object, for example: obj = bpy.context.object, and then if you run bpy.ops.ed.undo(), obj is invalid. So you need get the object again. $\endgroup$
    – X Y
    Commented Jul 10, 2022 at 10:24

1 Answer 1

7
$\begingroup$

Create a Restore point

enter image description here

import bpy

# make sure it has a active object
bpy.context.object.location.x += 1

bpy.ops.ed.undo_push(message = "Restore point 1")

bpy.context.object.location.x += 2

bpy.ops.ed.undo_push(message = "Restore point 2")


# restore part, use interface or run bpy.ops
def UNDO():
    try:
        bpy.ops.ed.undo()
        print("success")
    except:
        print("fail")

# undo 1 step
UNDO()
# because click to run script also create a store point
# so, Restore point 2 is gone!

Fix ReferenceError

import bpy

def UNDO():
    try:
        bpy.ops.ed.undo()
        print("success")
    except:
        print("fail")


bpy.ops.ed.undo_push(message = "Restore point 1")
obj = bpy.data.objects["Cube"]
obj.location.x += 1

UNDO()
print(obj) # obj cannot be used anymore (after undo)
# so need get the object again
obj = bpy.data.objects["Cube"]
print(obj.name)
$\endgroup$
2
  • $\begingroup$ I made some changes to make it more suitable for my needs, but there are some other mistakes appeared. $\endgroup$
    – P. Scotty
    Commented Jul 10, 2022 at 7:26
  • $\begingroup$ See the updated section for details. $\endgroup$
    – P. Scotty
    Commented Jul 10, 2022 at 7:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .