Blender V4.3
editmesh_undo.cc File Reference
#include <variant>
#include "MEM_guardedalloc.h"
#include "CLG_log.h"
#include "DNA_key_types.h"
#include "DNA_layer_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_array_utils.h"
#include "BLI_implicit_sharing.hh"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_task.hh"
#include "BLI_vector.hh"
#include "BKE_context.hh"
#include "BKE_customdata.hh"
#include "BKE_editmesh.hh"
#include "BKE_key.hh"
#include "BKE_layer.hh"
#include "BKE_lib_id.hh"
#include "BKE_main.hh"
#include "BKE_mesh.hh"
#include "BKE_object.hh"
#include "BKE_undo_system.hh"
#include "DEG_depsgraph.hh"
#include "ED_mesh.hh"
#include "ED_object.hh"
#include "ED_undo.hh"
#include "ED_util.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "BLI_array_store.h"
#include "BLI_array_store_utils.h"
#include "BLI_task.h"

Go to the source code of this file.

Classes

struct  BArrayCustomData
 
struct  UndoMesh
 
struct  UMArrayData
 
struct  MeshUndoStep_Elem
 
struct  MeshUndoStep
 

Macros

#define USE_ARRAY_STORE
 
#define ARRAY_CHUNK_SIZE_IN_BYTES   65536
 
#define ARRAY_CHUNK_NUM_MIN   256
 
#define USE_ARRAY_STORE_THREAD
 

Functions

static void * undomesh_from_editmesh (UndoMesh *um, BMEditMesh *em, Key *key, UndoMesh *um_ref)
 
static void undomesh_to_editmesh (UndoMesh *um, Object *ob, BMEditMesh *em)
 
static void undomesh_free_data (UndoMesh *um)
 
static Objecteditmesh_object_from_context (bContext *C)
 
Undo Conversion
static size_t array_chunk_size_calc (const size_t stride)
 
Array Store Utilities
static UndoMesh ** mesh_undostep_reference_elems_from_objects (Object **object, int object_len)
 
Implements ED Undo System
Note
This is similar for all edit-mode types.
static bool mesh_undosys_poll (bContext *C)
 
static bool mesh_undosys_step_encode (bContext *C, Main *bmain, UndoStep *us_p)
 
static void mesh_undosys_step_decode (bContext *C, Main *bmain, UndoStep *us_p, const eUndoStepDir, bool)
 
static void mesh_undosys_step_free (UndoStep *us_p)
 
static void mesh_undosys_foreach_ID_ref (UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
 
void ED_mesh_undosys_type (UndoType *ut)
 

Variables

static CLG_LogRef LOG = {"ed.undo.mesh"}
 

Array Store

#define ARRAY_STORE_INDEX_NUM   (ARRAY_STORE_INDEX_MSEL + 1)
 
enum  {
  ARRAY_STORE_INDEX_VERT = 0 , ARRAY_STORE_INDEX_EDGE , ARRAY_STORE_INDEX_LOOP , ARRAY_STORE_INDEX_POLY ,
  ARRAY_STORE_INDEX_POLY_OFFSETS , ARRAY_STORE_INDEX_SHAPE , ARRAY_STORE_INDEX_MSEL
}
 
struct { 
 
   BArrayStore_AtSize   bs_stride [ARRAY_STORE_INDEX_NUM
 
   int   users 
 
   ListBase   local_links 
 
   TaskPool *   task_pool 
 
um_arraystore = {{{nullptr}}} 
 
static void um_arraystore_cd_compact (CustomData *cdata, const size_t data_len, const bool create, const int bs_index, const BArrayCustomData *bcd_reference, BArrayCustomData **r_bcd_first)
 
static void um_arraystore_cd_expand (const BArrayCustomData *bcd, CustomData *cdata, const size_t data_len)
 
static void um_arraystore_cd_free (BArrayCustomData *bcd, const int bs_index)
 
static void um_arraystore_compact_ex (UndoMesh *um, const UndoMesh *um_ref, bool create)
 
static void um_arraystore_compact (UndoMesh *um, const UndoMesh *um_ref)
 
static void um_arraystore_compact_with_info (UndoMesh *um, const UndoMesh *um_ref)
 
static void um_arraystore_compact_cb (TaskPool *__restrict, void *taskdata)
 
static void um_arraystore_expand_clear (UndoMesh *um)
 
static void um_arraystore_expand (UndoMesh *um)
 
static void um_arraystore_free (UndoMesh *um)
 

Macro Definition Documentation

◆ ARRAY_CHUNK_NUM_MIN

#define ARRAY_CHUNK_NUM_MIN   256

Definition at line 69 of file editmesh_undo.cc.

Referenced by array_chunk_size_calc().

◆ ARRAY_CHUNK_SIZE_IN_BYTES

#define ARRAY_CHUNK_SIZE_IN_BYTES   65536

This used to be much smaller (256), but this caused too much overhead when selection moved to boolean arrays. Especially with high-poly meshes where managing a large number of small chunks could be slow, blocking user interactivity. Use a larger value (in bytes) which calculates the chunk size using array_chunk_size_calc. See: #105046 & #105205.

Definition at line 68 of file editmesh_undo.cc.

Referenced by array_chunk_size_calc().

◆ ARRAY_STORE_INDEX_NUM

#define ARRAY_STORE_INDEX_NUM   (ARRAY_STORE_INDEX_MSEL + 1)

Definition at line 160 of file editmesh_undo.cc.

Referenced by um_arraystore_compact_with_info(), and um_arraystore_free().

◆ USE_ARRAY_STORE

#define USE_ARRAY_STORE

Definition at line 50 of file editmesh_undo.cc.

◆ USE_ARRAY_STORE_THREAD

#define USE_ARRAY_STORE_THREAD

Definition at line 71 of file editmesh_undo.cc.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Store separate BArrayStore_AtSize so multiple threads can access array stores without locking.

Enumerator
ARRAY_STORE_INDEX_VERT 
ARRAY_STORE_INDEX_EDGE 
ARRAY_STORE_INDEX_LOOP 
ARRAY_STORE_INDEX_POLY 
ARRAY_STORE_INDEX_POLY_OFFSETS 
ARRAY_STORE_INDEX_SHAPE 
ARRAY_STORE_INDEX_MSEL 

Definition at line 151 of file editmesh_undo.cc.

Function Documentation

◆ array_chunk_size_calc()

static size_t array_chunk_size_calc ( const size_t stride)
static

◆ ED_mesh_undosys_type()

◆ editmesh_object_from_context()

static Object * editmesh_object_from_context ( bContext * C)
static

◆ mesh_undostep_reference_elems_from_objects()

static UndoMesh ** mesh_undostep_reference_elems_from_objects ( Object ** object,
int object_len )
static

Create an array of UndoMesh from objects.

where each element in the resulting array is the most recently created undo-mesh for the object's mesh. When no undo-mesh can be found that array index is nullptr.

This is used for de-duplicating memory between undo steps, failure to find the undo step will store a full duplicate in memory. define DEBUG_PRINT to check memory is de-duplicating as expected.

Definition at line 701 of file editmesh_undo.cc.

References BLI_assert, BLI_ghash_free(), BLI_ghash_insert(), BLI_ghash_len(), BLI_ghash_popkey(), BLI_ghash_ptr_new_ex(), Mesh::id, UndoMesh::local_prev, MEM_callocN, MEM_freeN(), UndoMesh::mesh, POINTER_FROM_INT, ID::session_uid, and um_arraystore.

Referenced by mesh_undosys_step_encode().

◆ mesh_undosys_foreach_ID_ref()

static void mesh_undosys_foreach_ID_ref ( UndoStep * us_p,
UndoTypeForEachIDRefFn foreach_ID_ref_fn,
void * user_data )
static

◆ mesh_undosys_poll()

static bool mesh_undosys_poll ( bContext * C)
static

Definition at line 937 of file editmesh_undo.cc.

References editmesh_object_from_context().

Referenced by ED_mesh_undosys_type(), and mesh_undosys_step_decode().

◆ mesh_undosys_step_decode()

◆ mesh_undosys_step_encode()

◆ mesh_undosys_step_free()

static void mesh_undosys_step_free ( UndoStep * us_p)
static

◆ um_arraystore_cd_compact()

◆ um_arraystore_cd_expand()

static void um_arraystore_cd_expand ( const BArrayCustomData * bcd,
CustomData * cdata,
const size_t data_len )
static
Note
There is no room for data going out of sync here. The layers and the states are stored together so this can be kept working.

Definition at line 320 of file editmesh_undo.cc.

References BLI_array_store_state_data_get_alloc(), BLI_assert, CustomData_sizeof(), CustomData::layers, BArrayCustomData::next, blender::Array< T, InlineBufferCapacity, Allocator >::size(), state, BArrayCustomData::states, BArrayCustomData::type, and UNUSED_VARS_NDEBUG.

Referenced by um_arraystore_expand().

◆ um_arraystore_cd_free()

◆ um_arraystore_compact()

static void um_arraystore_compact ( UndoMesh * um,
const UndoMesh * um_ref )
static

Move data from allocated arrays to de-duplicated states and clear arrays.

Definition at line 505 of file editmesh_undo.cc.

References um_arraystore_compact_ex().

Referenced by um_arraystore_compact_with_info().

◆ um_arraystore_compact_cb()

static void um_arraystore_compact_cb ( TaskPool * __restrict,
void * taskdata )
static

◆ um_arraystore_compact_ex()

static void um_arraystore_compact_ex ( UndoMesh * um,
const UndoMesh * um_ref,
bool create )
static
Parameters
createWhen false, only free the arrays. This is done since when reading from an undo state, they must be temporarily expanded. then discarded afterwards, having this argument avoids having 2x code paths.

Definition at line 382 of file editmesh_undo.cc.

References UndoMesh::mesh, and blender::threading::parallel_invoke().

Referenced by um_arraystore_compact(), and um_arraystore_expand_clear().

◆ um_arraystore_compact_with_info()

static void um_arraystore_compact_with_info ( UndoMesh * um,
const UndoMesh * um_ref )
static

◆ um_arraystore_expand()

◆ um_arraystore_expand_clear()

static void um_arraystore_expand_clear ( UndoMesh * um)
static

Remove data we only expanded for temporary use.

Definition at line 580 of file editmesh_undo.cc.

References um_arraystore_compact_ex().

Referenced by undomesh_to_editmesh().

◆ um_arraystore_free()

◆ undomesh_free_data()

◆ undomesh_from_editmesh()

◆ undomesh_to_editmesh()

Variable Documentation

◆ bs_stride

Definition at line 163 of file editmesh_undo.cc.

◆ local_links

ListBase local_links

A list of UndoMesh items ordered from oldest to newest used to access previous undo data for a mesh.

Definition at line 170 of file editmesh_undo.cc.

◆ LOG

CLG_LogRef LOG = {"ed.undo.mesh"}
static

We only need this locally.

Definition at line 79 of file editmesh_undo.cc.

Referenced by mesh_undosys_step_decode().

◆ task_pool

◆ [struct]

◆ users

int users

Definition at line 164 of file editmesh_undo.cc.