diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 7396edd3025..92a045bca6c 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -83,6 +83,7 @@ */ static void ui_free_but(const bContext *C, uiBut *but); +static void ui_rna_ID_autocomplete(bContext *C, char *str, void *arg_but); /* ************ GLOBALS ************* */ @@ -1401,32 +1402,217 @@ void ui_set_but_val(uiBut *but, double value) ui_is_but_sel(but); } +int ui_get_but_string_max_length(uiBut *but) +{ + if(but->type == TEX) + return but->hardmax; + else if(but->type == IDPOIN) + return sizeof(((ID*)NULL)->name)-2; + else + return UI_MAX_DRAW_STR; +} + void ui_get_but_string(uiBut *but, char *str, int maxlen) { - if(but->rnaprop) { - char *buf; - - buf= RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen); + if(but->rnaprop && ELEM(but->type, TEX, IDPOIN)) { + PropertyType type; + char *buf= NULL; - if(buf != str) { + type= RNA_property_type(&but->rnapoin, but->rnaprop); + + if(type == PROP_STRING) { + /* RNA string */ + buf= RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen); + } + else if(type == PROP_POINTER) { + /* RNA pointer */ + PointerRNA ptr= RNA_property_pointer_get(&but->rnapoin, but->rnaprop); + PropertyRNA *nameprop; + + if(ptr.data && (nameprop = RNA_struct_name_property(&ptr))) + buf= RNA_property_string_get_alloc(&ptr, nameprop, str, maxlen); + else + BLI_strncpy(str, "", maxlen); + } + else + BLI_strncpy(str, "", maxlen); + + if(buf && buf != str) { /* string was too long, we have to truncate */ BLI_strncpy(str, buf, maxlen); MEM_freeN(buf); } } - else - BLI_strncpy(str, but->poin, maxlen); + else if(but->type == IDPOIN) { + /* ID pointer */ + ID *id= *(but->idpoin_idpp); + if(id) BLI_strncpy(str, id->name+2, maxlen); + else BLI_strncpy(str, "", maxlen); + + return; + } + else if(but->type == TEX) { + /* string */ + BLI_strncpy(str, but->poin, maxlen); + return; + } + else { + /* number */ + double value; + + value= ui_get_but_val(but); + + if(ui_is_but_float(but)) { + if(but->a2) { /* amount of digits defined */ + if(but->a2==1) BLI_snprintf(str, maxlen, "%.1f", value); + else if(but->a2==2) BLI_snprintf(str, maxlen, "%.2f", value); + else if(but->a2==3) BLI_snprintf(str, maxlen, "%.3f", value); + else BLI_snprintf(str, maxlen, "%.4f", value); + } + else + BLI_snprintf(str, maxlen, "%.3f", value); + } + else + BLI_snprintf(str, maxlen, "%d", (int)value); + } } -void ui_set_but_string(uiBut *but, const char *str) +static void ui_rna_ID_collection(bContext *C, uiBut *but, PointerRNA *ptr, PropertyRNA **prop) { - if(but->rnaprop) { - if(RNA_property_editable(&but->rnapoin, but->rnaprop)) - RNA_property_string_set(&but->rnapoin, but->rnaprop, str); + CollectionPropertyIterator iter; + PropertyRNA *iterprop, *iprop; + StructRNA *srna; + + /* look for collection property in Main */ + RNA_pointer_create(NULL, &RNA_Main, CTX_data_main(C), ptr); + + iterprop= RNA_struct_iterator_property(ptr); + RNA_property_collection_begin(ptr, iterprop, &iter); + *prop= NULL; + + for(; iter.valid; RNA_property_collection_next(&iter)) { + iprop= iter.ptr.data; + + /* if it's a collection and has same pointer type, we've got it */ + if(RNA_property_type(ptr, iprop) == PROP_COLLECTION) { + srna= RNA_property_pointer_type(ptr, iprop); + + if(RNA_property_pointer_type(&but->rnapoin, but->rnaprop) == srna) { + *prop= iprop; + break; + } + } } - else + + RNA_property_collection_end(&iter); +} + +/* autocomplete callback for RNA pointers */ +static void ui_rna_ID_autocomplete(bContext *C, char *str, void *arg_but) +{ + uiBut *but= arg_but; + AutoComplete *autocpl; + CollectionPropertyIterator iter; + PointerRNA ptr; + PropertyRNA *prop, *nameprop; + char *name; + + if(str[0]==0) return; + + /* get the collection */ + ui_rna_ID_collection(C, but, &ptr, &prop); + if(prop==NULL) return; + + autocpl= autocomplete_begin(str, ui_get_but_string_max_length(but)); + RNA_property_collection_begin(&ptr, prop, &iter); + + /* loop over items in collection */ + for(; iter.valid; RNA_property_collection_next(&iter)) { + if(iter.ptr.data && (nameprop = RNA_struct_name_property(&iter.ptr))) { + name= RNA_property_string_get_alloc(&iter.ptr, nameprop, NULL, 0); + + if(name) { + /* test item name */ + autocomplete_do_name(autocpl, name); + MEM_freeN(name); + } + } + } + + RNA_property_collection_end(&iter); + autocomplete_end(autocpl, str); +} + +int ui_set_but_string(bContext *C, uiBut *but, const char *str) +{ + if(but->rnaprop && ELEM(but->type, TEX, IDPOIN)) { + if(RNA_property_editable(&but->rnapoin, but->rnaprop)) { + PropertyType type; + + type= RNA_property_type(&but->rnapoin, but->rnaprop); + + if(type == PROP_STRING) { + /* RNA string */ + RNA_property_string_set(&but->rnapoin, but->rnaprop, str); + return 1; + } + else if(type == PROP_POINTER) { + /* RNA pointer */ + PointerRNA ptr, rptr; + PropertyRNA *prop; + + /* XXX only ID pointers at the moment, needs to support + * custom collection too for bones, vertex groups, .. */ + ui_rna_ID_collection(C, but, &ptr, &prop); + + if(prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) { + RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr); + return 1; + } + else + return 0; + } + } + } + else if(but->type == IDPOIN) { + /* ID pointer */ + but->idpoin_func(C, (char*)str, but->idpoin_idpp); + return 1; + } + else if(but->type == TEX) { + /* string */ BLI_strncpy(but->poin, str, but->hardmax); + return 1; + } + else { + double value; + + /* XXX 2.50 missing python api */ +#if 0 + if(BPY_button_eval(str, &value)) { + BKE_report(CTX_reports(C), RPT_WARNING, "Invalid Python expression, check console"); + value = 0.0f; /* Zero out value on error */ + + if(str[0]) + return 0; + } +#else + value= atof(str); +#endif + + if(!ui_is_but_float(but)) value= (int)value; + if(but->type==NUMABS) value= fabs(value); + + /* not that we use hard limits here */ + if(valuehardmin) value= but->hardmin; + if(value>but->hardmax) value= but->hardmax; + + ui_set_but_val(but, value); + return 1; + } + + return 0; } static double soft_range_round_up(double value, double max) @@ -1754,7 +1940,6 @@ uiBlock *uiGetBlock(char *name, ARegion *ar) void ui_check_but(uiBut *but) { /* if something changed in the button */ - ID *id; double value; float okwidth; int transopts= ui_translate_buttons(); @@ -1866,11 +2051,6 @@ void ui_check_but(uiBut *but) break; case IDPOIN: - id= *(but->idpoin_idpp); - strcpy(but->drawstr, but->str); - if(id) strcat(but->drawstr, id->name+2); - break; - case TEX: if(!but->editstr) { char str[UI_MAX_DRAW_STR]; @@ -2409,6 +2589,9 @@ uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1, but->rnaindex= index; else but->rnaindex= 0; + + if(type == IDPOIN) + uiButSetCompleteFunc(but, ui_rna_ID_autocomplete, but); } if (!prop || !RNA_property_editable(&but->rnapoin, prop)) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 4220d9c2781..c76f6a11b29 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -393,7 +393,7 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data) if(!data->str) return; - ui_set_but_string(but, data->str); + ui_set_but_string(C, but, data->str); ui_check_but(but); /* give butfunc the original text too */ @@ -409,30 +409,17 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data) static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data) { if(data->str) { - /* XXX 2.50 missing python api */ -#if 0 - if(BPY_button_eval(data->str, &data->value)) { - BKE_report(CTX_reports(C), RPT_WARNING, "Invalid Python expression, check console"); - data->value = 0.0f; /* Zero out value on error */ - - if(data->str[0]) { - data->cancel= 1; /* invalidate return value if eval failed, except when string was null */ - return; - } + if(ui_set_but_string(C, but, data->str)) { + data->value= ui_get_but_val(but); + } + else { + data->cancel= 1; + return; } -#else - data->value= atof(data->str); -#endif - - if(!ui_is_but_float(but)) data->value= (int)data->value; - if(but->type==NUMABS) data->value= fabs(data->value); - - /* not that we use hard limits here */ - if(data->valuehardmin) data->value= but->hardmin; - if(data->value>but->hardmax) data->value= but->hardmax; } + else + ui_set_but_val(but, data->value); - ui_set_but_val(but, data->value); ui_check_but(but); ui_apply_but_func(C, but); @@ -506,7 +493,7 @@ static void ui_apply_but_CURVE(bContext *C, uiBut *but, uiHandleButtonData *data static void ui_apply_but_IDPOIN(bContext *C, uiBut *but, uiHandleButtonData *data) { - but->idpoin_func(C, data->str, but->idpoin_idpp); + ui_set_but_string(C, but, data->str); ui_check_but(but); ui_apply_but_func(C, but); data->retval= but->retval; @@ -1139,42 +1126,9 @@ static void ui_textedit_begin(uiBut *but, uiHandleButtonData *data) } /* retrieve string */ - if(but->type == TEX) { - data->maxlen= but->hardmax; - data->str= MEM_callocN(sizeof(char)*(data->maxlen+1), "textedit str"); - - ui_get_but_string(but, data->str, data->maxlen+1); - } - else if(but->type == IDPOIN) { - ID *id; - - data->maxlen= 22; - data->str= MEM_callocN(sizeof(char)*(data->maxlen+1), "textedit str"); - - id= *but->idpoin_idpp; - if(id) BLI_strncpy(data->str, id->name+2, data->maxlen+1); - else data->str[0]= 0; - } - else { - double value; - - data->maxlen= UI_MAX_DRAW_STR; - data->str= MEM_callocN(sizeof(char)*(data->maxlen+1), "textedit str"); - - value= ui_get_but_val(but); - if(ui_is_but_float(but)) { - if(but->a2) { /* amount of digits defined */ - if(but->a2==1) sprintf(data->str, "%.1f", value); - else if(but->a2==2) sprintf(data->str, "%.2f", value); - else if(but->a2==3) sprintf(data->str, "%.3f", value); - else sprintf(data->str, "%.4f", value); - } - else sprintf(data->str, "%.3f", value); - } - else { - sprintf(data->str, "%d", (int)value); - } - } + data->maxlen= ui_get_but_string_max_length(but); + data->str= MEM_callocN(sizeof(char)*(data->maxlen+1), "textedit str"); + ui_get_but_string(but, data->str, data->maxlen+1); data->origstr= BLI_strdup(data->str); data->selextend= 0; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 7f26f4fa89e..4574eb44cfa 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -258,8 +258,10 @@ extern void ui_set_but_val(uiBut *but, double value); extern void ui_set_but_hsv(uiBut *but); extern void ui_get_but_vectorf(uiBut *but, float *vec); extern void ui_set_but_vectorf(uiBut *but, float *vec); + extern void ui_get_but_string(uiBut *but, char *str, int maxlen); -extern void ui_set_but_string(uiBut *but, const char *str); +extern int ui_set_but_string(struct bContext *C, uiBut *but, const char *str); +extern int ui_get_but_string_max_length(uiBut *but); extern void ui_set_but_soft_range(uiBut *but, double value); diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 429b2de0227..f17ec52e99a 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -264,35 +264,14 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind break; case PROP_POINTER: { PointerRNA pptr; - PropertyRNA *nameprop; - char *text, *descr, textbuf[256]; int icon; pptr= RNA_property_pointer_get(ptr, prop); - descr= (char*)RNA_property_ui_description(ptr, prop); - if(!pptr.type) pptr.type= RNA_property_pointer_type(ptr, prop); - icon= UI_GetIconRNA(&pptr); - if(pptr.data == NULL) { - but= uiDefIconTextBut(block, LABEL, 0, icon, "", x1, y1, x2, y2, NULL, 0, 0, 0, 0, ""); - } - else { - nameprop= RNA_struct_name_property(&pptr); - - if(nameprop) { - text= RNA_property_string_get_alloc(&pptr, nameprop, textbuf, sizeof(textbuf)); - but= uiDefIconTextBut(block, LABEL, 0, icon, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, descr); - if(text != textbuf) - MEM_freeN(text); - } - else { - text= (char*)RNA_struct_ui_name(&pptr); - but= uiDefIconTextBut(block, LABEL, 0, icon, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, descr); - } - } + but= uiDefIconTextButR(block, IDPOIN, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); break; } case PROP_COLLECTION: { diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 3fcc2d18487..52b1b77ddf0 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -457,13 +457,20 @@ int RNA_property_string_maxlength(PointerRNA *ptr, PropertyRNA *prop) StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop) { - PointerPropertyRNA *pprop; - rna_idproperty_check(&prop, ptr); - pprop= (PointerPropertyRNA*)prop; - if(pprop->type) - return pprop->type; + if(prop->type == PROP_POINTER) { + PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop; + + if(pprop->type) + return pprop->type; + } + else if(prop->type == PROP_COLLECTION) { + CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop; + + if(cprop->type) + return cprop->type; + } return &RNA_UnknownType; } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 6e4fd39d039..1b23aad6214 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -430,6 +430,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Scene", "Scene consisting objects and defining time and render related settings."); prop= RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Active Camera", "Active camera used for rendering the scene."); prop= RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_VECTOR);