Blender V4.3
undo_system.cc File Reference
#include <cstdio>
#include <cstring>
#include "CLG_log.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
#include "BLT_translation.hh"
#include "DNA_listBase.h"
#include "DNA_windowmanager_types.h"
#include "BKE_context.hh"
#include "BKE_global.hh"
#include "BKE_lib_id.hh"
#include "BKE_lib_override.hh"
#include "BKE_main.hh"
#include "BKE_undo_system.hh"
#include "RNA_access.hh"
#include "MEM_guardedalloc.h"
#include "BKE_blender_undo.hh"

Go to the source code of this file.

Macros

#define undo_stack   _wm_undo_stack_disallow /* pass in as a variable always. */
 
#define WITH_GLOBAL_UNDO_KEEP_ONE
 
#define WITH_GLOBAL_UNDO_ENSURE_UPDATED
 
#define WITH_GLOBAL_UNDO_CORRECT_ORDER
 

Functions

Internal Callback Wrappers

UndoRefID is simply a way to avoid in-lining name copy and lookups, since it's easy to forget a single case when done inline (crashing in some cases).

static void undosys_id_ref_store (void *, UndoRefID *id_ref)
 
static void undosys_id_ref_resolve (void *user_data, UndoRefID *id_ref)
 
static bool undosys_step_encode (bContext *C, Main *bmain, UndoStack *ustack, UndoStep *us)
 
static void undosys_step_decode (bContext *C, Main *bmain, UndoStack *ustack, UndoStep *us, const eUndoStepDir dir, bool is_final)
 
static void undosys_step_free_and_unlink (UndoStack *ustack, UndoStep *us)
 
Undo Stack
static void undosys_stack_validate (UndoStack *ustack, bool expect_non_empty)
 
UndoStackBKE_undosys_stack_create ()
 
void BKE_undosys_stack_destroy (UndoStack *ustack)
 
void BKE_undosys_stack_clear (UndoStack *ustack)
 
void BKE_undosys_stack_clear_active (UndoStack *ustack)
 
static void undosys_stack_clear_all_last (UndoStack *ustack, UndoStep *us)
 
static void undosys_stack_clear_all_first (UndoStack *ustack, UndoStep *us, UndoStep *us_exclude)
 
static bool undosys_stack_push_main (UndoStack *ustack, const char *name, Main *bmain)
 
void BKE_undosys_stack_init_from_main (UndoStack *ustack, Main *bmain)
 
void BKE_undosys_stack_init_from_context (UndoStack *ustack, bContext *C)
 
bool BKE_undosys_stack_has_undo (const UndoStack *ustack, const char *name)
 
UndoStepBKE_undosys_stack_active_with_type (UndoStack *ustack, const UndoType *ut)
 
UndoStepBKE_undosys_stack_init_or_active_with_type (UndoStack *ustack, const UndoType *ut)
 
void BKE_undosys_stack_limit_steps_and_memory (UndoStack *ustack, int steps, size_t memory_limit)
 
Undo Step
UndoStepBKE_undosys_step_push_init_with_type (UndoStack *ustack, bContext *C, const char *name, const UndoType *ut)
 
UndoStepBKE_undosys_step_push_init (UndoStack *ustack, bContext *C, const char *name)
 
eUndoPushReturn BKE_undosys_step_push_with_type (UndoStack *ustack, bContext *C, const char *name, const UndoType *ut)
 
eUndoPushReturn BKE_undosys_step_push (UndoStack *ustack, bContext *C, const char *name)
 
UndoStepBKE_undosys_step_same_type_next (UndoStep *us)
 
UndoStepBKE_undosys_step_same_type_prev (UndoStep *us)
 
UndoStepBKE_undosys_step_find_by_name_with_type (UndoStack *ustack, const char *name, const UndoType *ut)
 
UndoStepBKE_undosys_step_find_by_name (UndoStack *ustack, const char *name)
 
UndoStepBKE_undosys_step_find_by_type (UndoStack *ustack, const UndoType *ut)
 
eUndoStepDir BKE_undosys_step_calc_direction (const UndoStack *ustack, const UndoStep *us_target, const UndoStep *us_reference)
 
static UndoStepundosys_step_iter_first (UndoStep *us_reference, const eUndoStepDir undo_dir)
 
bool BKE_undosys_step_load_data_ex (UndoStack *ustack, bContext *C, UndoStep *us_target, UndoStep *us_reference, const bool use_skip)
 
bool BKE_undosys_step_load_data (UndoStack *ustack, bContext *C, UndoStep *us_target)
 
void BKE_undosys_step_load_from_index (UndoStack *ustack, bContext *C, const int index)
 
bool BKE_undosys_step_undo_with_data_ex (UndoStack *ustack, bContext *C, UndoStep *us_target, bool use_skip)
 
bool BKE_undosys_step_undo_with_data (UndoStack *ustack, bContext *C, UndoStep *us_target)
 
bool BKE_undosys_step_undo (UndoStack *ustack, bContext *C)
 
bool BKE_undosys_step_redo_with_data_ex (UndoStack *ustack, bContext *C, UndoStep *us_target, bool use_skip)
 
bool BKE_undosys_step_redo_with_data (UndoStack *ustack, bContext *C, UndoStep *us_target)
 
bool BKE_undosys_step_redo (UndoStack *ustack, bContext *C)
 
UndoTypeBKE_undosys_type_append (void(*undosys_fn)(UndoType *))
 
void BKE_undosys_type_free_all ()
 
Undo Stack Grouping

This enables skip while group-level is set. In general it's not allowed that UndoStack.step_active have 'skip' enabled.

This rule is relaxed for grouping, however it's important each call to BKE_undosys_stack_group_begin has a matching BKE_undosys_stack_group_end.

  • Levels are used so nesting is supported, where the last call to BKE_undosys_stack_group_end will set the active undo step that should not be skipped.
  • Correct begin/end is checked by an assert since any errors here will cause undo to consider all steps part of one large group.
  • Calls to begin/end with no undo steps being pushed is supported and does nothing.
void BKE_undosys_stack_group_begin (UndoStack *ustack)
 
void BKE_undosys_stack_group_end (UndoStack *ustack)
 
ID Reference Utilities

Unfortunately we need this for a handful of places.

static void UNUSED_FUNCTION (BKE_undosys_foreach_ID_ref(UndoStack *ustack, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data))
 
Debug Helpers
void BKE_undosys_print (UndoStack *ustack)
 

Variables

static CLG_LogRef LOG = {"bke.undosys"}
 

Internal Nested Undo Checks

Make sure we're not running undo operations from 'step_encode', 'step_decode' callbacks. bugs caused by this situation aren't that hard to spot but aren't always so obvious. Best we have a check which shows the problem immediately.

#define WITH_NESTED_UNDO_CHECK
 
#define UNDO_NESTED_ASSERT(state)   BLI_assert(g_undo_callback_running == state)
 
#define UNDO_NESTED_CHECK_BEGIN
 
#define UNDO_NESTED_CHECK_END
 
static bool g_undo_callback_running = false
 

Undo Types

const UndoTypeBKE_UNDOSYS_TYPE_IMAGE = nullptr
 
const UndoTypeBKE_UNDOSYS_TYPE_MEMFILE = nullptr
 
const UndoTypeBKE_UNDOSYS_TYPE_PAINTCURVE = nullptr
 
const UndoTypeBKE_UNDOSYS_TYPE_PARTICLE = nullptr
 
const UndoTypeBKE_UNDOSYS_TYPE_SCULPT = nullptr
 
const UndoTypeBKE_UNDOSYS_TYPE_TEXT = nullptr
 
static ListBase g_undo_types = {nullptr, nullptr}
 
void bke_undo_system_linker_workaround ()
 
static const UndoTypeBKE_undosys_type_from_context (bContext *C)
 

Detailed Description

Used by ED_undo.hh, internal implementation.

Definition in file undo_system.cc.

Macro Definition Documentation

◆ UNDO_NESTED_ASSERT

◆ UNDO_NESTED_CHECK_BEGIN

#define UNDO_NESTED_CHECK_BEGIN
Value:
{ \
UNDO_NESTED_ASSERT(false); \
} \
((void)0)
static bool g_undo_callback_running

Definition at line 105 of file undo_system.cc.

Referenced by undosys_step_decode(), undosys_step_encode(), and undosys_step_free_and_unlink().

◆ UNDO_NESTED_CHECK_END

#define UNDO_NESTED_CHECK_END
Value:
{ \
UNDO_NESTED_ASSERT(true); \
} \
((void)0)

Definition at line 111 of file undo_system.cc.

Referenced by undosys_step_decode(), undosys_step_encode(), and undosys_step_free_and_unlink().

◆ undo_stack

#define undo_stack   _wm_undo_stack_disallow /* pass in as a variable always. */

Definition at line 40 of file undo_system.cc.

Referenced by ed_redo_poll(), and ed_undo_poll().

◆ WITH_GLOBAL_UNDO_CORRECT_ORDER

#define WITH_GLOBAL_UNDO_CORRECT_ORDER

Make sure we don't apply edits on top of a newer memfile state, see: #56163.

Note
Keep an eye on this, could solve differently.

Definition at line 52 of file undo_system.cc.

◆ WITH_GLOBAL_UNDO_ENSURE_UPDATED

#define WITH_GLOBAL_UNDO_ENSURE_UPDATED

Make sure all ID's created at the point we add an undo step that uses ID's.

Definition at line 46 of file undo_system.cc.

◆ WITH_GLOBAL_UNDO_KEEP_ONE

#define WITH_GLOBAL_UNDO_KEEP_ONE

Odd requirement of Blender that we always keep a memfile undo in the stack.

Definition at line 43 of file undo_system.cc.

◆ WITH_NESTED_UNDO_CHECK

#define WITH_NESTED_UNDO_CHECK

Definition at line 100 of file undo_system.cc.

Function Documentation

◆ bke_undo_system_linker_workaround()

void bke_undo_system_linker_workaround ( )

Definition at line 73 of file undo_system.cc.

References BKE_memfile_undo_free(), and BLI_assert_unreachable.

◆ BKE_undosys_print()

void BKE_undosys_print ( UndoStack * ustack)

◆ BKE_undosys_stack_active_with_type()

UndoStep * BKE_undosys_stack_active_with_type ( UndoStack * ustack,
const UndoType * ut )

◆ BKE_undosys_stack_clear()

◆ BKE_undosys_stack_clear_active()

void BKE_undosys_stack_clear_active ( UndoStack * ustack)

◆ BKE_undosys_stack_create()

UndoStack * BKE_undosys_stack_create ( )

Definition at line 269 of file undo_system.cc.

Referenced by ed_undo_push_exec(), and wm_file_read_post().

◆ BKE_undosys_stack_destroy()

void BKE_undosys_stack_destroy ( UndoStack * ustack)

Definition at line 275 of file undo_system.cc.

References BKE_undosys_stack_clear(), and MEM_freeN().

Referenced by ED_editors_exit(), and wm_close_and_free().

◆ BKE_undosys_stack_group_begin()

void BKE_undosys_stack_group_begin ( UndoStack * ustack)

Definition at line 950 of file undo_system.cc.

References BLI_assert, and UndoStack::group_level.

Referenced by ED_undo_group_begin().

◆ BKE_undosys_stack_group_end()

void BKE_undosys_stack_group_end ( UndoStack * ustack)

◆ BKE_undosys_stack_has_undo()

bool BKE_undosys_stack_has_undo ( const UndoStack * ustack,
const char * name )

◆ BKE_undosys_stack_init_from_context()

void BKE_undosys_stack_init_from_context ( UndoStack * ustack,
bContext * C )

◆ BKE_undosys_stack_init_from_main()

void BKE_undosys_stack_init_from_main ( UndoStack * ustack,
Main * bmain )

Definition at line 363 of file undo_system.cc.

References IFACE_, UNDO_NESTED_ASSERT, and undosys_stack_push_main().

Referenced by wm_file_read_post().

◆ BKE_undosys_stack_init_or_active_with_type()

◆ BKE_undosys_stack_limit_steps_and_memory()

void BKE_undosys_stack_limit_steps_and_memory ( UndoStack * ustack,
int steps,
size_t memory_limit )
Parameters
stepsLimit the number of undo steps.
memory_limitLimit the amount of memory used by the undo stack.

Definition at line 407 of file undo_system.cc.

References BKE_UNDOSYS_TYPE_MEMFILE, CLOG_INFO, UndoStep::data_size, ListBase::last, LOG, memory_limit, UndoStep::prev, UndoStep::skip, steps, UndoStack::steps, UndoStep::type, UNDO_NESTED_ASSERT, and undosys_stack_clear_all_first().

Referenced by ED_undo_push().

◆ BKE_undosys_step_calc_direction()

eUndoStepDir BKE_undosys_step_calc_direction ( const UndoStack * ustack,
const UndoStep * us_target,
const UndoStep * us_reference )

Return direction of the undo/redo from us_reference (or ustack->step_active if NULL), and us_target.

Note
If us_reference and us_target are the same, we consider this is an undo.
Returns
-1 for undo, 1 for redo, 0 in case of error.

Definition at line 691 of file undo_system.cc.

References BLI_assert, BLI_assert_msg, ELEM, UndoStep::next, UndoStep::prev, UndoStack::step_active, STEP_INVALID, STEP_REDO, and STEP_UNDO.

Referenced by BKE_undosys_step_load_data_ex(), BKE_undosys_step_redo_with_data_ex(), BKE_undosys_step_undo_with_data_ex(), and ed_undo_step_by_name().

◆ BKE_undosys_step_find_by_name()

UndoStep * BKE_undosys_step_find_by_name ( UndoStack * ustack,
const char * name )

Definition at line 676 of file undo_system.cc.

References BLI_rfindstring(), offsetof, and UndoStack::steps.

Referenced by ed_undo_step_by_name().

◆ BKE_undosys_step_find_by_name_with_type()

UndoStep * BKE_undosys_step_find_by_name_with_type ( UndoStack * ustack,
const char * name,
const UndoType * ut )

Definition at line 662 of file undo_system.cc.

References LISTBASE_FOREACH_BACKWARD, UndoStack::steps, and STREQ.

◆ BKE_undosys_step_find_by_type()

UndoStep * BKE_undosys_step_find_by_type ( UndoStack * ustack,
const UndoType * ut )

Definition at line 681 of file undo_system.cc.

References LISTBASE_FOREACH_BACKWARD, and UndoStack::steps.

Referenced by memfile_undosys_step_encode().

◆ BKE_undosys_step_load_data()

bool BKE_undosys_step_load_data ( UndoStack * ustack,
bContext * C,
UndoStep * us_target )

Undo/Redo until the given us_target step becomes the active (currently loaded) one.

Definition at line 840 of file undo_system.cc.

References BKE_undosys_step_load_data_ex().

Referenced by BKE_undosys_step_load_from_index().

◆ BKE_undosys_step_load_data_ex()

bool BKE_undosys_step_load_data_ex ( UndoStack * ustack,
bContext * C,
UndoStep * us_target,
UndoStep * us_reference,
bool use_skip )

Undo/Redo until the given us_target step becomes the active (currently loaded) one.

Note
Unless us_target is a 'skipped' one and use_skip is true, us_target will become the active step.
In case use_skip is true, the final target will always be beyond the given one (if the given one has to be skipped).
Parameters
us_referenceIf NULL, will be set to current active step in the undo stack. Otherwise, it is assumed to match the current state, and will be used as basis for the undo/redo process (i.e. all steps in-between us_reference and us_target will be processed).

Definition at line 750 of file undo_system.cc.

References BKE_undosys_step_calc_direction(), BLI_assert, BLI_assert_msg, CLOG_ERROR, CLOG_INFO, G_MAIN, LOG, UndoStep::name, UndoType::name, UndoStep::next, UndoStep::prev, UndoStep::skip, UndoStack::step_active, STEP_INVALID, CLG_LogRef::type, UndoStep::type, UNDO_NESTED_ASSERT, undosys_stack_validate(), undosys_step_decode(), and undosys_step_iter_first().

Referenced by BKE_undosys_step_load_data(), BKE_undosys_step_redo_with_data_ex(), BKE_undosys_step_undo_with_data_ex(), and ed_undo_step_by_name().

◆ BKE_undosys_step_load_from_index()

void BKE_undosys_step_load_from_index ( UndoStack * ustack,
bContext * C,
int index )

Undo/Redo until the step matching given index in the undo stack becomes the active (currently loaded) one.

Definition at line 846 of file undo_system.cc.

References BKE_undosys_step_load_data(), BLI_assert, BLI_findlink(), UndoStep::skip, UndoStack::step_active, and UndoStack::steps.

Referenced by ed_undo_step_by_index().

◆ BKE_undosys_step_push()

◆ BKE_undosys_step_push_init()

UndoStep * BKE_undosys_step_push_init ( UndoStack * ustack,
bContext * C,
const char * name )

◆ BKE_undosys_step_push_init_with_type()

◆ BKE_undosys_step_push_with_type()

◆ BKE_undosys_step_redo()

bool BKE_undosys_step_redo ( UndoStack * ustack,
bContext * C )

Redo one step from current active one.

Definition at line 903 of file undo_system.cc.

References BKE_undosys_step_redo_with_data(), UndoStep::next, and UndoStack::step_active.

Referenced by ed_undo_step_direction().

◆ BKE_undosys_step_redo_with_data()

bool BKE_undosys_step_redo_with_data ( UndoStack * ustack,
bContext * C,
UndoStep * us_target )

Redo until us_target step becomes the active (currently loaded) one.

Note
See BKE_undosys_step_redo_with_data_ex for details.

Definition at line 898 of file undo_system.cc.

References BKE_undosys_step_redo_with_data_ex().

Referenced by BKE_undosys_step_redo().

◆ BKE_undosys_step_redo_with_data_ex()

bool BKE_undosys_step_redo_with_data_ex ( UndoStack * ustack,
bContext * C,
UndoStep * us_target,
bool use_skip )

Redo until us_target step becomes the active (currently loaded) one.

Warning
This function assumes that the given target step is after current active one.
Note
Unless us_target is a 'skipped' one and use_skip is true, us_target will become the active step.
In case use_skip is true, the final target will always be after the given one (if the given one has to be skipped).

Definition at line 884 of file undo_system.cc.

References BKE_undosys_step_calc_direction(), BKE_undosys_step_load_data_ex(), BLI_assert, UndoStep::prev, and UndoStack::step_active.

Referenced by BKE_undosys_step_redo_with_data().

◆ BKE_undosys_step_same_type_next()

UndoStep * BKE_undosys_step_same_type_next ( UndoStep * us)

Useful when we want to diff against previous undo data but can't be sure the types match.

Definition at line 636 of file undo_system.cc.

References UndoStep::next, and UndoStep::type.

Referenced by memfile_undosys_step_free().

◆ BKE_undosys_step_same_type_prev()

UndoStep * BKE_undosys_step_same_type_prev ( UndoStep * us)

Useful when we want to diff against previous undo data but can't be sure the types match.

Definition at line 649 of file undo_system.cc.

References UndoStep::prev, and UndoStep::type.

◆ BKE_undosys_step_undo()

bool BKE_undosys_step_undo ( UndoStack * ustack,
bContext * C )

Undo one step from current active (currently loaded) one.

Definition at line 876 of file undo_system.cc.

References BKE_undosys_step_undo_with_data(), UndoStep::prev, and UndoStack::step_active.

Referenced by ed_undo_step_direction().

◆ BKE_undosys_step_undo_with_data()

bool BKE_undosys_step_undo_with_data ( UndoStack * ustack,
bContext * C,
UndoStep * us_target )

Undo until us_target step becomes the active (currently loaded) one.

Note
See BKE_undosys_step_undo_with_data_ex for details.

Definition at line 871 of file undo_system.cc.

References BKE_undosys_step_undo_with_data_ex().

Referenced by BKE_undosys_step_undo().

◆ BKE_undosys_step_undo_with_data_ex()

bool BKE_undosys_step_undo_with_data_ex ( UndoStack * ustack,
bContext * C,
UndoStep * us_target,
bool use_skip )

Undo until us_target step becomes the active (currently loaded) one.

Warning
This function assumes that the given target step is before current active one.
Note
Unless us_target is a 'skipped' one and use_skip is true, us_target will become the active step.
In case use_skip is true, the final target will always be before the given one (if the given one has to be skipped).

Definition at line 856 of file undo_system.cc.

References BKE_undosys_step_calc_direction(), BKE_undosys_step_load_data_ex(), BLI_assert, and UndoStack::step_active.

Referenced by BKE_undosys_step_undo_with_data().

◆ BKE_undosys_type_append()

UndoType * BKE_undosys_type_append ( void(* undosys_fn )(UndoType *))

Similar to WM_operatortype_append

Definition at line 911 of file undo_system.cc.

References BLI_addtail(), and g_undo_types.

Referenced by ED_undosys_type_init().

◆ BKE_undosys_type_free_all()

void BKE_undosys_type_free_all ( )

Definition at line 922 of file undo_system.cc.

References BLI_pophead(), g_undo_types, and MEM_freeN().

Referenced by ED_undosys_type_free().

◆ BKE_undosys_type_from_context()

static const UndoType * BKE_undosys_type_from_context ( bContext * C)
static

◆ undosys_id_ref_resolve()

static void undosys_id_ref_resolve ( void * user_data,
UndoRefID * id_ref )
static

◆ undosys_id_ref_store()

static void undosys_id_ref_store ( void * ,
UndoRefID * id_ref )
static

◆ undosys_stack_clear_all_first()

static void undosys_stack_clear_all_first ( UndoStack * ustack,
UndoStep * us,
UndoStep * us_exclude )
static

◆ undosys_stack_clear_all_last()

static void undosys_stack_clear_all_last ( UndoStack * ustack,
UndoStep * us )
static

◆ undosys_stack_push_main()

◆ undosys_stack_validate()

◆ undosys_step_decode()

◆ undosys_step_encode()

◆ undosys_step_free_and_unlink()

◆ undosys_step_iter_first()

static UndoStep * undosys_step_iter_first ( UndoStep * us_reference,
const eUndoStepDir undo_dir )
static

When reading undo steps for undo/redo, some extra checks are needed when so the correct undo step is decoded.

Definition at line 736 of file undo_system.cc.

References UndoType::flags, UndoStep::next, UndoStep::prev, UndoStep::type, and UNDOTYPE_FLAG_DECODE_ACTIVE_STEP.

Referenced by BKE_undosys_step_load_data_ex().

◆ UNUSED_FUNCTION()

static void UNUSED_FUNCTION ( BKE_undosys_foreach_ID_ref(UndoStack *ustack, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data) )
static

Definition at line 976 of file undo_system.cc.

References LISTBASE_FOREACH, UndoType::step_foreach_ID_ref, and UndoStack::steps.

Variable Documentation

◆ BKE_UNDOSYS_TYPE_IMAGE

◆ BKE_UNDOSYS_TYPE_MEMFILE

◆ BKE_UNDOSYS_TYPE_PAINTCURVE

const UndoType* BKE_UNDOSYS_TYPE_PAINTCURVE = nullptr

Definition at line 63 of file undo_system.cc.

Referenced by ED_paintcurve_undo_push_begin(), and ED_undosys_type_init().

◆ BKE_UNDOSYS_TYPE_PARTICLE

const UndoType* BKE_UNDOSYS_TYPE_PARTICLE = nullptr

Definition at line 64 of file undo_system.cc.

Referenced by ED_undosys_type_init().

◆ BKE_UNDOSYS_TYPE_SCULPT

◆ BKE_UNDOSYS_TYPE_TEXT

const UndoType* BKE_UNDOSYS_TYPE_TEXT = nullptr

◆ g_undo_callback_running

bool g_undo_callback_running = false
static

Definition at line 103 of file undo_system.cc.

◆ g_undo_types

ListBase g_undo_types = {nullptr, nullptr}
static

◆ LOG