This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/makesrna/intern/rna_define.c

3405 lines
91 KiB
C
Raw Normal View History

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
2010-02-12 13:34:04 +00:00
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Blender Foundation (2008).
*
* ***** END GPL LICENSE BLOCK *****
*/
2011-02-27 20:20:01 +00:00
/** \file blender/makesrna/intern/rna_define.c
* \ingroup RNA
*/
#include <float.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include "BLI_utildefines.h"
#include "MEM_guardedalloc.h"
#include "DNA_genfile.h"
#include "DNA_sdna_types.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_ghash.h"
#include "BLF_translation.h"
#include "RNA_define.h"
#include "rna_internal.h"
#ifdef DEBUG
# define ASSERT_SOFT_HARD_LIMITS \
if (softmin < hardmin || softmax > hardmax) { \
fprintf(stderr, "Error with soft/hard limits: %s.%s\n", CONTAINER_RNA_ID(cont), identifier); \
BLI_assert(!"invalid soft/hard limits"); \
} (void)0
#else
# define ASSERT_SOFT_HARD_LIMITS (void)0
#endif
/* Global used during defining */
BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1};
/* Duplicated code since we can't link in blenkernel or blenlib */
#ifndef MIN2
#define MIN2(x, y) ((x) < (y) ? (x) : (y))
#define MAX2(x, y) ((x) > (y) ? (x) : (y))
#endif
/* pedantic check for '.', do this since its a hassle for translators */
#ifndef NDEBUG
# define DESCR_CHECK(description, id1, id2) \
if (description && (description)[0]) { \
int i = strlen(description); \
if ((description)[i - 1] == '.') { \
fprintf(stderr, "%s: '%s' '%s' description ends with a '.' !\n", \
__func__, id1 ? id1 : "", id2 ? id2 : ""); \
} \
2012-05-27 20:13:59 +00:00
} (void)0
#else
# define DESCR_CHECK(description, id1, id2)
#endif
void rna_addtail(ListBase *listbase, void *vlink)
{
Link *link = vlink;
link->next = NULL;
link->prev = listbase->last;
if (listbase->last) ((Link *)listbase->last)->next = link;
if (listbase->first == NULL) listbase->first = link;
listbase->last = link;
}
static void rna_remlink(ListBase *listbase, void *vlink)
{
Link *link = vlink;
if (link->next) link->next->prev = link->prev;
if (link->prev) link->prev->next = link->next;
if (listbase->last == link) listbase->last = link->prev;
if (listbase->first == link) listbase->first = link->next;
}
PropertyDefRNA *rna_findlink(ListBase *listbase, const char *identifier)
{
Link *link;
for (link = listbase->first; link; link = link->next) {
PropertyRNA *prop = ((PropertyDefRNA *)link)->prop;
if (prop && (strcmp(prop->identifier, identifier) == 0)) {
return (PropertyDefRNA *)link;
}
}
return NULL;
}
void rna_freelinkN(ListBase *listbase, void *vlink)
{
rna_remlink(listbase, vlink);
MEM_freeN(vlink);
}
void rna_freelistN(ListBase *listbase)
{
Link *link, *next;
for (link = listbase->first; link; link = next) {
next = link->next;
MEM_freeN(link);
}
listbase->first = listbase->last = NULL;
}
StructDefRNA *rna_find_struct_def(StructRNA *srna)
{
StructDefRNA *dsrna;
if (!DefRNA.preprocess) {
/* we should never get here */
fprintf(stderr, "%s: only at preprocess time.\n", __func__);
return NULL;
}
dsrna = DefRNA.structs.last;
for (; dsrna; dsrna = dsrna->cont.prev)
if (dsrna->srna == srna)
return dsrna;
return NULL;
}
PropertyDefRNA *rna_find_struct_property_def(StructRNA *srna, PropertyRNA *prop)
{
StructDefRNA *dsrna;
PropertyDefRNA *dprop;
if (!DefRNA.preprocess) {
/* we should never get here */
fprintf(stderr, "%s: only at preprocess time.\n", __func__);
return NULL;
}
dsrna = rna_find_struct_def(srna);
dprop = dsrna->cont.properties.last;
for (; dprop; dprop = dprop->prev)
if (dprop->prop == prop)
return dprop;
dsrna = DefRNA.structs.last;
for (; dsrna; dsrna = dsrna->cont.prev) {
dprop = dsrna->cont.properties.last;
for (; dprop; dprop = dprop->prev)
if (dprop->prop == prop)
return dprop;
}
return NULL;
}
#if 0
static PropertyDefRNA *rna_find_property_def(PropertyRNA *prop)
{
PropertyDefRNA *dprop;
if (!DefRNA.preprocess) {
/* we should never get here */
fprintf(stderr, "%s: only at preprocess time.\n", __func__);
return NULL;
}
dprop = rna_find_struct_property_def(DefRNA.laststruct, prop);
if (dprop)
return dprop;
dprop = rna_find_parameter_def(prop);
if (dprop)
return dprop;
return NULL;
}
#endif
FunctionDefRNA *rna_find_function_def(FunctionRNA *func)
{
StructDefRNA *dsrna;
FunctionDefRNA *dfunc;
if (!DefRNA.preprocess) {
/* we should never get here */
fprintf(stderr, "%s: only at preprocess time.\n", __func__);
return NULL;
}
dsrna = rna_find_struct_def(DefRNA.laststruct);
dfunc = dsrna->functions.last;
for (; dfunc; dfunc = dfunc->cont.prev)
if (dfunc->func == func)
return dfunc;
dsrna = DefRNA.structs.last;
for (; dsrna; dsrna = dsrna->cont.prev) {
dfunc = dsrna->functions.last;
for (; dfunc; dfunc = dfunc->cont.prev)
if (dfunc->func == func)
return dfunc;
}
return NULL;
}
PropertyDefRNA *rna_find_parameter_def(PropertyRNA *parm)
{
StructDefRNA *dsrna;
FunctionDefRNA *dfunc;
PropertyDefRNA *dparm;
if (!DefRNA.preprocess) {
/* we should never get here */
fprintf(stderr, "%s: only at preprocess time.\n", __func__);
return NULL;
}
dsrna = rna_find_struct_def(DefRNA.laststruct);
dfunc = dsrna->functions.last;
for (; dfunc; dfunc = dfunc->cont.prev) {
dparm = dfunc->cont.properties.last;
for (; dparm; dparm = dparm->prev)
if (dparm->prop == parm)
return dparm;
}
dsrna = DefRNA.structs.last;
for (; dsrna; dsrna = dsrna->cont.prev) {
dfunc = dsrna->functions.last;
for (; dfunc; dfunc = dfunc->cont.prev) {
dparm = dfunc->cont.properties.last;
for (; dparm; dparm = dparm->prev)
if (dparm->prop == parm)
return dparm;
}
}
return NULL;
}
static ContainerDefRNA *rna_find_container_def(ContainerRNA *cont)
{
StructDefRNA *ds;
FunctionDefRNA *dfunc;
if (!DefRNA.preprocess) {
/* we should never get here */
fprintf(stderr, "%s: only at preprocess time.\n", __func__);
return NULL;
}
ds = rna_find_struct_def((StructRNA *)cont);
if (ds)
return &ds->cont;
dfunc = rna_find_function_def((FunctionRNA *)cont);
if (dfunc)
return &dfunc->cont;
return NULL;
}
/* DNA utility function for looking up members */
typedef struct DNAStructMember {
const char *type;
const char *name;
int arraylength;
int pointerlevel;
} DNAStructMember;
static int rna_member_cmp(const char *name, const char *oname)
{
int a = 0;
/* compare without pointer or array part */
while (name[0] == '*')
name++;
while (oname[0] == '*')
oname++;
while (1) {
if (name[a] == '[' && oname[a] == 0) return 1;
if (name[a] == '[' && oname[a] == '[') return 1;
if (name[a] == 0) break;
if (name[a] != oname[a]) return 0;
a++;
}
if (name[a] == 0 && oname[a] == '.') return 2;
if (name[a] == 0 && oname[a] == '-' && oname[a + 1] == '>') return 3;
return (name[a] == oname[a]);
}
static int rna_find_sdna_member(SDNA *sdna, const char *structname, const char *membername, DNAStructMember *smember)
{
const char *dnaname;
short *sp;
int a, b, structnr, totmember, cmp;
structnr = DNA_struct_find_nr(sdna, structname);
if (structnr == -1)
return 0;
sp = sdna->structs[structnr];
totmember = sp[1];
sp += 2;
for (a = 0; a < totmember; a++, sp += 2) {
dnaname = sdna->names[sp[1]];
cmp = rna_member_cmp(dnaname, membername);
if (cmp == 1) {
smember->type = sdna->types[sp[0]];
smember->name = dnaname;
if (strstr(membername, "["))
smember->arraylength = 0;
else
smember->arraylength = DNA_elem_array_size(smember->name, strlen(smember->name));
smember->pointerlevel = 0;
for (b = 0; dnaname[b] == '*'; b++)
smember->pointerlevel++;
return 1;
}
else if (cmp == 2) {
smember->type = "";
smember->name = dnaname;
smember->pointerlevel = 0;
smember->arraylength = 0;
membername = strstr(membername, ".") + strlen(".");
rna_find_sdna_member(sdna, sdna->types[sp[0]], membername, smember);
return 1;
}
else if (cmp == 3) {
smember->type = "";
smember->name = dnaname;
smember->pointerlevel = 0;
smember->arraylength = 0;
membername = strstr(membername, "->") + strlen("->");
rna_find_sdna_member(sdna, sdna->types[sp[0]], membername, smember);
return 1;
}
}
return 0;
}
static int rna_validate_identifier(const char *identifier, char *error, int property)
{
int a = 0;
2012-12-29 01:54:58 +00:00
/* list is from...
* ", ".join(['"%s"' % kw for kw in __import__("keyword").kwlist if kw not in {"False", "None", "True"}])
*/
static const char *kwlist[] = {
/* "False", "None", "True", */
"and", "as", "assert", "break",
"class", "continue", "def", "del", "elif", "else", "except",
"finally", "for", "from", "global", "if", "import", "in",
"is", "lambda", "nonlocal", "not", "or", "pass", "raise",
"return", "try", "while", "with", "yield", NULL
};
if (!isalpha(identifier[0])) {
strcpy(error, "first character failed isalpha() check");
return 0;
}
for (a = 0; identifier[a]; a++) {
if (DefRNA.preprocess && property) {
if (isalpha(identifier[a]) && isupper(identifier[a])) {
strcpy(error, "property names must contain lower case characters only");
return 0;
}
}
if (identifier[a] == '_') {
continue;
}
if (identifier[a] == ' ') {
strcpy(error, "spaces are not okay in identifier names");
return 0;
}
if (isalnum(identifier[a]) == 0) {
strcpy(error, "one of the characters failed an isalnum() check and is not an underscore");
return 0;
}
}
for (a = 0; kwlist[a]; a++) {
if (strcmp(identifier, kwlist[a]) == 0) {
strcpy(error, "this keyword is reserved by python");
return 0;
}
}
if (property) {
static const char *kwlist_prop[] = {
/* not keywords but reserved all the same because py uses */
"keys", "values", "items", "get",
NULL
};
for (a = 0; kwlist_prop[a]; a++) {
if (strcmp(identifier, kwlist_prop[a]) == 0) {
strcpy(error, "this keyword is reserved by python");
return 0;
}
}
}
return 1;
}
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
void RNA_identifier_sanitize(char *identifier, int property)
{
int a = 0;
/* list from http://docs.python.org/py3k/reference/lexical_analysis.html#keywords */
static const char *kwlist[] = {
/* "False", "None", "True", */
"and", "as", "assert", "break",
"class", "continue", "def", "del", "elif", "else", "except",
"finally", "for", "from", "global", "if", "import", "in",
"is", "lambda", "nonlocal", "not", "or", "pass", "raise",
"return", "try", "while", "with", "yield", NULL
};
if (!isalpha(identifier[0])) {
/* first character failed isalpha() check */
identifier[0] = '_';
}
for (a = 0; identifier[a]; a++) {
if (DefRNA.preprocess && property) {
if (isalpha(identifier[a]) && isupper(identifier[a])) {
/* property names must contain lower case characters only */
identifier[a] = tolower(identifier[a]);
}
}
if (identifier[a] == '_') {
continue;
}
if (identifier[a] == ' ') {
/* spaces are not okay in identifier names */
identifier[a] = '_';
}
if (isalnum(identifier[a]) == 0) {
/* one of the characters failed an isalnum() check and is not an underscore */
identifier[a] = '_';
}
}
for (a = 0; kwlist[a]; a++) {
if (strcmp(identifier, kwlist[a]) == 0) {
/* this keyword is reserved by python.
* just replace the last character by '_' to keep it readable.
*/
2013-03-18 18:25:05 +00:00
identifier[strlen(identifier) - 1] = '_';
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
break;
}
}
if (property) {
static const char *kwlist_prop[] = {
/* not keywords but reserved all the same because py uses */
"keys", "values", "items", "get",
NULL
};
for (a = 0; kwlist_prop[a]; a++) {
if (strcmp(identifier, kwlist_prop[a]) == 0) {
/* this keyword is reserved by python.
2013-06-06 06:02:46 +00:00
* just replace the last character by '_' to keep it readable.
*/
2013-03-18 18:25:05 +00:00
identifier[strlen(identifier) - 1] = '_';
Merge of the PyNodes branch (aka "custom nodes") into trunk. PyNodes opens up the node system in Blender to scripters and adds a number of UI-level improvements. === Dynamic node type registration === Node types can now be added at runtime, using the RNA registration mechanism from python. This enables addons such as render engines to create a complete user interface with nodes. Examples of how such nodes can be defined can be found in my personal wiki docs atm [1] and as a script template in release/scripts/templates_py/custom_nodes.py [2]. === Node group improvements === Each node editor now has a tree history of edited node groups, which allows opening and editing nested node groups. The node editor also supports pinning now, so that different spaces can be used to edit different node groups simultaneously. For more ramblings and rationale see (really old) blog post on code.blender.org [3]. The interface of node groups has been overhauled. Sockets of a node group are no longer displayed in columns on either side, but instead special input/output nodes are used to mirror group sockets inside a node tree. This solves the problem of long node lines in groups and allows more adaptable node layout. Internal sockets can be exposed from a group by either connecting to the extension sockets in input/output nodes (shown as empty circle) or by adding sockets from the node property bar in the "Interface" panel. Further details such as the socket name can also be changed there. [1] http://wiki.blender.org/index.php/User:Phonybone/Python_Nodes [2] http://projects.blender.org/scm/viewvc.php/trunk/blender/release/scripts/templates_py/custom_nodes.py?view=markup&root=bf-blender [3] http://code.blender.org/index.php/2012/01/improving-node-group-interface-editing/
2013-03-18 16:34:57 +00:00
break;
}
}
}
}
/* Blender Data Definition */
BlenderRNA *RNA_create(void)
{
BlenderRNA *brna;
brna = MEM_callocN(sizeof(BlenderRNA), "BlenderRNA");
DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false);
DefRNA.structs.first = DefRNA.structs.last = NULL;
DefRNA.error = 0;
DefRNA.preprocess = 1;
return brna;
}
2011-05-31 02:14:25 +00:00
void RNA_define_free(BlenderRNA *UNUSED(brna))
{
StructDefRNA *ds;
FunctionDefRNA *dfunc;
AllocDefRNA *alloc;
for (alloc = DefRNA.allocs.first; alloc; alloc = alloc->next)
MEM_freeN(alloc->mem);
rna_freelistN(&DefRNA.allocs);
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next) {
for (dfunc = ds->functions.first; dfunc; dfunc = dfunc->cont.next)
rna_freelistN(&dfunc->cont.properties);
rna_freelistN(&ds->cont.properties);
rna_freelistN(&ds->functions);
}
rna_freelistN(&DefRNA.structs);
if (DefRNA.sdna) {
DNA_sdna_free(DefRNA.sdna);
DefRNA.sdna = NULL;
}
DefRNA.error = 0;
}
void RNA_define_verify_sdna(int verify)
{
DefRNA.verify = verify;
}
#ifndef RNA_RUNTIME
void RNA_define_animate_sdna(int animate)
{
DefRNA.animate = animate;
}
#endif
void RNA_struct_free_extension(StructRNA *srna, ExtensionRNA *ext)
{
#ifdef RNA_RUNTIME
ext->free(ext->data); /* decref's the PyObject that the srna owns */
RNA_struct_blender_type_set(srna, NULL); /* this gets accessed again - XXX fixme */
RNA_struct_py_type_set(srna, NULL); /* NULL the srna's value so RNA_struct_free wont complain of a leak */
#else
(void)srna;
(void)ext;
#endif
}
void RNA_struct_free(BlenderRNA *brna, StructRNA *srna)
{
#ifdef RNA_RUNTIME
FunctionRNA *func, *nextfunc;
PropertyRNA *prop, *nextprop;
PropertyRNA *parm, *nextparm;
#if 0
if (srna->flag & STRUCT_RUNTIME) {
if (RNA_struct_py_type_get(srna)) {
fprintf(stderr, "%s '%s' freed while holding a python reference\n", __func__, srna->identifier);
}
}
#endif
for (prop = srna->cont.properties.first; prop; prop = nextprop) {
nextprop = prop->next;
RNA_def_property_free_pointers(prop);
if (prop->flag & PROP_RUNTIME)
rna_freelinkN(&srna->cont.properties, prop);
}
for (func = srna->functions.first; func; func = nextfunc) {
nextfunc = func->cont.next;
for (parm = func->cont.properties.first; parm; parm = nextparm) {
nextparm = parm->next;
RNA_def_property_free_pointers(parm);
if (parm->flag & PROP_RUNTIME)
rna_freelinkN(&func->cont.properties, parm);
}
RNA_def_func_free_pointers(func);
if (func->flag & FUNC_RUNTIME)
rna_freelinkN(&srna->functions, func);
}
RNA_def_struct_free_pointers(srna);
if (srna->flag & STRUCT_RUNTIME)
rna_freelinkN(&brna->structs, srna);
#else
(void)brna, (void)srna;
#endif
}
void RNA_free(BlenderRNA *brna)
{
StructRNA *srna, *nextsrna;
FunctionRNA *func;
if (DefRNA.preprocess) {
RNA_define_free(brna);
for (srna = brna->structs.first; srna; srna = srna->cont.next) {
for (func = srna->functions.first; func; func = func->cont.next)
rna_freelistN(&func->cont.properties);
rna_freelistN(&srna->cont.properties);
rna_freelistN(&srna->functions);
}
rna_freelistN(&brna->structs);
MEM_freeN(brna);
}
else {
for (srna = brna->structs.first; srna; srna = nextsrna) {
nextsrna = srna->cont.next;
RNA_struct_free(brna, srna);
}
}
}
static size_t rna_property_type_sizeof(PropertyType type)
{
switch (type) {
case PROP_BOOLEAN: return sizeof(BoolPropertyRNA);
case PROP_INT: return sizeof(IntPropertyRNA);
case PROP_FLOAT: return sizeof(FloatPropertyRNA);
case PROP_STRING: return sizeof(StringPropertyRNA);
case PROP_ENUM: return sizeof(EnumPropertyRNA);
case PROP_POINTER: return sizeof(PointerPropertyRNA);
case PROP_COLLECTION: return sizeof(CollectionPropertyRNA);
default: return 0;
}
}
static StructDefRNA *rna_find_def_struct(StructRNA *srna)
{
StructDefRNA *ds;
for (ds = DefRNA.structs.first; ds; ds = ds->cont.next)
if (ds->srna == srna)
return ds;
return NULL;
}
/* Struct Definition */
StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRNA *srnafrom)
{
StructRNA *srna;
StructDefRNA *ds = NULL, *dsfrom = NULL;
PropertyRNA *prop;
if (DefRNA.preprocess) {
char error[512];
if (rna_validate_identifier(identifier, error, FALSE) == 0) {
fprintf(stderr, "%s: struct identifier \"%s\" error - %s\n", __func__, identifier, error);
DefRNA.error = 1;
}
}
srna = MEM_callocN(sizeof(StructRNA), "StructRNA");
DefRNA.laststruct = srna;
if (srnafrom) {
/* copy from struct to derive stuff, a bit clumsy since we can't
* use MEM_dupallocN, data structs may not be alloced but builtin */
memcpy(srna, srnafrom, sizeof(StructRNA));
srna->cont.prophash = NULL;
srna->cont.properties.first = srna->cont.properties.last = NULL;
srna->functions.first = srna->functions.last = NULL;
srna->py_type = NULL;
if (DefRNA.preprocess) {
srna->base = srnafrom;
dsfrom = rna_find_def_struct(srnafrom);
}
else
srna->base = srnafrom;
}
srna->identifier = identifier;
srna->name = identifier; /* may be overwritten later RNA_def_struct_ui_text */
srna->description = "";
/* may be overwritten later RNA_def_struct_translation_context */
srna->translation_context = BLF_I18NCONTEXT_DEFAULT_BPYRNA;
srna->flag |= STRUCT_UNDO;
if (!srnafrom)
srna->icon = ICON_DOT;
rna_addtail(&brna->structs, srna);
if (DefRNA.preprocess) {
ds = MEM_callocN(sizeof(StructDefRNA), "StructDefRNA");
ds->srna = srna;
rna_addtail(&DefRNA.structs, ds);
if (dsfrom)
ds->dnafromname = dsfrom->dnaname;
}
/* in preprocess, try to find sdna */
if (DefRNA.preprocess)
RNA_def_struct_sdna(srna, srna->identifier);
else
srna->flag |= STRUCT_RUNTIME;
if (srnafrom) {
srna->nameproperty = srnafrom->nameproperty;
srna->iteratorproperty = srnafrom->iteratorproperty;
}
else {
/* define some builtin properties */
prop = RNA_def_property(&srna->cont, "rna_properties", PROP_COLLECTION, PROP_NONE);
RNA_def_property_flag(prop, PROP_BUILTIN);
RNA_def_property_ui_text(prop, "Properties", "RNA property collection");
if (DefRNA.preprocess) {
RNA_def_property_struct_type(prop, "Property");
RNA_def_property_collection_funcs(prop, "rna_builtin_properties_begin", "rna_builtin_properties_next",
"rna_iterator_listbase_end", "rna_builtin_properties_get", NULL, NULL,
"rna_builtin_properties_lookup_string", NULL);
}
else {
#ifdef RNA_RUNTIME
CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
cprop->begin = rna_builtin_properties_begin;
cprop->next = rna_builtin_properties_next;
cprop->get = rna_builtin_properties_get;
cprop->item_type = &RNA_Property;
#endif
}
prop = RNA_def_property(&srna->cont, "rna_type", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_property_ui_text(prop, "RNA", "RNA type definition");
if (DefRNA.preprocess) {
RNA_def_property_struct_type(prop, "Struct");
RNA_def_property_pointer_funcs(prop, "rna_builtin_type_get", NULL, NULL, NULL);
}
else {
#ifdef RNA_RUNTIME
PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
pprop->get = rna_builtin_type_get;
pprop->type = &RNA_Struct;
#endif
}
}
return srna;
}
StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *from)
{
StructRNA *srnafrom = NULL;
/* only use RNA_def_struct() while pre-processing, otherwise use RNA_def_struct_ptr() */
BLI_assert(DefRNA.preprocess);
if (from) {
/* find struct to derive from */
for (srnafrom = brna->structs.first; srnafrom; srnafrom = srnafrom->cont.next)
if (strcmp(srnafrom->identifier, from) == 0)
break;
if (!srnafrom) {
fprintf(stderr, "%s: struct %s not found to define %s.\n", __func__, from, identifier);
DefRNA.error = 1;
}
}
return RNA_def_struct_ptr(brna, identifier, srnafrom);
}
void RNA_def_struct_sdna(StructRNA *srna, const char *structname)
{
StructDefRNA *ds;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
ds = rna_find_def_struct(srna);
if (!DNA_struct_find_nr(DefRNA.sdna, structname)) {
if (!DefRNA.silent) {
fprintf(stderr, "%s: %s not found.\n", __func__, structname);
DefRNA.error = 1;
}
return;
}
ds->dnaname = structname;
}
void RNA_def_struct_sdna_from(StructRNA *srna, const char *structname, const char *propname)
{
StructDefRNA *ds;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
ds = rna_find_def_struct(srna);
if (!ds->dnaname) {
fprintf(stderr, "%s: %s base struct must know DNA already.\n", __func__, structname);
return;
}
if (!DNA_struct_find_nr(DefRNA.sdna, structname)) {
if (!DefRNA.silent) {
fprintf(stderr, "%s: %s not found.\n", __func__, structname);
DefRNA.error = 1;
}
return;
}
ds->dnafromprop = propname;
ds->dnaname = structname;
}
void RNA_def_struct_name_property(struct StructRNA *srna, struct PropertyRNA *prop)
{
if (prop->type != PROP_STRING) {
fprintf(stderr, "%s: \"%s.%s\", must be a string property.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
}
else
srna->nameproperty = prop;
}
void RNA_def_struct_nested(BlenderRNA *brna, StructRNA *srna, const char *structname)
{
StructRNA *srnafrom;
/* find struct to derive from */
for (srnafrom = brna->structs.first; srnafrom; srnafrom = srnafrom->cont.next)
if (strcmp(srnafrom->identifier, structname) == 0)
break;
if (!srnafrom) {
fprintf(stderr, "%s: struct %s not found for %s.\n", __func__, structname, srna->identifier);
DefRNA.error = 1;
}
srna->nested = srnafrom;
}
void RNA_def_struct_flag(StructRNA *srna, int flag)
{
srna->flag |= flag;
}
void RNA_def_struct_clear_flag(StructRNA *srna, int flag)
{
srna->flag &= ~flag;
}
void RNA_def_struct_refine_func(StructRNA *srna, const char *refine)
{
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (refine) srna->refine = (StructRefineFunc)refine;
}
void RNA_def_struct_idprops_func(StructRNA *srna, const char *idproperties)
{
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (idproperties) srna->idproperties = (IDPropertiesFunc)idproperties;
}
void RNA_def_struct_register_funcs(StructRNA *srna, const char *reg, const char *unreg, const char *instance)
{
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (reg) srna->reg = (StructRegisterFunc)reg;
if (unreg) srna->unreg = (StructUnregisterFunc)unreg;
if (instance) srna->instance = (StructInstanceFunc)instance;
}
void RNA_def_struct_path_func(StructRNA *srna, const char *path)
{
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (path) srna->path = (StructPathFunc)path;
}
void RNA_def_struct_identifier(StructRNA *srna, const char *identifier)
{
if (DefRNA.preprocess) {
fprintf(stderr, "%s: only at runtime.\n", __func__);
return;
}
srna->identifier = identifier;
}
void RNA_def_struct_ui_text(StructRNA *srna, const char *name, const char *description)
{
DESCR_CHECK(description, srna->identifier, NULL);
srna->name = name;
srna->description = description;
}
void RNA_def_struct_ui_icon(StructRNA *srna, int icon)
{
srna->icon = icon;
}
void RNA_def_struct_translation_context(StructRNA *srna, const char *context)
{
srna->translation_context = context ? context : BLF_I18NCONTEXT_DEFAULT_BPYRNA;
}
/* Property Definition */
PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype)
{
2012-10-26 04:14:10 +00:00
/*StructRNA *srna = DefRNA.laststruct;*/ /* invalid for python defined props */
ContainerRNA *cont = cont_;
ContainerDefRNA *dcont;
PropertyDefRNA *dprop = NULL;
PropertyRNA *prop;
if (DefRNA.preprocess) {
char error[512];
if (rna_validate_identifier(identifier, error, TRUE) == 0) {
fprintf(stderr, "%s: property identifier \"%s.%s\" - %s\n", __func__,
CONTAINER_RNA_ID(cont), identifier, error);
DefRNA.error = 1;
}
dcont = rna_find_container_def(cont);
/* XXX - toto, detect supertype collisions */
if (rna_findlink(&dcont->properties, identifier)) {
fprintf(stderr, "%s: duplicate identifier \"%s.%s\"\n", __func__, CONTAINER_RNA_ID(cont), identifier);
DefRNA.error = 1;
}
dprop = MEM_callocN(sizeof(PropertyDefRNA), "PropertyDefRNA");
rna_addtail(&dcont->properties, dprop);
}
else {
#ifdef DEBUG
char error[512];
if (rna_validate_identifier(identifier, error, TRUE) == 0) {
fprintf(stderr, "%s: runtime property identifier \"%s.%s\" - %s\n", __func__,
CONTAINER_RNA_ID(cont), identifier, error);
DefRNA.error = 1;
}
#endif
}
prop = MEM_callocN(rna_property_type_sizeof(type), "PropertyRNA");
switch (type) {
case PROP_BOOLEAN:
if (DefRNA.preprocess) {
if ((subtype & ~(PROP_LAYER_MEMBER)) != PROP_NONE) {
fprintf(stderr, "%s: subtype does not apply to 'PROP_BOOLEAN' \"%s.%s\"\n", __func__,
CONTAINER_RNA_ID(cont), identifier);
DefRNA.error = 1;
}
}
break;
2012-09-08 08:59:47 +00:00
case PROP_INT:
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
#ifndef RNA_RUNTIME
if (subtype == PROP_DISTANCE) {
fprintf(stderr, "%s: subtype does not apply to 'PROP_INT' \"%s.%s\"\n", __func__,
CONTAINER_RNA_ID(cont), identifier);
DefRNA.error = 1;
}
#endif
iprop->hardmin = (subtype == PROP_UNSIGNED) ? 0 : INT_MIN;
iprop->hardmax = INT_MAX;
iprop->softmin = (subtype == PROP_UNSIGNED) ? 0 : -10000; /* rather arbitrary .. */
iprop->softmax = 10000;
iprop->step = 1;
break;
}
2012-09-08 08:59:47 +00:00
case PROP_FLOAT:
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
fprop->hardmin = (subtype == PROP_UNSIGNED) ? 0.0f : -FLT_MAX;
fprop->hardmax = FLT_MAX;
if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
fprop->softmin = 0.0f;
fprop->softmax = 1.0f;
}
else if (subtype == PROP_FACTOR) {
fprop->softmin = fprop->hardmin = 0.0f;
fprop->softmax = fprop->hardmax = 1.0f;
}
else {
fprop->softmin = (subtype == PROP_UNSIGNED) ? 0.0f : -10000.0f; /* rather arbitrary .. */
fprop->softmax = 10000.0f;
}
fprop->step = 10;
fprop->precision = 3;
break;
}
2012-09-08 08:59:47 +00:00
case PROP_STRING:
{
StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
sprop->defaultvalue = "";
break;
}
case PROP_POINTER:
prop->flag |= PROP_THICK_WRAP; /* needed for default behavior when PROP_RNAPTR is set */
break;
case PROP_ENUM:
case PROP_COLLECTION:
break;
default:
fprintf(stderr, "%s: \"%s.%s\", invalid property type.\n", __func__, CONTAINER_RNA_ID(cont), identifier);
DefRNA.error = 1;
return NULL;
}
if (DefRNA.preprocess) {
dprop->cont = cont;
dprop->prop = prop;
}
prop->magic = RNA_MAGIC;
prop->identifier = identifier;
prop->type = type;
prop->subtype = subtype;
prop->name = identifier;
prop->description = "";
prop->translation_context = BLF_I18NCONTEXT_DEFAULT_BPYRNA;
/* a priori not raw editable */
prop->rawtype = -1;
if (type != PROP_COLLECTION && type != PROP_POINTER) {
prop->flag = PROP_EDITABLE;
if (type != PROP_STRING) {
#ifdef RNA_RUNTIME
prop->flag |= PROP_ANIMATABLE;
#else
if (DefRNA.animate) {
prop->flag |= PROP_ANIMATABLE;
}
#endif
}
}
if (type == PROP_STRING) {
/* used so generated 'get/length/set' functions skip a NULL check
* in some cases we want it */
RNA_def_property_flag(prop, PROP_NEVER_NULL);
}
if (DefRNA.preprocess) {
switch (type) {
case PROP_BOOLEAN:
DefRNA.silent = 1;
RNA_def_property_boolean_sdna(prop, NULL, identifier, 0);
DefRNA.silent = 0;
break;
2012-09-08 08:59:47 +00:00
case PROP_INT:
{
DefRNA.silent = 1;
RNA_def_property_int_sdna(prop, NULL, identifier);
DefRNA.silent = 0;
break;
}
2012-09-08 08:59:47 +00:00
case PROP_FLOAT:
{
DefRNA.silent = 1;
RNA_def_property_float_sdna(prop, NULL, identifier);
DefRNA.silent = 0;
break;
}
2012-09-08 08:59:47 +00:00
case PROP_STRING:
{
DefRNA.silent = 1;
RNA_def_property_string_sdna(prop, NULL, identifier);
DefRNA.silent = 0;
break;
}
case PROP_ENUM:
DefRNA.silent = 1;
RNA_def_property_enum_sdna(prop, NULL, identifier);
DefRNA.silent = 0;
break;
case PROP_POINTER:
DefRNA.silent = 1;
RNA_def_property_pointer_sdna(prop, NULL, identifier);
DefRNA.silent = 0;
break;
case PROP_COLLECTION:
DefRNA.silent = 1;
RNA_def_property_collection_sdna(prop, NULL, identifier, NULL);
DefRNA.silent = 0;
break;
}
}
else {
prop->flag |= PROP_IDPROPERTY | PROP_RUNTIME;
#ifdef RNA_RUNTIME
if (cont->prophash)
BLI_ghash_insert(cont->prophash, (void *)prop->identifier, prop);
#endif
}
rna_addtail(&cont->properties, prop);
return prop;
}
void RNA_def_property_flag(PropertyRNA *prop, int flag)
{
prop->flag |= flag;
}
void RNA_def_property_clear_flag(PropertyRNA *prop, int flag)
{
prop->flag &= ~flag;
}
void RNA_def_property_subtype(PropertyRNA *prop, PropertySubType subtype)
{
prop->subtype = subtype;
}
void RNA_def_property_array(PropertyRNA *prop, int length)
{
StructRNA *srna = DefRNA.laststruct;
if (length < 0) {
fprintf(stderr, "%s: \"%s.%s\", array length must be zero of greater.\n", __func__,
srna->identifier, prop->identifier);
DefRNA.error = 1;
return;
}
if (length > RNA_MAX_ARRAY_LENGTH) {
fprintf(stderr, "%s: \"%s.%s\", array length must be smaller than %d.\n", __func__,
srna->identifier, prop->identifier, RNA_MAX_ARRAY_LENGTH);
DefRNA.error = 1;
return;
}
if (prop->arraydimension > 1) {
fprintf(stderr, "%s: \"%s.%s\", array dimensions has been set to %u but would be overwritten as 1.\n",
__func__, srna->identifier, prop->identifier, prop->arraydimension);
DefRNA.error = 1;
return;
}
switch (prop->type) {
case PROP_BOOLEAN:
case PROP_INT:
case PROP_FLOAT:
prop->arraylength[0] = length;
prop->totarraylength = length;
prop->arraydimension = 1;
break;
default:
fprintf(stderr, "%s: \"%s.%s\", only boolean/int/float can be array.\n",
__func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int length[])
{
StructRNA *srna = DefRNA.laststruct;
int i;
if (dimension < 1 || dimension > RNA_MAX_ARRAY_DIMENSION) {
fprintf(stderr, "%s: \"%s.%s\", array dimension must be between 1 and %d.\n",
__func__, srna->identifier, prop->identifier, RNA_MAX_ARRAY_DIMENSION);
DefRNA.error = 1;
return;
}
switch (prop->type) {
case PROP_BOOLEAN:
case PROP_INT:
case PROP_FLOAT:
break;
default:
fprintf(stderr, "%s: \"%s.%s\", only boolean/int/float can be array.\n",
__func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
prop->arraydimension = dimension;
prop->totarraylength = 0;
if (length) {
memcpy(prop->arraylength, length, sizeof(int) * dimension);
prop->totarraylength = length[0];
for (i = 1; i < dimension; i++)
prop->totarraylength *= length[i];
}
else
memset(prop->arraylength, 0, sizeof(prop->arraylength));
/* TODO make sure arraylength values are sane */
}
void RNA_def_property_ui_text(PropertyRNA *prop, const char *name, const char *description)
{
DESCR_CHECK(description, prop->identifier, NULL);
prop->name = name;
prop->description = description;
}
void RNA_def_property_ui_icon(PropertyRNA *prop, int icon, int consecutive)
{
prop->icon = icon;
if (consecutive)
prop->flag |= PROP_ICONS_CONSECUTIVE;
}
/**
* The values hare are a little confusing:
*
* \param step For floats this is (step / 100), why /100? - nobody knows.
* for int's, whole values are used.
*
* \param precision The number of zeros to show
* (as a whole number - common range is 1 - 6), see PRECISION_FLOAT_MAX
*/
void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double step, int precision)
{
StructRNA *srna = DefRNA.laststruct;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_INT:
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
iprop->softmin = (int)min;
iprop->softmax = (int)max;
iprop->step = (int)step;
break;
}
2012-09-08 08:59:47 +00:00
case PROP_FLOAT:
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
fprop->softmin = (float)min;
fprop->softmax = (float)max;
fprop->step = (float)step;
fprop->precision = (int)precision;
#if 0 /* handy but annoying */
if (DefRNA.preprocess) {
/* check we're not over PRECISION_FLOAT_MAX */
if (fprop->precision > 6) {
fprintf(stderr, "%s: \"%s.%s\", precision value over maximum.\n",
__func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
}
else if (fprop->precision < 1) {
fprintf(stderr, "%s: \"%s.%s\", precision value under minimum.\n",
__func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
}
}
#endif
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", invalid type for ui range.\n",
__func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_range(PropertyRNA *prop, double min, double max)
{
StructRNA *srna = DefRNA.laststruct;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_INT:
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
iprop->hardmin = (int)min;
iprop->hardmax = (int)max;
iprop->softmin = MAX2((int)min, iprop->hardmin);
iprop->softmax = MIN2((int)max, iprop->hardmax);
break;
}
2012-09-08 08:59:47 +00:00
case PROP_FLOAT:
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
fprop->hardmin = (float)min;
fprop->hardmax = (float)max;
fprop->softmin = MAX2((float)min, fprop->hardmin);
fprop->softmax = MIN2((float)max, fprop->hardmax);
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", invalid type for range.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_struct_type(PropertyRNA *prop, const char *type)
{
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s \"%s.%s\": only during preprocessing.\n", __func__, srna->identifier, prop->identifier);
return;
}
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_POINTER:
{
PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
pprop->type = (StructRNA *)type;
break;
}
2012-09-08 08:59:47 +00:00
case PROP_COLLECTION:
{
CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
cprop->item_type = (StructRNA *)type;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", invalid type for struct type.\n",
__func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_struct_runtime(PropertyRNA *prop, StructRNA *type)
{
StructRNA *srna = DefRNA.laststruct;
if (DefRNA.preprocess) {
fprintf(stderr, "%s: only at runtime.\n", __func__);
return;
}
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_POINTER:
{
PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
pprop->type = type;
if (type && (type->flag & STRUCT_ID_REFCOUNT))
prop->flag |= PROP_ID_REFCOUNT;
break;
}
2012-09-08 08:59:47 +00:00
case PROP_COLLECTION:
{
CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
cprop->item_type = type;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", invalid type for struct type.\n",
__func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item)
{
StructRNA *srna = DefRNA.laststruct;
int i, defaultfound = 0;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_ENUM:
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
eprop->item = (EnumPropertyItem *)item;
eprop->totitem = 0;
for (i = 0; item[i].identifier; i++) {
eprop->totitem++;
if (item[i].identifier[0] && item[i].value == eprop->defaultvalue)
defaultfound = 1;
}
if (!defaultfound) {
for (i = 0; item[i].identifier; i++) {
if (item[i].identifier[0]) {
eprop->defaultvalue = item[i].value;
break;
}
}
}
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", invalid type for struct type.\n",
__func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_string_maxlength(PropertyRNA *prop, int maxlength)
{
StructRNA *srna = DefRNA.laststruct;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_STRING:
{
StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
sprop->maxlength = maxlength;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not string.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_boolean_default(PropertyRNA *prop, int value)
{
StructRNA *srna = DefRNA.laststruct;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_BOOLEAN:
{
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
bprop->defaultvalue = value;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not boolean.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_boolean_array_default(PropertyRNA *prop, const int *array)
{
StructRNA *srna = DefRNA.laststruct;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_BOOLEAN:
{
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
bprop->defaultarray = array;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not boolean.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_int_default(PropertyRNA *prop, int value)
{
StructRNA *srna = DefRNA.laststruct;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_INT:
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
iprop->defaultvalue = value;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not int.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_int_array_default(PropertyRNA *prop, const int *array)
{
StructRNA *srna = DefRNA.laststruct;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_INT:
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
iprop->defaultarray = array;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not int.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_float_default(PropertyRNA *prop, float value)
{
StructRNA *srna = DefRNA.laststruct;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_FLOAT:
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
fprop->defaultvalue = value;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not float.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
/* array must remain valid after this function finishes */
void RNA_def_property_float_array_default(PropertyRNA *prop, const float *array)
{
StructRNA *srna = DefRNA.laststruct;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_FLOAT:
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
fprop->defaultarray = array; /* WARNING, this array must not come from the stack and lost */
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not float.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_string_default(PropertyRNA *prop, const char *value)
{
StructRNA *srna = DefRNA.laststruct;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_STRING:
{
StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
sprop->defaultvalue = value;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not string.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_enum_default(PropertyRNA *prop, int value)
{
StructRNA *srna = DefRNA.laststruct;
int i, defaultfound = 0;
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_ENUM:
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
eprop->defaultvalue = value;
if (prop->flag & PROP_ENUM_FLAG) {
/* check all bits are accounted for */
int totflag = 0;
for (i = 0; i < eprop->totitem; i++) {
if (eprop->item[i].identifier[0]) {
totflag |= eprop->item[i].value;
}
}
if (eprop->defaultvalue & ~totflag) {
fprintf(stderr, "%s: \"%s.%s\", default includes unused bits (%d).\n",
__func__, srna->identifier, prop->identifier, eprop->defaultvalue & ~totflag);
DefRNA.error = 1;
}
}
else {
for (i = 0; i < eprop->totitem; i++) {
if (eprop->item[i].identifier[0] && eprop->item[i].value == eprop->defaultvalue)
defaultfound = 1;
}
if (!defaultfound && eprop->totitem) {
if (value == 0) {
eprop->defaultvalue = eprop->item[0].value;
}
else {
fprintf(stderr, "%s: \"%s.%s\", default is not in items.\n",
__func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
}
}
}
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not enum.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
/* SDNA */
static PropertyDefRNA *rna_def_property_sdna(PropertyRNA *prop, const char *structname, const char *propname)
{
DNAStructMember smember;
StructDefRNA *ds;
PropertyDefRNA *dp;
dp = rna_find_struct_property_def(DefRNA.laststruct, prop);
if (dp == NULL) return NULL;
ds = rna_find_struct_def((StructRNA *)dp->cont);
if (!structname)
structname = ds->dnaname;
if (!propname)
propname = prop->identifier;
if (!rna_find_sdna_member(DefRNA.sdna, structname, propname, &smember)) {
if (DefRNA.silent) {
return NULL;
}
else if (!DefRNA.verify) {
/* some basic values to survive even with sdna info */
dp->dnastructname = structname;
dp->dnaname = propname;
if (prop->type == PROP_BOOLEAN)
dp->dnaarraylength = 1;
if (prop->type == PROP_POINTER)
dp->dnapointerlevel = 1;
return dp;
}
else {
fprintf(stderr, "%s: \"%s.%s\" (identifier \"%s\") not found.\n",
__func__, structname, propname, prop->identifier);
DefRNA.error = 1;
return NULL;
}
}
if (smember.arraylength > 1) {
prop->arraylength[0] = smember.arraylength;
prop->totarraylength = smember.arraylength;
prop->arraydimension = 1;
}
else {
prop->arraydimension = 0;
prop->totarraylength = 0;
}
dp->dnastructname = structname;
dp->dnastructfromname = ds->dnafromname;
dp->dnastructfromprop = ds->dnafromprop;
dp->dnaname = propname;
dp->dnatype = smember.type;
dp->dnaarraylength = smember.arraylength;
dp->dnapointerlevel = smember.pointerlevel;
return dp;
}
void RNA_def_property_boolean_sdna(PropertyRNA *prop, const char *structname, const char *propname, int bit)
{
PropertyDefRNA *dp;
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (prop->type != PROP_BOOLEAN) {
fprintf(stderr, "%s: \"%s.%s\", type is not boolean.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
return;
}
if ((dp = rna_def_property_sdna(prop, structname, propname))) {
if (DefRNA.silent == 0) {
/* error check to ensure floats are not wrapped as ints/bools */
if (dp->dnatype && *dp->dnatype && IS_DNATYPE_INT_COMPAT(dp->dnatype) == 0) {
fprintf(stderr, "%s: %s.%s is a '%s' but wrapped as type '%s'.\n",
__func__, srna->identifier, prop->identifier, dp->dnatype, RNA_property_typename(prop->type));
DefRNA.error = 1;
return;
}
}
dp->booleanbit = bit;
}
}
void RNA_def_property_boolean_negative_sdna(PropertyRNA *prop, const char *structname,
const char *propname, int booleanbit)
{
PropertyDefRNA *dp;
RNA_def_property_boolean_sdna(prop, structname, propname, booleanbit);
dp = rna_find_struct_property_def(DefRNA.laststruct, prop);
if (dp)
dp->booleannegative = 1;
}
void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const char *propname)
{
PropertyDefRNA *dp;
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (prop->type != PROP_INT) {
fprintf(stderr, "%s: \"%s.%s\", type is not int.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
return;
}
if ((dp = rna_def_property_sdna(prop, structname, propname))) {
/* error check to ensure floats are not wrapped as ints/bools */
if (DefRNA.silent == 0) {
if (dp->dnatype && *dp->dnatype && IS_DNATYPE_INT_COMPAT(dp->dnatype) == 0) {
fprintf(stderr, "%s: %s.%s is a '%s' but wrapped as type '%s'.\n",
__func__, srna->identifier, prop->identifier, dp->dnatype, RNA_property_typename(prop->type));
DefRNA.error = 1;
return;
}
}
/* SDNA doesn't pass us unsigned unfortunately .. */
if (dp->dnatype && strcmp(dp->dnatype, "char") == 0) {
iprop->hardmin = iprop->softmin = CHAR_MIN;
iprop->hardmax = iprop->softmax = CHAR_MAX;
}
else if (dp->dnatype && strcmp(dp->dnatype, "short") == 0) {
iprop->hardmin = iprop->softmin = SHRT_MIN;
iprop->hardmax = iprop->softmax = SHRT_MAX;
}
else if (dp->dnatype && strcmp(dp->dnatype, "int") == 0) {
iprop->hardmin = INT_MIN;
iprop->hardmax = INT_MAX;
iprop->softmin = -10000; /* rather arbitrary .. */
iprop->softmax = 10000;
}
if (prop->subtype == PROP_UNSIGNED || prop->subtype == PROP_PERCENTAGE || prop->subtype == PROP_FACTOR)
iprop->hardmin = iprop->softmin = 0;
}
}
void RNA_def_property_float_sdna(PropertyRNA *prop, const char *structname, const char *propname)
{
PropertyDefRNA *dp;
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (prop->type != PROP_FLOAT) {
fprintf(stderr, "%s: \"%s.%s\", type is not float.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
return;
}
if ((dp = rna_def_property_sdna(prop, structname, propname))) {
/* silent is for internal use */
if (DefRNA.silent == 0) {
if (dp->dnatype && *dp->dnatype && IS_DNATYPE_FLOAT_COMPAT(dp->dnatype) == 0) {
if (prop->subtype != PROP_COLOR_GAMMA) { /* colors are an exception. these get translated */
fprintf(stderr, "%s: %s.%s is a '%s' but wrapped as type '%s'.\n",
__func__, srna->identifier, prop->identifier, dp->dnatype,
RNA_property_typename(prop->type));
DefRNA.error = 1;
return;
}
}
}
if (dp->dnatype && strcmp(dp->dnatype, "char") == 0) {
fprop->hardmin = fprop->softmin = 0.0f;
fprop->hardmax = fprop->softmax = 1.0f;
}
}
rna_def_property_sdna(prop, structname, propname);
}
void RNA_def_property_enum_sdna(PropertyRNA *prop, const char *structname, const char *propname)
{
/* PropertyDefRNA *dp; */
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (prop->type != PROP_ENUM) {
fprintf(stderr, "%s: \"%s.%s\", type is not enum.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
return;
}
if ((/* dp= */ rna_def_property_sdna(prop, structname, propname))) {
if (prop->arraydimension) {
prop->arraydimension = 0;
prop->totarraylength = 0;
if (!DefRNA.silent) {
fprintf(stderr, "%s: \"%s.%s\", array not supported for enum type.\n",
__func__, structname, propname);
DefRNA.error = 1;
}
}
}
}
void RNA_def_property_enum_bitflag_sdna(PropertyRNA *prop, const char *structname, const char *propname)
{
PropertyDefRNA *dp;
RNA_def_property_enum_sdna(prop, structname, propname);
dp = rna_find_struct_property_def(DefRNA.laststruct, prop);
if (dp)
dp->enumbitflags = 1;
}
void RNA_def_property_string_sdna(PropertyRNA *prop, const char *structname, const char *propname)
{
/* PropertyDefRNA *dp; */
StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (prop->type != PROP_STRING) {
fprintf(stderr, "%s: \"%s.%s\", type is not string.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
return;
}
if ((/* dp= */ rna_def_property_sdna(prop, structname, propname))) {
if (prop->arraydimension) {
sprop->maxlength = prop->totarraylength;
prop->arraydimension = 0;
prop->totarraylength = 0;
}
}
}
void RNA_def_property_pointer_sdna(PropertyRNA *prop, const char *structname, const char *propname)
{
/* PropertyDefRNA *dp; */
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (prop->type != PROP_POINTER) {
fprintf(stderr, "%s: \"%s.%s\", type is not pointer.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
return;
}
if ((/* dp= */ rna_def_property_sdna(prop, structname, propname))) {
if (prop->arraydimension) {
prop->arraydimension = 0;
prop->totarraylength = 0;
if (!DefRNA.silent) {
fprintf(stderr, "%s: \"%s.%s\", array not supported for pointer type.\n",
__func__, structname, propname);
DefRNA.error = 1;
}
}
}
}
void RNA_def_property_collection_sdna(PropertyRNA *prop, const char *structname, const char *propname,
const char *lengthpropname)
{
PropertyDefRNA *dp;
CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (prop->type != PROP_COLLECTION) {
fprintf(stderr, "%s: \"%s.%s\", type is not collection.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
return;
}
if ((dp = rna_def_property_sdna(prop, structname, propname))) {
if (prop->arraydimension && !lengthpropname) {
prop->arraydimension = 0;
prop->totarraylength = 0;
if (!DefRNA.silent) {
fprintf(stderr, "%s: \"%s.%s\", array of collections not supported.\n",
__func__, structname, propname);
DefRNA.error = 1;
}
}
if (dp->dnatype && strcmp(dp->dnatype, "ListBase") == 0) {
cprop->next = (PropCollectionNextFunc)"rna_iterator_listbase_next";
cprop->get = (PropCollectionGetFunc)"rna_iterator_listbase_get";
cprop->end = (PropCollectionEndFunc)"rna_iterator_listbase_end";
}
}
if (dp && lengthpropname) {
DNAStructMember smember;
StructDefRNA *ds = rna_find_struct_def((StructRNA *)dp->cont);
if (!structname)
structname = ds->dnaname;
if (lengthpropname[0] == 0 || rna_find_sdna_member(DefRNA.sdna, structname, lengthpropname, &smember)) {
if (lengthpropname[0] == 0) {
dp->dnalengthfixed = prop->totarraylength;
prop->arraydimension = 0;
prop->totarraylength = 0;
}
else {
dp->dnalengthstructname = structname;
dp->dnalengthname = lengthpropname;
prop->totarraylength = 0;
}
cprop->next = (PropCollectionNextFunc)"rna_iterator_array_next";
cprop->end = (PropCollectionEndFunc)"rna_iterator_array_end";
if (dp->dnapointerlevel >= 2)
cprop->get = (PropCollectionGetFunc)"rna_iterator_array_dereference_get";
else
cprop->get = (PropCollectionGetFunc)"rna_iterator_array_get";
}
else {
if (!DefRNA.silent) {
fprintf(stderr, "%s: \"%s.%s\" not found.\n", __func__, structname, lengthpropname);
DefRNA.error = 1;
}
}
}
}
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
{
prop->translation_context = context ? context : BLF_I18NCONTEXT_DEFAULT_BPYRNA;
}
/* Functions */
void RNA_def_property_editable_func(PropertyRNA *prop, const char *editable)
{
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (editable) prop->editable = (EditableFunc)editable;
}
void RNA_def_property_editable_array_func(PropertyRNA *prop, const char *editable)
{
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (editable) prop->itemeditable = (ItemEditableFunc)editable;
}
void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *func)
{
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
prop->noteflag = noteflag;
prop->update = (UpdateFunc)func;
}
void RNA_def_property_update_runtime(PropertyRNA *prop, void *func)
{
prop->update = func;
}
void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getlength)
{
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
if (!(prop->flag & PROP_DYNAMIC)) {
fprintf(stderr, "%s: property is a not dynamic array.\n", __func__);
DefRNA.error = 1;
return;
}
if (getlength) prop->getlength = (PropArrayLengthGetFunc)getlength;
}
void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const char *set)
{
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_BOOLEAN:
{
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
if (prop->arraydimension) {
if (get) bprop->getarray = (PropBooleanArrayGetFunc)get;
if (set) bprop->setarray = (PropBooleanArraySetFunc)set;
}
else {
if (get) bprop->get = (PropBooleanGetFunc)get;
if (set) bprop->set = (PropBooleanSetFunc)set;
}
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not boolean.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_boolean_funcs_runtime(PropertyRNA *prop, BooleanPropertyGetFunc getfunc, BooleanPropertySetFunc setfunc)
{
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
if (getfunc) bprop->get_ex = getfunc;
if (setfunc) bprop->set_ex = setfunc;
if (getfunc || setfunc) {
/* don't save in id properties */
prop->flag &= ~PROP_IDPROPERTY;
if (!setfunc)
prop->flag &= ~PROP_EDITABLE;
}
}
void RNA_def_property_boolean_array_funcs_runtime(PropertyRNA *prop, BooleanArrayPropertyGetFunc getfunc, BooleanArrayPropertySetFunc setfunc)
{
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
if (getfunc) bprop->getarray_ex = getfunc;
if (setfunc) bprop->setarray_ex = setfunc;
if (getfunc || setfunc) {
/* don't save in id properties */
prop->flag &= ~PROP_IDPROPERTY;
if (!setfunc)
prop->flag &= ~PROP_EDITABLE;
}
}
void RNA_def_property_int_funcs(PropertyRNA *prop, const char *get, const char *set, const char *range)
{
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_INT:
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
if (prop->arraydimension) {
if (get) iprop->getarray = (PropIntArrayGetFunc)get;
if (set) iprop->setarray = (PropIntArraySetFunc)set;
}
else {
if (get) iprop->get = (PropIntGetFunc)get;
if (set) iprop->set = (PropIntSetFunc)set;
}
if (range) iprop->range = (PropIntRangeFunc)range;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not int.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_int_funcs_runtime(PropertyRNA *prop, IntPropertyGetFunc getfunc, IntPropertySetFunc setfunc, IntPropertyRangeFunc rangefunc)
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
if (getfunc) iprop->get_ex = getfunc;
if (setfunc) iprop->set_ex = setfunc;
if (rangefunc) iprop->range_ex = rangefunc;
if (getfunc || setfunc) {
/* don't save in id properties */
prop->flag &= ~PROP_IDPROPERTY;
if (!setfunc)
prop->flag &= ~PROP_EDITABLE;
}
}
void RNA_def_property_int_array_funcs_runtime(PropertyRNA *prop, IntArrayPropertyGetFunc getfunc, IntArrayPropertySetFunc setfunc, IntPropertyRangeFunc rangefunc)
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
if (getfunc) iprop->getarray_ex = getfunc;
if (setfunc) iprop->setarray_ex = setfunc;
if (rangefunc) iprop->range_ex = rangefunc;
if (getfunc || setfunc) {
/* don't save in id properties */
prop->flag &= ~PROP_IDPROPERTY;
if (!setfunc)
prop->flag &= ~PROP_EDITABLE;
}
}
void RNA_def_property_float_funcs(PropertyRNA *prop, const char *get, const char *set, const char *range)
{
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_FLOAT:
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
if (prop->arraydimension) {
if (get) fprop->getarray = (PropFloatArrayGetFunc)get;
if (set) fprop->setarray = (PropFloatArraySetFunc)set;
}
else {
if (get) fprop->get = (PropFloatGetFunc)get;
if (set) fprop->set = (PropFloatSetFunc)set;
}
if (range) fprop->range = (PropFloatRangeFunc)range;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not float.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_float_funcs_runtime(PropertyRNA *prop, FloatPropertyGetFunc getfunc, FloatPropertySetFunc setfunc, FloatPropertyRangeFunc rangefunc)
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
if (getfunc) fprop->get_ex = getfunc;
if (setfunc) fprop->set_ex = setfunc;
if (rangefunc) fprop->range_ex = rangefunc;
if (getfunc || setfunc) {
/* don't save in id properties */
prop->flag &= ~PROP_IDPROPERTY;
if (!setfunc)
prop->flag &= ~PROP_EDITABLE;
}
}
void RNA_def_property_float_array_funcs_runtime(PropertyRNA *prop, FloatArrayPropertyGetFunc getfunc, FloatArrayPropertySetFunc setfunc, FloatPropertyRangeFunc rangefunc)
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
if (getfunc) fprop->getarray_ex = getfunc;
if (setfunc) fprop->setarray_ex = setfunc;
if (rangefunc) fprop->range_ex = rangefunc;
if (getfunc || setfunc) {
/* don't save in id properties */
prop->flag &= ~PROP_IDPROPERTY;
if (!setfunc)
prop->flag &= ~PROP_EDITABLE;
}
}
void RNA_def_property_enum_funcs(PropertyRNA *prop, const char *get, const char *set, const char *item)
{
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_ENUM:
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
if (get) eprop->get = (PropEnumGetFunc)get;
if (set) eprop->set = (PropEnumSetFunc)set;
if (item) eprop->itemf = (PropEnumItemFunc)item;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not enum.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_enum_funcs_runtime(PropertyRNA *prop, EnumPropertyGetFunc getfunc, EnumPropertySetFunc setfunc, EnumPropertyItemFunc itemfunc)
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
if (getfunc) eprop->get_ex = getfunc;
if (setfunc) eprop->set_ex = setfunc;
if (itemfunc) eprop->itemf = itemfunc;
if (getfunc || setfunc) {
/* don't save in id properties */
prop->flag &= ~PROP_IDPROPERTY;
if (!setfunc)
prop->flag &= ~PROP_EDITABLE;
}
}
void RNA_def_property_enum_py_data(PropertyRNA *prop, void *py_data)
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
eprop->py_data = py_data;
}
void RNA_def_property_string_funcs(PropertyRNA *prop, const char *get, const char *length, const char *set)
{
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_STRING:
{
StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
if (get) sprop->get = (PropStringGetFunc)get;
if (length) sprop->length = (PropStringLengthFunc)length;
if (set) sprop->set = (PropStringSetFunc)set;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not string.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_string_funcs_runtime(PropertyRNA *prop, StringPropertyGetFunc getfunc, StringPropertyLengthFunc lengthfunc, StringPropertySetFunc setfunc)
{
StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
if (getfunc) sprop->get_ex = getfunc;
if (lengthfunc) sprop->length_ex = lengthfunc;
if (setfunc) sprop->set_ex = setfunc;
if (getfunc || setfunc) {
/* don't save in id properties */
prop->flag &= ~PROP_IDPROPERTY;
if (!setfunc)
prop->flag &= ~PROP_EDITABLE;
}
}
void RNA_def_property_pointer_funcs(PropertyRNA *prop, const char *get, const char *set,
const char *typef, const char *poll)
{
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_POINTER:
{
PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
if (get) pprop->get = (PropPointerGetFunc)get;
if (set) pprop->set = (PropPointerSetFunc)set;
if (typef) pprop->typef = (PropPointerTypeFunc)typef;
if (poll) pprop->poll = (PropPointerPollFunc)poll;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not pointer.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_collection_funcs(PropertyRNA *prop, const char *begin, const char *next, const char *end,
const char *get, const char *length, const char *lookupint,
const char *lookupstring, const char *assignint)
{
StructRNA *srna = DefRNA.laststruct;
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return;
}
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_COLLECTION:
{
CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
if (begin) cprop->begin = (PropCollectionBeginFunc)begin;
if (next) cprop->next = (PropCollectionNextFunc)next;
if (end) cprop->end = (PropCollectionEndFunc)end;
if (get) cprop->get = (PropCollectionGetFunc)get;
if (length) cprop->length = (PropCollectionLengthFunc)length;
if (lookupint) cprop->lookupint = (PropCollectionLookupIntFunc)lookupint;
if (lookupstring) cprop->lookupstring = (PropCollectionLookupStringFunc)lookupstring;
if (assignint) cprop->assignint = (PropCollectionAssignIntFunc)assignint;
break;
}
default:
fprintf(stderr, "%s: \"%s.%s\", type is not collection.\n", __func__, srna->identifier, prop->identifier);
DefRNA.error = 1;
break;
}
}
void RNA_def_property_srna(PropertyRNA *prop, const char *type)
{
prop->srna = (StructRNA *)type;
}
void RNA_def_py_data(PropertyRNA *prop, void *py_data)
{
prop->py_data = py_data;
}
/* Compact definitions */
PropertyRNA *RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, int default_value,
const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_default(prop, default_value);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_boolean_array(StructOrFunctionRNA *cont_, const char *identifier, int len, int *default_value,
const char *ui_name, const char *ui_description)
2009-03-04 15:30:47 +00:00
{
ContainerRNA *cont = cont_;
2009-03-04 15:30:47 +00:00
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_BOOLEAN, PROP_NONE);
if (len != 0) RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_boolean_array_default(prop, default_value);
2009-03-04 15:30:47 +00:00
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_boolean_layer(StructOrFunctionRNA *cont_, const char *identifier, int len, int *default_value,
const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_BOOLEAN, PROP_LAYER);
if (len != 0) RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_boolean_array_default(prop, default_value);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_boolean_layer_member(StructOrFunctionRNA *cont_, const char *identifier, int len,
int *default_value, const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_BOOLEAN, PROP_LAYER_MEMBER);
if (len != 0) RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_boolean_array_default(prop, default_value);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_boolean_vector(StructOrFunctionRNA *cont_, const char *identifier, int len, int *default_value,
const char *ui_name, const char *ui_description)
2009-03-04 15:30:47 +00:00
{
ContainerRNA *cont = cont_;
2009-03-04 15:30:47 +00:00
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_BOOLEAN, PROP_XYZ); /* XXX */
if (len != 0) RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_boolean_array_default(prop, default_value);
2009-03-04 15:30:47 +00:00
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value,
int hardmin, int hardmax, const char *ui_name, const char *ui_description,
int softmin, int softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_INT, PROP_NONE);
RNA_def_property_int_default(prop, default_value);
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_int_vector(StructOrFunctionRNA *cont_, const char *identifier, int len, const int *default_value,
int hardmin, int hardmax, const char *ui_name, const char *ui_description,
int softmin, int softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_INT, PROP_XYZ); /* XXX */
if (len != 0) RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_int_array_default(prop, default_value);
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_int_array(StructOrFunctionRNA *cont_, const char *identifier, int len, const int *default_value,
int hardmin, int hardmax, const char *ui_name, const char *ui_description,
int softmin, int softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_INT, PROP_NONE);
if (len != 0) RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_int_array_default(prop, default_value);
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, int maxlen,
const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_STRING, PROP_NONE);
if (maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen);
if (default_value) RNA_def_property_string_default(prop, default_value);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_string_file_path(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value,
int maxlen, const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_STRING, PROP_FILEPATH);
if (maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen);
if (default_value) RNA_def_property_string_default(prop, default_value);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_string_dir_path(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value,
int maxlen, const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_STRING, PROP_DIRPATH);
if (maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen);
if (default_value) RNA_def_property_string_default(prop, default_value);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_string_file_name(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value,
int maxlen, const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_STRING, PROP_FILENAME);
if (maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen);
if (default_value) RNA_def_property_string_default(prop, default_value);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items,
int default_value, const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
if (!items) {
printf("%s: items not allowed to be NULL.\n", __func__);
return NULL;
}
prop = RNA_def_property(cont, identifier, PROP_ENUM, PROP_NONE);
if (items) RNA_def_property_enum_items(prop, items);
RNA_def_property_enum_default(prop, default_value);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
/* same as above but sets 'PROP_ENUM_FLAG' before setting the default value */
PropertyRNA *RNA_def_enum_flag(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items,
int default_value, const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
if (!items) {
printf("%s: items not allowed to be NULL.\n", __func__);
return NULL;
}
prop = RNA_def_property(cont, identifier, PROP_ENUM, PROP_NONE);
RNA_def_property_flag(prop, PROP_ENUM_FLAG); /* important to run before default set */
if (items) RNA_def_property_enum_items(prop, items);
RNA_def_property_enum_default(prop, default_value);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
eprop->itemf = itemfunc;
}
PropertyRNA *RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value,
float hardmin, float hardmax, const char *ui_name, const char *ui_description,
float softmin, float softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_NONE);
RNA_def_property_float_default(prop, default_value);
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_float_vector(StructOrFunctionRNA *cont_, const char *identifier, int len,
const float *default_value, float hardmin, float hardmax, const char *ui_name,
const char *ui_description, float softmin, float softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_XYZ);
if (len != 0) RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_float_array_default(prop, default_value);
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_float_vector_xyz(StructOrFunctionRNA *cont_, const char *identifier, int len,
const float *default_value, float hardmin, float hardmax, const char *ui_name,
const char *ui_description, float softmin, float softmax)
{
PropertyRNA *prop;
prop = RNA_def_float_vector(cont_, identifier, len, default_value, hardmin, hardmax, ui_name, ui_description,
softmin, softmax);
prop->subtype = PROP_XYZ_LENGTH;
return prop;
}
PropertyRNA *RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identifier, int len,
const float *default_value, float hardmin, float hardmax, const char *ui_name,
const char *ui_description, float softmin, float softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_COLOR);
if (len != 0) RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_float_array_default(prop, default_value);
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_float_matrix(StructOrFunctionRNA *cont_, const char *identifier, int rows, int columns,
const float *default_value, float hardmin, float hardmax, const char *ui_name,
const char *ui_description, float softmin, float softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
const int length[2] = {rows, columns};
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_MATRIX);
RNA_def_property_multi_array(prop, 2, length);
if (default_value) RNA_def_property_float_array_default(prop, default_value);
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_float_rotation(StructOrFunctionRNA *cont_, const char *identifier, int len,
const float *default_value, float hardmin, float hardmax, const char *ui_name,
const char *ui_description, float softmin, float softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_FLOAT, (len != 0) ? PROP_EULER : PROP_ANGLE);
if (len != 0) {
RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_float_array_default(prop, default_value);
}
else {
/* RNA_def_property_float_default must be called outside */
BLI_assert(default_value == NULL);
}
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_float_array(StructOrFunctionRNA *cont_, const char *identifier, int len,
const float *default_value, float hardmin, float hardmax, const char *ui_name,
const char *ui_description, float softmin, float softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_NONE);
if (len != 0) RNA_def_property_array(prop, len);
if (default_value) RNA_def_property_float_array_default(prop, default_value);
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_float_percentage(StructOrFunctionRNA *cont_, const char *identifier, float default_value,
float hardmin, float hardmax, const char *ui_name, const char *ui_description,
float softmin, float softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_PERCENTAGE);
RNA_def_property_float_default(prop, default_value);
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identifier, float default_value,
float hardmin, float hardmax, const char *ui_name, const char *ui_description,
float softmin, float softmax)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
ASSERT_SOFT_HARD_LIMITS;
prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_default(prop, default_value);
if (hardmin != hardmax) RNA_def_property_range(prop, hardmin, hardmax);
RNA_def_property_ui_text(prop, ui_name, ui_description);
RNA_def_property_ui_range(prop, softmin, softmax, 1, 3);
return prop;
}
PropertyRNA *RNA_def_pointer(StructOrFunctionRNA *cont_, const char *identifier, const char *type,
const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, type);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_pointer_runtime(StructOrFunctionRNA *cont_, const char *identifier, StructRNA *type,
const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_POINTER, PROP_NONE);
RNA_def_property_struct_runtime(prop, type);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_collection(StructOrFunctionRNA *cont_, const char *identifier, const char *type,
const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, type);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
PropertyRNA *RNA_def_collection_runtime(StructOrFunctionRNA *cont_, const char *identifier, StructRNA *type,
const char *ui_name, const char *ui_description)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
prop = RNA_def_property(cont, identifier, PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_runtime(prop, type);
RNA_def_property_ui_text(prop, ui_name, ui_description);
return prop;
}
/* Function */
static FunctionRNA *rna_def_function(StructRNA *srna, const char *identifier)
{
FunctionRNA *func;
StructDefRNA *dsrna;
FunctionDefRNA *dfunc;
if (DefRNA.preprocess) {
char error[512];
if (rna_validate_identifier(identifier, error, FALSE) == 0) {
fprintf(stderr, "%s: function identifier \"%s\" - %s\n", __func__, identifier, error);
DefRNA.error = 1;
}
}
func = MEM_callocN(sizeof(FunctionRNA), "FunctionRNA");
func->identifier = identifier;
func->description = identifier;
rna_addtail(&srna->functions, func);
if (DefRNA.preprocess) {
dsrna = rna_find_struct_def(srna);
dfunc = MEM_callocN(sizeof(FunctionDefRNA), "FunctionDefRNA");
rna_addtail(&dsrna->functions, dfunc);
dfunc->func = func;
}
else
func->flag |= FUNC_RUNTIME;
return func;
}
FunctionRNA *RNA_def_function(StructRNA *srna, const char *identifier, const char *call)
{
FunctionRNA *func;
FunctionDefRNA *dfunc;
if (BLI_findstring_ptr(&srna->functions, identifier, offsetof(FunctionRNA, identifier))) {
fprintf(stderr, "%s: %s.%s already defined.\n", __func__, srna->identifier, identifier);
return NULL;
}
func = rna_def_function(srna, identifier);
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only at preprocess time.\n", __func__);
return func;
}
dfunc = rna_find_function_def(func);
dfunc->call = call;
return func;
}
FunctionRNA *RNA_def_function_runtime(StructRNA *srna, const char *identifier, CallFunc call)
{
FunctionRNA *func;
func = rna_def_function(srna, identifier);
if (DefRNA.preprocess) {
fprintf(stderr, "%s: only at runtime.\n", __func__);
return func;
}
func->call = call;
return func;
}
/* C return value only!, multiple RNA returns can be done with RNA_def_function_output */
void RNA_def_function_return(FunctionRNA *func, PropertyRNA *ret)
{
if (ret->flag & PROP_DYNAMIC) {
fprintf(stderr, "%s: \"%s.%s\", dynamic values are not allowed as strict returns, "
"use RNA_def_function_output instead.\n", __func__, func->identifier, ret->identifier);
return;
}
else if (ret->arraydimension) {
fprintf(stderr, "%s: \"%s.%s\", arrays are not allowed as strict returns, "
"use RNA_def_function_output instead.\n", __func__, func->identifier, ret->identifier);
return;
}
BLI_assert(func->c_ret == NULL);
func->c_ret = ret;
RNA_def_function_output(func, ret);
}
2011-05-31 02:14:25 +00:00
void RNA_def_function_output(FunctionRNA *UNUSED(func), PropertyRNA *ret)
{
ret->flag |= PROP_OUTPUT;
}
void RNA_def_function_flag(FunctionRNA *func, int flag)
{
func->flag |= flag;
}
void RNA_def_function_ui_description(FunctionRNA *func, const char *description)
{
func->description = description;
}
int rna_parameter_size(PropertyRNA *parm)
{
PropertyType ptype = parm->type;
int len = parm->totarraylength;
/* XXX in other parts is mentioned that strings can be dynamic as well */
if (parm->flag & PROP_DYNAMIC)
return sizeof(ParameterDynAlloc);
if (len > 0) {
switch (ptype) {
case PROP_BOOLEAN:
case PROP_INT:
return sizeof(int) * len;
case PROP_FLOAT:
return sizeof(float) * len;
default:
break;
}
}
else {
switch (ptype) {
case PROP_BOOLEAN:
case PROP_INT:
case PROP_ENUM:
return sizeof(int);
case PROP_FLOAT:
return sizeof(float);
case PROP_STRING:
2012-02-24 11:04:09 +00:00
/* return values don't store a pointer to the original */
if (parm->flag & PROP_THICK_WRAP) {
StringPropertyRNA *sparm = (StringPropertyRNA *)parm;
return sizeof(char) * sparm->maxlength;
}
else
return sizeof(char *);
2012-09-08 08:59:47 +00:00
case PROP_POINTER:
{
#ifdef RNA_RUNTIME
if (parm->flag & PROP_RNAPTR)
if (parm->flag & PROP_THICK_WRAP) {
return sizeof(PointerRNA);
}
else {
return sizeof(PointerRNA *);
}
else
return sizeof(void *);
#else
if (parm->flag & PROP_RNAPTR) {
if (parm->flag & PROP_THICK_WRAP) {
return sizeof(PointerRNA);
}
else {
return sizeof(PointerRNA *);
}
}
else {
return sizeof(void *);
}
#endif
}
case PROP_COLLECTION:
return sizeof(ListBase);
}
}
return sizeof(void *);
}
/* Dynamic Enums */
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
{
EnumPropertyItem *newitems;
int tot = *totitem;
if (tot == 0) {
*items = MEM_callocN(sizeof(EnumPropertyItem) * 8, "RNA_enum_items_add");
}
else if (tot >= 8 && (tot & (tot - 1)) == 0) {
/* power of two > 8 */
newitems = MEM_callocN(sizeof(EnumPropertyItem) * tot * 2, "RNA_enum_items_add");
memcpy(newitems, *items, sizeof(EnumPropertyItem) * tot);
MEM_freeN(*items);
*items = newitems;
}
(*items)[tot] = *item;
*totitem = tot + 1;
}
void RNA_enum_item_add_separator(EnumPropertyItem **items, int *totitem)
{
static EnumPropertyItem sepr = {0, "", 0, NULL, NULL};
RNA_enum_item_add(items, totitem, &sepr);
}
void RNA_enum_items_add(EnumPropertyItem **items, int *totitem, EnumPropertyItem *item)
{
for (; item->identifier; item++)
RNA_enum_item_add(items, totitem, item);
}
void RNA_enum_items_add_value(EnumPropertyItem **items, int *totitem, EnumPropertyItem *item, int value)
{
for (; item->identifier; item++) {
if (item->value == value) {
RNA_enum_item_add(items, totitem, item);
/* break on first match - does this break anything?
* (is quick hack to get object->parent_type working ok for armature/lattice) */
break;
}
}
}
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
{
static EnumPropertyItem empty = {0, NULL, 0, NULL, NULL};
RNA_enum_item_add(items, totitem, &empty);
}
/* Memory management */
#ifdef RNA_RUNTIME
void RNA_def_struct_duplicate_pointers(StructRNA *srna)
{
if (srna->identifier) srna->identifier = BLI_strdup(srna->identifier);
if (srna->name) srna->name = BLI_strdup(srna->name);
if (srna->description) srna->description = BLI_strdup(srna->description);
srna->flag |= STRUCT_FREE_POINTERS;
}
void RNA_def_struct_free_pointers(StructRNA *srna)
{
if (srna->flag & STRUCT_FREE_POINTERS) {
if (srna->identifier) MEM_freeN((void *)srna->identifier);
if (srna->name) MEM_freeN((void *)srna->name);
if (srna->description) MEM_freeN((void *)srna->description);
}
}
void RNA_def_func_duplicate_pointers(FunctionRNA *func)
{
if (func->identifier) func->identifier = BLI_strdup(func->identifier);
if (func->description) func->description = BLI_strdup(func->description);
func->flag |= FUNC_FREE_POINTERS;
}
void RNA_def_func_free_pointers(FunctionRNA *func)
{
if (func->flag & FUNC_FREE_POINTERS) {
if (func->identifier) MEM_freeN((void *)func->identifier);
if (func->description) MEM_freeN((void *)func->description);
}
}
void RNA_def_property_duplicate_pointers(StructOrFunctionRNA *cont_, PropertyRNA *prop)
{
ContainerRNA *cont = cont_;
EnumPropertyItem *earray;
float *farray;
int *iarray;
int a;
/* annoying since we just added this to a hash, could make this add the correct key to the hash
* in the first place */
if (prop->identifier) {
if (cont->prophash) {
prop->identifier = BLI_strdup(prop->identifier);
BLI_ghash_assign(cont->prophash, (void *)prop->identifier, prop, NULL, NULL);
}
else {
prop->identifier = BLI_strdup(prop->identifier);
}
}
if (prop->name) prop->name = BLI_strdup(prop->name);
if (prop->description) prop->description = BLI_strdup(prop->description);
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_BOOLEAN:
{
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
if (bprop->defaultarray) {
iarray = MEM_callocN(sizeof(int) * prop->totarraylength, "RNA_def_property_store");
memcpy(iarray, bprop->defaultarray, sizeof(int) * prop->totarraylength);
bprop->defaultarray = iarray;
}
break;
}
2012-09-08 08:59:47 +00:00
case PROP_INT:
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
if (iprop->defaultarray) {
iarray = MEM_callocN(sizeof(int) * prop->totarraylength, "RNA_def_property_store");
memcpy(iarray, iprop->defaultarray, sizeof(int) * prop->totarraylength);
iprop->defaultarray = iarray;
}
break;
}
2012-09-08 08:59:47 +00:00
case PROP_ENUM:
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
if (eprop->item) {
earray = MEM_callocN(sizeof(EnumPropertyItem) * (eprop->totitem + 1), "RNA_def_property_store"),
memcpy(earray, eprop->item, sizeof(EnumPropertyItem) * (eprop->totitem + 1));
eprop->item = earray;
for (a = 0; a < eprop->totitem; a++) {
if (eprop->item[a].identifier)
eprop->item[a].identifier = BLI_strdup(eprop->item[a].identifier);
if (eprop->item[a].name)
eprop->item[a].name = BLI_strdup(eprop->item[a].name);
if (eprop->item[a].description)
eprop->item[a].description = BLI_strdup(eprop->item[a].description);
}
}
break;
}
2012-09-08 08:59:47 +00:00
case PROP_FLOAT:
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
if (fprop->defaultarray) {
farray = MEM_callocN(sizeof(float) * prop->totarraylength, "RNA_def_property_store");
memcpy(farray, fprop->defaultarray, sizeof(float) * prop->totarraylength);
fprop->defaultarray = farray;
}
break;
}
2012-09-08 08:59:47 +00:00
case PROP_STRING:
{
StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
if (sprop->defaultvalue)
sprop->defaultvalue = BLI_strdup(sprop->defaultvalue);
break;
}
default:
break;
}
prop->flag |= PROP_FREE_POINTERS;
}
void RNA_def_property_free_pointers(PropertyRNA *prop)
{
if (prop->flag & PROP_FREE_POINTERS) {
int a;
if (prop->identifier)
MEM_freeN((void *)prop->identifier);
if (prop->name)
MEM_freeN((void *)prop->name);
if (prop->description)
MEM_freeN((void *)prop->description);
if (prop->py_data)
MEM_freeN(prop->py_data);
switch (prop->type) {
2012-09-08 08:59:47 +00:00
case PROP_BOOLEAN:
{
BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
if (bprop->defaultarray)
MEM_freeN((void *)bprop->defaultarray);
break;
}
2012-09-08 08:59:47 +00:00
case PROP_INT:
{
IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
if (iprop->defaultarray)
MEM_freeN((void *)iprop->defaultarray);
break;
}
2012-09-08 08:59:47 +00:00
case PROP_FLOAT:
{
FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
if (fprop->defaultarray)
MEM_freeN((void *)fprop->defaultarray);
break;
}
2012-09-08 08:59:47 +00:00
case PROP_ENUM:
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
for (a = 0; a < eprop->totitem; a++) {
if (eprop->item[a].identifier)
MEM_freeN((void *)eprop->item[a].identifier);
if (eprop->item[a].name)
MEM_freeN((void *)eprop->item[a].name);
if (eprop->item[a].description)
MEM_freeN((void *)eprop->item[a].description);
}
if (eprop->item) MEM_freeN((void *)eprop->item);
break;
}
2012-09-08 08:59:47 +00:00
case PROP_STRING:
{
StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
if (sprop->defaultvalue)
MEM_freeN((void *)sprop->defaultvalue);
break;
}
default:
break;
}
}
}
static void rna_def_property_free(StructOrFunctionRNA *cont_, PropertyRNA *prop)
{
ContainerRNA *cont = cont_;
if (prop->flag & PROP_RUNTIME) {
if (cont->prophash)
BLI_ghash_remove(cont->prophash, (void *)prop->identifier, NULL, NULL);
RNA_def_property_free_pointers(prop);
rna_freelinkN(&cont->properties, prop);
}
else {
RNA_def_property_free_pointers(prop);
}
}
/* note: only intended for removing dynamic props */
int RNA_def_property_free_identifier(StructOrFunctionRNA *cont_, const char *identifier)
{
ContainerRNA *cont = cont_;
PropertyRNA *prop;
for (prop = cont->properties.first; prop; prop = prop->next) {
if (strcmp(prop->identifier, identifier) == 0) {
if (prop->flag & PROP_RUNTIME) {
rna_def_property_free(cont_, prop);
return 1;
}
else {
return -1;
}
}
}
return 0;
}
#endif
const char *RNA_property_typename(PropertyType type)
{
switch (type) {
case PROP_BOOLEAN: return "PROP_BOOLEAN";
case PROP_INT: return "PROP_INT";
case PROP_FLOAT: return "PROP_FLOAT";
case PROP_STRING: return "PROP_STRING";
case PROP_ENUM: return "PROP_ENUM";
case PROP_POINTER: return "PROP_POINTER";
case PROP_COLLECTION: return "PROP_COLLECTION";
}
return "PROP_UNKNOWN";
}