UI:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 30 Mar 2009 17:31:37 +0000 (17:31 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 30 Mar 2009 17:31:37 +0000 (17:31 +0000)
* Added support for RNA pointer buttons. It's like the existing
  ID pointer buttons but with an icon, and autocomplete works.
  There's some drawing issues currently but don't want to
  interfere with the refactoring here. Also todo is support for
  things like vertex groups or bones.

source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_intern.h
source/blender/editors/interface/interface_utils.c
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_scene.c

index 7396edd30250ca2a8f2395439f54dc28c6fcda43..92a045bca6c901ffc6a35368bc29870253742a45 100644 (file)
@@ -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;
+
+               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 != str) {
+               if(buf && buf != str) {
                        /* string was too long, we have to truncate */
                        BLI_strncpy(str, buf, maxlen);
                        MEM_freeN(buf);
                }
        }
-       else
+       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(value<but->hardmin) 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)) {
index 4220d9c27810932071efaccb8334573345a79e9e..c76f6a11b2972d063632d16d7c5331392ac7db19 100644 (file)
@@ -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->value<but->hardmin) 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;
index 7f26f4fa89eb4a91539756723162a40b77e92c55..4574eb44cfa7c47d622169330997254a77db8c43 100644 (file)
@@ -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);
 
index 429b2de022745bda6903c4a5ec4b495915f3d92e..f17ec52e99a0b4d7184b724ea28cd168b4b814c2 100644 (file)
@@ -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: {
index 3fcc2d18487e965a6ed58a94789048de3851c2f4..52b1b77ddf091c33bb7dc2d42a8a023887f1cb07 100644 (file)
@@ -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;
 }
index 6e4fd39d0392f1c21fb51323edc6662ebff045ec..1b23aad6214ae4131f5aa991dfe8536954b06eab 100644 (file)
@@ -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);