2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2006-11-29 23:31:46 +00:00
|
|
|
* 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
|
2008-01-07 19:13:47 +00:00
|
|
|
* of the License, or (at your option) any later version.
|
2006-11-29 23:31:46 +00:00
|
|
|
*
|
|
|
|
|
* 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2006-11-29 23:31:46 +00:00
|
|
|
*
|
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*/
|
2011-02-27 20:40:57 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2011-02-27 20:40:57 +00:00
|
|
|
*/
|
|
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <stddef.h>
|
2007-12-24 18:38:03 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2020-08-21 12:45:33 +02:00
|
|
|
#include "BLI_endian_switch.h"
|
2012-07-08 06:00:27 +00:00
|
|
|
#include "BLI_listbase.h"
|
2014-04-24 16:46:54 +02:00
|
|
|
#include "BLI_math.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_string.h"
|
|
|
|
|
#include "BLI_utildefines.h"
|
2012-07-08 06:00:27 +00:00
|
|
|
|
2020-08-21 12:45:33 +02:00
|
|
|
#include "BKE_global.h"
|
2006-11-17 04:46:48 +00:00
|
|
|
#include "BKE_idprop.h"
|
2020-02-10 12:58:59 +01:00
|
|
|
#include "BKE_lib_id.h"
|
2006-11-17 04:46:48 +00:00
|
|
|
|
2019-02-01 12:44:19 +11:00
|
|
|
#include "CLG_log.h"
|
|
|
|
|
|
2006-11-17 04:46:48 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2020-08-21 12:45:33 +02:00
|
|
|
#include "BLO_read_write.h"
|
|
|
|
|
|
2014-12-12 16:17:52 +01:00
|
|
|
#include "BLI_strict_flags.h"
|
|
|
|
|
|
2006-11-17 04:46:48 +00:00
|
|
|
/* IDPropertyTemplate is a union in DNA_ID.h */
|
2007-04-19 22:49:48 +00:00
|
|
|
|
2014-12-12 16:17:52 +01:00
|
|
|
/**
|
|
|
|
|
* if the new is 'IDP_ARRAY_REALLOC_LIMIT' items less,
|
|
|
|
|
* than #IDProperty.totallen, reallocate anyway.
|
|
|
|
|
*/
|
|
|
|
|
#define IDP_ARRAY_REALLOC_LIMIT 200
|
|
|
|
|
|
2019-02-01 12:44:19 +11:00
|
|
|
static CLG_LogRef LOG = {"bke.idprop"};
|
|
|
|
|
|
2007-04-19 22:49:48 +00:00
|
|
|
/*local size table.*/
|
2014-12-12 16:17:52 +01:00
|
|
|
static size_t idp_size_table[] = {
|
2007-04-19 22:49:48 +00:00
|
|
|
1, /*strings*/
|
2006-11-17 04:46:48 +00:00
|
|
|
sizeof(int),
|
|
|
|
|
sizeof(float),
|
2020-08-08 13:29:21 +10:00
|
|
|
sizeof(float[3]), /*Vector type, deprecated*/
|
|
|
|
|
sizeof(float[16]), /*Matrix type, deprecated*/
|
|
|
|
|
0, /*arrays don't have a fixed size*/
|
|
|
|
|
sizeof(ListBase), /*Group type*/
|
2012-05-06 17:22:54 +00:00
|
|
|
sizeof(void *),
|
2019-01-19 13:21:18 +11:00
|
|
|
sizeof(double),
|
2006-11-17 04:46:48 +00:00
|
|
|
};
|
|
|
|
|
|
2013-09-30 11:27:03 +00:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Array Functions (IDP Array API)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2014-08-01 21:59:42 +10:00
|
|
|
#define GETPROP(prop, i) &(IDP_IDPArray(prop)[i])
|
2006-11-17 04:46:48 +00:00
|
|
|
|
2008-12-31 13:16:37 +00:00
|
|
|
/* --------- property array type -------------*/
|
2006-11-17 04:46:48 +00:00
|
|
|
|
2013-03-24 01:51:54 +00:00
|
|
|
/**
|
|
|
|
|
* \note as a start to move away from the stupid IDP_New function, this type
|
|
|
|
|
* has its own allocation function.
|
|
|
|
|
*/
|
2008-12-31 13:16:37 +00:00
|
|
|
IDProperty *IDP_NewIDPArray(const char *name)
|
|
|
|
|
{
|
|
|
|
|
IDProperty *prop = MEM_callocN(sizeof(IDProperty), "IDProperty prop array");
|
|
|
|
|
prop->type = IDP_IDPARRAY;
|
|
|
|
|
prop->len = 0;
|
|
|
|
|
BLI_strncpy(prop->name, name, MAX_IDPROP_NAME);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2008-12-31 13:16:37 +00:00
|
|
|
return prop;
|
|
|
|
|
}
|
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag)
|
2008-12-31 13:16:37 +00:00
|
|
|
{
|
2012-03-18 07:38:51 +00:00
|
|
|
/* don't use MEM_dupallocN because this may be part of an array */
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(array->type == IDP_IDPARRAY);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
IDProperty *narray = MEM_mallocN(sizeof(IDProperty), __func__);
|
2012-05-06 17:22:54 +00:00
|
|
|
*narray = *array;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-31 13:16:37 +00:00
|
|
|
narray->data.pointer = MEM_dupallocN(array->data.pointer);
|
2020-09-09 16:35:20 +02:00
|
|
|
for (int i = 0; i < narray->len; i++) {
|
2012-03-03 20:19:11 +00:00
|
|
|
/* ok, the copy functions always allocate a new structure,
|
|
|
|
|
* which doesn't work here. instead, simply copy the
|
|
|
|
|
* contents of the new structure into the array cell,
|
|
|
|
|
* then free it. this makes for more maintainable
|
2020-02-13 14:01:52 +11:00
|
|
|
* code than simply re-implementing the copy functions
|
2012-03-03 20:19:11 +00:00
|
|
|
* in this loop.*/
|
2021-01-25 23:47:56 -06:00
|
|
|
IDProperty *tmp = IDP_CopyProperty_ex(GETPROP(narray, i), flag);
|
2008-12-31 13:16:37 +00:00
|
|
|
memcpy(GETPROP(narray, i), tmp, sizeof(IDProperty));
|
|
|
|
|
MEM_freeN(tmp);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2008-12-31 13:16:37 +00:00
|
|
|
return narray;
|
|
|
|
|
}
|
|
|
|
|
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
static void IDP_FreeIDPArray(IDProperty *prop, const bool do_id_user)
|
2008-12-31 13:16:37 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_IDPARRAY);
|
|
|
|
|
|
2020-09-09 16:35:20 +02:00
|
|
|
for (int i = 0; i < prop->len; i++) {
|
2019-05-16 14:17:11 +02:00
|
|
|
IDP_FreePropertyContent_ex(GETPROP(prop, i), do_id_user);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-12-31 13:16:37 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (prop->data.pointer) {
|
2008-12-31 13:16:37 +00:00
|
|
|
MEM_freeN(prop->data.pointer);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-12-31 13:16:37 +00:00
|
|
|
}
|
|
|
|
|
|
2017-03-30 22:52:12 +02:00
|
|
|
/* shallow copies item */
|
2008-12-31 13:16:37 +00:00
|
|
|
void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
|
|
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_IDPARRAY);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (index >= prop->len || index < 0) {
|
2017-03-30 22:52:12 +02:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2017-03-30 22:52:12 +02:00
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
IDProperty *old = GETPROP(prop, index);
|
2017-03-30 22:52:12 +02:00
|
|
|
if (item != old) {
|
2019-05-16 14:11:11 +02:00
|
|
|
IDP_FreePropertyContent(old);
|
2017-03-30 22:52:12 +02:00
|
|
|
|
|
|
|
|
memcpy(old, item, sizeof(IDProperty));
|
|
|
|
|
}
|
2008-12-31 13:16:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IDProperty *IDP_GetIndexArray(IDProperty *prop, int index)
|
|
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_IDPARRAY);
|
|
|
|
|
|
2008-12-31 13:16:37 +00:00
|
|
|
return GETPROP(prop, index);
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-08 06:00:27 +00:00
|
|
|
void IDP_AppendArray(IDProperty *prop, IDProperty *item)
|
2008-12-31 13:16:37 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_IDPARRAY);
|
|
|
|
|
|
2012-05-06 17:22:54 +00:00
|
|
|
IDP_ResizeIDPArray(prop, prop->len + 1);
|
|
|
|
|
IDP_SetIndexArray(prop, prop->len - 1, item);
|
2008-12-31 13:16:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
|
|
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_IDPARRAY);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-05 04:26:08 +00:00
|
|
|
/* first check if the array buffer size has room */
|
2013-05-15 14:36:58 +00:00
|
|
|
if (newlen <= prop->totallen) {
|
2014-12-12 16:17:52 +01:00
|
|
|
if (newlen < prop->len && prop->totallen - newlen < IDP_ARRAY_REALLOC_LIMIT) {
|
2020-09-09 16:35:20 +02:00
|
|
|
for (int i = newlen; i < prop->len; i++) {
|
2019-05-16 14:11:11 +02:00
|
|
|
IDP_FreePropertyContent(GETPROP(prop, i));
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-15 14:36:58 +00:00
|
|
|
prop->len = newlen;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (newlen >= prop->len) {
|
2013-05-15 14:36:58 +00:00
|
|
|
prop->len = newlen;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-12-31 13:16:37 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-05 04:26:08 +00:00
|
|
|
/* free trailing items */
|
|
|
|
|
if (newlen < prop->len) {
|
|
|
|
|
/* newlen is smaller */
|
2020-09-09 16:35:20 +02:00
|
|
|
for (int i = newlen; i < prop->len; i++) {
|
2019-05-16 14:11:11 +02:00
|
|
|
IDP_FreePropertyContent(GETPROP(prop, i));
|
2013-09-05 04:26:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-25 16:04:03 +00:00
|
|
|
/* - Note: This code comes from python, here's the corresponding comment. - */
|
2008-12-31 13:16:37 +00:00
|
|
|
/* This over-allocates proportional to the list size, making room
|
|
|
|
|
* for additional growth. The over-allocation is mild, but is
|
|
|
|
|
* enough to give linear-time amortized behavior over a long
|
|
|
|
|
* sequence of appends() in the presence of a poorly-performing
|
|
|
|
|
* system realloc().
|
|
|
|
|
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
|
|
|
|
|
*/
|
2021-01-25 23:47:56 -06:00
|
|
|
int newsize = newlen;
|
2008-12-31 13:16:37 +00:00
|
|
|
newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
|
2014-12-12 16:17:52 +01:00
|
|
|
prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * (size_t)newsize);
|
2008-12-31 13:16:37 +00:00
|
|
|
prop->len = newlen;
|
|
|
|
|
prop->totallen = newsize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ----------- Numerical Array Type ----------- */
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr)
|
|
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (prop->subtype != IDP_GROUP) {
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
return;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (newlen >= prop->len) {
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
/* bigger */
|
2012-05-06 17:22:54 +00:00
|
|
|
IDProperty **array = newarr;
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
IDPropertyTemplate val;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
for (int a = prop->len; a < newlen; a++) {
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
val.i = 0; /* silence MSVC warning about uninitialized var when debugging */
|
2012-05-06 17:22:54 +00:00
|
|
|
array[a] = IDP_New(IDP_GROUP, &val, "IDP_ResizeArray group");
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* smaller */
|
2012-05-06 17:22:54 +00:00
|
|
|
IDProperty **array = prop->data.pointer;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
for (int a = newlen; a < prop->len; a++) {
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
IDP_FreeProperty(array[a]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-17 04:46:48 +00:00
|
|
|
/*this function works for strings too!*/
|
|
|
|
|
void IDP_ResizeArray(IDProperty *prop, int newlen)
|
|
|
|
|
{
|
2013-09-05 04:26:08 +00:00
|
|
|
const bool is_grow = newlen >= prop->len;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-05 04:26:08 +00:00
|
|
|
/* first check if the array buffer size has room */
|
2014-12-12 16:17:52 +01:00
|
|
|
if (newlen <= prop->totallen && prop->totallen - newlen < IDP_ARRAY_REALLOC_LIMIT) {
|
2009-01-23 20:36:47 +00:00
|
|
|
idp_resize_group_array(prop, newlen, prop->data.pointer);
|
2006-11-17 04:46:48 +00:00
|
|
|
prop->len = newlen;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-02-25 16:04:03 +00:00
|
|
|
/* - Note: This code comes from python, here's the corresponding comment. - */
|
2006-11-17 04:46:48 +00:00
|
|
|
/* This over-allocates proportional to the list size, making room
|
|
|
|
|
* for additional growth. The over-allocation is mild, but is
|
|
|
|
|
* enough to give linear-time amortized behavior over a long
|
|
|
|
|
* sequence of appends() in the presence of a poorly-performing
|
|
|
|
|
* system realloc().
|
|
|
|
|
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
|
|
|
|
|
*/
|
2021-01-25 23:47:56 -06:00
|
|
|
int newsize = newlen;
|
2014-08-15 19:59:31 +10:00
|
|
|
newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (is_grow == false) {
|
2013-09-05 04:26:08 +00:00
|
|
|
idp_resize_group_array(prop, newlen, prop->data.pointer);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-12-12 16:17:52 +01:00
|
|
|
prop->data.pointer = MEM_recallocN(prop->data.pointer,
|
|
|
|
|
idp_size_table[(int)prop->subtype] * (size_t)newsize);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (is_grow == true) {
|
2013-09-05 04:26:08 +00:00
|
|
|
idp_resize_group_array(prop, newlen, prop->data.pointer);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-11-17 04:46:48 +00:00
|
|
|
prop->len = newlen;
|
|
|
|
|
prop->totallen = newsize;
|
|
|
|
|
}
|
|
|
|
|
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
void IDP_FreeArray(IDProperty *prop)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
if (prop->data.pointer) {
|
|
|
|
|
idp_resize_group_array(prop, 0, NULL);
|
2006-11-17 04:46:48 +00:00
|
|
|
MEM_freeN(prop->data.pointer);
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
}
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
static IDProperty *idp_generic_copy(const IDProperty *prop, const int UNUSED(flag))
|
2012-05-06 17:22:54 +00:00
|
|
|
{
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
IDProperty *newp = MEM_callocN(sizeof(IDProperty), __func__);
|
2007-07-09 20:42:14 +00:00
|
|
|
|
2008-12-31 13:16:37 +00:00
|
|
|
BLI_strncpy(newp->name, prop->name, MAX_IDPROP_NAME);
|
2007-07-09 20:42:14 +00:00
|
|
|
newp->type = prop->type;
|
|
|
|
|
newp->flag = prop->flag;
|
|
|
|
|
newp->data.val = prop->data.val;
|
2008-10-05 01:15:58 +00:00
|
|
|
newp->data.val2 = prop->data.val2;
|
2007-07-09 20:42:14 +00:00
|
|
|
|
|
|
|
|
return newp;
|
2012-05-06 17:22:54 +00:00
|
|
|
}
|
2007-07-09 20:42:14 +00:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
static IDProperty *IDP_CopyArray(const IDProperty *prop, const int flag)
|
2007-07-09 20:42:14 +00:00
|
|
|
{
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
IDProperty *newp = idp_generic_copy(prop, flag);
|
2007-07-09 20:42:14 +00:00
|
|
|
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
if (prop->data.pointer) {
|
|
|
|
|
newp->data.pointer = MEM_dupallocN(prop->data.pointer);
|
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (prop->type == IDP_GROUP) {
|
2012-05-06 17:22:54 +00:00
|
|
|
IDProperty **array = newp->data.pointer;
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
int a;
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
for (a = 0; a < prop->len; a++) {
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
array[a] = IDP_CopyProperty_ex(array[a], flag);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
RNA:
* Added support for using pointers + collections as operator properties,
but with the restriction that they must point to other type derived from
ID property groups. The "add" function for these properties will allocate
a new ID property group and point to that.
* Added support for arrays with type IDP_GROUP in ID properties.
* Fix bug getting/setting float array values.
Example code for collections, note the "OperatorMousePath" type is defined
in rna_wm.c and has a float[2] property named "loc".
Defining the operator property:
prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
Adding values:
PointerRNA itemptr;
float loc[2] = {1, 1},
RNA_collection_add(op->ptr, "path", &itemptr);
RNA_float_set_array(&itemptr, "loc", loc);
Iterating:
RNA_BEGIN(op->ptr, itemptr, "path") {
float loc[2];
RNA_float_get_array(&itemptr, "loc", loc);
printf("Location: %f %f\n", loc[0], loc[1]);
}
RNA_END;
2008-12-26 20:38:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
2007-07-09 20:42:14 +00:00
|
|
|
newp->len = prop->len;
|
|
|
|
|
newp->subtype = prop->subtype;
|
|
|
|
|
newp->totallen = prop->totallen;
|
|
|
|
|
|
|
|
|
|
return newp;
|
|
|
|
|
}
|
2013-09-30 11:27:03 +00:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name String Functions (IDProperty String API)
|
|
|
|
|
* \{ */
|
2013-09-05 04:26:08 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
2018-12-12 12:50:58 +11:00
|
|
|
* \param st: The string to assign.
|
|
|
|
|
* \param name: The property name.
|
|
|
|
|
* \param maxlen: The size of the new string (including the \0 terminator).
|
2014-11-15 21:28:29 +01:00
|
|
|
* \return The new string property.
|
2013-09-05 04:26:08 +00:00
|
|
|
*/
|
2010-06-12 17:30:21 +00:00
|
|
|
IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
|
|
|
|
|
{
|
|
|
|
|
IDProperty *prop = MEM_callocN(sizeof(IDProperty), "IDProperty string");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-06-12 17:30:21 +00:00
|
|
|
if (st == NULL) {
|
2013-09-05 04:26:08 +00:00
|
|
|
prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
|
|
|
|
|
*IDP_String(prop) = '\0';
|
2010-06-12 17:30:21 +00:00
|
|
|
prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS;
|
2013-09-05 04:26:08 +00:00
|
|
|
prop->len = 1; /* NULL string, has len of 1 to account for null byte. */
|
2010-06-12 17:30:21 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2014-02-15 12:31:58 +11:00
|
|
|
/* include null terminator '\0' */
|
2014-12-12 16:17:52 +01:00
|
|
|
int stlen = (int)strlen(st) + 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (maxlen > 0 && maxlen < stlen) {
|
2010-06-12 17:30:21 +00:00
|
|
|
stlen = maxlen;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-12-12 16:17:52 +01:00
|
|
|
prop->data.pointer = MEM_mallocN((size_t)stlen, "id property string 2");
|
2010-06-12 17:30:21 +00:00
|
|
|
prop->len = prop->totallen = stlen;
|
2014-12-12 16:17:52 +01:00
|
|
|
BLI_strncpy(prop->data.pointer, st, (size_t)stlen);
|
2010-06-12 17:30:21 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-06-12 17:30:21 +00:00
|
|
|
prop->type = IDP_STRING;
|
|
|
|
|
BLI_strncpy(prop->name, name, MAX_IDPROP_NAME);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-06-12 17:30:21 +00:00
|
|
|
return prop;
|
|
|
|
|
}
|
|
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
static IDProperty *IDP_CopyString(const IDProperty *prop, const int flag)
|
2007-07-09 20:42:14 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_STRING);
|
2021-01-25 23:47:56 -06:00
|
|
|
IDProperty *newp = idp_generic_copy(prop, flag);
|
2007-07-09 20:42:14 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (prop->data.pointer) {
|
2013-09-30 11:27:03 +00:00
|
|
|
newp->data.pointer = MEM_dupallocN(prop->data.pointer);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2007-07-09 20:42:14 +00:00
|
|
|
newp->len = prop->len;
|
|
|
|
|
newp->subtype = prop->subtype;
|
|
|
|
|
newp->totallen = prop->totallen;
|
|
|
|
|
|
|
|
|
|
return newp;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-19 02:14:18 +00:00
|
|
|
void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_STRING);
|
2021-01-25 23:47:56 -06:00
|
|
|
int stlen = (int)strlen(st);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (maxlen > 0 && maxlen < stlen) {
|
2012-05-06 17:22:54 +00:00
|
|
|
stlen = maxlen;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-11-15 09:12:10 +00:00
|
|
|
if (prop->subtype == IDP_STRING_SUB_BYTE) {
|
|
|
|
|
IDP_ResizeArray(prop, stlen);
|
2014-12-12 16:17:52 +01:00
|
|
|
memcpy(prop->data.pointer, st, (size_t)stlen);
|
2011-11-15 09:12:10 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2013-09-05 04:26:08 +00:00
|
|
|
stlen++;
|
2011-11-15 09:12:10 +00:00
|
|
|
IDP_ResizeArray(prop, stlen);
|
2014-12-12 16:17:52 +01:00
|
|
|
BLI_strncpy(prop->data.pointer, st, (size_t)stlen);
|
2011-11-15 09:12:10 +00:00
|
|
|
}
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
|
|
|
|
|
2010-11-19 02:14:18 +00:00
|
|
|
void IDP_ConcatStringC(IDProperty *prop, const char *st)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_STRING);
|
|
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
int newlen = prop->len + (int)strlen(st);
|
2012-03-03 20:19:11 +00:00
|
|
|
/* we have to remember that prop->len includes the null byte for strings.
|
|
|
|
|
* so there's no need to add +1 to the resize function.*/
|
2006-11-17 04:46:48 +00:00
|
|
|
IDP_ResizeArray(prop, newlen);
|
|
|
|
|
strcat(prop->data.pointer, st);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IDP_ConcatString(IDProperty *str1, IDProperty *append)
|
|
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(append->type == IDP_STRING);
|
|
|
|
|
|
2012-03-03 20:19:11 +00:00
|
|
|
/* since ->len for strings includes the NULL byte, we have to subtract one or
|
2012-03-04 04:35:12 +00:00
|
|
|
* we'll get an extra null byte after each concatenation operation.*/
|
2021-01-25 23:47:56 -06:00
|
|
|
int newlen = str1->len + append->len - 1;
|
2006-11-17 04:46:48 +00:00
|
|
|
IDP_ResizeArray(str1, newlen);
|
|
|
|
|
strcat(str1->data.pointer, append->data.pointer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IDP_FreeString(IDProperty *prop)
|
|
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_STRING);
|
|
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (prop->data.pointer) {
|
2008-12-31 13:16:37 +00:00
|
|
|
MEM_freeN(prop->data.pointer);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
2013-09-30 11:27:03 +00:00
|
|
|
/** \} */
|
2006-11-17 04:46:48 +00:00
|
|
|
|
2013-09-30 11:27:03 +00:00
|
|
|
/* -------------------------------------------------------------------- */
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
/** \name ID Type (IDProperty ID API)
|
2013-09-30 11:27:03 +00:00
|
|
|
* \{ */
|
2006-11-17 04:46:48 +00:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
static IDProperty *IDP_CopyID(const IDProperty *prop, const int flag)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
BLI_assert(prop->type == IDP_ID);
|
2021-01-25 23:47:56 -06:00
|
|
|
IDProperty *newp = idp_generic_copy(prop, flag);
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
|
|
|
|
|
newp->data.pointer = prop->data.pointer;
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
|
|
|
|
|
id_us_plus(IDP_Id(newp));
|
|
|
|
|
}
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
|
|
|
|
|
return newp;
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
|
2020-01-24 11:26:02 +01:00
|
|
|
void IDP_AssignID(IDProperty *prop, ID *id, const int flag)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(prop->type == IDP_ID);
|
|
|
|
|
|
|
|
|
|
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0 && IDP_Id(prop) != NULL) {
|
|
|
|
|
id_us_min(IDP_Id(prop));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prop->data.pointer = id;
|
|
|
|
|
|
|
|
|
|
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
|
|
|
|
|
id_us_plus(IDP_Id(prop));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-30 11:27:03 +00:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Group Functions (IDProperty Group API)
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks if a property with the same name as prop exists, and if so replaces it.
|
|
|
|
|
*/
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
static IDProperty *IDP_CopyGroup(const IDProperty *prop, const int flag)
|
2007-07-09 20:42:14 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_GROUP);
|
2021-01-25 23:47:56 -06:00
|
|
|
IDProperty *newp = idp_generic_copy(prop, flag);
|
2013-09-30 11:27:03 +00:00
|
|
|
newp->len = prop->len;
|
2017-03-30 17:01:23 +02:00
|
|
|
newp->subtype = prop->subtype;
|
2013-09-30 11:27:03 +00:00
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
LISTBASE_FOREACH (IDProperty *, link, &prop->data.group) {
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
BLI_addtail(&newp->data.group, IDP_CopyProperty_ex(link, flag));
|
2007-07-09 20:42:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return newp;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-15 18:43:54 +00:00
|
|
|
/* use for syncing proxies.
|
|
|
|
|
* When values name and types match, copy the values, else ignore */
|
2013-12-12 21:57:37 +11:00
|
|
|
void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src)
|
2010-02-15 18:43:54 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(dest->type == IDP_GROUP);
|
|
|
|
|
BLI_assert(src->type == IDP_GROUP);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) {
|
|
|
|
|
IDProperty *other = BLI_findstring(&dest->data.group, prop->name, offsetof(IDProperty, name));
|
2012-05-06 17:22:54 +00:00
|
|
|
if (other && prop->type == other->type) {
|
2011-05-01 06:34:40 +00:00
|
|
|
switch (prop->type) {
|
|
|
|
|
case IDP_INT:
|
|
|
|
|
case IDP_FLOAT:
|
|
|
|
|
case IDP_DOUBLE:
|
2012-05-06 17:22:54 +00:00
|
|
|
other->data = prop->data;
|
2011-05-01 06:34:40 +00:00
|
|
|
break;
|
|
|
|
|
case IDP_GROUP:
|
|
|
|
|
IDP_SyncGroupValues(other, prop);
|
|
|
|
|
break;
|
|
|
|
|
default: {
|
2017-04-09 16:07:09 +10:00
|
|
|
BLI_insertlinkreplace(&dest->data.group, other, IDP_CopyProperty(prop));
|
|
|
|
|
IDP_FreeProperty(other);
|
2013-07-21 08:16:37 +00:00
|
|
|
break;
|
2010-02-15 18:43:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-04 20:59:13 +02:00
|
|
|
void IDP_SyncGroupTypes(IDProperty *dest, const IDProperty *src, const bool do_arraylen)
|
2013-12-13 00:28:35 +11:00
|
|
|
{
|
2021-05-05 18:42:41 +02:00
|
|
|
LISTBASE_FOREACH_MUTABLE (IDProperty *, prop_dst, &dest->data.group) {
|
2021-01-25 23:47:56 -06:00
|
|
|
const IDProperty *prop_src = IDP_GetPropertyFromGroup((IDProperty *)src, prop_dst->name);
|
|
|
|
|
if (prop_src != NULL) {
|
2013-12-13 00:28:35 +11:00
|
|
|
/* check of we should replace? */
|
|
|
|
|
if ((prop_dst->type != prop_src->type || prop_dst->subtype != prop_src->subtype) ||
|
|
|
|
|
(do_arraylen && ELEM(prop_dst->type, IDP_ARRAY, IDP_IDPARRAY) &&
|
|
|
|
|
(prop_src->len != prop_dst->len))) {
|
2020-09-04 20:59:13 +02:00
|
|
|
BLI_insertlinkreplace(&dest->data.group, prop_dst, IDP_CopyProperty(prop_src));
|
2017-04-09 16:07:09 +10:00
|
|
|
IDP_FreeProperty(prop_dst);
|
2013-12-13 00:28:35 +11:00
|
|
|
}
|
|
|
|
|
else if (prop_dst->type == IDP_GROUP) {
|
|
|
|
|
IDP_SyncGroupTypes(prop_dst, prop_src, do_arraylen);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-09-04 20:59:13 +02:00
|
|
|
IDP_FreeFromGroup(dest, prop_dst);
|
2013-12-13 00:28:35 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-24 01:51:54 +00:00
|
|
|
/**
|
|
|
|
|
* Replaces all properties with the same name in a destination group from a source group.
|
2012-03-03 20:19:11 +00:00
|
|
|
*/
|
2013-12-12 21:57:37 +11:00
|
|
|
void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src)
|
2010-01-05 03:29:41 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(dest->type == IDP_GROUP);
|
|
|
|
|
BLI_assert(src->type == IDP_GROUP);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) {
|
|
|
|
|
IDProperty *loop;
|
2012-05-06 17:22:54 +00:00
|
|
|
for (loop = dest->data.group.first; loop; loop = loop->next) {
|
2013-03-10 06:18:03 +00:00
|
|
|
if (STREQ(loop->name, prop->name)) {
|
2017-04-09 16:07:09 +10:00
|
|
|
BLI_insertlinkreplace(&dest->data.group, loop, IDP_CopyProperty(prop));
|
2010-01-05 03:29:41 +00:00
|
|
|
IDP_FreeProperty(loop);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-01-21 21:01:18 +00:00
|
|
|
/* only add at end if not added yet */
|
|
|
|
|
if (loop == NULL) {
|
|
|
|
|
IDProperty *copy = IDP_CopyProperty(prop);
|
|
|
|
|
dest->len++;
|
|
|
|
|
BLI_addtail(&dest->data.group, copy);
|
|
|
|
|
}
|
2010-01-05 03:29:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
2013-03-24 01:51:54 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks if a property with the same name as prop exists, and if so replaces it.
|
|
|
|
|
* Use this to preserve order!
|
2012-03-03 20:19:11 +00:00
|
|
|
*/
|
2014-11-10 17:10:58 +01:00
|
|
|
void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop_exist)
|
2007-05-22 04:41:21 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(group->type == IDP_GROUP);
|
2014-11-10 17:10:58 +01:00
|
|
|
BLI_assert(prop_exist == IDP_GetPropertyFromGroup(group, prop->name));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-05 09:31:17 +02:00
|
|
|
if (prop_exist != NULL) {
|
2017-04-09 16:07:09 +10:00
|
|
|
BLI_insertlinkreplace(&group->data.group, prop_exist, prop);
|
2014-11-10 17:10:58 +01:00
|
|
|
IDP_FreeProperty(prop_exist);
|
2010-08-13 06:30:04 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
group->len++;
|
|
|
|
|
BLI_addtail(&group->data.group, prop);
|
2007-05-22 04:41:21 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-10 17:10:58 +01:00
|
|
|
void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop)
|
|
|
|
|
{
|
|
|
|
|
IDProperty *prop_exist = IDP_GetPropertyFromGroup(group, prop->name);
|
|
|
|
|
|
|
|
|
|
IDP_ReplaceInGroup_ex(group, prop, prop_exist);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-30 11:27:03 +00:00
|
|
|
/**
|
2012-10-31 19:07:25 +00:00
|
|
|
* If a property is missing in \a dest, add it.
|
2017-05-03 11:37:24 +02:00
|
|
|
* Do it recursively.
|
2012-10-31 19:07:25 +00:00
|
|
|
*/
|
2017-08-15 16:42:20 +02:00
|
|
|
void IDP_MergeGroup_ex(IDProperty *dest,
|
|
|
|
|
const IDProperty *src,
|
|
|
|
|
const bool do_overwrite,
|
|
|
|
|
const int flag)
|
2012-10-31 19:07:25 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(dest->type == IDP_GROUP);
|
|
|
|
|
BLI_assert(src->type == IDP_GROUP);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-31 19:07:25 +00:00
|
|
|
if (do_overwrite) {
|
2021-01-25 23:47:56 -06:00
|
|
|
LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) {
|
2017-05-03 11:37:24 +02:00
|
|
|
if (prop->type == IDP_GROUP) {
|
|
|
|
|
IDProperty *prop_exist = IDP_GetPropertyFromGroup(dest, prop->name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-05-03 11:37:24 +02:00
|
|
|
if (prop_exist != NULL) {
|
2017-08-15 16:42:20 +02:00
|
|
|
IDP_MergeGroup_ex(prop_exist, prop, do_overwrite, flag);
|
2017-05-03 11:37:24 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-08-15 16:42:20 +02:00
|
|
|
IDProperty *copy = IDP_CopyProperty_ex(prop, flag);
|
2012-10-31 19:07:25 +00:00
|
|
|
IDP_ReplaceInGroup(dest, copy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-01-25 23:47:56 -06:00
|
|
|
LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) {
|
2017-05-03 11:37:24 +02:00
|
|
|
IDProperty *prop_exist = IDP_GetPropertyFromGroup(dest, prop->name);
|
|
|
|
|
if (prop_exist != NULL) {
|
|
|
|
|
if (prop->type == IDP_GROUP) {
|
2017-08-15 16:42:20 +02:00
|
|
|
IDP_MergeGroup_ex(prop_exist, prop, do_overwrite, flag);
|
2017-05-03 11:37:24 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2017-08-15 16:42:20 +02:00
|
|
|
IDProperty *copy = IDP_CopyProperty_ex(prop, flag);
|
2012-10-31 19:07:25 +00:00
|
|
|
dest->len++;
|
|
|
|
|
BLI_addtail(&dest->data.group, copy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-15 16:42:20 +02:00
|
|
|
/**
|
|
|
|
|
* If a property is missing in \a dest, add it.
|
|
|
|
|
* Do it recursively.
|
|
|
|
|
*/
|
|
|
|
|
void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite)
|
|
|
|
|
{
|
|
|
|
|
IDP_MergeGroup_ex(dest, src, do_overwrite, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-24 01:51:54 +00:00
|
|
|
/**
|
|
|
|
|
* 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
|
2019-04-27 12:07:07 +10:00
|
|
|
* (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.
|
2013-03-24 01:51:54 +00:00
|
|
|
*/
|
2013-12-12 21:57:37 +11:00
|
|
|
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(group->type == IDP_GROUP);
|
|
|
|
|
|
2012-02-27 10:35:39 +00:00
|
|
|
if (IDP_GetPropertyFromGroup(group, prop->name) == NULL) {
|
2010-08-13 06:30:04 +00:00
|
|
|
group->len++;
|
|
|
|
|
BLI_addtail(&group->data.group, prop);
|
2014-11-15 21:28:29 +01:00
|
|
|
return true;
|
2006-11-17 08:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
2014-11-15 21:28:29 +01:00
|
|
|
return false;
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-24 01:51:54 +00:00
|
|
|
/**
|
|
|
|
|
* This is the same as IDP_AddToGroup, only you pass an item
|
|
|
|
|
* in the group list to be inserted after.
|
|
|
|
|
*/
|
2013-12-12 21:57:37 +11:00
|
|
|
bool IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew)
|
2006-12-16 23:54:45 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(group->type == IDP_GROUP);
|
|
|
|
|
|
2012-02-27 10:35:39 +00:00
|
|
|
if (IDP_GetPropertyFromGroup(group, pnew->name) == NULL) {
|
2010-08-13 06:30:04 +00:00
|
|
|
group->len++;
|
2013-02-22 14:12:55 +00:00
|
|
|
BLI_insertlinkafter(&group->data.group, previous, pnew);
|
2014-11-15 21:28:29 +01:00
|
|
|
return true;
|
2006-12-16 23:54:45 +00:00
|
|
|
}
|
2008-10-06 10:24:32 +00:00
|
|
|
|
2014-11-15 21:28:29 +01:00
|
|
|
return false;
|
2006-12-16 23:54:45 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-24 01:51:54 +00:00
|
|
|
/**
|
|
|
|
|
* \note this does not free the property!!
|
|
|
|
|
*
|
|
|
|
|
* To free the property, you have to do:
|
2019-05-16 14:11:11 +02:00
|
|
|
* IDP_FreeProperty(prop);
|
2013-03-24 01:51:54 +00:00
|
|
|
*/
|
2013-10-16 05:29:28 +00:00
|
|
|
void IDP_RemoveFromGroup(IDProperty *group, IDProperty *prop)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(group->type == IDP_GROUP);
|
|
|
|
|
|
2006-11-17 04:46:48 +00:00
|
|
|
group->len--;
|
|
|
|
|
BLI_remlink(&group->data.group, prop);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-16 05:29:28 +00:00
|
|
|
/**
|
|
|
|
|
* Removes the property from the group and frees it.
|
|
|
|
|
*/
|
|
|
|
|
void IDP_FreeFromGroup(IDProperty *group, IDProperty *prop)
|
|
|
|
|
{
|
|
|
|
|
IDP_RemoveFromGroup(group, prop);
|
|
|
|
|
IDP_FreeProperty(prop);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-20 13:50:12 +10:00
|
|
|
IDProperty *IDP_GetPropertyFromGroup(const IDProperty *prop, const char *name)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_GROUP);
|
|
|
|
|
|
2010-08-13 06:30:04 +00:00
|
|
|
return (IDProperty *)BLI_findstring(&prop->data.group, name, offsetof(IDProperty, name));
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
2013-03-24 01:51:54 +00:00
|
|
|
/** same as above but ensure type match */
|
2020-06-20 13:50:12 +10:00
|
|
|
IDProperty *IDP_GetPropertyTypeFromGroup(const IDProperty *prop, const char *name, const char type)
|
2011-02-07 05:05:41 +00:00
|
|
|
{
|
2012-05-06 17:22:54 +00:00
|
|
|
IDProperty *idprop = IDP_GetPropertyFromGroup(prop, name);
|
2011-02-07 05:05:41 +00:00
|
|
|
return (idprop && idprop->type == type) ? idprop : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-03 20:19:11 +00:00
|
|
|
/* Ok, the way things work, Groups free the ID Property structs of their children.
|
|
|
|
|
* This is because all ID Property freeing functions free only direct data (not the ID Property
|
|
|
|
|
* struct itself), but for Groups the child properties *are* considered
|
|
|
|
|
* direct data. */
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
2013-09-30 11:27:03 +00:00
|
|
|
BLI_assert(prop->type == IDP_GROUP);
|
2021-01-25 23:47:56 -06:00
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) {
|
2019-05-16 14:17:11 +02:00
|
|
|
IDP_FreePropertyContent_ex(loop, do_id_user);
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
2010-01-21 21:01:18 +00:00
|
|
|
BLI_freelistN(&prop->data.group);
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
2013-09-30 11:27:03 +00:00
|
|
|
/** \} */
|
2006-11-17 04:46:48 +00:00
|
|
|
|
2013-09-30 11:27:03 +00:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Main Functions (IDProperty Main API)
|
|
|
|
|
* \{ */
|
2020-10-27 21:32:09 +11:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
IDProperty *IDP_CopyProperty_ex(const IDProperty *prop, const int flag)
|
2007-07-09 20:42:14 +00:00
|
|
|
{
|
|
|
|
|
switch (prop->type) {
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
case IDP_GROUP:
|
|
|
|
|
return IDP_CopyGroup(prop, flag);
|
|
|
|
|
case IDP_STRING:
|
|
|
|
|
return IDP_CopyString(prop, flag);
|
|
|
|
|
case IDP_ID:
|
|
|
|
|
return IDP_CopyID(prop, flag);
|
|
|
|
|
case IDP_ARRAY:
|
|
|
|
|
return IDP_CopyArray(prop, flag);
|
|
|
|
|
case IDP_IDPARRAY:
|
|
|
|
|
return IDP_CopyIDPArray(prop, flag);
|
|
|
|
|
default:
|
|
|
|
|
return idp_generic_copy(prop, flag);
|
2007-07-09 20:42:14 +00:00
|
|
|
}
|
|
|
|
|
}
|
2006-11-17 04:46:48 +00:00
|
|
|
|
Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
2017-08-07 16:39:55 +02:00
|
|
|
IDProperty *IDP_CopyProperty(const IDProperty *prop)
|
|
|
|
|
{
|
|
|
|
|
return IDP_CopyProperty_ex(prop, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-18 15:11:31 +02:00
|
|
|
/**
|
|
|
|
|
* Copy content from source IDProperty into destination one, freeing destination property's content
|
|
|
|
|
* first.
|
|
|
|
|
*/
|
|
|
|
|
void IDP_CopyPropertyContent(IDProperty *dst, IDProperty *src)
|
|
|
|
|
{
|
|
|
|
|
IDProperty *idprop_tmp = IDP_CopyProperty(src);
|
|
|
|
|
idprop_tmp->prev = dst->prev;
|
|
|
|
|
idprop_tmp->next = dst->next;
|
|
|
|
|
SWAP(IDProperty, *dst, *idprop_tmp);
|
|
|
|
|
IDP_FreeProperty(idprop_tmp);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-24 01:51:54 +00:00
|
|
|
/**
|
|
|
|
|
* Get the Group property that contains the id properties for ID id. Set create_if_needed
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
2013-12-12 21:57:37 +11:00
|
|
|
IDProperty *IDP_GetProperties(ID *id, const bool create_if_needed)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
2012-07-08 17:08:27 +00:00
|
|
|
if (id->properties) {
|
|
|
|
|
return id->properties;
|
|
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
|
|
|
|
|
if (create_if_needed) {
|
|
|
|
|
id->properties = MEM_callocN(sizeof(IDProperty), "IDProperty");
|
|
|
|
|
id->properties->type = IDP_GROUP;
|
|
|
|
|
/* don't overwrite the data's name and type
|
|
|
|
|
* some functions might need this if they
|
|
|
|
|
* don't have a real ID, should be named elsewhere - Campbell */
|
|
|
|
|
/* strcpy(id->name, "top_level_group");*/
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
return id->properties;
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-31 20:29:32 +00:00
|
|
|
/**
|
2018-12-12 12:50:58 +11:00
|
|
|
* \param is_strict: When false treat missing items as a match */
|
2013-12-12 21:57:37 +11:00
|
|
|
bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is_strict)
|
2009-01-28 23:29:27 +00:00
|
|
|
{
|
2019-04-22 09:39:35 +10:00
|
|
|
if (prop1 == NULL && prop2 == NULL) {
|
2014-11-15 21:28:29 +01:00
|
|
|
return true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (prop1 == NULL || prop2 == NULL) {
|
2014-11-15 21:28:29 +01:00
|
|
|
return is_strict ? false : true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2020-08-07 12:30:43 +02:00
|
|
|
if (prop1->type != prop2->type) {
|
2014-11-15 21:28:29 +01:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-31 19:42:02 +00:00
|
|
|
switch (prop1->type) {
|
|
|
|
|
case IDP_INT:
|
|
|
|
|
return (IDP_Int(prop1) == IDP_Int(prop2));
|
|
|
|
|
case IDP_FLOAT:
|
2014-08-11 20:58:42 +06:00
|
|
|
#if !defined(NDEBUG) && defined(WITH_PYTHON)
|
2014-04-24 16:46:54 +02:00
|
|
|
{
|
|
|
|
|
float p1 = IDP_Float(prop1);
|
|
|
|
|
float p2 = IDP_Float(prop2);
|
2014-04-25 03:18:19 +10:00
|
|
|
if ((p1 != p2) && ((fabsf(p1 - p2) / max_ff(p1, p2)) < 0.001f)) {
|
2014-04-24 16:46:54 +02:00
|
|
|
printf(
|
|
|
|
|
"WARNING: Comparing two float properties that have nearly the same value (%f vs. "
|
|
|
|
|
"%f)\n",
|
|
|
|
|
p1,
|
|
|
|
|
p2);
|
|
|
|
|
printf(" p1: ");
|
2018-05-04 07:26:42 +02:00
|
|
|
IDP_print(prop1);
|
2014-04-24 16:46:54 +02:00
|
|
|
printf(" p2: ");
|
2018-05-04 07:26:42 +02:00
|
|
|
IDP_print(prop2);
|
2014-04-24 16:46:54 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2012-10-31 19:42:02 +00:00
|
|
|
return (IDP_Float(prop1) == IDP_Float(prop2));
|
|
|
|
|
case IDP_DOUBLE:
|
|
|
|
|
return (IDP_Double(prop1) == IDP_Double(prop2));
|
|
|
|
|
case IDP_STRING: {
|
2014-12-12 16:17:52 +01:00
|
|
|
return (((prop1->len == prop2->len) &&
|
2015-01-26 16:03:11 +01:00
|
|
|
STREQLEN(IDP_String(prop1), IDP_String(prop2), (size_t)prop1->len)));
|
2014-12-12 16:17:52 +01:00
|
|
|
}
|
2012-10-31 19:42:02 +00:00
|
|
|
case IDP_ARRAY:
|
|
|
|
|
if (prop1->len == prop2->len && prop1->subtype == prop2->subtype) {
|
2014-12-12 16:17:52 +01:00
|
|
|
return (memcmp(IDP_Array(prop1),
|
|
|
|
|
IDP_Array(prop2),
|
2014-12-14 18:24:13 +01:00
|
|
|
idp_size_table[(int)prop1->subtype] * (size_t)prop1->len) == 0);
|
2012-10-31 19:42:02 +00:00
|
|
|
}
|
2014-11-15 21:28:29 +01:00
|
|
|
return false;
|
2012-10-31 19:42:02 +00:00
|
|
|
case IDP_GROUP: {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (is_strict && prop1->len != prop2->len) {
|
2014-11-15 21:28:29 +01:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
LISTBASE_FOREACH (IDProperty *, link1, &prop1->data.group) {
|
|
|
|
|
IDProperty *link2 = IDP_GetPropertyFromGroup(prop2, link1->name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!IDP_EqualsProperties_ex(link1, link2, is_strict)) {
|
2014-11-15 21:28:29 +01:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-10-31 19:42:02 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-11-15 21:28:29 +01:00
|
|
|
return true;
|
2012-10-31 19:42:02 +00:00
|
|
|
}
|
|
|
|
|
case IDP_IDPARRAY: {
|
|
|
|
|
IDProperty *array1 = IDP_IDPArray(prop1);
|
|
|
|
|
IDProperty *array2 = IDP_IDPArray(prop2);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (prop1->len != prop2->len) {
|
2014-11-15 21:28:29 +01:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-09 16:35:20 +02:00
|
|
|
for (int i = 0; i < prop1->len; i++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (!IDP_EqualsProperties_ex(&array1[i], &array2[i], is_strict)) {
|
2014-11-15 21:28:29 +01:00
|
|
|
return false;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-03-14 18:05:09 +01:00
|
|
|
}
|
2014-11-15 21:28:29 +01:00
|
|
|
return true;
|
2012-10-31 19:42:02 +00:00
|
|
|
}
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
case IDP_ID:
|
|
|
|
|
return (IDP_Id(prop1) == IDP_Id(prop2));
|
2012-10-31 19:42:02 +00:00
|
|
|
default:
|
|
|
|
|
BLI_assert(0);
|
|
|
|
|
break;
|
2009-01-28 23:29:27 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-11-15 21:28:29 +01:00
|
|
|
return true;
|
2009-01-28 23:29:27 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-12 21:57:37 +11:00
|
|
|
bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2)
|
2012-10-31 20:29:32 +00:00
|
|
|
{
|
2014-04-01 11:34:00 +11:00
|
|
|
return IDP_EqualsProperties_ex(prop1, prop2, true);
|
2012-10-31 20:29:32 +00:00
|
|
|
}
|
|
|
|
|
|
2013-03-24 01:51:54 +00:00
|
|
|
/**
|
|
|
|
|
* Allocate a new ID.
|
|
|
|
|
*
|
|
|
|
|
* This function takes three arguments: the ID property type, a union which defines
|
|
|
|
|
* its initial value, and a name.
|
|
|
|
|
*
|
2020-10-27 17:14:40 -05:00
|
|
|
* The union is simple to use; see the top of BKE_idprop.h for its definition.
|
2013-03-24 01:51:54 +00:00
|
|
|
* An example of using this function:
|
|
|
|
|
*
|
2017-04-09 16:26:04 +10:00
|
|
|
* \code{.c}
|
|
|
|
|
* IDPropertyTemplate val;
|
|
|
|
|
* IDProperty *group, *idgroup, *color;
|
|
|
|
|
* group = IDP_New(IDP_GROUP, val, "group1"); // groups don't need a template.
|
2013-03-24 01:51:54 +00:00
|
|
|
*
|
2017-04-09 16:26:04 +10:00
|
|
|
* val.array.len = 4
|
|
|
|
|
* val.array.type = IDP_FLOAT;
|
|
|
|
|
* color = IDP_New(IDP_ARRAY, val, "color1");
|
2013-03-24 01:51:54 +00:00
|
|
|
*
|
2017-04-09 16:26:04 +10:00
|
|
|
* idgroup = IDP_GetProperties(some_id, 1);
|
|
|
|
|
* IDP_AddToGroup(idgroup, color);
|
|
|
|
|
* IDP_AddToGroup(idgroup, group);
|
|
|
|
|
* \endcode
|
2013-03-24 01:51:54 +00:00
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
2014-12-12 16:17:52 +01:00
|
|
|
IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
2012-05-06 17:22:54 +00:00
|
|
|
IDProperty *prop = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-11-17 04:46:48 +00:00
|
|
|
switch (type) {
|
|
|
|
|
case IDP_INT:
|
|
|
|
|
prop = MEM_callocN(sizeof(IDProperty), "IDProperty int");
|
2011-11-15 09:22:52 +00:00
|
|
|
prop->data.val = val->i;
|
2006-11-17 04:46:48 +00:00
|
|
|
break;
|
|
|
|
|
case IDP_FLOAT:
|
|
|
|
|
prop = MEM_callocN(sizeof(IDProperty), "IDProperty float");
|
2012-05-06 17:22:54 +00:00
|
|
|
*(float *)&prop->data.val = val->f;
|
2006-11-17 04:46:48 +00:00
|
|
|
break;
|
2008-07-24 19:22:17 +00:00
|
|
|
case IDP_DOUBLE:
|
2017-04-10 21:06:00 +10:00
|
|
|
prop = MEM_callocN(sizeof(IDProperty), "IDProperty double");
|
2012-05-06 17:22:54 +00:00
|
|
|
*(double *)&prop->data.val = val->d;
|
2012-09-16 04:58:18 +00:00
|
|
|
break;
|
2006-11-17 04:46:48 +00:00
|
|
|
case IDP_ARRAY: {
|
2012-08-17 14:43:20 +00:00
|
|
|
/* for now, we only support float and int and double arrays */
|
2011-12-22 00:03:20 +00:00
|
|
|
if ((val->array.type == IDP_FLOAT) || (val->array.type == IDP_INT) ||
|
|
|
|
|
(val->array.type == IDP_DOUBLE) || (val->array.type == IDP_GROUP)) {
|
2006-11-17 04:46:48 +00:00
|
|
|
prop = MEM_callocN(sizeof(IDProperty), "IDProperty array");
|
2011-11-15 09:22:52 +00:00
|
|
|
prop->subtype = val->array.type;
|
2014-12-12 16:17:52 +01:00
|
|
|
if (val->array.len) {
|
|
|
|
|
prop->data.pointer = MEM_callocN(
|
|
|
|
|
idp_size_table[val->array.type] * (size_t)val->array.len, "id property array");
|
|
|
|
|
}
|
2011-11-15 09:22:52 +00:00
|
|
|
prop->len = prop->totallen = val->array.len;
|
2006-11-17 04:46:48 +00:00
|
|
|
break;
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2019-02-01 12:44:19 +11:00
|
|
|
CLOG_ERROR(&LOG, "bad array type.");
|
2013-07-21 08:16:37 +00:00
|
|
|
return NULL;
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
|
|
|
|
case IDP_STRING: {
|
2011-11-15 09:22:52 +00:00
|
|
|
const char *st = val->string.str;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-11-17 04:46:48 +00:00
|
|
|
prop = MEM_callocN(sizeof(IDProperty), "IDProperty string");
|
2011-11-15 09:22:52 +00:00
|
|
|
if (val->string.subtype == IDP_STRING_SUB_BYTE) {
|
2011-11-15 09:12:10 +00:00
|
|
|
/* note, intentionally not null terminated */
|
|
|
|
|
if (st == NULL) {
|
2013-09-05 04:26:08 +00:00
|
|
|
prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
|
|
|
|
|
*IDP_String(prop) = '\0';
|
2011-11-15 09:12:10 +00:00
|
|
|
prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS;
|
|
|
|
|
prop->len = 0;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2014-12-12 16:17:52 +01:00
|
|
|
prop->data.pointer = MEM_mallocN((size_t)val->string.len, "id property string 2");
|
2011-11-15 09:22:52 +00:00
|
|
|
prop->len = prop->totallen = val->string.len;
|
2014-12-12 16:17:52 +01:00
|
|
|
memcpy(prop->data.pointer, st, (size_t)val->string.len);
|
2011-11-15 09:12:10 +00:00
|
|
|
}
|
2012-05-06 17:22:54 +00:00
|
|
|
prop->subtype = IDP_STRING_SUB_BYTE;
|
2011-11-15 09:12:10 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2016-07-31 16:52:44 +10:00
|
|
|
if (st == NULL || val->string.len <= 1) {
|
2013-09-05 04:26:08 +00:00
|
|
|
prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
|
|
|
|
|
*IDP_String(prop) = '\0';
|
2011-11-15 09:12:10 +00:00
|
|
|
prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS;
|
2018-07-13 10:51:49 +02:00
|
|
|
/* NULL string, has len of 1 to account for null byte. */
|
|
|
|
|
prop->len = 1;
|
2011-11-15 09:12:10 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2016-07-31 16:52:44 +10:00
|
|
|
BLI_assert((int)val->string.len <= (int)strlen(st) + 1);
|
|
|
|
|
prop->data.pointer = MEM_mallocN((size_t)val->string.len, "id property string 3");
|
|
|
|
|
memcpy(prop->data.pointer, st, (size_t)val->string.len - 1);
|
|
|
|
|
IDP_String(prop)[val->string.len - 1] = '\0';
|
|
|
|
|
prop->len = prop->totallen = val->string.len;
|
2011-11-15 09:12:10 +00:00
|
|
|
}
|
2012-05-06 17:22:54 +00:00
|
|
|
prop->subtype = IDP_STRING_SUB_UTF8;
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IDP_GROUP: {
|
2018-07-13 10:51:49 +02:00
|
|
|
/* Values are set properly by calloc. */
|
2006-11-17 04:46:48 +00:00
|
|
|
prop = MEM_callocN(sizeof(IDProperty), "IDProperty group");
|
|
|
|
|
break;
|
|
|
|
|
}
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
case IDP_ID: {
|
|
|
|
|
prop = MEM_callocN(sizeof(IDProperty), "IDProperty datablock");
|
|
|
|
|
prop->data.pointer = (void *)val->id;
|
|
|
|
|
prop->type = IDP_ID;
|
|
|
|
|
id_us_plus(IDP_Id(prop));
|
|
|
|
|
break;
|
|
|
|
|
}
|
2006-11-17 04:46:48 +00:00
|
|
|
default: {
|
|
|
|
|
prop = MEM_callocN(sizeof(IDProperty), "IDProperty array");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-11-17 04:46:48 +00:00
|
|
|
prop->type = type;
|
2008-12-31 13:16:37 +00:00
|
|
|
BLI_strncpy(prop->name, name, MAX_IDPROP_NAME);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-11-17 04:46:48 +00:00
|
|
|
return prop;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-24 01:51:54 +00:00
|
|
|
/**
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
* \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.
|
2013-03-24 01:51:54 +00:00
|
|
|
*/
|
2019-05-16 14:17:11 +02:00
|
|
|
void IDP_FreePropertyContent_ex(IDProperty *prop, const bool do_id_user)
|
2006-11-17 04:46:48 +00:00
|
|
|
{
|
|
|
|
|
switch (prop->type) {
|
|
|
|
|
case IDP_ARRAY:
|
|
|
|
|
IDP_FreeArray(prop);
|
|
|
|
|
break;
|
|
|
|
|
case IDP_STRING:
|
|
|
|
|
IDP_FreeString(prop);
|
|
|
|
|
break;
|
|
|
|
|
case IDP_GROUP:
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
IDP_FreeGroup(prop, do_id_user);
|
2006-11-17 04:46:48 +00:00
|
|
|
break;
|
2008-12-31 13:16:37 +00:00
|
|
|
case IDP_IDPARRAY:
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
IDP_FreeIDPArray(prop, do_id_user);
|
|
|
|
|
break;
|
|
|
|
|
case IDP_ID:
|
|
|
|
|
if (do_id_user) {
|
|
|
|
|
id_us_min(IDP_Id(prop));
|
|
|
|
|
}
|
2008-12-31 13:16:37 +00:00
|
|
|
break;
|
2006-11-17 04:46:48 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-16 14:11:11 +02:00
|
|
|
void IDP_FreePropertyContent(IDProperty *prop)
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
{
|
2019-05-16 14:17:11 +02:00
|
|
|
IDP_FreePropertyContent_ex(prop, true);
|
Datablock ID Properties
The absence of datablock properties "will certainly be resolved soon as the need for them is becoming obvious" said the [[http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.67/Python_Nodes|Python Nodes release notes]]. So this patch allows Python scripts to create ID Properties which reference datablocks.
This functionality is implemented for `PointerProperty` and now such properties can be created with Python.
In addition to the standard update callback, `PointerProperty` can have a `poll` callback (standard RNA) which is useful for search menus. For details see the test included in this patch.
Original author: @artfunkel
Alexander (Blend4Web Team)
Reviewers: brecht, artfunkel, mont29, campbellbarton
Reviewed By: mont29, campbellbarton
Subscribers: jta, sergey, campbellbarton, wisaac, poseidon4o, mont29, homyachetser, Evgeny_Rodygin, AlexKowel, yurikovelenov, fjuhec, sharlybg, cardboard, duarteframos, blueprintrandom, a.romanov, BYOB, disnel, aditiapratama, bliblubli, dfelinto, lukastoenne
Maniphest Tasks: T37754
Differential Revision: https://developer.blender.org/D113
2017-04-13 12:30:03 +03:00
|
|
|
}
|
|
|
|
|
|
2019-11-04 15:02:03 +01:00
|
|
|
void IDP_FreeProperty_ex(IDProperty *prop, const bool do_id_user)
|
|
|
|
|
{
|
|
|
|
|
IDP_FreePropertyContent_ex(prop, do_id_user);
|
|
|
|
|
MEM_freeN(prop);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-16 14:11:11 +02:00
|
|
|
void IDP_FreeProperty(IDProperty *prop)
|
|
|
|
|
{
|
|
|
|
|
IDP_FreePropertyContent(prop);
|
|
|
|
|
MEM_freeN(prop);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-02 23:10:14 +00:00
|
|
|
void IDP_ClearProperty(IDProperty *prop)
|
|
|
|
|
{
|
2019-05-16 14:11:11 +02:00
|
|
|
IDP_FreePropertyContent(prop);
|
2013-01-02 23:10:14 +00:00
|
|
|
prop->data.pointer = NULL;
|
|
|
|
|
prop->len = prop->totallen = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-24 15:00:01 +01:00
|
|
|
void IDP_Reset(IDProperty *prop, const IDProperty *reference)
|
|
|
|
|
{
|
|
|
|
|
if (prop == NULL) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
IDP_ClearProperty(prop);
|
|
|
|
|
if (reference != NULL) {
|
|
|
|
|
IDP_MergeGroup(prop, reference, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-25 20:58:55 +02:00
|
|
|
/**
|
|
|
|
|
* 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(IDProperty *id_property_root,
|
|
|
|
|
const int type_filter,
|
|
|
|
|
IDPForeachPropertyCallback callback,
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
|
|
|
|
if (!id_property_root) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type_filter == 0 || (1 << id_property_root->type) & type_filter) {
|
|
|
|
|
callback(id_property_root, user_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Recursive call into container types of ID properties. */
|
|
|
|
|
switch (id_property_root->type) {
|
|
|
|
|
case IDP_GROUP: {
|
|
|
|
|
LISTBASE_FOREACH (IDProperty *, loop, &id_property_root->data.group) {
|
|
|
|
|
IDP_foreach_property(loop, type_filter, callback, user_data);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IDP_IDPARRAY: {
|
|
|
|
|
IDProperty *loop = IDP_Array(id_property_root);
|
|
|
|
|
for (int i = 0; i < id_property_root->len; i++) {
|
|
|
|
|
IDP_foreach_property(&loop[i], type_filter, callback, user_data);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break; /* Nothing to do here with other types of IDProperties... */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-21 12:45:33 +02:00
|
|
|
void IDP_WriteProperty_OnlyData(const IDProperty *prop, BlendWriter *writer);
|
|
|
|
|
|
|
|
|
|
static void IDP_WriteArray(const IDProperty *prop, BlendWriter *writer)
|
|
|
|
|
{
|
|
|
|
|
/*REMEMBER to set totalen to len in the linking code!!*/
|
|
|
|
|
if (prop->data.pointer) {
|
2020-09-20 18:41:50 +02:00
|
|
|
BLO_write_raw(writer, MEM_allocN_len(prop->data.pointer), prop->data.pointer);
|
2020-08-21 12:45:33 +02:00
|
|
|
|
|
|
|
|
if (prop->subtype == IDP_GROUP) {
|
|
|
|
|
IDProperty **array = prop->data.pointer;
|
|
|
|
|
int a;
|
|
|
|
|
|
|
|
|
|
for (a = 0; a < prop->len; a++) {
|
|
|
|
|
IDP_BlendWrite(writer, array[a]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void IDP_WriteIDPArray(const IDProperty *prop, BlendWriter *writer)
|
|
|
|
|
{
|
|
|
|
|
/*REMEMBER to set totalen to len in the linking code!!*/
|
|
|
|
|
if (prop->data.pointer) {
|
|
|
|
|
const IDProperty *array = prop->data.pointer;
|
|
|
|
|
|
|
|
|
|
BLO_write_struct_array(writer, IDProperty, prop->len, array);
|
|
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
for (int a = 0; a < prop->len; a++) {
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_WriteProperty_OnlyData(&array[a], writer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void IDP_WriteString(const IDProperty *prop, BlendWriter *writer)
|
|
|
|
|
{
|
|
|
|
|
/*REMEMBER to set totalen to len in the linking code!!*/
|
2020-09-20 18:41:50 +02:00
|
|
|
BLO_write_raw(writer, (size_t)prop->len, prop->data.pointer);
|
2020-08-21 12:45:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void IDP_WriteGroup(const IDProperty *prop, BlendWriter *writer)
|
|
|
|
|
{
|
2021-01-25 23:47:56 -06:00
|
|
|
LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) {
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_BlendWrite(writer, loop);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Functions to read/write ID Properties */
|
|
|
|
|
void IDP_WriteProperty_OnlyData(const IDProperty *prop, BlendWriter *writer)
|
|
|
|
|
{
|
|
|
|
|
switch (prop->type) {
|
|
|
|
|
case IDP_GROUP:
|
|
|
|
|
IDP_WriteGroup(prop, writer);
|
|
|
|
|
break;
|
|
|
|
|
case IDP_STRING:
|
|
|
|
|
IDP_WriteString(prop, writer);
|
|
|
|
|
break;
|
|
|
|
|
case IDP_ARRAY:
|
|
|
|
|
IDP_WriteArray(prop, writer);
|
|
|
|
|
break;
|
|
|
|
|
case IDP_IDPARRAY:
|
|
|
|
|
IDP_WriteIDPArray(prop, writer);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
|
|
|
|
|
{
|
|
|
|
|
BLO_write_struct(writer, IDProperty, prop);
|
|
|
|
|
IDP_WriteProperty_OnlyData(prop, writer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void IDP_DirectLinkProperty(IDProperty *prop, BlendDataReader *reader);
|
|
|
|
|
|
|
|
|
|
static void IDP_DirectLinkIDPArray(IDProperty *prop, BlendDataReader *reader)
|
|
|
|
|
{
|
|
|
|
|
/* since we didn't save the extra buffer, set totallen to len */
|
|
|
|
|
prop->totallen = prop->len;
|
|
|
|
|
BLO_read_data_address(reader, &prop->data.pointer);
|
|
|
|
|
|
2021-01-25 23:47:56 -06:00
|
|
|
IDProperty *array = (IDProperty *)prop->data.pointer;
|
2020-08-21 12:45:33 +02:00
|
|
|
|
|
|
|
|
/* note!, idp-arrays didn't exist in 2.4x, so the pointer will be cleared
|
|
|
|
|
* there's not really anything we can do to correct this, at least don't crash */
|
|
|
|
|
if (array == NULL) {
|
|
|
|
|
prop->len = 0;
|
|
|
|
|
prop->totallen = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-09 16:35:20 +02:00
|
|
|
for (int i = 0; i < prop->len; i++) {
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_DirectLinkProperty(&array[i], reader);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void IDP_DirectLinkArray(IDProperty *prop, BlendDataReader *reader)
|
|
|
|
|
{
|
|
|
|
|
/* since we didn't save the extra buffer, set totallen to len */
|
|
|
|
|
prop->totallen = prop->len;
|
|
|
|
|
|
|
|
|
|
if (prop->subtype == IDP_GROUP) {
|
|
|
|
|
BLO_read_pointer_array(reader, &prop->data.pointer);
|
2021-01-25 23:47:56 -06:00
|
|
|
IDProperty **array = prop->data.pointer;
|
2020-08-21 12:45:33 +02:00
|
|
|
|
2020-09-09 16:35:20 +02:00
|
|
|
for (int i = 0; i < prop->len; i++) {
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_DirectLinkProperty(array[i], reader);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (prop->subtype == IDP_DOUBLE) {
|
|
|
|
|
BLO_read_double_array(reader, prop->len, (double **)&prop->data.pointer);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* also used for floats */
|
|
|
|
|
BLO_read_int32_array(reader, prop->len, (int **)&prop->data.pointer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void IDP_DirectLinkString(IDProperty *prop, BlendDataReader *reader)
|
|
|
|
|
{
|
|
|
|
|
/*since we didn't save the extra string buffer, set totallen to len.*/
|
|
|
|
|
prop->totallen = prop->len;
|
|
|
|
|
BLO_read_data_address(reader, &prop->data.pointer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void IDP_DirectLinkGroup(IDProperty *prop, BlendDataReader *reader)
|
|
|
|
|
{
|
|
|
|
|
ListBase *lb = &prop->data.group;
|
|
|
|
|
|
|
|
|
|
BLO_read_list(reader, lb);
|
|
|
|
|
|
|
|
|
|
/*Link child id properties now*/
|
2021-01-25 23:47:56 -06:00
|
|
|
LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) {
|
2020-08-21 12:45:33 +02:00
|
|
|
IDP_DirectLinkProperty(loop, reader);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void IDP_DirectLinkProperty(IDProperty *prop, BlendDataReader *reader)
|
|
|
|
|
{
|
|
|
|
|
switch (prop->type) {
|
|
|
|
|
case IDP_GROUP:
|
|
|
|
|
IDP_DirectLinkGroup(prop, reader);
|
|
|
|
|
break;
|
|
|
|
|
case IDP_STRING:
|
|
|
|
|
IDP_DirectLinkString(prop, reader);
|
|
|
|
|
break;
|
|
|
|
|
case IDP_ARRAY:
|
|
|
|
|
IDP_DirectLinkArray(prop, reader);
|
|
|
|
|
break;
|
|
|
|
|
case IDP_IDPARRAY:
|
|
|
|
|
IDP_DirectLinkIDPArray(prop, reader);
|
|
|
|
|
break;
|
|
|
|
|
case IDP_DOUBLE:
|
|
|
|
|
/* Workaround for doubles.
|
2020-08-22 00:09:17 +10:00
|
|
|
* They are stored in the same field as `int val, val2` in the #IDPropertyData struct,
|
2020-08-21 12:45:33 +02:00
|
|
|
* they have to deal with endianness specifically.
|
|
|
|
|
*
|
|
|
|
|
* In theory, val and val2 would've already been swapped
|
2020-08-22 00:09:17 +10:00
|
|
|
* if switch_endian is true, so we have to first un-swap
|
2020-08-21 12:45:33 +02:00
|
|
|
* them then re-swap them as a single 64-bit entity. */
|
|
|
|
|
if (BLO_read_requires_endian_switch(reader)) {
|
|
|
|
|
BLI_endian_switch_int32(&prop->data.val);
|
|
|
|
|
BLI_endian_switch_int32(&prop->data.val2);
|
|
|
|
|
BLI_endian_switch_int64((int64_t *)&prop->data.val);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case IDP_INT:
|
|
|
|
|
case IDP_FLOAT:
|
|
|
|
|
case IDP_ID:
|
|
|
|
|
break; /* Nothing special to do here. */
|
|
|
|
|
default:
|
|
|
|
|
/* Unknown IDP type, nuke it (we cannot handle unknown types everywhere in code,
|
|
|
|
|
* IDP are way too polymorphic to do it safely. */
|
|
|
|
|
printf(
|
|
|
|
|
"%s: found unknown IDProperty type %d, reset to Integer one !\n", __func__, prop->type);
|
|
|
|
|
/* Note: we do not attempt to free unknown prop, we have no way to know how to do that! */
|
|
|
|
|
prop->type = IDP_INT;
|
|
|
|
|
prop->subtype = 0;
|
|
|
|
|
IDP_Int(prop) = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-28 13:18:24 +02:00
|
|
|
void IDP_BlendReadData_impl(BlendDataReader *reader, IDProperty **prop, const char *caller_func_id)
|
2020-08-21 12:45:33 +02:00
|
|
|
{
|
|
|
|
|
if (*prop) {
|
|
|
|
|
if ((*prop)->type == IDP_GROUP) {
|
|
|
|
|
IDP_DirectLinkGroup(*prop, reader);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* corrupt file! */
|
|
|
|
|
printf("%s: found non group data, freeing type %d!\n", caller_func_id, (*prop)->type);
|
|
|
|
|
/* don't risk id, data's likely corrupt. */
|
|
|
|
|
// IDP_FreePropertyContent(*prop);
|
|
|
|
|
*prop = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-28 13:18:24 +02:00
|
|
|
void IDP_BlendReadLib(BlendLibReader *reader, IDProperty *prop)
|
2020-08-21 12:45:33 +02:00
|
|
|
{
|
|
|
|
|
if (!prop) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (prop->type) {
|
|
|
|
|
case IDP_ID: /* PointerProperty */
|
|
|
|
|
{
|
|
|
|
|
void *newaddr = BLO_read_get_new_id_address(reader, NULL, IDP_Id(prop));
|
|
|
|
|
if (IDP_Id(prop) && !newaddr && G.debug) {
|
|
|
|
|
printf("Error while loading \"%s\". Data not found in file!\n", prop->name);
|
|
|
|
|
}
|
|
|
|
|
prop->data.pointer = newaddr;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IDP_IDPARRAY: /* CollectionProperty */
|
|
|
|
|
{
|
|
|
|
|
IDProperty *idp_array = IDP_IDPArray(prop);
|
|
|
|
|
for (int i = 0; i < prop->len; i++) {
|
2020-08-28 13:18:24 +02:00
|
|
|
IDP_BlendReadLib(reader, &(idp_array[i]));
|
2020-08-21 12:45:33 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IDP_GROUP: /* PointerProperty */
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) {
|
2020-08-28 13:18:24 +02:00
|
|
|
IDP_BlendReadLib(reader, loop);
|
2020-08-21 12:45:33 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break; /* Nothing to do for other IDProps. */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-28 13:18:24 +02:00
|
|
|
void IDP_BlendReadExpand(struct BlendExpander *expander, IDProperty *prop)
|
2020-08-21 12:45:33 +02:00
|
|
|
{
|
|
|
|
|
if (!prop) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (prop->type) {
|
|
|
|
|
case IDP_ID:
|
|
|
|
|
BLO_expand(expander, IDP_Id(prop));
|
|
|
|
|
break;
|
|
|
|
|
case IDP_IDPARRAY: {
|
|
|
|
|
IDProperty *idp_array = IDP_IDPArray(prop);
|
|
|
|
|
for (int i = 0; i < prop->len; i++) {
|
2020-08-28 13:18:24 +02:00
|
|
|
IDP_BlendReadExpand(expander, &idp_array[i]);
|
2020-08-21 12:45:33 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case IDP_GROUP:
|
|
|
|
|
LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) {
|
2020-08-28 13:18:24 +02:00
|
|
|
IDP_BlendReadExpand(expander, loop);
|
2020-08-21 12:45:33 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-30 11:27:03 +00:00
|
|
|
/** \} */
|