Welcome to mirror list, hosted at ThFree Co, Russian Federation.

BKE_gpencil_update_cache.h « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: a4fd70eb8830b3b3abfbea080630e77a381135aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright 2022 Blender Foundation. */

#pragma once

/** \file
 * \ingroup bke
 */

#ifdef __cplusplus
extern "C" {
#endif

#include "BLI_sys_types.h" /* for bool */

struct DLRBT_Tree;
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
struct bGPDstroke;
struct GPencilUpdateCache;

/* 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