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

BKE_idprop.h « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c14da538e7cb0f489f3b29a445617e4a6c25b63d (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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
/* SPDX-License-Identifier: GPL-2.0-or-later */

#pragma once

/** \file
 * \ingroup bke
 */

#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h"

#ifdef __cplusplus
extern "C" {
#endif

struct BlendDataReader;
struct BlendExpander;
struct BlendLibReader;
struct BlendWriter;
struct ID;
struct IDProperty;
struct IDPropertyUIData;
struct Library;

typedef union IDPropertyTemplate {
  int i;
  float f;
  double d;
  struct {
    const char *str;
    int len;
    char subtype;
  } string;
  struct ID *id;
  struct {
    int len;
    char type;
  } array;
  struct {
    int matvec_size;
    const float *example;
  } matrix_or_vector;
} IDPropertyTemplate;

/* ----------- Property Array Type ---------- */

/**
 * \note as a start to move away from the stupid #IDP_New function,
 * this type has its own allocation function.
 */
struct IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
struct IDProperty *IDP_CopyIDPArray(const struct IDProperty *array,
                                    int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();

/**
 * Shallow copies item.
 */
void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL();
struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT
    ATTR_NONNULL();
void IDP_AppendArray(struct IDProperty *prop, struct IDProperty *item);
void IDP_ResizeIDPArray(struct IDProperty *prop, int len);

/* ----------- Numeric Array Type ----------- */

/**
 * This function works for strings too!
 */
void IDP_ResizeArray(struct IDProperty *prop, int newlen);
void IDP_FreeArray(struct IDProperty *prop);

/* ---------- String Type ------------ */
/**
 * \param st: The string to assign.
 * \param name: The property name.
 * \param maxlen: The size of the new string (including the \0 terminator).
 * \return The new string property.
 */
struct IDProperty *IDP_NewString(const char *st,
                                 const char *name,
                                 int maxlen) ATTR_WARN_UNUSED_RESULT
    ATTR_NONNULL(2 /* 'name 'arg */); /* maxlen excludes '\0' */
void IDP_AssignString(struct IDProperty *prop, const char *st, int maxlen)
    ATTR_NONNULL(); /* maxlen excludes '\0' */
void IDP_ConcatStringC(struct IDProperty *prop, const char *st) ATTR_NONNULL();
void IDP_ConcatString(struct IDProperty *str1, struct IDProperty *append) ATTR_NONNULL();
void IDP_FreeString(struct IDProperty *prop) ATTR_NONNULL();

/*-------- ID Type -------*/

typedef void (*IDPWalkFunc)(void *userData, struct IDProperty *idp);

void IDP_AssignID(struct IDProperty *prop, struct ID *id, int flag);

/*-------- Group Functions -------*/

/**
 * Sync values from one group to another when values name and types match,
 * copy the values, else ignore.
 *
 * \note Use for syncing proxies.
 */
void IDP_SyncGroupValues(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL();
void IDP_SyncGroupTypes(struct IDProperty *dest, const struct IDProperty *src, bool do_arraylen)
    ATTR_NONNULL();
/**
 * Replaces all properties with the same name in a destination group from a source group.
 */
void IDP_ReplaceGroupInGroup(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL();
void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
/**
 * Checks if a property with the same name as prop exists, and if so replaces it.
 * Use this to preserve order!
 */
void IDP_ReplaceInGroup_ex(struct IDProperty *group,
                           struct IDProperty *prop,
                           struct IDProperty *prop_exist);
/**
 * If a property is missing in \a dest, add it.
 * Do it recursively.
 */
void IDP_MergeGroup(struct IDProperty *dest, const struct IDProperty *src, bool do_overwrite)
    ATTR_NONNULL();
/**
 * If a property is missing in \a dest, add it.
 * Do it recursively.
 */
void IDP_MergeGroup_ex(struct IDProperty *dest,
                       const struct IDProperty *src,
                       bool do_overwrite,
                       int flag) ATTR_NONNULL();
/**
 * This function has a sanity check to make sure ID properties with the same name don't
 * get added to the group.
 *
 * The sanity check just means the property is not added to the group if another property
 * exists with the same name; the client code using ID properties then needs to detect this
 * (the function that adds new properties to groups, #IDP_AddToGroup,
 * returns false if a property can't be added to the group, and true if it can)
 * and free the property.
 */
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
/**
 * This is the same as IDP_AddToGroup, only you pass an item
 * in the group list to be inserted after.
 */
bool IDP_InsertToGroup(struct IDProperty *group,
                       struct IDProperty *previous,
                       struct IDProperty *pnew) ATTR_NONNULL(1 /* group */, 3 /* pnew */);
/**
 * \note this does not free the property!
 *
 * To free the property, you have to do:
 * #IDP_FreeProperty(prop);
 */
void IDP_RemoveFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();
/**
 * Removes the property from the group and frees it.
 */
void IDP_FreeFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL();

struct IDProperty *IDP_GetPropertyFromGroup(const struct IDProperty *prop,
                                            const char *name) ATTR_WARN_UNUSED_RESULT
    ATTR_NONNULL();
/**
 * Same as above but ensure type match.
 */
struct IDProperty *IDP_GetPropertyTypeFromGroup(const struct IDProperty *prop,
                                                const char *name,
                                                char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();

/*-------- Main Functions --------*/
/**
 * Get the Group property that contains the id properties for ID `id`.
 *
 * \param create_if_needed: Set to create the group property and attach it to id if it doesn't
 * exist; otherwise the function will return NULL if there's no Group property attached to the ID.
 */
struct IDProperty *IDP_GetProperties(struct ID *id, bool create_if_needed) ATTR_WARN_UNUSED_RESULT
    ATTR_NONNULL();
struct IDProperty *IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT
    ATTR_NONNULL();
struct IDProperty *IDP_CopyProperty_ex(const struct IDProperty *prop,
                                       int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/**
 * Copy content from source #IDProperty into destination one,
 * freeing destination property's content first.
 */
void IDP_CopyPropertyContent(struct IDProperty *dst, struct IDProperty *src) ATTR_NONNULL();

/**
 * \param is_strict: When false treat missing items as a match.
 */
bool IDP_EqualsProperties_ex(struct IDProperty *prop1,
                             struct IDProperty *prop2,
                             bool is_strict) ATTR_WARN_UNUSED_RESULT;

bool IDP_EqualsProperties(struct IDProperty *prop1,
                          struct IDProperty *prop2) ATTR_WARN_UNUSED_RESULT;

/**
 * Allocate a new ID.
 *
 * This function takes three arguments: the ID property type, a union which defines
 * its initial value, and a name.
 *
 * The union is simple to use; see the top of BKE_idprop.h for its definition.
 * An example of using this function:
 *
 * \code{.c}
 * IDPropertyTemplate val;
 * IDProperty *group, *idgroup, *color;
 * group = IDP_New(IDP_GROUP, val, "group1"); // groups don't need a template.
 *
 * val.array.len = 4
 * val.array.type = IDP_FLOAT;
 * color = IDP_New(IDP_ARRAY, val, "color1");
 *
 * idgroup = IDP_GetProperties(some_id, 1);
 * IDP_AddToGroup(idgroup, color);
 * IDP_AddToGroup(idgroup, group);
 * \endcode
 *
 * Note that you MUST either attach the id property to an id property group with
 * IDP_AddToGroup or MEM_freeN the property, doing anything else might result in
 * a memory leak.
 */
struct IDProperty *IDP_New(char type,
                           const IDPropertyTemplate *val,
                           const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();

/**
 * \note This will free allocated data, all child properties of arrays and groups, and unlink IDs!
 * But it does not free the actual #IDProperty struct itself.
 */
void IDP_FreePropertyContent_ex(struct IDProperty *prop, bool do_id_user);
void IDP_FreePropertyContent(struct IDProperty *prop);
void IDP_FreeProperty_ex(struct IDProperty *prop, bool do_id_user);
void IDP_FreeProperty(struct IDProperty *prop);

void IDP_ClearProperty(struct IDProperty *prop);

void IDP_Reset(struct IDProperty *prop, const struct IDProperty *reference);

#define IDP_Int(prop) ((prop)->data.val)
#define IDP_Array(prop) ((prop)->data.pointer)
/* C11 const correctness for casts */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#  define IDP_Float(prop) \
    _Generic((prop), \
  struct IDProperty *:             (*(float *)&(prop)->data.val), \
  const struct IDProperty *: (*(const float *)&(prop)->data.val))
#  define IDP_Double(prop) \
    _Generic((prop), \
  struct IDProperty *:             (*(double *)&(prop)->data.val), \
  const struct IDProperty *: (*(const double *)&(prop)->data.val))
#  define IDP_String(prop) \
    _Generic((prop), \
  struct IDProperty *:             ((char *) (prop)->data.pointer), \
  const struct IDProperty *: ((const char *) (prop)->data.pointer))
#  define IDP_IDPArray(prop) \
    _Generic((prop), \
  struct IDProperty *:             ((struct IDProperty *) (prop)->data.pointer), \
  const struct IDProperty *: ((const struct IDProperty *) (prop)->data.pointer))
#  define IDP_Id(prop) \
    _Generic((prop), \
  struct IDProperty *:             ((ID *) (prop)->data.pointer), \
  const struct IDProperty *: ((const ID *) (prop)->data.pointer))
#else
#  define IDP_Float(prop) (*(float *)&(prop)->data.val)
#  define IDP_Double(prop) (*(double *)&(prop)->data.val)
#  define IDP_String(prop) ((char *)(prop)->data.pointer)
#  define IDP_IDPArray(prop) ((struct IDProperty *)(prop)->data.pointer)
#  define IDP_Id(prop) ((ID *)(prop)->data.pointer)
#endif

/**
 * Return an int from an #IDProperty with a compatible type. This should be avoided, but
 * it's sometimes necessary, for example when legacy files have incorrect property types.
 */
int IDP_coerce_to_int_or_zero(const struct IDProperty *prop);
/**
 * Return a float from an #IDProperty with a compatible type. This should be avoided, but
 * it's sometimes necessary, for example when legacy files have incorrect property types.
 */
float IDP_coerce_to_float_or_zero(const struct IDProperty *prop);
/**
 * Return a double from an #IDProperty with a compatible type. This should be avoided, but
 * it's sometimes necessary, for example when legacy files have incorrect property types.
 */
double IDP_coerce_to_double_or_zero(const struct IDProperty *prop);

/**
 * Call a callback for each #IDproperty in the hierarchy under given root one (included).
 */
typedef void (*IDPForeachPropertyCallback)(struct IDProperty *id_property, void *user_data);

/**
 * Loop through all ID properties in hierarchy of given \a id_property_root included.
 *
 * \note Container types (groups and arrays) are processed after applying the callback on them.
 *
 * \param type_filter: If not 0, only apply callback on properties of matching types, see
 * IDP_TYPE_FILTER_ enum in DNA_ID.h.
 */
void IDP_foreach_property(struct IDProperty *id_property_root,
                          int type_filter,
                          IDPForeachPropertyCallback callback,
                          void *user_data);

/* Format IDProperty as strings */
char *IDP_reprN(const struct IDProperty *prop, uint *r_len);
void IDP_repr_fn(const struct IDProperty *prop,
                 void (*str_append_fn)(void *user_data, const char *str, uint str_len),
                 void *user_data);
void IDP_print(const struct IDProperty *prop);

void IDP_BlendWrite(struct BlendWriter *writer, const struct IDProperty *prop);
void IDP_BlendReadData_impl(struct BlendDataReader *reader,
                            struct IDProperty **prop,
                            const char *caller_func_id);
#define IDP_BlendDataRead(reader, prop) IDP_BlendReadData_impl(reader, prop, __func__)
void IDP_BlendReadLib(struct BlendLibReader *reader, struct Library *lib, struct IDProperty *prop);
void IDP_BlendReadExpand(struct BlendExpander *expander, struct IDProperty *prop);

typedef enum eIDPropertyUIDataType {
  /** Other properties types that don't support RNA UI data. */
  IDP_UI_DATA_TYPE_UNSUPPORTED = -1,
  /** IDP_INT or IDP_ARRAY with subtype IDP_INT. */
  IDP_UI_DATA_TYPE_INT = 0,
  /** IDP_FLOAT and IDP_DOUBLE or IDP_ARRAY properties with a float or double subtypes. */
  IDP_UI_DATA_TYPE_FLOAT = 1,
  /** IDP_STRING properties. */
  IDP_UI_DATA_TYPE_STRING = 2,
  /** IDP_ID. */
  IDP_UI_DATA_TYPE_ID = 3,
} eIDPropertyUIDataType;

bool IDP_ui_data_supported(const struct IDProperty *prop);
eIDPropertyUIDataType IDP_ui_data_type(const struct IDProperty *prop);
void IDP_ui_data_free(struct IDProperty *prop);
/**
 * Free allocated pointers in the UI data that isn't shared with the UI data in the `other`
 * argument. Useful for returning early on failure when updating UI data in place, or when
 * replacing a subset of the UI data's allocated pointers.
 */
void IDP_ui_data_free_unique_contents(struct IDPropertyUIData *ui_data,
                                      eIDPropertyUIDataType type,
                                      const struct IDPropertyUIData *other);
struct IDPropertyUIData *IDP_ui_data_ensure(struct IDProperty *prop);
struct IDPropertyUIData *IDP_ui_data_copy(const struct IDProperty *prop);

#ifdef __cplusplus
}
#endif