From 222fe6b1a5d49f67177cbb762f55a0e482145f5d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 27 Jun 2009 01:15:31 +0000 Subject: UI * Search popup + autocomplete for bones, vertex groups, etc. This is done with layout.item_pointerR, specifying an RNA collection to take the items from. Used by constraints and modifiers. * Some tests with the List template, ignore those for now.. --- release/ui/buttons_data_mesh.py | 12 + release/ui/buttons_data_modifier.py | 169 ++++----- release/ui/buttons_object_constraint.py | 11 +- release/ui/space_image.py | 12 +- release/ui/space_text.py | 2 +- source/blender/editors/include/UI_interface.h | 5 +- source/blender/editors/interface/interface.c | 88 +---- .../blender/editors/interface/interface_handlers.c | 26 +- source/blender/editors/interface/interface_icons.c | 21 ++ .../blender/editors/interface/interface_intern.h | 8 +- .../blender/editors/interface/interface_layout.c | 150 +++++++- .../blender/editors/interface/interface_regions.c | 29 +- .../editors/interface/interface_templates.c | 383 +++++++++++---------- source/blender/editors/interface/interface_utils.c | 7 +- source/blender/makesrna/intern/rna_ui_api.c | 17 +- 15 files changed, 557 insertions(+), 383 deletions(-) diff --git a/release/ui/buttons_data_mesh.py b/release/ui/buttons_data_mesh.py index 6f64de312ed..3360f4c47ad 100644 --- a/release/ui/buttons_data_mesh.py +++ b/release/ui/buttons_data_mesh.py @@ -74,6 +74,18 @@ class DATA_PT_materials(DataButtonsPanel): row.itemO("OBJECT_OT_material_slot_select", text="Select"); row.itemO("OBJECT_OT_material_slot_deselect", text="Deselect"); + layout.itemS() + + box= layout.box() + + row = box.row() + row.template_list(ob, "materials", "active_material_index", compact=True) + + subrow = row.row(align=True) + subrow.itemO("OBJECT_OT_material_slot_add", icon="ICON_ZOOMIN", text="") + subrow.itemO("OBJECT_OT_material_slot_remove", icon="ICON_ZOOMOUT", text="") + + bpy.types.register(DATA_PT_mesh) bpy.types.register(DATA_PT_materials) diff --git a/release/ui/buttons_data_modifier.py b/release/ui/buttons_data_modifier.py index ecb0590f8e5..366f2b8a86b 100644 --- a/release/ui/buttons_data_modifier.py +++ b/release/ui/buttons_data_modifier.py @@ -23,68 +23,68 @@ class DATA_PT_modifiers(DataButtonsPanel): if box: if md.type == 'ARMATURE': - self.armature(box, md) + self.armature(box, ob, md) if md.type == 'ARRAY': - self.array(box, md) + self.array(box, ob, md) if md.type == 'BEVEL': - self.bevel(box, md) + self.bevel(box, ob, md) if md.type == 'BOOLEAN': - self.boolean(box, md) + self.boolean(box, ob, md) if md.type == 'BUILD': - self.build(box, md) + self.build(box, ob, md) if md.type == 'CAST': - self.cast(box, md) + self.cast(box, ob, md) if md.type == 'CLOTH': - self.cloth(box, md) + self.cloth(box, ob, md) if md.type == 'COLLISION': - self.collision(box, md) + self.collision(box, ob, md) if md.type == 'CURVE': - self.curve(box, md) + self.curve(box, ob, md) if md.type == 'DECIMATE': - self.decimate(box, md) + self.decimate(box, ob, md) if md.type == 'DISPLACE': - self.displace(box, md) + self.displace(box, ob, md) if md.type == 'EDGE_SPLIT': - self.edgesplit(box, md) + self.edgesplit(box, ob, md) if md.type == 'EXPLODE': - self.explode(box, md) + self.explode(box, ob, md) if md.type == 'FLUID_SIMULATION': - self.fluid(box, md) + self.fluid(box, ob, md) if md.type == 'HOOK': - self.hook(box, md) + self.hook(box, ob, md) if md.type == 'LATTICE': - self.lattice(box, md) + self.lattice(box, ob, md) if md.type == 'MASK': - self.mask(box, md) + self.mask(box, ob, md) if md.type == 'MESH_DEFORM': - self.mesh_deform(box, md) + self.mesh_deform(box, ob, md) if md.type == 'MIRROR': - self.mirror(box, md) + self.mirror(box, ob, md) if md.type == 'MULTIRES': - self.multires(box, md) + self.multires(box, ob, md) if md.type == 'PARTICLE_INSTANCE': - self.particleinstance(box, md) + self.particleinstance(box, ob, md) if md.type == 'PARTICLE_SYSTEM': - self.particlesystem(box, md) + self.particlesystem(box, ob, md) if md.type == 'SHRINKWRAP': - self.shrinkwrap(box, md) + self.shrinkwrap(box, ob, md) if md.type == 'SIMPLE_DEFORM': - self.simpledeform(box, md) + self.simpledeform(box, ob, md) if md.type == 'SMOOTH': - self.smooth(box, md) + self.smooth(box, ob, md) if md.type == 'SOFTBODY': - self.softbody(box, md) + self.softbody(box, ob, md) if md.type == 'SUBSURF': - self.subsurf(box, md) + self.subsurf(box, ob, md) if md.type == 'UV_PROJECT': - self.uvproject(box, md) + self.uvproject(box, ob, md) if md.type == 'WAVE': - self.wave(box, md) + self.wave(box, ob, md) - def armature(self, layout, md): + def armature(self, layout, ob, md): layout.itemR(md, "object") row = layout.row() - row.itemR(md, "vertex_group") + row.item_pointerR(md, "vertex_group", ob, "vertex_groups") row.itemR(md, "invert") flow = layout.column_flow() flow.itemR(md, "use_vertex_groups", text="Vertex Groups") @@ -92,7 +92,7 @@ class DATA_PT_modifiers(DataButtonsPanel): flow.itemR(md, "quaternion") flow.itemR(md, "multi_modifier") - def array(self, layout, md): + def array(self, layout, ob, md): layout.itemR(md, "fit_type") if md.fit_type == 'FIXED_COUNT': layout.itemR(md, "count") @@ -141,7 +141,7 @@ class DATA_PT_modifiers(DataButtonsPanel): col.itemR(md, "start_cap") col.itemR(md, "end_cap") - def bevel(self, layout, md): + def bevel(self, layout, ob, md): row = layout.row() row.itemR(md, "width") row.itemR(md, "only_vertices") @@ -156,11 +156,11 @@ class DATA_PT_modifiers(DataButtonsPanel): row = layout.row() row.itemR(md, "edge_weight_method", expand=True) - def boolean(self, layout, md): + def boolean(self, layout, ob, md): layout.itemR(md, "operation") layout.itemR(md, "object") - def build(self, layout, md): + def build(self, layout, ob, md): split = layout.split() col = split.column() @@ -175,7 +175,7 @@ class DATA_PT_modifiers(DataButtonsPanel): - def cast(self, layout, md): + def cast(self, layout, ob, md): layout.itemR(md, "cast_type") col = layout.column_flow() col.itemR(md, "x") @@ -184,26 +184,26 @@ class DATA_PT_modifiers(DataButtonsPanel): col.itemR(md, "factor") col.itemR(md, "radius") col.itemR(md, "size") - layout.itemR(md, "vertex_group") + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") #Missing: "OB" and "From Radius" - def cloth(self, layout, md): + def cloth(self, layout, ob, md): layout.itemL(text="See Cloth panel.") - def collision(self, layout, md): + def collision(self, layout, ob, md): layout.itemL(text="See Collision panel.") - def curve(self, layout, md): + def curve(self, layout, ob, md): layout.itemR(md, "object") - layout.itemR(md, "vertex_group") + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") layout.itemR(md, "deform_axis") - def decimate(self, layout, md): + def decimate(self, layout, ob, md): layout.itemR(md, "ratio") layout.itemR(md, "face_count") - def displace(self, layout, md): - layout.itemR(md, "vertex_group") + def displace(self, layout, ob, md): + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") layout.itemR(md, "texture") layout.itemR(md, "midlevel") layout.itemR(md, "strength") @@ -211,10 +211,10 @@ class DATA_PT_modifiers(DataButtonsPanel): layout.itemR(md, "texture_coordinates") if md.texture_coordinates == 'OBJECT': layout.itemR(md, "texture_coordinate_object", text="Object") - if md.texture_coordinates == 'UV': - layout.itemR(md, "uv_layer") + if md.texture_coordinates == 'UV' and ob.type == 'MESH': + layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers") - def edgesplit(self, layout, md): + def edgesplit(self, layout, ob, md): split = layout.split() col = split.column() @@ -225,8 +225,8 @@ class DATA_PT_modifiers(DataButtonsPanel): col = split.column() col.itemR(md, "use_sharp", text="Sharp Edges") - def explode(self, layout, md): - layout.itemR(md, "vertex_group") + def explode(self, layout, ob, md): + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") layout.itemR(md, "protect") layout.itemR(md, "split_edges") layout.itemR(md, "unborn") @@ -234,31 +234,31 @@ class DATA_PT_modifiers(DataButtonsPanel): layout.itemR(md, "dead") # Missing: "Refresh" and "Clear Vertex Group" ? - def fluid(self, layout, md): + def fluid(self, layout, ob, md): layout.itemL(text="See Fluidsim panel.") - def hook(self, layout, md): + def hook(self, layout, ob, md): layout.itemR(md, "falloff") layout.itemR(md, "force", slider=True) layout.itemR(md, "object") - layout.itemR(md, "vertex_group") + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") # Missing: "Reset" and "Recenter" - def lattice(self, layout, md): + def lattice(self, layout, ob, md): layout.itemR(md, "object") - layout.itemR(md, "vertex_group") + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") - def mask(self, layout, md): + def mask(self, layout, ob, md): layout.itemR(md, "mode") if md.mode == 'ARMATURE': layout.itemR(md, "armature") if md.mode == 'VERTEX_GROUP': - layout.itemR(md, "vertex_group") + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") layout.itemR(md, "inverse") - def mesh_deform(self, layout, md): + def mesh_deform(self, layout, ob, md): layout.itemR(md, "object") - layout.itemR(md, "vertex_group") + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") layout.itemR(md, "invert") layout.itemS() @@ -267,7 +267,7 @@ class DATA_PT_modifiers(DataButtonsPanel): row.itemR(md, "precision") row.itemR(md, "dynamic") - def mirror(self, layout, md): + def mirror(self, layout, ob, md): layout.itemR(md, "merge_limit") split = layout.split() @@ -285,12 +285,12 @@ class DATA_PT_modifiers(DataButtonsPanel): layout.itemR(md, "mirror_object") - def multires(self, layout, md): + def multires(self, layout, ob, md): layout.itemR(md, "subdivision_type") layout.itemO("OBJECT_OT_multires_subdivide", text="Subdivide") layout.itemR(md, "level") - def particleinstance(self, layout, md): + def particleinstance(self, layout, ob, md): layout.itemR(md, "object") layout.itemR(md, "particle_system_number") @@ -302,12 +302,12 @@ class DATA_PT_modifiers(DataButtonsPanel): col.itemR(md, "alive") col.itemR(md, "dead") - def particlesystem(self, layout, md): + def particlesystem(self, layout, ob, md): layout.itemL(text="See Particle panel.") - def shrinkwrap(self, layout, md): + def shrinkwrap(self, layout, ob, md): layout.itemR(md, "target") - layout.itemR(md, "vertex_group") + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") layout.itemR(md, "offset") layout.itemR(md, "subsurf_levels") layout.itemR(md, "mode") @@ -329,9 +329,9 @@ class DATA_PT_modifiers(DataButtonsPanel): layout.itemR(md, "keep_above_surface") # To-Do: Validate if structs - def simpledeform(self, layout, md): + def simpledeform(self, layout, ob, md): layout.itemR(md, "mode") - layout.itemR(md, "vertex_group") + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") layout.itemR(md, "origin") layout.itemR(md, "relative") layout.itemR(md, "factor") @@ -340,7 +340,7 @@ class DATA_PT_modifiers(DataButtonsPanel): layout.itemR(md, "lock_x_axis") layout.itemR(md, "lock_y_axis") - def smooth(self, layout, md): + def smooth(self, layout, ob, md): split = layout.split() sub = split.column() sub.itemR(md, "x") @@ -350,12 +350,12 @@ class DATA_PT_modifiers(DataButtonsPanel): sub.itemR(md, "factor") sub.itemR(md, "repeat") - layout.itemR(md, "vertex_group") + layout.template_pointer(md, "vertex_group", ob, "vertex_groups") - def softbody(self, layout, md): + def softbody(self, layout, ob, md): layout.itemL(text="See Softbody panel.") - def subsurf(self, layout, md): + def subsurf(self, layout, ob, md): layout.itemR(md, "subdivision_type") col = layout.column_flow() col.itemR(md, "levels", text="Preview") @@ -363,16 +363,17 @@ class DATA_PT_modifiers(DataButtonsPanel): col.itemR(md, "optimal_draw", text="Optimal Display") col.itemR(md, "subsurf_uv") - def uvproject(self, layout, md): - layout.itemR(md, "uv_layer") - layout.itemR(md, "projectors") - layout.itemR(md, "image") - layout.itemR(md, "horizontal_aspect_ratio") - layout.itemR(md, "vertical_aspect_ratio") - layout.itemR(md, "override_image") - #"Projectors" don't work. - - def wave(self, layout, md): + def uvproject(self, layout, ob, md): + if ob.type == 'MESH': + layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers") + layout.itemR(md, "projectors") + layout.itemR(md, "image") + layout.itemR(md, "horizontal_aspect_ratio") + layout.itemR(md, "vertical_aspect_ratio") + layout.itemR(md, "override_image") + #"Projectors" don't work. + + def wave(self, layout, ob, md): split = layout.split() sub = split.column() @@ -398,11 +399,11 @@ class DATA_PT_modifiers(DataButtonsPanel): col.itemR(md, "start_position_y") layout.itemR(md, "start_position_object") - layout.itemR(md, "vertex_group") + layout.item_pointerR(md, "vertex_group", ob, "vertex_groups") layout.itemR(md, "texture") layout.itemR(md, "texture_coordinates") - if md.texture_coordinates == 'MAP_UV': - layout.itemR(md, "uv_layer") + if md.texture_coordinates == 'MAP_UV' and ob.type == 'MESH': + layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers") if md.texture_coordinates == 'OBJECT': layout.itemR(md, "texture_coordinates_object") @@ -412,4 +413,4 @@ class DATA_PT_modifiers(DataButtonsPanel): col.itemR(md, "width", slider=True) col.itemR(md, "narrowness", slider=True) -bpy.types.register(DATA_PT_modifiers) \ No newline at end of file +bpy.types.register(DATA_PT_modifiers) diff --git a/release/ui/buttons_object_constraint.py b/release/ui/buttons_object_constraint.py index 52e43406790..3048bdaa399 100644 --- a/release/ui/buttons_object_constraint.py +++ b/release/ui/buttons_object_constraint.py @@ -77,13 +77,14 @@ class ConstraintButtonsPanel(bpy.types.Panel): if con.target and subtargets: if con.target.type == "ARMATURE": - layout.itemR(con, "subtarget", text="Bone") # XXX autocomplete + layout.item_pointerR(con, "subtarget", con.target.data, "bones", text="Bone") - row = layout.row() - row.itemL(text="Head/Tail:") - row.itemR(con, "head_tail", text="") + if con.type == 'COPY_LOCATION': + row = layout.row() + row.itemL(text="Head/Tail:") + row.itemR(con, "head_tail", text="") elif con.target.type in ("MESH", "LATTICE"): - layout.itemR(con, "subtarget", text="Vertex Group") # XXX autocomplete + layout.item_pointerR(con, "subtarget", con.target, "vertex_groups", text="Vertex Group") def child_of(self, layout, con): self.target_template(layout, con) diff --git a/release/ui/space_image.py b/release/ui/space_image.py index e49172fd3f1..63ca316efe7 100644 --- a/release/ui/space_image.py +++ b/release/ui/space_image.py @@ -273,16 +273,8 @@ class IMAGE_HT_header(bpy.types.Header): row.itemR(settings, "snap_mode", text="") """ - /* uv layers */ - { - Object *obedit= CTX_data_edit_object(C); - char menustr[34*MAX_MTFACE]; - static int act; - - image_menu_uvlayers(obedit, menustr, &act); - - but = uiDefButI(block, MENU, B_NOP, menustr ,xco,yco,85,YIC, &act, 0, 0, 0, 0, "Active UV Layer for editing."); - // uiButSetFunc(but, do_image_buttons_set_uvlayer_callback, &act, NULL); + mesh = context.edit_object.data + row.item_pointerR(mesh, "active_uv_layer", mesh, "uv_layers") """ if ima: diff --git a/release/ui/space_text.py b/release/ui/space_text.py index 19a495d375e..07e43f32054 100644 --- a/release/ui/space_text.py +++ b/release/ui/space_text.py @@ -29,7 +29,7 @@ class TEXT_HT_header(bpy.types.Header): row.itemR(st, "word_wrap", text="") row.itemR(st, "syntax_highlight", text="") - layout.template_ID(st, "text", new="TEXT_OT_new", open="TEXT_OT_open", unlink="TEXT_OT_unlink") + layout.template_ID(st, "text", new="TEXT_OT_new", unlink="TEXT_OT_unlink") if text: row = layout.row() diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index f5e2b45d41e..b6d71759373 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -609,7 +609,7 @@ uiBlock *uiLayoutFreeBlock(uiLayout *layout); /* templates */ void uiTemplateHeader(uiLayout *layout, struct bContext *C); void uiTemplateID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, - char *newop, char *openop, char *unlinkop); + char *newop, char *unlinkop); uiLayout *uiTemplateModifier(uiLayout *layout, struct PointerRNA *ptr); uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); void uiTemplatePreview(uiLayout *layout, struct ID *id); @@ -617,7 +617,7 @@ void uiTemplateColorRamp(uiLayout *layout, struct ColorBand *coba, int expand); void uiTemplateCurveMapping(uiLayout *layout, struct CurveMapping *cumap, int type); void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, char *propname); void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser); -void uiTemplateList(uiLayout *layout, struct PointerRNA *ptr, char *propname, char *activeprop, int items); +ListBase uiTemplateList(uiLayout *layout, struct PointerRNA *ptr, char *propname, char *activeprop, int rows, int columns, int compact); /* items */ void uiItemO(uiLayout *layout, char *name, int icon, char *opname); @@ -634,6 +634,7 @@ void uiItemR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, cha void uiItemFullR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, int value, int expand, int slider, int toggle); void uiItemEnumR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, int value); void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname); +void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, struct PointerRNA *searchptr, char *searchpropname); void uiItemL(uiLayout *layout, char *name, int icon); /* label */ void uiItemM(uiLayout *layout, struct bContext *C, char *name, int icon, char *menuname); /* menu */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 73425eac0e1..3a61237e1cb 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -80,7 +80,6 @@ */ static void ui_free_but(const bContext *C, uiBut *but); -static void ui_rna_ID_autocomplete(bContext *C, char *str, void *arg_but); /* ************* translation ************** */ @@ -1334,61 +1333,6 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen) } } -static void ui_rna_ID_collection(bContext *C, uiBut *but, PointerRNA *ptr, PropertyRNA **prop) -{ - StructRNA *srna; - - /* look for collection property in Main */ - RNA_pointer_create(NULL, &RNA_Main, CTX_data_main(C), ptr); - - *prop= NULL; - - RNA_STRUCT_BEGIN(ptr, iprop) { - /* if it's a collection and has same pointer type, we've got it */ - if(RNA_property_type(iprop) == PROP_COLLECTION) { - srna= RNA_property_pointer_type(ptr, iprop); - - if(RNA_property_pointer_type(ptr, but->rnaprop) == srna) { - *prop= iprop; - break; - } - } - } - RNA_STRUCT_END; -} - -/* autocomplete callback for RNA pointers */ -static void ui_rna_ID_autocomplete(bContext *C, char *str, void *arg_but) -{ - uiBut *but= arg_but; - AutoComplete *autocpl; - PointerRNA ptr; - PropertyRNA *prop; - 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)); - - /* loop over items in collection */ - RNA_PROP_BEGIN(&ptr, itemptr, prop) { - name= RNA_struct_name_get_alloc(&itemptr, NULL, 0); - - /* test item name */ - if(name) { - autocomplete_do_name(autocpl, name); - MEM_freeN(name); - } - } - RNA_PROP_END; - - autocomplete_end(autocpl, str); -} - int ui_set_but_string(bContext *C, uiBut *but, const char *str) { if(but->rnaprop && ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) { @@ -1407,21 +1351,21 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) 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(str == NULL || str[0] == '\0') { - memset(&rptr, 0, sizeof(rptr)); - RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr); + RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL); return 1; } - else if(prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) { - RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr); + else { + ptr= but->rnasearchpoin; + prop= but->rnasearchprop; + + 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; + + return 0; } } } @@ -2133,7 +2077,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short rgb_to_hsv(rgb[0], rgb[1], rgb[2], but->hsv, but->hsv+1, but->hsv+2); } - if((block->flag & UI_BLOCK_LOOP) || ELEM6(but->type, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM)) { + if((block->flag & UI_BLOCK_LOOP) || ELEM7(but->type, MENU, TEX, LABEL, IDPOIN, BLOCK, BUTM, SEARCH_MENU)) { but->flag |= UI_TEXT_LEFT; } @@ -2289,10 +2233,6 @@ 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(icon) { @@ -2408,7 +2348,11 @@ void autocomplete_do_name(AutoComplete *autocpl, const char *name) else { /* remove from truncate what is not in bone->name */ for(a=0; amaxlen-1; a++) { - if(truncate[a]!=name[a]) + if(name[a] == 0) { + truncate[a]= 0; + break; + } + else if(truncate[a]!=name[a]) truncate[a]= 0; } } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 2382af53a11..5049fc0b130 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1223,8 +1223,14 @@ static int ui_textedit_autocomplete(bContext *C, uiBut *but, uiHandleButtonData int changed= 1; str= data->str; - but->autocomplete_func(C, str, but->autofunc_arg); + + if(data->searchbox) + ui_searchbox_autocomplete(C, data->searchbox, but, data->str); + else + but->autocomplete_func(C, str, but->autofunc_arg); + but->pos= strlen(str); + but->selsta= but->selend= but->pos; return changed; } @@ -1351,14 +1357,14 @@ static void ui_textedit_next_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa return; for(but= actbut->next; but; but= but->next) { - if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) { + if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) { data->postbut= but; data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; return; } } for(but= block->buttons.first; but!=actbut; but= but->next) { - if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) { + if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) { data->postbut= but; data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; return; @@ -1375,14 +1381,14 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa return; for(but= actbut->prev; but; but= but->prev) { - if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) { + if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) { data->postbut= but; data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; return; } } for(but= block->buttons.last; but!=actbut; but= but->prev) { - if(ELEM5(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI)) { + if(ELEM7(but->type, TEX, NUM, NUMABS, NUMSLI, HSVSLI, IDPOIN, SEARCH_MENU)) { data->postbut= but; data->posttype= BUTTON_ACTIVATE_TEXT_EDITING; return; @@ -1506,7 +1512,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle case TABKEY: /* there is a key conflict here, we can't tab with autocomplete */ - if(but->autocomplete_func) { + if(but->autocomplete_func || data->searchbox) { changed= ui_textedit_autocomplete(C, but, data); retval= WM_UI_HANDLER_BREAK; } @@ -4103,7 +4109,7 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo uiBlock *block; uiHandleButtonData *data; uiPopupBlockHandle *submenu; - int mx, my; + int mx, my, update; ar= menu->region; block= ar->uiblocks.first; @@ -4121,14 +4127,16 @@ static int ui_handle_menu_return_submenu(bContext *C, wmEvent *event, uiPopupBlo menu->butretval= data->retval; } } - else if(submenu->menuretval == UI_RETURN_UPDATE) + + update= (submenu->menuretval == UI_RETURN_UPDATE); + if(update) menu->menuretval = UI_RETURN_UPDATE; /* now let activated button in this menu exit, which * will actually close the submenu too */ ui_handle_button_return_submenu(C, event, but); - if(submenu->menuretval == UI_RETURN_UPDATE) + if(update) submenu->menuretval = 0; } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 6b566012525..4d8ec5996be 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -927,7 +927,28 @@ void ui_id_icon_render(Scene *scene, ID *id) } } +int ui_id_icon_get(Scene *scene, ID *id) +{ + int iconid= 0; + + /* icon */ + switch(GS(id->name)) + { + case ID_MA: /* fall through */ + case ID_TE: /* fall through */ + case ID_IM: /* fall through */ + case ID_WO: /* fall through */ + case ID_LA: /* fall through */ + iconid= BKE_icon_getid(id); + /* checks if not exists, or changed */ + ui_id_icon_render(scene, id); + break; + default: + break; + } + return iconid; +} static void icon_draw_mipmap(float x, float y, int icon_id, float aspect, int miplevel, int nocreate) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index c27eafd501c..1b16155c7e6 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -211,6 +211,9 @@ struct uiBut { struct PropertyRNA *rnaprop; int rnaindex; + struct PointerRNA rnasearchpoin; + struct PropertyRNA *rnasearchprop; + /* Operator data */ struct wmOperatorType *optype; int opcontext; @@ -371,6 +374,7 @@ void ui_tooltip_free(struct bContext *C, struct ARegion *ar); ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBut *but); int ui_searchbox_inside(struct ARegion *ar, int x, int y); void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, int reset); +void ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str); void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, struct wmEvent *event); void ui_searchbox_apply(uiBut *but, struct ARegion *ar); void ui_searchbox_free(struct bContext *C, struct ARegion *ar); @@ -429,6 +433,7 @@ void uiStyleInit(void); /* interface_icons.c */ void ui_id_icon_render(struct Scene *scene, struct ID *id); +int ui_id_icon_get(struct Scene *scene, struct ID *id); /* resources.c */ void init_userdef_do_versions(void); @@ -437,8 +442,9 @@ void ui_resources_init(void); void ui_resources_free(void); /* interface_layout.c */ -void ui_layout_add_but(struct uiLayout *layout, uiBut *but); +void ui_layout_add_but(uiLayout *layout, uiBut *but); int ui_but_can_align(uiBut *but); +void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop); /* interface_anim.c */ void ui_but_anim_flag(uiBut *but, float cfra); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 03da6861974..94280ec37d3 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -455,9 +455,10 @@ static void ui_item_enum_row(uiLayout *layout, uiBlock *block, PointerRNA *ptr, } /* create label + button for RNA property */ -static void ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h) +static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int icon, PointerRNA *ptr, PropertyRNA *prop, int index, int x, int y, int w, int h) { uiLayout *sub; + uiBut *but; PropertySubType subtype; sub= uiLayoutRow(layout, 0); @@ -473,12 +474,13 @@ static void ui_item_with_label(uiLayout *layout, uiBlock *block, char *name, int if(subtype == PROP_FILEPATH || subtype == PROP_DIRPATH) { uiBlockSetCurLayout(block, uiLayoutRow(sub, 1)); uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w-UI_UNIT_X, h); - uiDefIconBut(block, BUT, 0, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "DUMMY file select button"); /* XXX */ + but= uiDefIconBut(block, BUT, 0, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL, 0.0f, 0.0f, 0.0f, 0.0f, "DUMMY file select button"); /* XXX */ } else - uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h); + but= uiDefAutoButR(block, ptr, prop, index, "", icon, x, y, w, h); uiBlockSetCurLayout(block, layout); + return but; } /********************* Button Items *************************/ @@ -782,8 +784,10 @@ void uiItemFullR(uiLayout *layout, char *name, int icon, PointerRNA *ptr, Proper else if(type == PROP_ENUM && expand) ui_item_enum_row(layout, block, ptr, prop, name, 0, 0, w, h); /* property with separate label */ - else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) - ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h); + else if(type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) { + but= ui_item_with_label(layout, block, name, icon, ptr, prop, index, 0, 0, w, h); + ui_but_add_search(but, ptr, prop, NULL, NULL); + } /* single button */ else { but= uiDefAutoButR(block, ptr, prop, index, (char*)name, icon, 0, 0, w, h); @@ -854,6 +858,142 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname) } } +/* Pointer RNA button with search */ + +static void rna_search_cb(const struct bContext *C, void *arg_but, char *str, uiSearchItems *items) +{ + Scene *scene= CTX_data_scene(C); + uiBut *but= arg_but; + char *name; + int i, iconid; + + i = 0; + RNA_PROP_BEGIN(&but->rnasearchpoin, itemptr, but->rnasearchprop) { + iconid= 0; + if(RNA_struct_is_ID(itemptr.type)) + iconid= ui_id_icon_get(scene, itemptr.data); + + name= RNA_struct_name_get_alloc(&itemptr, NULL, 0); + + if(name) { + if(BLI_strcasestr(name, str)) { + if(!uiSearchItemAdd(items, name, SET_INT_IN_POINTER(i), iconid)) { + MEM_freeN(name); + break; + } + } + + MEM_freeN(name); + } + + i++; + } + RNA_PROP_END; +} + +static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA **prop) +{ + StructRNA *srna; + + /* look for collection property in Main */ + RNA_main_pointer_create(G.main, ptr); + + *prop= NULL; + + RNA_STRUCT_BEGIN(ptr, iprop) { + /* if it's a collection and has same pointer type, we've got it */ + if(RNA_property_type(iprop) == PROP_COLLECTION) { + srna= RNA_property_pointer_type(ptr, iprop); + + if(ptype == srna) { + *prop= iprop; + break; + } + } + } + RNA_STRUCT_END; +} + +void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *searchptr, PropertyRNA *searchprop) +{ + StructRNA *ptype; + PointerRNA sptr; + + /* for ID's we do automatic lookup */ + if(!searchprop) { + if(RNA_property_type(prop) == PROP_POINTER) { + ptype= RNA_property_pointer_type(ptr, prop); + search_id_collection(ptype, &sptr, &searchprop); + searchptr= &sptr; + } + } + + /* turn button into search button */ + if(searchprop) { + but->type= SEARCH_MENU; + but->hardmax= MAX2(but->hardmax, 256); + but->rnasearchpoin= *searchptr; + but->rnasearchprop= searchprop; + but->flag |= UI_ICON_LEFT|UI_TEXT_LEFT; + + uiButSetSearchFunc(but, rna_search_cb, but, NULL); + } +} + +void uiItemPointerR(uiLayout *layout, char *name, int icon, struct PointerRNA *ptr, char *propname, struct PointerRNA *searchptr, char *searchpropname) +{ + PropertyRNA *prop, *searchprop; + PropertyType type; + uiBut *but; + uiBlock *block; + StructRNA *icontype; + int w, h; + + /* validate arguments */ + if(!ptr->data || !searchptr->data) + return; + + prop= RNA_struct_find_property(ptr, propname); + + if(!prop) { + printf("uiItemPointerR: property not found: %s\n", propname); + return; + } + + type= RNA_property_type(prop); + if(!ELEM(type, PROP_POINTER, PROP_STRING)) { + printf("uiItemPointerR: property %s must be a pointer or string.\n", propname); + return; + } + + searchprop= RNA_struct_find_property(searchptr, searchpropname); + + if(!searchprop || RNA_property_type(searchprop) != PROP_COLLECTION) { + printf("uiItemPointerR: search collection property not found: %s\n", searchpropname); + return; + } + + /* get icon & name */ + if(!icon) { + if(type == PROP_POINTER) + icontype= RNA_property_pointer_type(ptr, prop); + else + icontype= RNA_property_pointer_type(searchptr, searchprop); + + icon= RNA_struct_ui_icon(icontype); + } + if(!name) + name= (char*)RNA_property_ui_name(prop); + + /* create button */ + block= uiLayoutGetBlock(layout); + + ui_item_rna_size(layout, name, icon, prop, 0, &w, &h); + but= ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h); + + ui_but_add_search(but, ptr, prop, searchptr, searchprop); +} + /* menu item */ static void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) { diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index a1dae39d687..61cf612e912 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -435,6 +435,8 @@ struct uiSearchItems { char **names; void **pointers; int *icons; + + AutoComplete *autocpl; }; typedef struct uiSearchboxData { @@ -451,6 +453,11 @@ typedef struct uiSearchboxData { /* returns zero if nothing to add */ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid) { + /* hijack for autocomplete */ + if(items->autocpl) { + autocomplete_do_name(items->autocpl, name); + return 1; + } if(items->totitem>=items->maxitem) { items->more= 1; @@ -622,6 +629,18 @@ void ui_searchbox_update(bContext *C, ARegion *ar, uiBut *but, int reset) ED_region_tag_redraw(ar); } +void ui_searchbox_autocomplete(bContext *C, ARegion *ar, uiBut *but, char *str) +{ + uiSearchboxData *data= ar->regiondata; + + data->items.autocpl= autocomplete_begin(str, ui_get_but_string_max_length(but)); + + but->search_func(C, but->search_arg, but->editstr, &data->items); + + autocomplete_end(data->items.autocpl, str); + data->items.autocpl= NULL; +} + static void ui_searchbox_region_draw(const bContext *C, ARegion *ar) { uiSearchboxData *data= ar->regiondata; @@ -683,7 +702,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) uiSearchboxData *data; float aspect= but->block->aspect; float x1f, x2f, y1f, y2f; - int x1, x2, y1, y2, winx, winy; + int x1, x2, y1, y2, winx, winy, ofsx, ofsy; /* create area region */ ar= ui_add_temporary_region(CTX_wm_screen(C)); @@ -736,6 +755,14 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) x2f= but->x2 + 5; /* symmetrical */ y2f= but->y1; y1f= y2f - uiSearchBoxhHeight(); + + ofsx= (but->block->panel)? but->block->panel->ofsx: 0; + ofsy= (but->block->panel)? but->block->panel->ofsy: 0; + + x1f += ofsx; + x2f += ofsx; + y1f += ofsy; + y2f += ofsy; /* minimal width */ if(x2f - x1f < 150) x2f= x1f+150; // XXX arbitrary diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 37b2a4af84e..a006187c4aa 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -27,12 +27,14 @@ #include "MEM_guardedalloc.h" +#include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "BLI_string.h" #include "BKE_context.h" #include "BKE_icons.h" +#include "BKE_global.h" #include "BKE_library.h" #include "BKE_utildefines.h" @@ -62,121 +64,51 @@ void uiTemplateHeader(uiLayout *layout, bContext *C) ED_area_header_standardbuttons(C, block, 0); } -/******************* Header ID Template ************************/ +/********************** Search Callbacks *************************/ typedef struct TemplateID { PointerRNA ptr; PropertyRNA *prop; - int flag; - short browse; - - char newop[256]; - char openop[256]; - char unlinkop[256]; - - short idtype; + ListBase *idlb; } TemplateID; -static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) +/* Search browse menu, assign */ +static void id_search_call_cb(struct bContext *C, void *arg_template, void *item) { - TemplateID *template= (TemplateID*)arg_litem; - PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop); - ID *id= idptr.data; - int event= GET_INT_FROM_POINTER(arg_event); - - if(event == UI_ID_BROWSE && template->browse == 32767) - event= UI_ID_ADD_NEW; - else if(event == UI_ID_BROWSE && template->browse == 32766) - event= UI_ID_OPEN; + TemplateID *template= (TemplateID*)arg_template; - switch(event) { - case UI_ID_BROWSE: - printf("warning, id browse shouldnt come here\n"); - break; - case UI_ID_DELETE: - memset(&idptr, 0, sizeof(idptr)); - RNA_property_pointer_set(&template->ptr, template->prop, idptr); - RNA_property_update(C, &template->ptr, template->prop); - break; - case UI_ID_FAKE_USER: - if(id) { - if(id->flag & LIB_FAKEUSER) id->us++; - else id->us--; - } - else return; - break; - case UI_ID_PIN: - break; - case UI_ID_ADD_NEW: - WM_operator_name_call(C, template->newop, WM_OP_INVOKE_REGION_WIN, NULL); - break; - case UI_ID_OPEN: - WM_operator_name_call(C, template->openop, WM_OP_INVOKE_REGION_WIN, NULL); - break; -#if 0 - case UI_ID_ALONE: - if(!id || id->us < 1) - return; - break; - case UI_ID_LOCAL: - if(!id || id->us < 1) - return; - break; - case UI_ID_AUTO_NAME: - break; -#endif - } -} - -/* ID Search browse menu, assign */ -static void id_search_call_cb(struct bContext *C, void *arg_litem, void *item) -{ + /* ID */ if(item) { - TemplateID *template= (TemplateID*)arg_litem; - PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop); + PointerRNA idptr; RNA_id_pointer_create(item, &idptr); RNA_property_pointer_set(&template->ptr, template->prop, idptr); RNA_property_update(C, &template->ptr, template->prop); - } + } } /* ID Search browse menu, do the search */ -static void id_search_cb(const struct bContext *C, void *arg_litem, char *str, uiSearchItems *items) +static void id_search_cb(const struct bContext *C, void *arg_template, char *str, uiSearchItems *items) { - TemplateID *template= (TemplateID*)arg_litem; - ListBase *lb= wich_libbase(CTX_data_main(C), template->idtype); + TemplateID *template= (TemplateID*)arg_template; + Scene *scene= CTX_data_scene(C); + ListBase *lb= template->idlb; ID *id; - + int iconid; + + /* ID listbase */ for(id= lb->first; id; id= id->next) { - int iconid= 0; - - /* icon */ - switch(GS(id->name)) - { - case ID_MA: /* fall through */ - case ID_TE: /* fall through */ - case ID_IM: /* fall through */ - case ID_WO: /* fall through */ - case ID_LA: /* fall through */ - iconid= BKE_icon_getid(id); - /* checks if not exists, or changed */ - ui_id_icon_render(CTX_data_scene(C), id); - break; - default: - break; - } - - if(BLI_strcasestr(id->name+2, str)) { - if(0==uiSearchItemAdd(items, id->name+2, id, iconid)) + iconid= ui_id_icon_get(scene, id); + + if(BLI_strcasestr(id->name+2, str)) + if(!uiSearchItemAdd(items, id->name+2, id, iconid)) break; - } } } /* ID Search browse menu, open */ -static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) +static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem) { static char search[256]; static TemplateID template; @@ -213,17 +145,57 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) return block; } -/* ****************** */ +/************************ ID Template ***************************/ +static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) +{ + TemplateID *template= (TemplateID*)arg_litem; + PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop); + ID *id= idptr.data; + int event= GET_INT_FROM_POINTER(arg_event); + + switch(event) { + case UI_ID_BROWSE: + case UI_ID_PIN: + case UI_ID_OPEN: + case UI_ID_ADD_NEW: + printf("warning, id event %d shouldnt come here\n", event); + break; + case UI_ID_DELETE: + memset(&idptr, 0, sizeof(idptr)); + RNA_property_pointer_set(&template->ptr, template->prop, idptr); + RNA_property_update(C, &template->ptr, template->prop); + break; + case UI_ID_FAKE_USER: + if(id) { + if(id->flag & LIB_FAKEUSER) id->us++; + else id->us--; + } + else return; + break; +#if 0 + case UI_ID_ALONE: + if(!id || id->us < 1) + return; + break; + case UI_ID_LOCAL: + if(!id || id->us < 1) + return; + break; + case UI_ID_AUTO_NAME: + break; +#endif + } +} -static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type) +static void template_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type, int flag, char *newop, char *unlinkop) { uiBut *but; PointerRNA idptr; ListBase *lb; idptr= RNA_property_pointer_get(&template->ptr, template->prop); - lb= wich_libbase(CTX_data_main(C), template->idtype); + lb= template->idlb; if(idptr.type) type= idptr.type; @@ -231,29 +203,8 @@ static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template uiDefIconBut(block, LABEL, 0, RNA_struct_ui_icon(type), 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); uiBlockBeginAlign(block); - if(template->flag & UI_ID_BROWSE) { - /* - char *extrastr, *str; - - if((template->flag & UI_ID_ADD_NEW) && (template->flag & UI_ID_OPEN)) - extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767"; - else if(template->flag & UI_ID_ADD_NEW) - extrastr= "ADD NEW %x 32767"; - else if(template->flag & UI_ID_OPEN) - extrastr= "OPEN NEW %x 32766"; - else - extrastr= NULL; - - duptemplate= MEM_dupallocN(template); - IDnames_to_pupstring(&str, NULL, extrastr, lb, idptr.data, &duptemplate->browse); - - but= uiDefButS(block, MENU, 0, str, 0, 0, UI_UNIT_X, UI_UNIT_Y, &duptemplate->browse, 0, 0, 0, 0, "Browse existing choices, or add new"); - uiButSetNFunc(but, template_id_cb, duptemplate, SET_INT_IN_POINTER(UI_ID_BROWSE)); - - MEM_freeN(str); - */ - uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Browse ID data"); - } + if(flag & UI_ID_BROWSE) + uiDefBlockButN(block, search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Browse ID data"); /* text button with name */ if(idptr.data) { @@ -265,11 +216,11 @@ static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME)); } - if(template->flag & UI_ID_ADD_NEW) { + if(flag & UI_ID_ADD_NEW) { int w= idptr.data?UI_UNIT_X:UI_UNIT_X*6; - if(template->newop[0]) { - but= uiDefIconTextButO(block, BUT, template->newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL); + if(newop) { + but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL); } else { but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); @@ -278,9 +229,9 @@ static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template } /* delete button */ - if(idptr.data && (template->flag & UI_ID_DELETE)) { - if(template->unlinkop[0]) { - but= uiDefIconButO(block, BUT, template->unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); + if(idptr.data && (flag & UI_ID_DELETE)) { + if(unlinkop) { + but= uiDefIconButO(block, BUT, unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); } else { but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); @@ -291,12 +242,13 @@ static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template uiBlockEndAlign(block); } -void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop) +void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *unlinkop) { TemplateID *template; uiBlock *block; PropertyRNA *prop; StructRNA *type; + int flag; if(!ptr->data) return; @@ -311,26 +263,19 @@ void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname template= MEM_callocN(sizeof(TemplateID), "TemplateID"); template->ptr= *ptr; template->prop= prop; - template->flag= UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE; - if(newop) { - template->flag |= UI_ID_ADD_NEW; - BLI_strncpy(template->newop, newop, sizeof(template->newop)); - } - if(openop) { - template->flag |= UI_ID_OPEN; - BLI_strncpy(template->openop, openop, sizeof(template->openop)); - } - if(unlinkop) - BLI_strncpy(template->unlinkop, unlinkop, sizeof(template->unlinkop)); + flag= UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE; + + if(newop) + flag |= UI_ID_ADD_NEW; type= RNA_property_pointer_type(ptr, prop); - template->idtype = RNA_type_to_ID_code(type); + template->idlb= wich_libbase(CTX_data_main(C), RNA_type_to_ID_code(type)); - if(template->idtype) { + if(template->idlb) { uiLayoutRow(layout, 1); block= uiLayoutGetBlock(layout); - template_header_ID(C, block, template, type); + template_ID(C, block, template, type, flag, newop, unlinkop); } MEM_freeN(template); @@ -1529,6 +1474,7 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname) /************************* List Template **************************/ +#if 0 typedef struct ListItem { PointerRNA ptr; PropertyRNA *prop; @@ -1560,50 +1506,52 @@ static void list_item_cb(bContext *C, void *arg_item, void *arg_unused) } } } +#endif -void uiTemplateList(uiLayout *layout, PointerRNA *ptr, char *propname, char *activepropname, int items) +ListBase uiTemplateList(uiLayout *layout, PointerRNA *ptr, char *propname, char *activepropname, int rows, int columns, int compact) { + CollectionPointerLink *link; PropertyRNA *prop, *activeprop; PropertyType type, activetype; PointerRNA activeptr; uiLayout *box, *row, *col; uiBlock *block; uiBut *but; - char *name, *activename= NULL; - int i= 1, activei= 0, len; + ListBase lb; + char *name, *activename= NULL, str[32]; + int i= 1, activei= 0, len, items, found; static int scroll = 1; + + lb.first= lb.last= NULL; /* validate arguments */ if(!ptr->data) - return; + return lb; prop= RNA_struct_find_property(ptr, propname); if(!prop) { printf("uiTemplateList: property not found: %s\n", propname); - return; + return lb; } activeprop= RNA_struct_find_property(ptr, activepropname); if(!activeprop) { printf("uiTemplateList: property not found: %s\n", activepropname); - return; + return lb; } type= RNA_property_type(prop); if(type != PROP_COLLECTION) { printf("uiTemplateList: expected collection property.\n"); - return; + return lb; } activetype= RNA_property_type(activeprop); if(!ELEM3(activetype, PROP_POINTER, PROP_INT, PROP_STRING)) { printf("uiTemplateList: expected pointer, integer or string property.\n"); - return; + return lb; } - if(items == 0) - items= 5; - /* get active data */ if(activetype == PROP_POINTER) activeptr= RNA_property_pointer_get(ptr, activeprop); @@ -1612,62 +1560,119 @@ void uiTemplateList(uiLayout *layout, PointerRNA *ptr, char *propname, char *act else if(activetype == PROP_STRING) activename= RNA_property_string_get_alloc(ptr, activeprop, NULL, 0); - box= uiLayoutBox(layout); - row= uiLayoutRow(box, 0); - col = uiLayoutColumn(row, 1); + block= uiLayoutGetBlock(layout); - block= uiLayoutGetBlock(col); - uiBlockSetEmboss(block, UI_EMBOSSN); + if(compact) { + /* compact layout */ + found= 0; + + row= uiLayoutRow(layout, 1); + + RNA_PROP_BEGIN(ptr, itemptr, prop) { + if(activetype == PROP_POINTER) + found= (activeptr.data == itemptr.data); + else if(activetype == PROP_INT) + found= (activei == i); + else if(activetype == PROP_STRING) + found= (strcmp(activename, name) == 0); + + if(found) { + name= RNA_struct_name_get_alloc(&itemptr, NULL, 0); + if(name) { + uiItemL(row, name, RNA_struct_ui_icon(itemptr.type)); + MEM_freeN(name); + } + + link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return"); + link->ptr= itemptr; + BLI_addtail(&lb, link); + } + + i++; + } + RNA_PROP_END; - len= RNA_property_collection_length(ptr, prop); - scroll= MIN2(scroll, len-items+1); - scroll= MAX2(scroll, 1); + if(i == 1) + uiItemL(row, "", 0); - RNA_PROP_BEGIN(ptr, itemptr, prop) { - if(i >= scroll && iptr= *ptr; - item->prop= prop; - item->activeprop= activeprop; - item->activeptr= itemptr; - item->activei= i; + box= uiLayoutBox(layout); + row= uiLayoutRow(box, 0); + col = uiLayoutColumn(row, 1); + + uiBlockSetEmboss(block, UI_EMBOSSN); + + len= RNA_property_collection_length(ptr, prop); + scroll= MIN2(scroll, len-items+1); + scroll= MAX2(scroll, 1); + + RNA_PROP_BEGIN(ptr, itemptr, prop) { + if(i >= scroll && iptr= *ptr; + item->prop= prop; + item->activeprop= activeprop; + item->activeptr= itemptr; + item->activei= i; + + if(activetype == PROP_POINTER) + item->selected= (activeptr.data == itemptr.data)? i: -1; + else if(activetype == PROP_INT) + item->selected= (activei == i)? i: -1; + else if(activetype == PROP_STRING) + item->selected= (strcmp(activename, name) == 0)? i: -1; +#endif - if(activetype == PROP_POINTER) - item->selected= (activeptr.data == itemptr.data)? i: -1; - else if(activetype == PROP_INT) - item->selected= (activei == i)? i: -1; - else if(activetype == PROP_STRING) - item->selected= (strcmp(activename, name) == 0)? i: -1; + //but= uiDefIconTextButI(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, &item->selected, 0, i, 0, 0, ""); + but= uiDefIconTextButR(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, ptr, activepropname, 0/*&item->selected*/, 0, i, 0, 0, ""); + uiButSetFlag(but, UI_ICON_LEFT|UI_TEXT_LEFT); + //uiButSetNFunc(but, list_item_cb, item, NULL); - but= uiDefIconTextButI(block, ROW, 0, RNA_struct_ui_icon(itemptr.type), name, 0,0,UI_UNIT_X*10,UI_UNIT_Y, &item->selected, 0, i, 0, 0, ""); - uiButSetFlag(but, UI_ICON_LEFT|UI_TEXT_LEFT); - uiButSetNFunc(but, list_item_cb, item, NULL); + MEM_freeN(name); - MEM_freeN(name); + link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return"); + link->ptr= itemptr; + BLI_addtail(&lb, link); + } } + + i++; } + RNA_PROP_END; - i++; - } - RNA_PROP_END; + while(i < scroll+items) { + if(i >= scroll) + uiItemL(col, "", 0); + i++; + } - while(i < scroll+items) { - if(i >= scroll) - uiItemL(col, "", 0); - i++; - } + uiBlockSetEmboss(block, UI_EMBOSS); - uiBlockSetEmboss(block, UI_EMBOSS); + if(len > items) { + col= uiLayoutColumn(row, 0); + uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &scroll, 1, len-items+1, items, 0, ""); + } - if(len > items) { - col= uiLayoutColumn(row, 0); - uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &scroll, 1, len-items+1, items, 0, ""); + //uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*15,UI_UNIT_Y*0.75, &scroll, 1, 16-5, 5, 0, ""); } - //uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*15,UI_UNIT_Y*0.75, &scroll, 1, 16-5, 5, 0, ""); + return lb; } diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index e67e5b5a871..3ed81a3e9bc 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -111,7 +111,12 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind but= uiDefButR(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); break; case PROP_STRING: - but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + if(icon && name && strcmp(name, "") == 0) + but= uiDefIconButR(block, TEX, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + else if(icon) + but= uiDefIconTextButR(block, TEX, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + else + but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); break; case PROP_POINTER: { PointerRNA pptr; diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 75de9d53766..a4aa60775f2 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -136,6 +136,14 @@ void RNA_api_ui_layout(StructRNA *srna) parm= RNA_def_string(func, "value", "", 0, "", "Enum property value."); RNA_def_property_flag(parm, PROP_REQUIRED);*/ + func= RNA_def_function(srna, "item_pointerR", "uiItemPointerR"); + api_ui_item_common(func); + api_ui_item_rna_common(func); + parm= RNA_def_pointer(func, "search_data", "AnyType", "", "Data from which to take collection to search in."); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_RNAPTR); + parm= RNA_def_string(func, "search_property", "", 0, "", "Identifier of search collection property."); + RNA_def_property_flag(parm, PROP_REQUIRED); + func= RNA_def_function(srna, "itemO", "uiItemO"); api_ui_item_op_common(func); @@ -211,7 +219,6 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); api_ui_item_rna_common(func); RNA_def_string(func, "new", "", 0, "", "Operator identifier to create a new ID block."); - RNA_def_string(func, "open", "", 0, "", "Operator identifier to open a new ID block."); RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block."); func= RNA_def_function(srna, "template_modifier", "uiTemplateModifier"); @@ -252,9 +259,13 @@ void RNA_api_ui_layout(StructRNA *srna) func= RNA_def_function(srna, "template_list", "uiTemplateList"); api_ui_item_rna_common(func); - parm= RNA_def_string(func, "active_property", "", 0, "", "Identifier of property in data, indicating the active element."); + parm= RNA_def_string(func, "active_property", "", 0, "", "Identifier of property in data, for the active element."); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_int(func, "items", 5, 0, INT_MAX, "", "Number of items to display.", 0, INT_MAX); + parm= RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display.", 0, INT_MAX); + parm= RNA_def_int(func, "columns", 5, 0, INT_MAX, "", "Number of columns to display.", 0, INT_MAX); + parm= RNA_def_boolean(func, "compact", 0, "", "Use compact, single row list template."); + parm= RNA_def_collection(func, "items", 0, "", "Items visible in the list."); + RNA_def_function_return(func, parm); } #endif -- cgit v1.2.3