tornavis/source/blender/blenkernel/BKE_gpencil_update_cache_le...

139 lines
5.1 KiB
C

/* SPDX-FileCopyrightText: 2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "BLI_sys_types.h" /* for bool */
struct DLRBT_Tree;
struct GPencilUpdateCache;
struct bGPDframe;
struct bGPDlayer;
struct bGPDstroke;
struct bGPdata;
/** #GPencilUpdateCache.flag */
typedef enum eGPUpdateCacheNodeFlag {
/* Node is a placeholder (e.g. when only an index is needed). */
GP_UPDATE_NODE_NO_COPY = 0,
/* Copy only element, not the content. */
GP_UPDATE_NODE_LIGHT_COPY = 1,
/* Copy the element as well as all of its content. */
GP_UPDATE_NODE_FULL_COPY = 2,
} eGPUpdateCacheNodeFlag;
/**
* Cache for what needs to be updated after bGPdata was modified.
*
* Every node holds information about one element that was changed:
* - The index of where that element is in the linked-list.
* - The pointer to the original element in bGPdata.
*
* Additionally, nodes also hold other nodes that are one "level" below them.
* E.g. a node that represents a change on a bGPDframe could contain a set of
* nodes that represent a change on bGPDstrokes.
* These nodes are stored in a red-black tree so that they are sorted by their
* index to make sure they can be processed in the correct order.
*/
typedef struct GPencilUpdateCache {
/* Mapping from index to a GPencilUpdateCache struct. */
struct DLRBT_Tree *children;
/* eGPUpdateCacheNodeFlag */
int flag;
/* Index of the element in the linked-list. */
int index;
/* Pointer to one of bGPdata, bGPDLayer, bGPDFrame, bGPDStroke. */
void *data;
} GPencilUpdateCache;
/* Node structure in the DLRBT_Tree for GPencilUpdateCache mapping. */
typedef struct GPencilUpdateCacheNode {
/* DLRB tree capabilities. */
struct GPencilUpdateCacheNode *next, *prev;
struct GPencilUpdateCacheNode *left, *right;
struct GPencilUpdateCacheNode *parent;
char tree_col;
char _pad[7];
/* Content of DLRB tree node. */
GPencilUpdateCache *cache;
} GPencilUpdateCacheNode;
/**
* Callback that is called in BKE_gpencil_traverse_update_cache at each level. If the callback
* returns true, then the children will not be iterated over and instead continue.
* \param cache: The cache at this level.
* \param user_data: Pointer to the user_data passed to BKE_gpencil_traverse_update_cache.
* \returns true, if iterating over the children of \a cache should be skipped, false if not.
*/
typedef bool (*GPencilUpdateCacheIter_Cb)(GPencilUpdateCache *cache, void *user_data);
typedef struct GPencilUpdateCacheTraverseSettings {
/* Callbacks for the update cache traversal. Callback with index 0 is for layers, 1 for frames
* and 2 for strokes. */
GPencilUpdateCacheIter_Cb update_cache_cb[3];
} GPencilUpdateCacheTraverseSettings;
/**
* Allocates a new GPencilUpdateCache and populates it.
* \param data: A data pointer to populate the initial cache with.
* \param full_copy: If true, will mark this update cache as a full copy
* (GP_UPDATE_NODE_FULL_COPY). If false, it will be marked as a struct copy
* (GP_UPDATE_NODE_LIGHT_COPY).
*/
GPencilUpdateCache *BKE_gpencil_create_update_cache(void *data, bool full_copy);
/**
* Traverses an update cache and executes callbacks at each level.
* \param cache: The update cache to traverse.
* \param ts: The traversal settings. This stores the callbacks that are called at each level.
* \param user_data: Custom data passed to each callback.
*/
void BKE_gpencil_traverse_update_cache(GPencilUpdateCache *cache,
GPencilUpdateCacheTraverseSettings *ts,
void *user_data);
/**
* Tags an element (bGPdata, bGPDlayer, bGPDframe, or bGPDstroke) and all of its containing data to
* be updated in the next update-on-write operation.
*
* The function assumes that when a parameter is NULL all of the following parameters are NULL too.
* E.g. in order to tag a layer (gpl), the parameters would *have* to be (gpd, gpl, NULL, NULL).
*/
void BKE_gpencil_tag_full_update(struct bGPdata *gpd,
struct bGPDlayer *gpl,
struct bGPDframe *gpf,
struct bGPDstroke *gps);
/**
* Tags an element (bGPdata, bGPDlayer, bGPDframe, or bGPDstroke) to be updated in the next
* update-on-write operation. This function will not update any of the containing data, only the
* struct itself.
*
* The function assumes that when a parameter is NULL all of the following parameters are NULL too.
* E.g. in order to tag a layer (gpl), the parameters would *have* to be (gpd, gpl, NULL, NULL).
*/
void BKE_gpencil_tag_light_update(struct bGPdata *gpd,
struct bGPDlayer *gpl,
struct bGPDframe *gpf,
struct bGPDstroke *gps);
/**
* Frees the GPencilUpdateCache on the gpd->runtime. This will not free the data that the cache
* node might point to. It assumes that the cache does not own the data.
*/
void BKE_gpencil_free_update_cache(struct bGPdata *gpd);
#ifdef __cplusplus
}
#endif