/* * ***** 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, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Contributor(s): Blender Foundation (2008). * * ***** END GPL LICENSE BLOCK ***** */ /** \file blender/makesrna/intern/rna_define.c * \ingroup RNA */ #include #include #include #include #include #include #include #include "BLI_utildefines.h" #include "MEM_guardedalloc.h" #include "DNA_genfile.h" #include "DNA_sdna_types.h" #include "BLI_listbase.h" #include "BLI_ghash.h" #include "BLT_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 */ /* pedantic check for final '.', note '...' are allowed though. */ #ifndef NDEBUG # define DESCR_CHECK(description, id1, id2) \ if (description && (description)[0]) { \ int i = strlen(description); \ if (i > 3 && (description)[i - 1] == '.' && (description)[i - 3] != '.') { \ fprintf(stderr, "%s: '%s' '%s' description ends with a '.' !\n", \ __func__, id1 ? id1 : "", id2 ? id2 : ""); \ } \ } (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 && (STREQ(prop->identifier, identifier))) { 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; const 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); 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, bool property) { int a = 0; /* 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 (STREQ(identifier, kwlist[a])) { 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 (STREQ(identifier, kwlist_prop[a])) { strcpy(error, "this keyword is reserved by python"); return 0; } } } return 1; } 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 (STREQ(identifier, kwlist[a])) { /* this keyword is reserved by python. * just replace the last character by '_' to keep it readable. */ identifier[strlen(identifier) - 1] = '_'; 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 (STREQ(identifier, kwlist_prop[a])) { /* this keyword is reserved by python. * just replace the last character by '_' to keep it readable. */ identifier[strlen(identifier) - 1] = '_'; break; } } } } /* Blender Data Definition */ BlenderRNA *RNA_create(void) { BlenderRNA *brna; brna = MEM_callocN(sizeof(BlenderRNA), "BlenderRNA"); const char *error_message = NULL; BLI_listbase_clear(&DefRNA.structs); DefRNA.error = 0; DefRNA.preprocess = 1; DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, &error_message); if (DefRNA.sdna == NULL) { fprintf(stderr, "Error decoding SDNA: %s\n", error_message); DefRNA.error = 1; } return brna; } 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(bool verify) { DefRNA.verify = verify; } #ifndef RNA_RUNTIME void RNA_define_animate_sdna(bool 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_internal & PROP_INTERN_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_internal & PROP_INTERN_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 UNUSED_VARS(brna, 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; BLI_listbase_clear(&srna->cont.properties); BLI_listbase_clear(&srna->functions); 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 = BLT_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); prop->flag_internal |= PROP_INTERN_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 (STREQ(srnafrom->identifier, from)) 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); /* there are far too many structs which initialize without valid DNA struct names, * this can't be checked without adding an option to disable (tested this and it means changes all over - Campbell) */ #if 0 if (DNA_struct_find_nr(DefRNA.sdna, structname) == -1) { if (!DefRNA.silent) { fprintf(stderr, "%s: %s not found.\n", __func__, structname); DefRNA.error = 1; } return; } #endif 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) == -1) { 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 (STREQ(srnafrom->identifier, structname)) 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 : BLT_I18NCONTEXT_DEFAULT_BPYRNA; } /* Property Definition */ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, const char *identifier, int type, int subtype) { /*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; 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; } 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 = fprop->hardmin = 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; } case PROP_STRING: { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; sprop->defaultvalue = ""; break; } case PROP_POINTER: prop->flag |= PROP_THICK_WRAP; /* needed for default behavior when PARM_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 = BLT_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; case PROP_INT: { DefRNA.silent = 1; RNA_def_property_int_sdna(prop, NULL, identifier); DefRNA.silent = 0; break; } case PROP_FLOAT: { DefRNA.silent = 1; RNA_def_property_float_sdna(prop, NULL, identifier); DefRNA.silent = 0; break; } 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->flag_internal |= PROP_INTERN_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, PropertyFlag flag) { prop->flag |= flag; } void RNA_def_property_clear_flag(PropertyRNA *prop, PropertyFlag flag) { prop->flag &= ~flag; } void RNA_def_parameter_flags(PropertyRNA *prop, PropertyFlag flag_property, ParameterFlag flag_parameter) { prop->flag |= flag_property; prop->flag_parameter |= flag_parameter; } void RNA_def_parameter_clear_flags(PropertyRNA *prop, PropertyFlag flag_property, ParameterFlag flag_parameter) { prop->flag &= ~flag_property; prop->flag_parameter &= ~flag_parameter; } 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; } } /* common args for length */ const int rna_matrix_dimsize_3x3[] = {3, 3}; const int rna_matrix_dimsize_4x4[] = {4, 4}; const int rna_matrix_dimsize_4x2[] = {4, 2}; 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, bool consecutive) { prop->icon = icon; if (consecutive) prop->flag |= PROP_ICONS_CONSECUTIVE; } /** * The values hare are a little confusing: * * \param step: Used as the value to increase/decrease when clicking on number buttons, * as well as scaling mouse input for click-dragging number buttons. * For floats this is (step * UI_PRECISION_FLOAT_SCALE), why? - nobody knows. * For ints, 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; #ifdef DEBUG if (min > max) { fprintf(stderr, "%s: \"%s.%s\", min > max.\n", __func__, srna->identifier, prop->identifier); DefRNA.error = 1; } if (step < 0 || step > 100) { fprintf(stderr, "%s: \"%s.%s\", step outside range.\n", __func__, srna->identifier, prop->identifier); DefRNA.error = 1; } if (precision < -1 || precision > 10) { fprintf(stderr, "%s: \"%s.%s\", step outside range.\n", __func__, srna->identifier, prop->identifier); DefRNA.error = 1; } #endif switch (prop->type) { case PROP_INT: { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; iprop->softmin = (int)min; iprop->softmax = (int)max; iprop->step = (int)step; break; } 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; #ifdef DEBUG if (min > max) { fprintf(stderr, "%s: \"%s.%s\", min > max.\n", __func__, srna->identifier, prop->identifier); DefRNA.error = 1; } #endif switch (prop->type) { 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; } 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) { case PROP_POINTER: { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; pprop->type = (StructRNA *)type; break; } 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) { case PROP_POINTER: { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; pprop->type = type; if (type && (type->flag & STRUCT_ID_REFCOUNT)) prop->flag |= PROP_ID_REFCOUNT; break; } 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) { 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) { 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) { case PROP_BOOLEAN: { BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; BLI_assert(ELEM(value, false, true)); 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) { 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) { 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) { 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) { 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) { 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) { case PROP_STRING: { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; if (value == NULL) { fprintf(stderr, "%s: \"%s.%s\", NULL string passed (dont call in this case).\n", __func__, srna->identifier, prop->identifier); DefRNA.error = 1; break; } if (!value[0]) { fprintf(stderr, "%s: \"%s.%s\", empty string passed (dont call in this case).\n", __func__, srna->identifier, prop->identifier); DefRNA.error = 1; // BLI_assert(0); break; } 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) { 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 && STREQ(dp->dnatype, "char")) { iprop->hardmin = iprop->softmin = CHAR_MIN; iprop->hardmax = iprop->softmax = CHAR_MAX; } else if (dp->dnatype && STREQ(dp->dnatype, "short")) { iprop->hardmin = iprop->softmin = SHRT_MIN; iprop->hardmax = iprop->softmax = SHRT_MAX; } else if (dp->dnatype && STREQ(dp->dnatype, "int")) { 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 && STREQ(dp->dnatype, "char")) { 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 && STREQ(dp->dnatype, "ListBase")) { 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 : BLT_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, const void *func) { prop->update = (void *)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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { ContainerRNA *cont = cont_; 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); 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) { ContainerRNA *cont = cont_; 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); 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; BLI_assert(default_value == NULL || default_value[0]); 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; BLI_assert(default_value == NULL || default_value[0]); 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; BLI_assert(default_value == NULL || default_value[0]); 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; BLI_assert(default_value == NULL || default_value[0]); 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 >= 3) ? 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, 10, 3); return prop; } PropertyRNA *RNA_def_float_distance(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax) { PropertyRNA *prop = RNA_def_float(cont_, identifier, default_value, hardmin, hardmax, ui_name, ui_description, softmin, softmax); RNA_def_property_subtype(prop, PROP_DISTANCE); 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); } void RNA_def_function_output(FunctionRNA *UNUSED(func), PropertyRNA *ret) { ret->flag_parameter |= PARM_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: /* 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 *); } case PROP_POINTER: { #ifdef RNA_RUNTIME if (parm->flag_parameter & PARM_RNAPTR) if (parm->flag & PROP_THICK_WRAP) { return sizeof(PointerRNA); } else { return sizeof(PointerRNA *); } else return sizeof(void *); #else if (parm->flag_parameter & PARM_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_reinsert(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) { 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; } 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; } 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; } 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; } case PROP_STRING: { StringPropertyRNA *sprop = (StringPropertyRNA *)prop; if (sprop->defaultvalue) sprop->defaultvalue = BLI_strdup(sprop->defaultvalue); break; } default: break; } prop->flag_internal |= PROP_INTERN_FREE_POINTERS; } void RNA_def_property_free_pointers(PropertyRNA *prop) { if (prop->flag_internal & PROP_INTERN_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) { case PROP_BOOLEAN: { BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; if (bprop->defaultarray) MEM_freeN((void *)bprop->defaultarray); break; } case PROP_INT: { IntPropertyRNA *iprop = (IntPropertyRNA *)prop; if (iprop->defaultarray) MEM_freeN((void *)iprop->defaultarray); break; } case PROP_FLOAT: { FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; if (fprop->defaultarray) MEM_freeN((void *)fprop->defaultarray); break; } 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; } 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_internal & PROP_INTERN_RUNTIME) { if (cont->prophash) BLI_ghash_remove(cont->prophash, 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 (STREQ(prop->identifier, identifier)) { if (prop->flag_internal & PROP_INTERN_RUNTIME) { rna_def_property_free(cont_, prop); return 1; } else { return -1; } } } return 0; } #endif /* RNA_RUNTIME */ 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"; }