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

BKE_lib_query.h « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 353ee3bbf5ab160f2f749123e3da81add3a3eeb6 (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * The Original Code is Copyright (C) 2014 by Blender Foundation.
 * All rights reserved.
 */
#ifndef __BKE_LIB_QUERY_H__
#define __BKE_LIB_QUERY_H__

/** \file
 * \ingroup bke
 *
 * API to perform operations over all ID pointers used by a given data-block.
 *
 * \note `BKE_lib_` files are for operations over data-blocks themselves, although they might
 * alter Main as well (when creating/renaming/deleting an ID e.g.).
 *
 * \section Function Names
 *
 * \warning Descriptions below is ideal goal, current status of naming does not yet fully follow it
 * (this is WIP).
 *
 * - `BKE_lib_query_` should be used for functions in that file.
 */

#ifdef __cplusplus
extern "C" {
#endif

struct ID;
struct IDProperty;
struct Main;

/* Tips for the callback for cases it's gonna to modify the pointer. */
enum {
  IDWALK_CB_NOP = 0,
  IDWALK_CB_NEVER_NULL = (1 << 0),
  IDWALK_CB_NEVER_SELF = (1 << 1),

  /**
   * Indicates whether this is direct (i.e. by local data) or indirect (i.e. by linked data) usage.
   * \note Object proxies are half-local, half-linked...
   */
  IDWALK_CB_INDIRECT_USAGE = (1 << 2),

  /**
   * That ID is used as mere sub-data by its owner (only case currently: those root nodetrees in
   * materials etc., and the Scene's master collections).
   * This means callback shall not *do* anything, only use this as informative data if it needs it.
   */
  IDWALK_CB_EMBEDDED = (1 << 3),

  /**
   * That ID is not really used by its owner, it's just an internal hint/helper.
   * This addresses Their Highest Ugliness the 'from' pointers: Object->from_proxy and Key->from.
   * How to handle that kind of cases totally depends on what caller code is doing... */
  IDWALK_CB_LOOPBACK = (1 << 4),

  /** That ID is used as library override's reference by its owner. */
  IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE = (1 << 5),

  /**
   * This ID usage is fully refcounted.
   * Callback is responsible to deal accordingly with #ID.us if needed.
   */
  IDWALK_CB_USER = (1 << 8),
  /**
   * This ID usage is not refcounted, but at least one user should be generated by it (to avoid
   * e.g. loosing the used ID on save/reload).
   * Callback is responsible to deal accordingly with #ID.us if needed.
   */
  IDWALK_CB_USER_ONE = (1 << 9),
};

enum {
  IDWALK_RET_NOP = 0,
  /** Completely stop iteration. */
  IDWALK_RET_STOP_ITER = 1 << 0,
  /** Stop recursion, that is, do not loop over ID used by current one. */
  IDWALK_RET_STOP_RECURSION = 1 << 1,
};

typedef struct LibraryIDLinkCallbackData {
  void *user_data;
  /**
   * 'Real' ID, the one that might be in bmain, only differs from self_id when the later is an
   * embedded one.
   */
  struct ID *id_owner;
  /**
   * ID from which the current ID pointer is being processed. It may be an embedded ID like master
   * collection or root node tree.
   */
  struct ID *id_self;
  struct ID **id_pointer;
  int cb_flag;
} LibraryIDLinkCallbackData;

/**
 * Call a callback for each ID link which the given ID uses.
 *
 * \return a set of flags to control further iteration (0 to keep going).
 */
typedef int (*LibraryIDLinkCallback)(LibraryIDLinkCallbackData *cb_data);

/* Flags for the foreach function itself. */
enum {
  IDWALK_NOP = 0,
  IDWALK_READONLY = (1 << 0),
  IDWALK_RECURSE = (1 << 1),    /* Also implies IDWALK_READONLY. */
  IDWALK_INCLUDE_UI = (1 << 2), /* Include UI pointers (from WM and screens editors). */
  /** Do not process ID pointers inside embedded IDs. Needed by depsgraph processing e.g. */
  IDWALK_IGNORE_EMBEDDED_ID = (1 << 3),

  IDWALK_NO_INDIRECT_PROXY_DATA_USAGE = (1 << 8), /* Ugly special case :(((( */
};

typedef struct LibraryForeachIDData LibraryForeachIDData;

bool BKE_lib_query_foreachid_process(struct LibraryForeachIDData *data,
                                     struct ID **id_pp,
                                     int cb_flag);

#define BKE_LIB_FOREACHID_PROCESS_ID(_data, _id, _cb_flag) \
  { \
    CHECK_TYPE_ANY((_id), ID *, void *); \
    if (!BKE_lib_query_foreachid_process((_data), (ID **)&(_id), (_cb_flag))) { \
      return; \
    } \
  } \
  ((void)0)

#define BKE_LIB_FOREACHID_PROCESS(_data, _id_super, _cb_flag) \
  { \
    CHECK_TYPE(&((_id_super)->id), ID *); \
    if (!BKE_lib_query_foreachid_process((_data), (ID **)&(_id_super), (_cb_flag))) { \
      return; \
    } \
  } \
  ((void)0)

bool BKE_library_foreach_ID_embedded(struct LibraryForeachIDData *data, struct ID **id_pp);
void BKE_lib_query_idpropertiesForeachIDLink_callback(struct IDProperty *id_prop, void *user_data);

/* Loop over all of the ID's this datablock links to. */
void BKE_library_foreach_ID_link(
    struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cb_flag);

int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);

bool BKE_library_id_can_use_idtype(struct ID *id_owner, const short id_type_used);

bool BKE_library_ID_is_locally_used(struct Main *bmain, void *idv);
bool BKE_library_ID_is_indirectly_used(struct Main *bmain, void *idv);
void BKE_library_ID_test_usages(struct Main *bmain,
                                void *idv,
                                bool *is_used_local,
                                bool *is_used_linked);

void BKE_library_unused_linked_data_set_tag(struct Main *bmain, const bool do_init_tag);
void BKE_library_indirectly_used_data_tag_clear(struct Main *bmain);

#ifdef __cplusplus
}
#endif

#endif /* __BKE_LIB_QUERY_H__ */