Changeset View
Changeset View
Standalone View
Standalone View
source/blender/makesrna/intern/rna_access.c
| Show All 30 Lines | |||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "DNA_windowmanager_types.h" | #include "DNA_windowmanager_types.h" | ||||
| #include "BLI_alloca.h" | #include "BLI_alloca.h" | ||||
| #include "BLI_blenlib.h" | #include "BLI_blenlib.h" | ||||
| #include "BLI_dynstr.h" | #include "BLI_dynstr.h" | ||||
| #include "BLI_ghash.h" | #include "BLI_ghash.h" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_sort.h" | |||||
| #include "BLI_threads.h" | #include "BLI_threads.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BLF_api.h" | #include "BLF_api.h" | ||||
| #include "BLT_translation.h" | #include "BLT_translation.h" | ||||
| #include "BKE_anim_data.h" | #include "BKE_anim_data.h" | ||||
| #include "BKE_collection.h" | #include "BKE_collection.h" | ||||
| ▲ Show 20 Lines • Show All 1,608 Lines • ▼ Show 20 Lines | if (prop->type == PROP_POINTER) { | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| printf("%s: %s is not a pointer property.\n", __func__, prop->identifier); | printf("%s: %s is not a pointer property.\n", __func__, prop->identifier); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| void RNA_property_enum_items_ex(bContext *C, | static int sort_enum_item_by_identifier_fn(const void *index1_v, | ||||
| const void *index2_v, | |||||
| void *item_v) | |||||
| { | |||||
| const EnumPropertyItem *items = item_v; | |||||
| const short index1 = *(unsigned int *)index1_v; | |||||
| const short index2 = *(unsigned int *)index2_v; | |||||
| return strcmp(items[index1].identifier, items[index2].identifier); | |||||
| } | |||||
| static void rna_property_enum_order_init_from_static_items(EnumPropertyRNA *eprop) | |||||
| { | |||||
| EnumPropertyItem_Order *order = &eprop->item_order; | |||||
| BLI_assert(order->indices_len == -1); | |||||
| /* This may be an over-allocation (with separators for example). */ | |||||
| unsigned int *indices = MEM_mallocN(sizeof(*indices) * eprop->totitem, __func__); | |||||
| /* Uninitialized! */ | |||||
| int indices_len = 0; | |||||
| int i = 0; | |||||
| for (const EnumPropertyItem *item = eprop->item; item->identifier; item++, i++) { | |||||
| if (item->identifier[0]) { | |||||
| indices[indices_len] = i; | |||||
| indices_len++; | |||||
| } | |||||
| } | |||||
| BLI_qsort_r(indices, | |||||
| indices_len, | |||||
| sizeof(*indices), | |||||
| sort_enum_item_by_identifier_fn, | |||||
| (void *)eprop->item); | |||||
| order->indices = indices; | |||||
| order->indices_len = indices_len; | |||||
| } | |||||
| void RNA_property_enum_items_with_order_ex(bContext *C, | |||||
| PointerRNA *ptr, | PointerRNA *ptr, | ||||
| PropertyRNA *prop, | PropertyRNA *prop, | ||||
| const bool use_static, | const bool use_static, | ||||
| const EnumPropertyItem **r_item, | const EnumPropertyItem **r_item, | ||||
| const EnumPropertyItem_Order **r_item_order, | |||||
| int *r_totitem, | int *r_totitem, | ||||
| bool *r_free) | bool *r_free) | ||||
| { | { | ||||
| EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop); | EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop); | ||||
| *r_free = false; | *r_free = false; | ||||
| if (!use_static && (eprop->item_fn != NULL)) { | if (!use_static && (eprop->item_fn != NULL)) { | ||||
| const bool no_context = (prop->flag & PROP_ENUM_NO_CONTEXT) || | const bool no_context = (prop->flag & PROP_ENUM_NO_CONTEXT) || | ||||
| ((ptr->type->flag & STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID) && | ((ptr->type->flag & STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID) && | ||||
| Show All 10 Lines | if (C != NULL || no_context) { | ||||
| int tot; | int tot; | ||||
| for (tot = 0; item[tot].identifier; tot++) { | for (tot = 0; item[tot].identifier; tot++) { | ||||
| /* pass */ | /* pass */ | ||||
| } | } | ||||
| *r_totitem = tot; | *r_totitem = tot; | ||||
| } | } | ||||
| *r_item = item; | *r_item = item; | ||||
| /* Currently only static enumerations support order (could be supported in the future). */ | |||||
| if (r_item_order) { | |||||
| *r_item_order = NULL; | |||||
| } | |||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| /* TODO: as this is used for a binary search, it could be set to a larger number | |||||
| * as it's not needed for small collections. */ | |||||
| const int items_order_min = 1; | |||||
| *r_item = eprop->item; | *r_item = eprop->item; | ||||
| if (r_totitem) { | if (r_totitem) { | ||||
| *r_totitem = eprop->totitem; | *r_totitem = eprop->totitem; | ||||
| } | } | ||||
| if (r_item_order) { | |||||
| EnumPropertyItem_Order *order = &eprop->item_order; | |||||
| if (order->indices_len == -1 && eprop->totitem > items_order_min) { | |||||
| rna_property_enum_order_init_from_static_items(eprop); | |||||
| } | |||||
| if (order->indices_len > 0) { | |||||
| *r_item_order = order; | |||||
| } | |||||
| else { | |||||
| *r_item_order = NULL; | |||||
| } | |||||
| } | |||||
| } | |||||
| void RNA_property_enum_items_ex(bContext *C, | |||||
| PointerRNA *ptr, | |||||
| PropertyRNA *prop, | |||||
| const bool use_static, | |||||
| const EnumPropertyItem **r_item, | |||||
| int *r_totitem, | |||||
| bool *r_free) | |||||
| { | |||||
| RNA_property_enum_items_with_order_ex(C, ptr, prop, use_static, r_item, NULL, r_totitem, r_free); | |||||
| } | } | ||||
| void RNA_property_enum_items(bContext *C, | void RNA_property_enum_items(bContext *C, | ||||
| PointerRNA *ptr, | PointerRNA *ptr, | ||||
| PropertyRNA *prop, | PropertyRNA *prop, | ||||
| const EnumPropertyItem **r_item, | const EnumPropertyItem **r_item, | ||||
| int *r_totitem, | int *r_totitem, | ||||
| bool *r_free) | bool *r_free) | ||||
| { | { | ||||
| RNA_property_enum_items_ex(C, ptr, prop, false, r_item, r_totitem, r_free); | RNA_property_enum_items_ex(C, ptr, prop, false, r_item, r_totitem, r_free); | ||||
| } | } | ||||
| void RNA_property_enum_items_with_order(bContext *C, | |||||
| PointerRNA *ptr, | |||||
| PropertyRNA *prop, | |||||
| const EnumPropertyItem **r_item, | |||||
| const EnumPropertyItem_Order **r_item_order, | |||||
| int *r_totitem, | |||||
| bool *r_free) | |||||
| { | |||||
| RNA_property_enum_items_with_order_ex( | |||||
| C, ptr, prop, false, r_item, r_item_order, r_totitem, r_free); | |||||
| } | |||||
| #ifdef WITH_INTERNATIONAL | #ifdef WITH_INTERNATIONAL | ||||
| static void property_enum_translate(PropertyRNA *prop, | static void property_enum_translate(PropertyRNA *prop, | ||||
| EnumPropertyItem **r_item, | EnumPropertyItem **r_item, | ||||
| const int *totitem, | const int *totitem, | ||||
| bool *r_free) | bool *r_free) | ||||
| { | { | ||||
| if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) { | if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) { | ||||
| int i; | int i; | ||||
| Show All 39 Lines | for (i = 0; nitem[i].identifier; i++) { | ||||
| } | } | ||||
| } | } | ||||
| *r_item = nitem; | *r_item = nitem; | ||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| void RNA_property_enum_items_gettexted(bContext *C, | void RNA_property_enum_items_gettexted_with_order(bContext *C, | ||||
| PointerRNA *ptr, | PointerRNA *ptr, | ||||
| PropertyRNA *prop, | PropertyRNA *prop, | ||||
| const EnumPropertyItem **r_item, | const EnumPropertyItem **r_item, | ||||
| const EnumPropertyItem_Order **r_item_order, | |||||
| int *r_totitem, | int *r_totitem, | ||||
| bool *r_free) | bool *r_free) | ||||
| { | { | ||||
| RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free); | RNA_property_enum_items_with_order(C, ptr, prop, r_item, r_item_order, r_totitem, r_free); | ||||
| #ifdef WITH_INTERNATIONAL | #ifdef WITH_INTERNATIONAL | ||||
| /* Normally dropping 'const' is _not_ ok, in this case it's only modified if we own the memory | /* Normally dropping 'const' is _not_ ok, in this case it's only modified if we own the memory | ||||
| * so allow the exception (callers are creating new arrays in this case). */ | * so allow the exception (callers are creating new arrays in this case). */ | ||||
| property_enum_translate(prop, (EnumPropertyItem **)r_item, r_totitem, r_free); | property_enum_translate(prop, (EnumPropertyItem **)r_item, r_totitem, r_free); | ||||
| #endif | #endif | ||||
| } | } | ||||
| void RNA_property_enum_items_gettexted(bContext *C, | |||||
| PointerRNA *ptr, | |||||
| PropertyRNA *prop, | |||||
| const EnumPropertyItem **r_item, | |||||
| int *r_totitem, | |||||
| bool *r_free) | |||||
| { | |||||
| RNA_property_enum_items_gettexted_with_order(C, ptr, prop, r_item, NULL, r_totitem, r_free); | |||||
| } | |||||
| void RNA_property_enum_items_gettexted_all(bContext *C, | void RNA_property_enum_items_gettexted_all(bContext *C, | ||||
| PointerRNA *ptr, | PointerRNA *ptr, | ||||
| PropertyRNA *prop, | PropertyRNA *prop, | ||||
| const EnumPropertyItem **r_item, | const EnumPropertyItem **r_item, | ||||
| int *r_totitem, | int *r_totitem, | ||||
| bool *r_free) | bool *r_free) | ||||
| { | { | ||||
| EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop); | EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop); | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
| #endif | #endif | ||||
| *r_item = item_array; | *r_item = item_array; | ||||
| } | } | ||||
| bool RNA_property_enum_value( | bool RNA_property_enum_value( | ||||
| bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value) | bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value) | ||||
| { | { | ||||
| const EnumPropertyItem *item; | const EnumPropertyItem *item; | ||||
| const EnumPropertyItem_Order *item_order; | |||||
| bool free; | bool free; | ||||
| bool found; | bool found; | ||||
| RNA_property_enum_items(C, ptr, prop, &item, NULL, &free); | RNA_property_enum_items_with_order(C, ptr, prop, &item, &item_order, NULL, &free); | ||||
| if (item) { | if (item) { | ||||
| const int i = RNA_enum_from_identifier(item, identifier); | const int i = RNA_enum_from_identifier_with_order(item, item_order, identifier); | ||||
| if (i != -1) { | if (i != -1) { | ||||
| *r_value = item[i].value; | *r_value = item[i].value; | ||||
| found = true; | found = true; | ||||
| } | } | ||||
| else { | else { | ||||
| found = false; | found = false; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | int RNA_enum_from_identifier(const EnumPropertyItem *item, const char *identifier) | ||||
| for (; item->identifier; item++, i++) { | for (; item->identifier; item++, i++) { | ||||
| if (item->identifier[0] && STREQ(item->identifier, identifier)) { | if (item->identifier[0] && STREQ(item->identifier, identifier)) { | ||||
| return i; | return i; | ||||
| } | } | ||||
| } | } | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| int RNA_enum_from_identifier_with_order(const EnumPropertyItem *item, | |||||
| const EnumPropertyItem_Order *item_order, | |||||
| const char *identifier) | |||||
| { | |||||
| if (item_order == NULL) { | |||||
| return RNA_enum_from_identifier(item, identifier); | |||||
| } | |||||
| const unsigned int *indices = item_order->indices; | |||||
| int low = 0; | |||||
| int high = item_order->indices_len - 1; | |||||
| while (low <= high) { | |||||
| const int middle = (high + low) / 2; | |||||
| const int cmp = strcmp(item[indices[middle]].identifier, identifier); | |||||
| if (cmp == 0) { | |||||
| // BLI_assert(RNA_enum_from_identifier(item, identifier) == indices[middle]); | |||||
| return indices[middle]; | |||||
| } | |||||
| if (cmp < 0) { | |||||
| low = middle + 1; | |||||
| } | |||||
| else { | |||||
| high = middle - 1; | |||||
| } | |||||
| } | |||||
| // BLI_assert(RNA_enum_from_identifier(item, identifier) == -1); | |||||
| return -1; | |||||
| } | |||||
| /** | /** | ||||
| * Take care using this with translated enums, | * Take care using this with translated enums, | ||||
| * prefer #RNA_enum_from_identifier where possible. | * prefer #RNA_enum_from_identifier where possible. | ||||
| */ | */ | ||||
| int RNA_enum_from_name(const EnumPropertyItem *item, const char *name) | int RNA_enum_from_name(const EnumPropertyItem *item, const char *name) | ||||
| { | { | ||||
| int i = 0; | int i = 0; | ||||
| for (; item->identifier; item++, i++) { | for (; item->identifier; item++, i++) { | ||||
| ▲ Show 20 Lines • Show All 4,595 Lines • ▼ Show 20 Lines | bool RNA_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value) | ||||
| const int i = RNA_enum_from_identifier(item, identifier); | const int i = RNA_enum_from_identifier(item, identifier); | ||||
| if (i != -1) { | if (i != -1) { | ||||
| *r_value = item[i].value; | *r_value = item[i].value; | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool RNA_enum_value_from_id_with_order(const EnumPropertyItem *item, | |||||
| const EnumPropertyItem_Order *item_order, | |||||
| const char *identifier, | |||||
| int *r_value) | |||||
| { | |||||
| const int i = RNA_enum_from_identifier_with_order(item, item_order, identifier); | |||||
| if (i != -1) { | |||||
| *r_value = item[i].value; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool RNA_enum_id_from_value(const EnumPropertyItem *item, int value, const char **r_identifier) | bool RNA_enum_id_from_value(const EnumPropertyItem *item, int value, const char **r_identifier) | ||||
| { | { | ||||
| const int i = RNA_enum_from_value(item, value); | const int i = RNA_enum_from_value(item, value); | ||||
| if (i != -1) { | if (i != -1) { | ||||
| *r_identifier = item[i].identifier; | *r_identifier = item[i].identifier; | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| ▲ Show 20 Lines • Show All 1,713 Lines • Show Last 20 Lines | |||||