2.5: Modifiers & Menus
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 21 Aug 2009 02:51:56 +0000 (02:51 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 21 Aug 2009 02:51:56 +0000 (02:51 +0000)
* Popup menus now remember the last clicked item again.
* Modifier and File Format menus are now organized in multiple
  columns with categories.
* Hook, explode, uv project modifiers have all their buttons
  again with the relevant operators implemented.
* Modifiers that can't be added by the user, or don't work on
  curves for example, are not in the menu anymore.
* Fix search menu overlapping buttons when near the bottom of
  the screen.
* Fix uv layers search menu not working in some modifiers.
* Cleanup popup menu code a bit, layout engine is used in more
  cases now instead of ugly position calculation code.

24 files changed:
release/ui/buttons_data_mesh.py
release/ui/buttons_data_modifier.py
release/ui/buttons_material.py
release/ui/space_image.py
source/blender/blenkernel/BKE_modifier.h
source/blender/blenkernel/intern/modifier.c
source/blender/editors/include/UI_interface.h
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_layout.c
source/blender/editors/interface/interface_regions.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_ops.c
source/blender/editors/screen/area.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesrna/intern/rna_define.c
source/blender/makesrna/intern/rna_modifier.c
source/blender/makesrna/intern/rna_scene.c
source/blender/windowmanager/intern/wm_operators.c

index b681218a8fe27d01cfb2082ef6f5aba0fd23f792..c7663be192301e6e4e6073b4ba3acdd0a572a883 100644 (file)
@@ -105,7 +105,7 @@ class DATA_PT_vertex_groups(DataButtonsPanel):
                        row = layout.row()
                        row.itemR(group, "name")
 
-               if context.edit_object:
+               if ob.mode == 'EDIT':
                        row = layout.row()
                        
                        sub = row.row(align=True)
@@ -180,7 +180,7 @@ class DATA_PT_shape_keys(DataButtonsPanel):
 
                                layout.itemR(kb, "name")
 
-               if context.edit_object:
+               if ob.mode == 'EDIT':
                        layout.enabled = False
 
 class DATA_PT_uv_texture(DataButtonsPanel):
index 436baa540d490fc306818e8e456d1bc318dcee7f..cc50256f216ddadff99603fc30998abc824df9be 100644 (file)
@@ -170,7 +170,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
                if md.texture_coordinates == 'OBJECT':
                        layout.itemR(md, "texture_coordinate_object", text="Object")
                elif md.texture_coordinates == 'UV' and ob.type == 'MESH':
-                       layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
+                       layout.item_pointerR(md, "uv_layer", ob.data, "uv_textures")
        
        def EDGE_SPLIT(self, layout, ob, md):
                split = layout.split()
@@ -187,21 +187,36 @@ class DATA_PT_modifiers(DataButtonsPanel):
        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")
-               layout.itemR(md, "alive")
-               layout.itemR(md, "dead")
-               # Missing: "Refresh" and "Clear Vertex Group" Operator
+
+               flow = layout.column_flow(2)
+               flow.itemR(md, "split_edges")
+               flow.itemR(md, "unborn")
+               flow.itemR(md, "alive")
+               flow.itemR(md, "dead")
+
+               layout.itemO("object.explode_refresh", text="Refresh");
                
        def FLUID_SIMULATION(self, layout, ob, md):
                layout.itemL(text="See Fluid panel.")
                
        def HOOK(self, layout, ob, md):
-               layout.itemR(md, "falloff")
-               layout.itemR(md, "force", slider=True)
                layout.itemR(md, "object")
                layout.item_pointerR(md, "vertex_group", ob, "vertex_groups")
-               # Missing: "Reset" and "Recenter" Operator
+
+               split = layout.split()
+               split.itemR(md, "falloff")
+               split.itemR(md, "force", slider=True)
+
+               layout.itemS()
+
+               row = layout.row()
+               row.itemO("object.hook_reset", text="Reset")
+               row.itemO("object.hook_recenter", text="Recenter")
+
+               if ob.mode == 'EDIT':
+                       row = layout.row()
+                       row.itemO("object.hook_select", text="Select")
+                       row.itemO("object.hook_assign", text="Assign")
                
        def LATTICE(self, layout, ob, md):
                layout.itemR(md, "object")
@@ -222,7 +237,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
 
                layout.itemS()
                
-               layout.itemO("object.modifier_mdef_bind", text="Bind")
+               layout.itemO("object.meshdeform_bind", text="Bind")
                row = layout.row()
                row.itemR(md, "precision")
                row.itemR(md, "dynamic")
@@ -346,16 +361,26 @@ class DATA_PT_modifiers(DataButtonsPanel):
        
        def UV_PROJECT(self, layout, ob, md):
                if ob.type == 'MESH':
-                       layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
-                       #layout.itemR(md, "projectors")
+                       layout.item_pointerR(md, "uv_layer", ob.data, "uv_textures")
                        layout.itemR(md, "image")
                        layout.itemR(md, "override_image")
-                       layout.itemL(text="Aspect Ratio:")
-                       col = layout.column(align=True)
-                       col.itemR(md, "horizontal_aspect_ratio", text="Horizontal")
-                       col.itemR(md, "vertical_aspect_ratio", text="Vertical")
-                       
-                       #"Projectors" don't work.
+
+                       split = layout.split()
+
+                       col = split.column()
+                       col.itemL(text="Aspect Ratio:")
+
+                       sub = col.column(align=True)
+                       sub.itemR(md, "horizontal_aspect_ratio", text="Horizontal")
+                       sub.itemR(md, "vertical_aspect_ratio", text="Vertical")
+
+                       col = split.column()
+                       col.itemL(text="Projectors:")
+
+                       sub = col.column(align=True)
+                       sub.itemR(md, "num_projectors", text="Number")
+                       for proj in md.projectors:
+                               sub.itemR(proj, "object", text="")
                
        def WAVE(self, layout, ob, md):
                split = layout.split()
@@ -387,7 +412,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
                layout.itemR(md, "texture")
                layout.itemR(md, "texture_coordinates")
                if md.texture_coordinates == 'MAP_UV' and ob.type == 'MESH':
-                       layout.item_pointerR(md, "uv_layer", ob.data, "uv_layers")
+                       layout.item_pointerR(md, "uv_layer", ob.data, "uv_textures")
                elif md.texture_coordinates == 'OBJECT':
                        layout.itemR(md, "texture_coordinates_object")
                
index b971a6789260b551bebb387701dc4cddd5a93504..ed3888ee4d89ed52ae7ab90b0eb32dfc7cbd9a30 100644 (file)
@@ -48,7 +48,7 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel):
                        col.itemO("object.material_slot_add", icon="ICON_ZOOMIN", text="")
                        col.itemO("object.material_slot_remove", icon="ICON_ZOOMOUT", text="")
 
-                       if context.edit_object:
+                       if ob.mode == 'EDIT':
                                row = layout.row(align=True)
                                row.itemO("object.material_slot_assign", text="Assign")
                                row.itemO("object.material_slot_select", text="Select")
index 090067120b1f979fc4fb46791d3a13c1f78b23a4..888b46e060e3deb8d799bdcb42c99857ed48bab2 100644 (file)
@@ -247,7 +247,7 @@ class IMAGE_HT_header(bpy.types.Header):
 
                        """
                        mesh = context.edit_object.data
-                       row.item_pointerR(mesh, "active_uv_layer", mesh, "uv_layers")
+                       row.item_pointerR(mesh, "active_uv_layer", mesh, "uv_textures")
                        """
 
                if ima:
index b65d77751e2b1a9b851dd2333d680dbf33340712..27c751260265d01d88121b031db22b63dbf33bda 100644 (file)
@@ -90,7 +90,10 @@ typedef enum {
        eModifierTypeFlag_UsesPointCache = (1<<6),
 
        /* For physics modifiers, max one per type */
-       eModifierTypeFlag_Single = (1<<7)
+       eModifierTypeFlag_Single = (1<<7),
+
+       /* Some modifier can't be added manually by user */
+       eModifierTypeFlag_NoUserAdd = (1<<8)
 } ModifierTypeFlag;
 
 typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin);
index 4d567245ce1ba0b0e8e12a2ebda9db0b1e9200db..37cf427b8972bdc0fe9679c69648989a3f634a61 100644 (file)
@@ -8616,7 +8616,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
                mti->freeData = smokeHRModifier_freeData; 
                mti->flags = eModifierTypeFlag_AcceptsMesh 
                                | eModifierTypeFlag_UsesPointCache
-                               | eModifierTypeFlag_Single;
+                               | eModifierTypeFlag_Single
+                               | eModifierTypeFlag_NoUserAdd;
                mti->deformVerts = smokeHRModifier_deformVerts;
                mti->dependsOnTime = smokeHRModifier_dependsOnTime;
                mti->updateDepgraph = smokeHRModifier_updateDepgraph;
@@ -8647,7 +8648,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
                mti = INIT_TYPE(Surface);
                mti->type = eModifierTypeType_OnlyDeform;
                mti->initData = surfaceModifier_initData;
-               mti->flags = eModifierTypeFlag_AcceptsMesh;
+               mti->flags = eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_NoUserAdd;
                mti->dependsOnTime = surfaceModifier_dependsOnTime;
                mti->freeData = surfaceModifier_freeData; 
                mti->deformVerts = surfaceModifier_deformVerts;
index 42280ad17c9f20adf04c25d47a51e5718b6834a2..5bf59b06bc4fdb875e7005d67f99e4ff2744dc7b 100644 (file)
@@ -100,6 +100,8 @@ typedef struct uiLayout uiLayout;
 #define UI_BLOCK_KEEP_OPEN             256
 #define UI_BLOCK_POPUP                 512
 #define UI_BLOCK_OUT_1                 1024
+#define UI_BLOCK_NO_FLIP               2048
+#define UI_BLOCK_POPUP_MEMORY  4096
 
 /* uiPopupBlockHandle->menuretval */
 #define UI_RETURN_CANCEL       1       /* cancel all menus cascading */
@@ -254,8 +256,6 @@ void uiPupMenuNotice(struct bContext *C, char *str, ...);
 void uiPupMenuError(struct bContext *C, char *str, ...);
 void uiPupMenuReports(struct bContext *C, struct ReportList *reports);
 
-void uiPupMenuSetActive(int val);
-
 /* Popup Blocks
  *
  * Functions used to create popup blocks. These are like popup menus
index 92a3a4cf8412bb5aed1a79f58c1f4fcc31cbdbad..9bd6c2577ff665d376d67b60a67bf4999f48ab49 100644 (file)
@@ -225,6 +225,7 @@ static void ui_text_bounds_block(uiBlock *block, float offset)
        uiStyle *style= U.uistyles.first;       // XXX pass on as arg
        uiBut *bt;
        int i = 0, j, x1addval= offset, nextcol;
+       int lastcol= 0, col= 0;
        
        uiStyleFontSet(&style->widget);
        
@@ -237,18 +238,26 @@ static void ui_text_bounds_block(uiBlock *block, float offset)
 
                        if(j > i) i = j;
                }
+
+               if(bt->next && bt->x1 < bt->next->x1)
+                       lastcol++;
        }
 
        /* cope with multi collumns */
        bt= block->buttons.first;
        while(bt) {
-               if(bt->next && bt->x1 < bt->next->x1)
+               if(bt->next && bt->x1 < bt->next->x1) {
                        nextcol= 1;
+                       col++;
+               }
                else nextcol= 0;
                
                bt->x1 = x1addval;
                bt->x2 = bt->x1 + i + block->bounds;
                
+               if(col == lastcol)
+                       bt->x2= MAX2(bt->x2, offset + block->minbounds);
+
                ui_check_but(bt);       // clips text again
                
                if(nextcol)
@@ -281,7 +290,7 @@ void ui_bounds_block(uiBlock *block)
        
                        if(bt->x2 > block->maxx) block->maxx= bt->x2;
                        if(bt->y2 > block->maxy) block->maxy= bt->y2;
-                       
+
                        bt= bt->next;
                }
                
@@ -291,6 +300,8 @@ void ui_bounds_block(uiBlock *block)
                block->maxy += block->bounds;
        }
 
+       block->maxx= block->minx + MAX2(block->maxx - block->minx, block->minbounds);
+
        /* hardcoded exception... but that one is annoying with larger safety */ 
        bt= block->buttons.first;
        if(bt && strncmp(bt->str, "ERROR", 5)==0) xof= 10;
@@ -2286,8 +2297,12 @@ uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, char *str, short x1,
                                dynstr= BLI_dynstr_new();
                                BLI_dynstr_appendf(dynstr, "%s%%t", RNA_property_ui_name(prop));
                                for(i=0; i<totitem; i++) {
-                                       if(!item[i].identifier[0])
-                                               BLI_dynstr_append(dynstr, "|%l");
+                                       if(!item[i].identifier[0]) {
+                                               if(item[i].name)
+                                                       BLI_dynstr_appendf(dynstr, "|%s%%l", item[i].name);
+                                               else
+                                                       BLI_dynstr_append(dynstr, "|%l");
+                                       }
                                        else if(item[i].icon)
                                                BLI_dynstr_appendf(dynstr, "|%s %%i%d %%x%d", item[i].name, item[i].icon, item[i].value);
                                        else
@@ -2839,6 +2854,8 @@ void uiBlockFlipOrder(uiBlock *block)
 
        if(U.uiflag & USER_MENUFIXEDORDER)
                return;
+       else if(block->flag & UI_BLOCK_NO_FLIP)
+               return;
        
        for(but= block->buttons.first; but; but= but->next) {
                if(but->flag & UI_BUT_ALIGN) return;
index e3518b446ba17b805df42fc8425285e7790693d4..b69e8319956a80e558b19a400efe96aa5f65d1cc 100644 (file)
@@ -1720,6 +1720,7 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
        uiBlockCreateFunc func= NULL;
        uiBlockHandleCreateFunc handlefunc= NULL;
        uiMenuCreateFunc menufunc= NULL;
+       char *menustr= NULL;
        void *arg= NULL;
 
        switch(but->type) {
@@ -1744,16 +1745,15 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
                                data->value= data->origvalue;
                                but->editval= &data->value;
 
-                               handlefunc= ui_block_func_MENU;
-                               arg= but;
+                               menustr= but->str;
                        }
                        break;
                case ICONROW:
-                       handlefunc= ui_block_func_ICONROW;
+                       menufunc= ui_block_func_ICONROW;
                        arg= but;
                        break;
                case ICONTEXTROW:
-                       handlefunc= ui_block_func_ICONTEXTROW;
+                       menufunc= ui_block_func_ICONTEXTROW;
                        arg= but;
                        break;
                case COL:
@@ -1771,8 +1771,8 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
                if(but->block->handle)
                        data->menu->popup= but->block->handle->popup;
        }
-       else if(menufunc) {
-               data->menu= ui_popup_menu_create(C, data->region, but, menufunc, arg);
+       else if(menufunc || menustr) {
+               data->menu= ui_popup_menu_create(C, data->region, but, menufunc, arg, menustr);
                if(but->block->handle)
                        data->menu->popup= but->block->handle->popup;
        }
@@ -3729,10 +3729,15 @@ static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *b
                }
        }
 
-       /* autokey & undo push */
-       if(!data->cancel)
+       if(!data->cancel) {
+               /* autokey & undo push */
                ui_apply_autokey_undo(C, but);
 
+               /* popup menu memory */
+               if(block->flag & UI_BLOCK_POPUP_MEMORY)
+                       ui_popup_menu_memory(block, but);
+       }
+
        /* disable tooltips until mousemove + last active flag */
        for(block=data->region->uiblocks.first; block; block=block->next) {
                for(bt=block->buttons.first; bt; bt=bt->next)
index 9ef5d65b69f45b17cfdac33f7b917b24f1760f64..806b40b864608a07c21d704e7bc9fe00601d78ad 100644 (file)
@@ -287,7 +287,8 @@ struct uiBlock {
        char *lockstr;
        
        float xofs, yofs;                               // offset to parent button
-       int bounds, dobounds, mx, my;   // for doing delayed
+       int dobounds, mx, my;                   // for doing delayed
+       int bounds, minbounds;                  // for doing delayed
        int endblock;                                   // uiEndBlock done?
 
        rctf safety;                            // pulldowns, to detect outside, can differ per case how it is created
@@ -297,6 +298,7 @@ struct uiBlock {
        int tooltipdisabled;            // to avoid tooltip after click
 
        int active;                                     // to keep blocks while drawing and free them afterwards
+       int puphash;                            // popup menu hash for memory
 
        void *evil_C;                           // XXX hack for dynamic operator enums
 };
@@ -372,14 +374,15 @@ struct uiPopupBlockHandle {
        float retvec[3];
 };
 
-uiBlock *ui_block_func_MENU(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
-uiBlock *ui_block_func_ICONROW(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
-uiBlock *ui_block_func_ICONTEXTROW(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
 uiBlock *ui_block_func_COL(struct bContext *C, uiPopupBlockHandle *handle, void *arg_but);
+void ui_block_func_ICONROW(struct bContext *C, uiLayout *layout, void *arg_but);
+void ui_block_func_ICONTEXTROW(struct bContext *C, uiLayout *layout, void *arg_but);
 
 struct ARegion *ui_tooltip_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
 void ui_tooltip_free(struct bContext *C, struct ARegion *ar);
 
+uiBut *ui_popup_menu_memory(uiBlock *block, uiBut *but);
+
 /* searchbox for string button */
 ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
 int ui_searchbox_inside(struct ARegion *ar, int x, int y);
@@ -394,7 +397,8 @@ typedef uiBlock* (*uiBlockHandleCreateFunc)(struct bContext *C, struct uiPopupBl
 uiPopupBlockHandle *ui_popup_block_create(struct bContext *C, struct ARegion *butregion, uiBut *but,
        uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, void *arg);
 uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C, struct ARegion *butregion, uiBut *but,
-       uiMenuCreateFunc create_func, void *arg);
+       uiMenuCreateFunc create_func, void *arg, char *str);
+
 void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle);
 
 void ui_set_name_menu(uiBut *but, int value);
index fc4f7da56d26e47c4b37401293313604db1c52e3..ab27f8fb0f60a2adba1954932f730a5e006dabfa 100644 (file)
@@ -619,6 +619,8 @@ void uiItemsEnumO(uiLayout *layout, char *opname, char *propname)
        wmOperatorType *ot= WM_operatortype_find(opname, 0);
        PointerRNA ptr;
        PropertyRNA *prop;
+       uiBut *bt;
+       uiBlock *block= layout->root->block;
 
        if(!ot || !ot->srna) {
                ui_item_disabled(layout, opname);
@@ -631,14 +633,31 @@ void uiItemsEnumO(uiLayout *layout, char *opname, char *propname)
        if(prop && RNA_property_type(prop) == PROP_ENUM) {
                EnumPropertyItem *item;
                int totitem, i, free;
+               uiLayout *split= uiLayoutSplit(layout, 0);
+               uiLayout *column= uiLayoutColumn(split, 0);
 
-               RNA_property_enum_items(layout->root->block->evil_C, &ptr, prop, &item, &totitem, &free);
+               RNA_property_enum_items(block->evil_C, &ptr, prop, &item, &totitem, &free);
 
-               for(i=0; i<totitem; i++)
-                       if(item[i].identifier[0])
-                               uiItemEnumO(layout, (char*)item[i].name, item[i].icon, opname, propname, item[i].value);
-                       else
-                               uiItemS(layout);
+               for(i=0; i<totitem; i++) {
+                       if(item[i].identifier[0]) {
+                               uiItemEnumO(column, (char*)item[i].name, item[i].icon, opname, propname, item[i].value);
+                       }
+                       else {
+                               if(item[i].name) {
+                                       if(i != 0) {
+                                               column= uiLayoutColumn(split, 0);
+                                               /* inconsistent, but menus with labels do not look good flipped */
+                                               block->flag |= UI_BLOCK_NO_FLIP;
+                                       }
+
+                                       uiItemL(column, (char*)item[i].name, 0);
+                                       bt= block->buttons.last;
+                                       bt->flag= UI_TEXT_LEFT;
+                               }
+                               else
+                                       uiItemS(column);
+                       }
+               }
 
                if(free)
                        MEM_freeN(item);
@@ -924,6 +943,8 @@ void uiItemEnumR_string(uiLayout *layout, char *name, int icon, struct PointerRN
 void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname)
 {
        PropertyRNA *prop;
+       uiBlock *block= layout->root->block;
+       uiBut *bt;
 
        prop= RNA_struct_find_property(ptr, propname);
 
@@ -935,14 +956,31 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, char *propname)
        if(RNA_property_type(prop) == PROP_ENUM) {
                EnumPropertyItem *item;
                int totitem, i, free;
+               uiLayout *split= uiLayoutSplit(layout, 0);
+               uiLayout *column= uiLayoutColumn(split, 0);
 
-               RNA_property_enum_items(layout->root->block->evil_C, ptr, prop, &item, &totitem, &free);
+               RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free);
 
-               for(i=0; i<totitem; i++)
-                       if(item[i].identifier[0])
-                               uiItemEnumR(layout, (char*)item[i].name, 0, ptr, propname, item[i].value);
-                       else
-                               uiItemS(layout);
+               for(i=0; i<totitem; i++) {
+                       if(item[i].identifier[0]) {
+                               uiItemEnumR(column, (char*)item[i].name, 0, ptr, propname, item[i].value);
+                       }
+                       else {
+                               if(item[i].name) {
+                                       if(i != 0) {
+                                               column= uiLayoutColumn(split, 0);
+                                               /* inconsistent, but menus with labels do not look good flipped */
+                                               block->flag |= UI_BLOCK_NO_FLIP;
+                                       }
+
+                                       uiItemL(column, (char*)item[i].name, 0);
+                                       bt= block->buttons.last;
+                                       bt->flag= UI_TEXT_LEFT;
+                               }
+                               else
+                                       uiItemS(column);
+                       }
+               }
 
                if(free)
                        MEM_freeN(item);
index bf9217155247d1836eb9e440f467561f756b01d3..e83dca5a5009517f160daa3da08b8a6e15c96ad7 100644 (file)
@@ -38,6 +38,7 @@
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
 #include "BLI_dynstr.h"
+#include "BLI_ghash.h"
 
 #include "BKE_context.h"
 #include "BKE_icons.h"
 
 /*********************** Menu Data Parsing ********************* */
 
-typedef struct {
+typedef struct MenuEntry {
        char *str;
        int retval;
        int icon;
+       int sepr;
 } MenuEntry;
 
-typedef struct {
+typedef struct MenuData {
        char *instr;
        char *title;
        int titleicon;
@@ -111,7 +113,7 @@ static void menudata_set_title(MenuData *md, char *title, int titleicon)
                md->titleicon= titleicon;
 }
 
-static void menudata_add_item(MenuData *md, char *str, int retval, int icon)
+static void menudata_add_item(MenuData *md, char *str, int retval, int icon, int sepr)
 {
        if (md->nitems==md->itemssize) {
                int nsize= md->itemssize?(md->itemssize<<1):1;
@@ -129,6 +131,7 @@ static void menudata_add_item(MenuData *md, char *str, int retval, int icon)
        md->items[md->nitems].str= str;
        md->items[md->nitems].retval= retval;
        md->items[md->nitems].icon= icon;
+       md->items[md->nitems].sepr= sepr;
        md->nitems++;
 }
 
@@ -142,12 +145,13 @@ void menudata_free(MenuData *md)
 
        /**
         * Parse menu description strings, string is of the
-        * form "[sss%t|]{(sss[%xNN]|), (%l|)}", ssss%t indicates the
+        * form "[sss%t|]{(sss[%xNN]|), (%l|), (sss%l|)}", ssss%t indicates the
         * menu title, sss or sss%xNN indicates an option, 
         * if %xNN is given then NN is the return value if
         * that option is selected otherwise the return value
         * is the index of the option (starting with 1). %l
-        * indicates a seperator.
+        * indicates a seperator, sss%l indicates a label and
+        * new column.
         * 
         * @param str String to be parsed.
         * @retval new menudata structure, free with menudata_free()
@@ -157,7 +161,7 @@ MenuData *decompose_menu_string(char *str)
        char *instr= BLI_strdup(str);
        MenuData *md= menudata_new(instr);
        char *nitem= NULL, *s= instr;
-       int nicon=0, nretval= 1, nitem_is_title= 0;
+       int nicon=0, nretval= 1, nitem_is_title= 0, nitem_is_sepr= 0;
        
        while (1) {
                char c= *s;
@@ -174,7 +178,10 @@ MenuData *decompose_menu_string(char *str)
                                *s= '\0';
                                s++;
                        } else if (s[1]=='l') {
-                               nitem= "%l";
+                               nitem_is_sepr= 1;
+                               if(!nitem) nitem= "";
+
+                               *s= '\0';
                                s++;
                        } else if (s[1]=='i') {
                                nicon= atoi(s+2);
@@ -186,15 +193,18 @@ MenuData *decompose_menu_string(char *str)
                        if (nitem) {
                                *s= '\0';
 
-                               if (nitem_is_title) {
+                               if(nitem_is_title) {
                                        menudata_set_title(md, nitem, nicon);
                                        nitem_is_title= 0;
-                               } else {
+                               }
+                               else if(nitem_is_sepr) {
                                        /* prevent separator to get a value */
-                                       if(nitem[0]=='%' && nitem[1]=='l')
-                                               menudata_add_item(md, nitem, -1, nicon);
-                                       else
-                                               menudata_add_item(md, nitem, nretval, nicon);
+                                       menudata_add_item(md, nitem, -1, nicon, 1);
+                                       nretval= md->nitems+1;
+                                       nitem_is_sepr= 0;
+                               }
+                               else {
+                                       menudata_add_item(md, nitem, nretval, nicon, 0);
                                        nretval= md->nitems+1;
                                } 
                                
@@ -827,6 +837,8 @@ static void ui_searchbox_region_free(ARegion *ar)
        ar->regiondata= NULL;
 }
 
+static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, uiBlock *block);
+
 ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
 {
        uiStyle *style= U.uistyles.first;       // XXX pass on as arg
@@ -847,7 +859,7 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
        
        /* create searchbox data */
        data= MEM_callocN(sizeof(uiSearchboxData), "uiSearchboxData");
-       
+
        /* set font, get bb */
        data->fstyle= style->widget; /* copy struct */
        data->fstyle.align= UI_STYLE_TEXT_CENTER;
@@ -929,10 +941,14 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
                        }
                }
                if(y1 < 0) {
-                       y1 += 36;
-                       y2 += 36;
+                       int newy1;
+                       UI_view2d_to_region_no_clip(&butregion->v2d, 0, but->y2 + ofsy, 0, &newy1);
+                       newy1 += butregion->winrct.ymin;
+
+                       y2= y2-y1 + newy1;
+                       y1= newy1;
                }
-               
+
                /* widget rect, in region coords */
                data->bbox.xmin= MENU_SHADOW_SIDE;
                data->bbox.xmax= x2-x1 + MENU_SHADOW_SIDE;
@@ -1310,24 +1326,21 @@ void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
 
 /***************************** Menu Button ***************************/
 
-uiBlock *ui_block_func_MENU(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
+static void ui_block_func_MENUSTR(bContext *C, uiLayout *layout, void *arg_str)
 {
-       uiBut *but= arg_but;
-       uiBlock *block;
+       uiBlock *block= uiLayoutGetBlock(layout);
+       uiPopupBlockHandle *handle= block->handle;
+       uiLayout *split, *column;
        uiBut *bt;
        MenuData *md;
-       ListBase lb;
-       float aspect;
-       int width, height, boxh, columns, rows, startx, starty, x1, y1, xmax, a;
-
-       /* create the block */
-       block= uiBeginBlock(C, handle->region, "menu", UI_EMBOSSP);
-       block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
+       MenuEntry *entry;
+       char *instr= arg_str;
+       int columns, rows, a, b;
 
        /* compute menu data */
-       md= decompose_menu_string(but->str);
+       md= decompose_menu_string(instr);
 
-       /* columns and row calculation */
+       /* columns and row estimation */
        columns= (md->nitems+20)/20;
        if(columns<1)
                columns= 1;
@@ -1339,180 +1352,114 @@ uiBlock *ui_block_func_MENU(bContext *C, uiPopupBlockHandle *handle, void *arg_b
                rows= 1;
        while(rows*columns<md->nitems)
                rows++;
-               
-       /* prevent scaling up of pupmenu */
-       aspect= but->block->aspect;
-       if(aspect < 1.0f)
-               aspect = 1.0f;
-
-       /* size and location */
-       if(md->title)
-               width= 1.5*aspect*strlen(md->title)+UI_GetStringWidth(md->title);
-       else
-               width= 0;
 
-       for(a=0; a<md->nitems; a++) {
-               xmax= aspect*UI_GetStringWidth(md->items[a].str);
-               if(md->items[a].icon)
-                       xmax += 20*aspect;
-               if(xmax>width)
-                       width= xmax;
-       }
-
-       width+= 10;
-       if(width < (but->x2 - but->x1))
-               width = (but->x2 - but->x1);
-       if(width<50)
-               width=50;
-       
-       boxh= MENU_BUTTON_HEIGHT;
-       
-       height= rows*boxh;
-       if(md->title)
-               height+= boxh;
-
-       /* here we go! */
-       startx= but->x1;
-       starty= but->y1;
-       
+       /* create title */
        if(md->title) {
-               uiBut *bt;
-
-               if (md->titleicon) {
-                       bt= uiDefIconTextBut(block, LABEL, 0, md->titleicon, md->title, startx, (short)(starty+rows*boxh), (short)width, (short)boxh, NULL, 0.0, 0.0, 0, 0, "");
-               } else {
-                       bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+rows*boxh), (short)width, (short)boxh, NULL, 0.0, 0.0, 0, 0, "");
+               if(md->titleicon) {
+                       uiItemL(layout, md->title, md->titleicon);
+               }
+               else {
+                       uiItemL(layout, md->title, 0);
+                       bt= block->buttons.last;
                        bt->flag= UI_TEXT_LEFT;
                }
        }
 
-       for(a=0; a<md->nitems; a++) {
+       /* inconsistent, but menus with labels do not look good flipped */
+       for(a=0, b=0; a<md->nitems; a++, b++) {
+               entry= &md->items[a];
+
+               if(entry->sepr && entry->str[0])
+                       block->flag |= UI_BLOCK_NO_FLIP;
+       }
+
+       /* create items */
+       split= uiLayoutSplit(layout, 0);
+
+       for(a=0, b=0; a<md->nitems; a++, b++) {
+               if(block->flag & UI_BLOCK_NO_FLIP)
+                       entry= &md->items[a];
+               else
+                       entry= &md->items[md->nitems-a-1];
                
-               x1= startx + width*((int)(md->nitems-a-1)/rows);
-               y1= starty - boxh*(rows - ((md->nitems - a - 1)%rows)) + (rows*boxh);
+               /* new column on N rows or on separation label */
+               if((b % rows == 0) || (entry->sepr && entry->str[0])) {
+                       column= uiLayoutColumn(split, 0);
+                       b= 0;
+               }
 
-               if (strcmp(md->items[md->nitems-a-1].str, "%l")==0) {
-                       bt= uiDefBut(block, SEPR, B_NOP, "", x1, y1,(short)(width-(rows>1)), (short)(boxh-1), NULL, 0.0, 0.0, 0, 0, "");
+               if(entry->sepr) {
+                       uiItemL(column, entry->str, entry->icon);
+                       bt= block->buttons.last;
+                       bt->flag= UI_TEXT_LEFT;
                }
-               else if(md->items[md->nitems-a-1].icon) {
-                       bt= uiDefIconTextButF(block, BUTM|FLO, B_NOP, md->items[md->nitems-a-1].icon ,md->items[md->nitems-a-1].str, x1, y1,(short)(width-(rows>1)), (short)(boxh-1), &handle->retvalue, (float) md->items[md->nitems-a-1].retval, 0.0, 0, 0, "");
+               else if(entry->icon) {
+                       uiDefIconTextButF(block, BUTM|FLO, B_NOP, entry->icon, entry->str, 0, 0,
+                               UI_UNIT_X*5, UI_UNIT_Y, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, "");
                }
                else {
-                       bt= uiDefButF(block, BUTM|FLO, B_NOP, md->items[md->nitems-a-1].str, x1, y1,(short)(width-(rows>1)), (short)(boxh-1), &handle->retvalue, (float) md->items[md->nitems-a-1].retval, 0.0, 0, 0, "");
+                       uiDefButF(block, BUTM|FLO, B_NOP, entry->str, 0, 0,
+                               UI_UNIT_X*5, UI_UNIT_X, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, "");
                }
        }
        
        menudata_free(md);
-
-       /* the code up here has flipped locations, because of change of preferred order */
-       /* thats why we have to switch list order too, to make arrowkeys work */
-       
-       lb.first= lb.last= NULL;
-       bt= block->buttons.first;
-       while(bt) {
-               uiBut *next= bt->next;
-               BLI_remlink(&block->buttons, bt);
-               BLI_addhead(&lb, bt);
-               bt= next;
-       }
-       block->buttons= lb;
-
-       block->direction= UI_TOP;
-       uiEndBlock(C, block);
-
-       return block;
 }
 
-uiBlock *ui_block_func_ICONROW(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
+void ui_block_func_ICONROW(bContext *C, uiLayout *layout, void *arg_but)
 {
+       uiBlock *block= uiLayoutGetBlock(layout);
+       uiPopupBlockHandle *handle= block->handle;
        uiBut *but= arg_but;
-       uiBlock *block;
        int a;
        
-       block= uiBeginBlock(C, handle->region, "menu", UI_EMBOSSP);
-       block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
-       
-       for(a=(int)but->hardmin; a<=(int)but->hardmax; a++) {
-               uiDefIconButF(block, BUTM|FLO, B_NOP, but->icon+(a-but->hardmin), 0, (short)(18*a), (short)(but->x2-but->x1-4), 18, &handle->retvalue, (float)a, 0.0, 0, 0, "");
-       }
-
-       block->direction= UI_TOP;       
-
-       uiEndBlock(C, block);
-
-       return block;
+       for(a=(int)but->hardmin; a<=(int)but->hardmax; a++)
+               uiDefIconButF(block, BUTM|FLO, B_NOP, but->icon+(a-but->hardmin), 0, 0, UI_UNIT_X*5, UI_UNIT_Y,
+                       &handle->retvalue, (float)a, 0.0, 0, 0, "");
 }
 
-uiBlock *ui_block_func_ICONTEXTROW(bContext *C, uiPopupBlockHandle *handle, void *arg_but)
+void ui_block_func_ICONTEXTROW(bContext *C, uiLayout *layout, void *arg_but)
 {
-       uiBut *but= arg_but;
-       uiBlock *block;
+       uiBlock *block= uiLayoutGetBlock(layout);
+       uiPopupBlockHandle *handle= block->handle;
+       uiBut *but= arg_but, *bt;
        MenuData *md;
-       int width, xmax, ypos, a;
-
-       block= uiBeginBlock(C, handle->region, "menu", UI_EMBOSSP);
-       block->flag= UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT;
+       MenuEntry *entry;
+       int a;
 
        md= decompose_menu_string(but->str);
 
-       /* size and location */
-       /* expand menu width to fit labels */
-       if(md->title)
-               width= 2*strlen(md->title)+UI_GetStringWidth(md->title);
-       else
-               width= 0;
-
-       for(a=0; a<md->nitems; a++) {
-               xmax= UI_GetStringWidth(md->items[a].str);
-               if(xmax>width) width= xmax;
+       /* title */
+       if(md->title) {
+               bt= uiDefBut(block, LABEL, 0, md->title, 0, 0, UI_UNIT_X*5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
+               bt->flag= UI_TEXT_LEFT;
        }
 
-       width+= 30;
-       if (width<50) width=50;
-
-       ypos = 1;
-
        /* loop through the menu options and draw them out with icons & text labels */
        for(a=0; a<md->nitems; a++) {
+               entry= &md->items[md->nitems-a-1];
 
-               /* add a space if there's a separator (%l) */
-               if (strcmp(md->items[a].str, "%l")==0) {
-                       ypos +=3;
-               }
-               else {
-                       uiDefIconTextButF(block, BUTM|FLO, B_NOP, (short)((but->icon)+(md->items[a].retval-but->hardmin)), md->items[a].str, 0, ypos,(short)width, 19, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, "");
-                       ypos += 20;
-               }
+               if(entry->sepr)
+                       uiItemS(layout);
+               else
+                       uiDefIconTextButF(block, BUTM|FLO, B_NOP, (short)((but->icon)+(entry->retval-but->hardmin)), entry->str,
+                               0, 0, UI_UNIT_X*5, UI_UNIT_Y, &handle->retvalue, (float) entry->retval, 0.0, 0, 0, "");
        }
-       
-       if(md->title) {
-               uiBut *bt;
 
-               bt= uiDefBut(block, LABEL, 0, md->title, 0, ypos, (short)width, 19, NULL, 0.0, 0.0, 0, 0, "");
-               bt->flag= UI_TEXT_LEFT;
-       }
-       
        menudata_free(md);
-
-       block->direction= UI_TOP;
-
-       uiBoundsBlock(block, 3);
-       uiEndBlock(C, block);
-
-       return block;
 }
 
+#if 0
 static void ui_warp_pointer(short x, short y)
 {
        /* XXX 2.50 which function to use for this? */
-#if 0
        /* OSX has very poor mousewarp support, it sends events;
           this causes a menu being pressed immediately ... */
        #ifndef __APPLE__
        warp_pointer(x, y);
        #endif
-#endif
 }
+#endif
 
 /********************* Color Button ****************/
 
@@ -2158,406 +2105,115 @@ void uiBlockColorbandButtons(uiBlock *block, ColorBand *coba, rctf *butr, int ev
 }
 
 
-/* ******************** PUPmenu ****************** */
-
-static int pupmenu_set= 0;
+/************************ Popup Menu Memory ****************************/
 
-void uiPupMenuSetActive(int val)
+static int ui_popup_menu_hash(char *str)
 {
-       pupmenu_set= val;
+       return BLI_ghashutil_strhash(str);
 }
 
-/* value== -1 read, otherwise set */
-static int pupmenu_memory(char *str, int value)
+/* but == NULL read, otherwise set */
+uiBut *ui_popup_menu_memory(uiBlock *block, uiBut *but)
 {
        static char mem[256], first=1;
-       int val=0, nr=0;
+       int hash= block->puphash;
        
        if(first) {
-               memset(mem, 0, 256);
+               /* init */
+               memset(mem, -1, sizeof(mem));
                first= 0;
        }
-       while(str[nr]) {
-               val+= str[nr];
-               nr++;
-       }
-
-       if(value >= 0) mem[ val & 255 ]= value;
-       else return mem[ val & 255 ];
-       
-       return 0;
-}
-
-#define PUP_LABELH     6
-
-typedef struct uiPupMenuInfo {
-       char *instr;
-       int mx, my;
-       int startx, starty;
-       int maxrow;
-} uiPupMenuInfo;
-
-uiBlock *ui_block_func_PUPMENU(bContext *C, uiPopupBlockHandle *handle, void *arg_info)
-{
-       uiBlock *block;
-       uiPupMenuInfo *info;
-       int columns, rows, mousemove[2]= {0, 0}, mousewarp= 0;
-       int width, height, xmax, ymax, maxrow;
-       int a, startx, starty, endx, endy, x1, y1;
-       int lastselected;
-       MenuData *md;
-
-       info= arg_info;
-       maxrow= info->maxrow;
-       height= 0;
-
-       /* block stuff first, need to know the font */
-       block= uiBeginBlock(C, handle->region, "menu", UI_EMBOSSP);
-       uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_NUMSELECT);
-       block->direction= UI_DOWN;
-       
-       md= decompose_menu_string(info->instr);
-
-       rows= md->nitems;
-       if(rows<1)
-               rows= 1;
-       
-       columns= 1;
-
-       /* size and location, title slightly bigger for bold */
-       if(md->title) {
-               width= 2*strlen(md->title)+UI_GetStringWidth(md->title);
-               width /= columns;
-       }
-       else width= 0;
-
-       for(a=0; a<md->nitems; a++) {
-               xmax= UI_GetStringWidth(md->items[a].str);
-               if(xmax>width) width= xmax;
-
-               if(strcmp(md->items[a].str, "%l")==0) height+= PUP_LABELH;
-               else height+= MENU_BUTTON_HEIGHT;
-       }
-
-       width+= 10;
-       if (width<50) width=50;
-       
-       wm_window_get_size(CTX_wm_window(C), &xmax, &ymax);
-
-       /* set first item */
-       lastselected= 0;
-       if(pupmenu_set) {
-               lastselected= pupmenu_set-1;
-               pupmenu_set= 0;
-       }
-       else if(md->nitems>1) {
-               lastselected= pupmenu_memory(info->instr, -1);
-       }
-
-       startx= info->mx-(0.8*(width));
-       starty= info->my-height+MENU_BUTTON_HEIGHT/2;
-       if(lastselected>=0 && lastselected<md->nitems) {
-               for(a=0; a<md->nitems; a++) {
-                       if(a==lastselected) break;
-                       if( strcmp(md->items[a].str, "%l")==0) starty+= PUP_LABELH;
-                       else starty+=MENU_BUTTON_HEIGHT;
-               }
-               
-               //starty= info->my-height+MENU_BUTTON_HEIGHT/2+lastselected*MENU_BUTTON_HEIGHT;
-       }
-       
-       if(startx<10) {
-               startx= 10;
-       }
-       if(starty<10) {
-               mousemove[1]= 10-starty;
-               starty= 10;
-       }
-       
-       endx= startx+width*columns;
-       endy= starty+height;
 
-       if(endx>xmax) {
-               endx= xmax-10;
-               startx= endx-width*columns;
-       }
-       if(endy>ymax-20) {
-               mousemove[1]= ymax-endy-20;
-               endy= ymax-20;
-               starty= endy-height;
-       }
-
-       if(mousemove[0] || mousemove[1]) {
-               ui_warp_pointer(info->mx+mousemove[0], info->my+mousemove[1]);
-               mousemove[0]= info->mx;
-               mousemove[1]= info->my;
-               mousewarp= 1;
+       if(but) {
+               /* set */
+               mem[hash & 255 ]= BLI_findindex(&block->buttons, but);
+               return NULL;
        }
-
-       /* here we go! */
-       if(md->title) {
-               uiBut *bt;
-               char titlestr[256];
-
-               if(md->titleicon) {
-                       width+= 20;
-                       sprintf(titlestr, " %s", md->title);
-                       uiDefIconTextBut(block, LABEL, 0, md->titleicon, titlestr, startx, (short)(starty+height), width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
-               }
-               else {
-                       bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+height), columns*width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
-                       bt->flag= UI_TEXT_LEFT;
-               }
-               
-               //uiDefBut(block, SEPR, 0, "", startx, (short)(starty+height)-MENU_SEPR_HEIGHT, width, MENU_SEPR_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
+       else {
+               /* get */
+               return BLI_findlink(&block->buttons, mem[hash & 255]);
        }
+}
 
-       x1= startx + width*((int)a/rows);
-       y1= starty + height - MENU_BUTTON_HEIGHT; // - MENU_SEPR_HEIGHT;
-               
-       for(a=0; a<md->nitems; a++) {
-               char *name= md->items[a].str;
-               int icon = md->items[a].icon;
+/******************** Popup Menu with callback or string **********************/
 
-               if(strcmp(name, "%l")==0) {
-                       uiDefBut(block, SEPR, B_NOP, "", x1, y1, width, PUP_LABELH, NULL, 0, 0.0, 0, 0, "");
-                       y1 -= PUP_LABELH;
-               }
-               else if (icon) {
-                       uiDefIconButF(block, BUTM, B_NOP, icon, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, "");
-                       y1 -= MENU_BUTTON_HEIGHT;
-               }
-               else {
-                       uiDefButF(block, BUTM, B_NOP, name, x1, y1, width, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, "");
-                       y1 -= MENU_BUTTON_HEIGHT;
-               }
-       }
-       
-       uiBoundsBlock(block, 1);
-       uiEndBlock(C, block);
-
-       menudata_free(md);
+struct uiPopupMenu {
+       uiBlock *block;
+       uiLayout *layout;
+       uiBut *but;
 
-       /* XXX 2.5 need to store last selected */
-#if 0
-       /* calculate last selected */
-       if(event & ui_return_ok) {
-               lastselected= 0;
-               for(a=0; a<md->nitems; a++) {
-                       if(val==md->items[a].retval) lastselected= a;
-               }
-               
-               pupmenu_memory(info->instr, lastselected);
-       }
-#endif
-       
-       /* XXX 2.5 need to warp back */
-#if 0
-       if(mousemove[1] && (event & ui_return_out)==0)
-               ui_warp_pointer(mousemove[0], mousemove[1]);
-       return val;
-#endif
+       int mx, my, popup, slideout;
+       int startx, starty, maxrow;
 
-       return block;
-}
+       uiMenuCreateFunc menu_func;
+       void *menu_arg;
+};
 
-uiBlock *ui_block_func_PUPMENUCOL(bContext *C, uiPopupBlockHandle *handle, void *arg_info)
+static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
 {
        uiBlock *block;
-       uiPupMenuInfo *info;
-       int columns, rows, mousemove[2]= {0, 0}, mousewarp;
-       int width, height, xmax, ymax, maxrow;
-       int a, startx, starty, endx, endy, x1, y1;
-       float fvalue;
-       MenuData *md;
-
-       info= arg_info;
-       maxrow= info->maxrow;
-       height= 0;
-
-       /* block stuff first, need to know the font */
-       block= uiBeginBlock(C, handle->region, "menu", UI_EMBOSSP);
-       uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_NUMSELECT);
-       block->direction= UI_DOWN;
-       
-       md= decompose_menu_string(info->instr);
-
-       /* columns and row calculation */
-       columns= (md->nitems+maxrow)/maxrow;
-       if (columns<1) columns= 1;
-       
-       if(columns > 8) {
-               maxrow += 5;
-               columns= (md->nitems+maxrow)/maxrow;
-       }
-       
-       rows= (int) md->nitems/columns;
-       if (rows<1) rows= 1;
-       
-       while (rows*columns<(md->nitems+columns) ) rows++;
-
-       /* size and location, title slightly bigger for bold */
-       if(md->title) {
-               width= 2*strlen(md->title)+UI_GetStringWidth(md->title);
-               width /= columns;
-       }
-       else width= 0;
-
-       for(a=0; a<md->nitems; a++) {
-               xmax= UI_GetStringWidth(md->items[a].str);
-               if(xmax>width) width= xmax;
-       }
-
-       width+= 10;
-       if (width<50) width=50;
-       
-       height= rows*MENU_BUTTON_HEIGHT;
-       if (md->title) height+= MENU_BUTTON_HEIGHT;
-       
-       wm_window_get_size(CTX_wm_window(C), &xmax, &ymax);
-
-       /* find active item */
-       fvalue= handle->retvalue;
-       for(a=0; a<md->nitems; a++) {
-               if( md->items[a].retval== (int)fvalue ) break;
-       }
-
-       /* no active item? */
-       if(a==md->nitems) {
-               if(md->title) a= -1;
-               else a= 0;
-       }
-
-       if(a>0)
-               startx = info->mx-width/2 - ((int)(a)/rows)*width;
-       else
-               startx= info->mx-width/2;
-       starty = info->my-height + MENU_BUTTON_HEIGHT/2 + ((a)%rows)*MENU_BUTTON_HEIGHT;
-
-       if (md->title) starty+= MENU_BUTTON_HEIGHT;
-       
-       if(startx<10) {
-               mousemove[0]= 10-startx;
-               startx= 10;
-       }
-       if(starty<10) {
-               mousemove[1]= 10-starty;
-               starty= 10;
-       }
-       
-       endx= startx+width*columns;
-       endy= starty+height;
-
-       if(endx>xmax) {
-               mousemove[0]= xmax-endx-10;
-               endx= xmax-10;
-               startx= endx-width*columns;
-       }
-       if(endy>ymax) {
-               mousemove[1]= ymax-endy-10;
-               endy= ymax-10;
-               starty= endy-height;
-       }
+       uiBut *bt;
+       ScrArea *sa;
+       ARegion *ar;
+       uiPopupMenu *pup= arg_pup;
+       int offset, direction, minwidth, flip;
 
-       if(mousemove[0] || mousemove[1]) {
-               ui_warp_pointer(info->mx+mousemove[0], info->my+mousemove[1]);
-               mousemove[0]= info->mx;
-               mousemove[1]= info->my;
-               mousewarp= 1;
+       if(pup->menu_func) {
+               pup->block->handle= handle;
+               pup->menu_func(C, pup->layout, pup->menu_arg);
+               pup->block->handle= NULL;
        }
 
-       /* here we go! */
-       if(md->title) {
-               uiBut *bt;
+       if(pup->but) {
+               /* minimum width to enforece */
+               minwidth= pup->but->x2 - pup->but->x1;
 
-               if(md->titleicon) {
+               if(pup->but->type == PULLDOWN || pup->but->menu_create_func) {
+                       direction= UI_DOWN;
+                       flip= 1;
                }
                else {
-                       bt= uiDefBut(block, LABEL, 0, md->title, startx, (short)(starty+rows*MENU_BUTTON_HEIGHT), columns*width, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
-                       bt->flag= UI_TEXT_LEFT;
+                       direction= UI_TOP;
+                       flip= 0;
                }
        }
-
-       for(a=0; a<md->nitems; a++) {
-               char *name= md->items[a].str;
-               int icon = md->items[a].icon;
-
-               x1= startx + width*((int)a/rows);
-               y1= starty - MENU_BUTTON_HEIGHT*(a%rows) + (rows-1)*MENU_BUTTON_HEIGHT; 
-               
-               if(strcmp(name, "%l")==0) {
-                       uiDefBut(block, SEPR, B_NOP, "", x1, y1, width, PUP_LABELH, NULL, 0, 0.0, 0, 0, "");
-                       y1 -= PUP_LABELH;
-               }
-               else if (icon) {
-                       uiDefIconButF(block, BUTM, B_NOP, icon, x1, y1, width+16, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, "");
-                       y1 -= MENU_BUTTON_HEIGHT;
-               }
-               else {
-                       uiDefButF(block, BUTM, B_NOP, name, x1, y1, width, MENU_BUTTON_HEIGHT-1, &handle->retvalue, (float) md->items[a].retval, 0.0, 0, 0, "");
-                       y1 -= MENU_BUTTON_HEIGHT;
-               }
+       else {
+               minwidth= 50;
+               direction= UI_DOWN;
+               flip= 1;
        }
-       
-       uiBoundsBlock(block, 1);
-       uiEndBlock(C, block);
-       
-       menudata_free(md);
-       
-       /* XXX 2.5 need to warp back */
-#if 0
-       if((event & UI_RETURN_OUT)==0)
-               ui_warp_pointer(mousemove[0], mousemove[1]);
-#endif
-
-       return block;
-}
 
-/************************** Menu Definitions ***************************/
-
-/* prototype */
-static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiPopupBlockHandle *handle, void *arg_info);
-
-struct uiPopupMenu {
-       uiBlock *block;
-       uiLayout *layout;
-};
-
-typedef struct uiMenuInfo {
-       uiPopupMenu *pup;
-       int mx, my, popup, slideout;
-       int startx, starty;
-} uiMenuInfo;
-
-/************************ Menu Definitions to uiBlocks ***********************/
-
-static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiPopupBlockHandle *handle, void *arg_info)
-{
-       uiBlock *block;
-       uiMenuInfo *info= arg_info;
-       uiPopupMenu *pup;
-       ScrArea *sa;
-       ARegion *ar;
-       
-       pup= info->pup;
        block= pup->block;
        
-       /* block stuff first, need to know the font */
-       uiBlockSetRegion(block, handle->region);
-       block->direction= UI_DOWN;
+       /* in some cases we create the block before the region,
+          so we set it delayed here if necessary */
+       if(BLI_findindex(&handle->region->uiblocks, block) == -1)
+               uiBlockSetRegion(block, handle->region);
+
+       block->direction= direction;
 
        uiBlockLayoutResolve(C, block, NULL, NULL);
 
-       if(info->popup) {
+       if(pup->popup) {
                uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_RET_1);
-               uiBlockSetDirection(block, UI_DOWN);
+               uiBlockSetDirection(block, direction);
+
+               /* offset the mouse position, possibly based on earlier selection */
+               offset= 1.5*MENU_BUTTON_HEIGHT;
 
-               /* here we set an offset for the mouse position */
-               uiMenuPopupBoundsBlock(block, 1, 0, 1.5*MENU_BUTTON_HEIGHT);
+               if(block->flag & UI_BLOCK_POPUP_MEMORY) {
+                       bt= ui_popup_menu_memory(block, NULL);
+
+                       if(bt)
+                               offset= -bt->y1 - 0.5f*MENU_BUTTON_HEIGHT;
+               }
+
+               block->minbounds= minwidth;
+               uiMenuPopupBoundsBlock(block, 1, 20, offset);
        }
        else {
                /* for a header menu we set the direction automatic */
-               if(!info->slideout) {
+               if(!pup->slideout && flip) {
                        sa= CTX_wm_area(C);
                        ar= CTX_wm_region(C);
 
@@ -2569,59 +2225,77 @@ static uiBlock *ui_block_func_MENU_ITEM(bContext *C, uiPopupBlockHandle *handle,
                        }
                }
 
-               uiTextBoundsBlock(block, 50);
+               block->minbounds= minwidth;
+               uiTextBoundsBlock(block, 40);
        }
 
        /* if menu slides out of other menu, override direction */
-       if(info->slideout)
+       if(pup->slideout)
                uiBlockSetDirection(block, UI_RIGHT);
 
        uiEndBlock(C, block);
-       
-       return block;
+
+       return pup->block;
 }
 
-uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg)
+uiPopupBlockHandle *ui_popup_menu_create(bContext *C, ARegion *butregion, uiBut *but, uiMenuCreateFunc menu_func, void *arg, char *str)
 {
+       wmWindow *window= CTX_wm_window(C);
        uiStyle *style= U.uistyles.first;
        uiPopupBlockHandle *handle;
        uiPopupMenu *pup;
-       uiMenuInfo info;
        
        pup= MEM_callocN(sizeof(uiPopupMenu), "menu dummy");
-       pup->block= uiBeginBlock(C, NULL, "ui_popup_menu_create", UI_EMBOSSP);
+       pup->block= uiBeginBlock(C, NULL, "ui_button_menu_create", UI_EMBOSSP);
        pup->layout= uiBlockLayout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, style);
+       pup->slideout= (but && (but->block->flag & UI_BLOCK_LOOP));
+       pup->but= but;
        uiLayoutSetOperatorContext(pup->layout, WM_OP_INVOKE_REGION_WIN);
 
-       /* create in advance so we can let buttons point to retval already */
-       pup->block->handle= MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
+       if(!but) {
+               /* no button to start from, means we are a popup */
+               pup->mx= window->eventstate->x;
+               pup->my= window->eventstate->y;
+               pup->popup= 1;
+       }
 
-       menu_func(C, pup->layout, arg);
-       
-       memset(&info, 0, sizeof(info));
-       info.pup= pup;
-       info.slideout= (but && (but->block->flag & UI_BLOCK_LOOP));
+       if(str) {
+               /* menu is created from a string */
+               pup->menu_func= ui_block_func_MENUSTR;
+               pup->menu_arg= str;
+       }
+       else {
+               /* menu is created from a callback */
+               pup->menu_func= menu_func;
+               pup->menu_arg= arg;
+       }
        
-       handle= ui_popup_block_create(C, butregion, but, NULL, ui_block_func_MENU_ITEM, &info);
+       handle= ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup);
+
+       if(!but) {
+               handle->popup= 1;
+
+               UI_add_popup_handlers(C, &window->handlers, handle);
+               WM_event_add_mousemove(C);
+       }
        
        MEM_freeN(pup);
 
        return handle;
 }
 
-/*************************** Menu Creating API **************************/
-
-
-/*************************** Popup Menu API **************************/
+/******************** Popup Menu API with begin and end ***********************/
 
 /* only return handler, and set optional title */
 uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon)
 {
        uiStyle *style= U.uistyles.first;
-       uiPopupMenu *pup= MEM_callocN(sizeof(uiPopupMenu), "menu start");
+       uiPopupMenu *pup= MEM_callocN(sizeof(uiPopupMenu), "popup menu");
        uiBut *but;
        
        pup->block= uiBeginBlock(C, NULL, "uiPupMenuBegin", UI_EMBOSSP);
+       pup->block->flag |= UI_BLOCK_POPUP_MEMORY;
+       pup->block->puphash= ui_popup_menu_hash((char*)title);
        pup->layout= uiBlockLayout(pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, style);
        uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN);
 
@@ -2640,8 +2314,6 @@ uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon)
                        but= uiDefBut(pup->block, LABEL, 0, (char*)title, 0, 0, 200, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
                        but->flag= UI_TEXT_LEFT;
                }
-               
-               //uiDefBut(block, SEPR, 0, "", startx, (short)(starty+height)-MENU_SEPR_HEIGHT, width, MENU_SEPR_HEIGHT, NULL, 0.0, 0.0, 0, 0, "");
        }
 
        return pup;
@@ -2651,16 +2323,13 @@ uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon)
 void uiPupMenuEnd(bContext *C, uiPopupMenu *pup)
 {
        wmWindow *window= CTX_wm_window(C);
-       uiMenuInfo info;
        uiPopupBlockHandle *menu;
        
-       memset(&info, 0, sizeof(info));
-       info.popup= 1;
-       info.mx= window->eventstate->x;
-       info.my= window->eventstate->y;
-       info.pup= pup;
+       pup->popup= 1;
+       pup->mx= window->eventstate->x;
+       pup->my= window->eventstate->y;
        
-       menu= ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_MENU_ITEM, &info);
+       menu= ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPUP, pup);
        menu->popup= 1;
        
        UI_add_popup_handlers(C, &window->handlers, menu);
@@ -2674,32 +2343,7 @@ uiLayout *uiPupMenuLayout(uiPopupMenu *pup)
        return pup->layout;
 }
 
-/* ************** standard pupmenus *************** */
-
-/* this one can called with operatortype name and operators */
-static uiPopupBlockHandle *ui_pup_menu(bContext *C, int maxrow, uiMenuHandleFunc func, void *arg, char *str, ...)
-{
-       wmWindow *window= CTX_wm_window(C);
-       uiPupMenuInfo info;
-       uiPopupBlockHandle *menu;
-
-       memset(&info, 0, sizeof(info));
-       info.mx= window->eventstate->x;
-       info.my= window->eventstate->y;
-       info.maxrow= maxrow;
-       info.instr= str;
-
-       menu= ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PUPMENU, &info);
-       menu->popup= 1;
-
-       UI_add_popup_handlers(C, &window->handlers, menu);
-       WM_event_add_mousemove(C);
-
-       menu->popup_func= func;
-       menu->popup_arg= arg;
-       
-       return menu;
-}
+/*************************** Standard Popup Menus ****************************/
 
 static void operator_name_cb(bContext *C, void *arg, int retval)
 {
@@ -2709,17 +2353,6 @@ static void operator_name_cb(bContext *C, void *arg, int retval)
                WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
 }
 
-static void vconfirm_opname(bContext *C, char *opname, char *title, char *itemfmt, va_list ap)
-{
-       char *s, buf[512];
-
-       s= buf;
-       if (title) s+= sprintf(s, "%s%%t|", title);
-       vsprintf(s, itemfmt, ap);
-
-       ui_pup_menu(C, 0, operator_name_cb, opname, buf);
-}
-
 static void operator_cb(bContext *C, void *arg, int retval)
 {
        wmOperator *op= arg;
@@ -2735,6 +2368,21 @@ static void confirm_cancel_operator(void *opv)
        WM_operator_free(opv);
 }
 
+static void vconfirm_opname(bContext *C, char *opname, char *title, char *itemfmt, va_list ap)
+{
+       uiPopupBlockHandle *handle;
+       char *s, buf[512];
+
+       s= buf;
+       if (title) s+= sprintf(s, "%s%%t|", title);
+       vsprintf(s, itemfmt, ap);
+
+       handle= ui_popup_menu_create(C, NULL, NULL, NULL, NULL, buf);
+
+       handle->popup_func= operator_name_cb;
+       handle->popup_arg= opname;
+}
+
 static void confirm_operator(bContext *C, wmOperator *op, char *title, char *item)
 {
        uiPopupBlockHandle *handle;
@@ -2743,11 +2391,13 @@ static void confirm_operator(bContext *C, wmOperator *op, char *title, char *ite
        s= buf;
        if (title) s+= sprintf(s, "%s%%t|%s", title, item);
        
-       handle= ui_pup_menu(C, 0, operator_cb, op, buf);
+       handle= ui_popup_menu_create(C, NULL, NULL, NULL, NULL, buf);
+
+       handle->popup_func= operator_cb;
+       handle->popup_arg= op;
        handle->cancel_func= confirm_cancel_operator;
 }
 
-
 void uiPupMenuOkee(bContext *C, char *opname, char *str, ...)
 {
        va_list ap;
@@ -2760,7 +2410,6 @@ void uiPupMenuOkee(bContext *C, char *opname, char *str, ...)
        va_end(ap);
 }
 
-
 void uiPupMenuSaveOver(bContext *C, wmOperator *op, char *filename)
 {
        size_t len= strlen(filename);
@@ -2776,7 +2425,7 @@ void uiPupMenuSaveOver(bContext *C, wmOperator *op, char *filename)
        if(BLI_exists(filename)==0)
                operator_cb(C, op, 1);
        else
-               confirm_operator(C, op, "Save over", filename);
+               confirm_operator(C, op, "Save Over", filename);
 }
 
 void uiPupMenuNotice(bContext *C, char *str, ...)
@@ -2826,7 +2475,7 @@ void uiPupMenuReports(bContext *C, ReportList *reports)
        }
 
        str= BLI_dynstr_get_cstring(ds);
-       ui_pup_menu(C, 0, NULL, NULL, str);
+       ui_popup_menu_create(C, NULL, NULL, NULL, NULL, str);
        MEM_freeN(str);
 
        BLI_dynstr_free(ds);
@@ -2870,3 +2519,4 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int
        UI_add_popup_handlers(C, &window->handlers, handle);
        WM_event_add_mousemove(C);
 }
+
index 0557512cc2a1c8e1e6dbd3df51a13ff909ce7ecb..e7c99f10a66c39f2adad55828010e230f1e8dcc1 100644 (file)
@@ -237,11 +237,11 @@ static void template_ID(bContext *C, uiBlock *block, TemplateID *template, Struc
                int w= idptr.data?UI_UNIT_X:UI_UNIT_X*6;
                
                if(newop) {
-                       but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_REGION_WIN, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL);
+                       but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_REGION_WIN, ICON_ZOOMIN, (idptr.data)? "": "Add New", 0, 0, w, UI_UNIT_Y, NULL);
                        uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
                }
                else {
-                       but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
+                       but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (idptr.data)? "": "Add New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
                        uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
                }
        }
index 39fd64335481f210f48b3776bf163717ba5f2a28..2fb9835f833b59365ec11e3c1a3adf34d6d4bdc0 100644 (file)
@@ -1150,7 +1150,7 @@ void ED_object_apply_obmat(Object *ob)
        
 }
 
-int hook_getIndexArray(Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
+int object_hook_index_array(Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
 {
        *indexar= NULL;
        *tot= 0;
@@ -1232,9 +1232,8 @@ static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
        }
 }
 
-void obedit_hook_select(Object *ob, HookModifierData *hmd) 
+void object_hook_select(Object *ob, HookModifierData *hmd) 
 {
-       
        if(ob->type==OB_MESH) select_editmesh_hook(ob, hmd);
        else if(ob->type==OB_LATTICE) select_editlattice_hook(ob, hmd);
        else if(ob->type==OB_CURVE) select_editcurve_hook(ob, hmd);
@@ -1318,7 +1317,7 @@ void add_hook(Scene *scene, View3D *v3d, int mode)
                int tot, ok, *indexar;
                char name[32];
                
-               ok = hook_getIndexArray(obedit, &tot, &indexar, name, cent);
+               ok = object_hook_index_array(obedit, &tot, &indexar, name, cent);
                
                if(ok==0) {
                        error("Requires selected vertices or active Vertex Group");
@@ -1381,7 +1380,7 @@ void add_hook(Scene *scene, View3D *v3d, int mode)
                modifier_free(md);
        }
        else if(mode==5) { /* select */
-               obedit_hook_select(obedit, hmd);
+               object_hook_select(obedit, hmd);
        }
        else if(mode==6) { /* clear offset */
                where_is_object(scene, ob);     /* ob is hook->parent */
index e47087a3c27df8754526a1ecde15042815ec65b6..2f164102be2f5a32c88939f6458ae185811d1f53 100644 (file)
@@ -34,6 +34,7 @@ struct Lattice;
 struct Curve;
 struct Object;
 struct Mesh;
+struct HookModifierData;
 
 /* internal exports only */
 
@@ -80,6 +81,9 @@ void OBJECT_OT_armature_add(struct wmOperatorType *ot);
        /* only used as menu */
 void OBJECT_OT_primitive_add(struct wmOperatorType *ot);
 
+int object_hook_index_array(Object *obedit, int *tot, int **indexar, char *name, float *cent_r);
+void object_hook_select(Object *obedit, struct HookModifierData *hmd);
+
 /* editlattice.c */
 void free_editLatt(Object *ob);
 void make_editLatt(Object *obedit);
@@ -104,7 +108,12 @@ void OBJECT_OT_modifier_apply(struct wmOperatorType *ot);
 void OBJECT_OT_modifier_convert(struct wmOperatorType *ot);
 void OBJECT_OT_modifier_copy(struct wmOperatorType *ot);
 void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot);
-void OBJECT_OT_modifier_mdef_bind(struct wmOperatorType *ot);
+void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot);
+void OBJECT_OT_hook_reset(struct wmOperatorType *ot);
+void OBJECT_OT_hook_recenter(struct wmOperatorType *ot);
+void OBJECT_OT_hook_select(struct wmOperatorType *ot);
+void OBJECT_OT_hook_assign(struct wmOperatorType *ot);
+void OBJECT_OT_explode_refresh(struct wmOperatorType *ot);
 
 /* editconstraint.c */
 void OBJECT_OT_constraint_add(struct wmOperatorType *ot);
index 16900d6d8941f3f700ae9a2bed9555e0e9ee12ee..32a1297aaf44b62f656ae29890087fce1943e360 100644 (file)
@@ -39,6 +39,7 @@
 #include "DNA_object_force.h"
 #include "DNA_scene_types.h"
 
+#include "BLI_arithb.h"
 #include "BLI_listbase.h"
 
 #include "BKE_curve.h"
@@ -410,6 +411,11 @@ int ED_object_modifier_copy(ReportList *reports, Object *ob, ModifierData *md)
 
 /***************************** OPERATORS ****************************/
 
+static int modifier_poll(bContext *C)
+{
+       return (CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier).data != NULL);
+}
+
 /************************ add modifier operator *********************/
 
 static int modifier_add_exec(bContext *C, wmOperator *op)
@@ -426,8 +432,46 @@ static int modifier_add_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
+static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *ptr, int *free)
+{      
+       EnumPropertyItem *item= NULL, *md_item;
+       ModifierTypeInfo *mti;
+       Object *ob;
+       int totitem= 0, a;
+       
+       if(!C) /* needed for docs */
+               return modifier_type_items;
+       
+       ob= CTX_data_active_object(C);
+
+       for(a=0; modifier_type_items[a].identifier; a++) {
+               md_item= &modifier_type_items[a];
+
+               if(md_item->identifier[0]) {
+                       mti= modifierType_getInfo(md_item->value);
+
+                       if(mti->flags & eModifierTypeFlag_NoUserAdd)
+                               continue;
+
+                       if(!((mti->flags & eModifierTypeFlag_AcceptsCVs) ||
+                          (ob->type==OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh))))
+                               continue;
+               }
+
+               RNA_enum_item_add(&item, &totitem, md_item);
+       }
+
+       RNA_enum_item_end(&item, &totitem);
+
+       *free= 1;
+
+       return item;
+}
+
 void OBJECT_OT_modifier_add(wmOperatorType *ot)
 {
+       PropertyRNA *prop;
+
        /* identifiers */
        ot->name= "Add Modifier";
        ot->description = "Add a modifier to the active object.";
@@ -436,14 +480,14 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot)
        /* api callbacks */
        ot->invoke= WM_menu_invoke;
        ot->exec= modifier_add_exec;
-       
        ot->poll= ED_operator_object_active;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
        
-       /* XXX only some types should be here */
-       RNA_def_enum(ot->srna, "type", modifier_type_items, 0, "Type", "");
+       /* properties */
+       prop= RNA_def_enum(ot->srna, "type", modifier_type_items, eModifierType_Subsurf, "Type", "");
+       RNA_def_enum_funcs(prop, modifier_add_itemf);
 }
 
 /************************ remove modifier operator *********************/
@@ -455,7 +499,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op)
        Object *ob= ptr.id.data;
        ModifierData *md= ptr.data;
 
-       if(!ob || !md || !ED_object_modifier_remove(op->reports, scene, ob, md))
+       if(!ED_object_modifier_remove(op->reports, scene, ob, md))
                return OPERATOR_CANCELLED;
 
        WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
@@ -471,6 +515,7 @@ void OBJECT_OT_modifier_remove(wmOperatorType *ot)
        ot->poll= ED_operator_object_active;
 
        ot->exec= modifier_remove_exec;
+       ot->poll= modifier_poll;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -485,7 +530,7 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op)
        Object *ob= ptr.id.data;
        ModifierData *md= ptr.data;
 
-       if(!ob || !md || !ED_object_modifier_move_up(op->reports, ob, md))
+       if(!ED_object_modifier_move_up(op->reports, ob, md))
                return OPERATOR_CANCELLED;
 
        DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
@@ -502,6 +547,7 @@ void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
        ot->poll= ED_operator_object_active;
 
        ot->exec= modifier_move_up_exec;
+       ot->poll= modifier_poll;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -533,6 +579,7 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
        ot->poll= ED_operator_object_active;
 
        ot->exec= modifier_move_down_exec;
+       ot->poll= modifier_poll;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -564,6 +611,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
        ot->poll= ED_operator_object_active;
 
        ot->exec= modifier_apply_exec;
+       ot->poll= modifier_poll;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -595,6 +643,7 @@ void OBJECT_OT_modifier_convert(wmOperatorType *ot)
        ot->poll= ED_operator_object_active;
 
        ot->exec= modifier_convert_exec;
+       ot->poll= modifier_poll;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -626,6 +675,7 @@ void OBJECT_OT_modifier_copy(wmOperatorType *ot)
        ot->poll= ED_operator_object_active;
 
        ot->exec= modifier_copy_exec;
+       ot->poll= modifier_poll;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -639,17 +689,15 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
        Object *ob= ptr.id.data;
        MultiresModifierData *mmd= ptr.data;
 
-       if(mmd) {
-               multiresModifier_subdivide(mmd, ob, 1, 0, mmd->simple);
-               WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
-       }
+       multiresModifier_subdivide(mmd, ob, 1, 0, mmd->simple);
+       WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
        
        return OPERATOR_FINISHED;
 }
 
 static int multires_subdivide_poll(bContext *C)
 {
-       return NULL != CTX_data_active_object(C) && NULL == CTX_data_edit_object(C);
+       return (CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier).data != NULL);
 }
 
 void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
@@ -667,12 +715,12 @@ void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
 
 /************************ mdef bind operator *********************/
 
-static int modifier_mdef_bind_poll(bContext *C)
+static int meshdeform_poll(bContext *C)
 {
        return CTX_data_pointer_get_type(C, "modifier", &RNA_MeshDeformModifier).data != NULL;
 }
 
-static int modifier_mdef_bind_exec(bContext *C, wmOperator *op)
+static int meshdeform_bind_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
        PointerRNA ptr= CTX_data_pointer_get(C, "modifier");
@@ -723,41 +771,22 @@ static int modifier_mdef_bind_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void OBJECT_OT_modifier_mdef_bind(wmOperatorType *ot)
+void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Mesh Deform Bind";
        ot->description = "Bind mesh to cage in mesh deform modifier.";
-       ot->idname= "OBJECT_OT_modifier_mdef_bind";
+       ot->idname= "OBJECT_OT_meshdeform_bind";
        
        /* api callbacks */
-       ot->poll= modifier_mdef_bind_poll;
-       ot->exec= modifier_mdef_bind_exec;
+       ot->poll= meshdeform_poll;
+       ot->exec= meshdeform_bind_exec;
        
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 #if 0
-static void modifiers_add(void *ob_v, int type)
-{
-       Object *ob = ob_v;
-       ModifierTypeInfo *mti = modifierType_getInfo(type);
-       
-       if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
-               ModifierData *md = ob->modifiers.first;
-
-               while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
-                       md = md->next;
-               }
-
-               BLI_insertlinkbefore(&ob->modifiers, md, modifier_new(type));
-       } else {
-               BLI_addtail(&ob->modifiers, modifier_new(type));
-       }
-       ED_undo_push("Add modifier");
-}
-
 typedef struct MenuEntry {
        char *name;
        int ID;
@@ -809,89 +838,176 @@ static uiBlock *modifiers_add_menu(void *ob_v)
 }
 #endif
 
-#if 0
-static void modifiers_clearHookOffset(bContext *C, void *ob_v, void *md_v)
+/******************** hook operators ************************/
+
+static int hook_poll(bContext *C)
 {
-       Object *ob = ob_v;
-       ModifierData *md = md_v;
-       HookModifierData *hmd = (HookModifierData*) md;
-       
-       if (hmd->object) {
+       return CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier).data != NULL;
+}
+
+static int hook_reset_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+       Object *ob= ptr.id.data;
+       HookModifierData *hmd= ptr.data;
+
+       if(hmd->object) {
                Mat4Invert(hmd->object->imat, hmd->object->obmat);
                Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
-               ED_undo_push(C, "Clear hook offset");
        }
+
+       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+       
+       return OPERATOR_FINISHED;
 }
 
-static void modifiers_cursorHookCenter(bContext *C, void *ob_v, void *md_v)
+void OBJECT_OT_hook_reset(wmOperatorType *ot)
 {
-       /* XXX 
-       Object *ob = ob_v;
-       ModifierData *md = md_v;
-       HookModifierData *hmd = (HookModifierData*) md;
+       ot->name= "Hook Reset";
+       ot->description= "Recalculate and and clear offset transformation.";
+       ot->idname= "OBJECT_OT_hook_reset";
+
+       ot->exec= hook_reset_exec;
+       ot->poll= hook_poll;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int hook_recenter_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+       Object *ob= ptr.id.data;
+       HookModifierData *hmd= ptr.data;
+       float bmat[3][3], imat[3][3];
+
+       Mat3CpyMat4(bmat, ob->obmat);
+       Mat3Inv(imat, bmat);
+
+       VECSUB(hmd->cent, scene->cursor, ob->obmat[3]);
+       Mat3MulVecfl(imat, hmd->cent);
+
+       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+       
+       return OPERATOR_FINISHED;
+}
 
-       if(G.vd) {
-               float *curs = give_cursor();
-               float bmat[3][3], imat[3][3];
+void OBJECT_OT_hook_recenter(wmOperatorType *ot)
+{
+       ot->name= "Hook Recenter";
+       ot->description= "Set hook center to cursor position.";
+       ot->idname= "OBJECT_OT_hook_recenter";
 
-               where_is_object(ob);
+       ot->exec= hook_recenter_exec;
+       ot->poll= hook_poll;
        
-               Mat3CpyMat4(bmat, ob->obmat);
-               Mat3Inv(imat, bmat);
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int hook_select_exec(bContext *C, wmOperator *op)
+{
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+       Object *ob= ptr.id.data;
+       HookModifierData *hmd= ptr.data;
 
-               curs= give_cursor();
-               hmd->cent[0]= curs[0]-ob->obmat[3][0];
-               hmd->cent[1]= curs[1]-ob->obmat[3][1];
-               hmd->cent[2]= curs[2]-ob->obmat[3][2];
-               Mat3MulVecfl(imat, hmd->cent);
+       object_hook_select(ob, hmd);
 
-               ED_undo_push(C, "Hook cursor center");
-       }*/
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
+       
+       return OPERATOR_FINISHED;
 }
 
-static void modifiers_selectHook(bContext *C, void *ob_v, void *md_v)
+void OBJECT_OT_hook_select(wmOperatorType *ot)
 {
-       /* XXX ModifierData *md = md_v;
-       HookModifierData *hmd = (HookModifierData*) md;
+       ot->name= "Hook Select";
+       ot->description= "Selects effected vertices on mesh.";
+       ot->idname= "OBJECT_OT_hook_select";
 
-       hook_select(hmd);*/
+       ot->exec= hook_select_exec;
+       ot->poll= hook_poll;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-static void modifiers_reassignHook(bContext *C, void *ob_v, void *md_v)
+static int hook_assign_exec(bContext *C, wmOperator *op)
 {
-       /* XXX ModifierData *md = md_v;
-       HookModifierData *hmd = (HookModifierData*) md;
+       Scene *scene= CTX_data_scene(C);
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
+       Object *ob= ptr.id.data;
+       HookModifierData *hmd= ptr.data;
        float cent[3];
-       int *indexar, tot, ok;
        char name[32];
+       int *indexar, tot;
                
-       ok= hook_getIndexArray(&tot, &indexar, name, cent);
+       if(!object_hook_index_array(ob, &tot, &indexar, name, cent)) {
+               BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
+               return OPERATOR_CANCELLED;
+       }
 
-       if (!ok) {
-               uiPupMenuError(C, "Requires selected vertices or active Vertex Group");
-       } else {
-               if (hmd->indexar) {
-                       MEM_freeN(hmd->indexar);
-               }
+       if(hmd->indexar)
+               MEM_freeN(hmd->indexar);
+
+       VECCOPY(hmd->cent, cent);
+       hmd->indexar= indexar;
+       hmd->totindex= tot;
 
-               VECCOPY(hmd->cent, cent);
-               hmd->indexar = indexar;
-               hmd->totindex = tot;
-       }*/
+       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+       
+       return OPERATOR_FINISHED;
 }
 
-void modifiers_explodeFacepa(bContext *C, void *arg1, void *arg2)
+void OBJECT_OT_hook_assign(wmOperatorType *ot)
 {
-       ExplodeModifierData *emd=arg1;
+       ot->name= "Hook Assign";
+       ot->description= "Reassigns selected vertices to hook.";
+       ot->idname= "OBJECT_OT_hook_assign";
 
-       emd->flag |= eExplodeFlag_CalcFaces;
+       ot->exec= hook_assign_exec;
+       ot->poll= hook_poll;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-void modifiers_explodeDelVg(bContext *C, void *arg1, void *arg2)
+/****************** explode refresh operator *********************/
+
+static int explode_refresh_poll(bContext *C)
 {
-       ExplodeModifierData *emd=arg1;
-       emd->vgroup = 0;
+       return CTX_data_pointer_get_type(C, "modifier", &RNA_ExplodeModifier).data != NULL;
 }
-#endif
 
+static int explode_refresh_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_ExplodeModifier);
+       Object *ob= ptr.id.data;
+       ExplodeModifierData *emd= ptr.data;
+
+       emd->flag |= eExplodeFlag_CalcFaces;
+
+       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+       
+       return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_explode_refresh(wmOperatorType *ot)
+{
+       ot->name= "Explode Refresh";
+       ot->description= "Refresh data in the Explode modifier.";
+       ot->idname= "OBJECT_OT_explode_refresh";
+
+       ot->exec= explode_refresh_exec;
+       ot->poll= explode_refresh_poll;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
 
index f2e048284f4ceffb664319b4f48dacb773b9bf85..6f1a3b5f6cbfc603ea5ee05431fcda7016be6366 100644 (file)
@@ -118,7 +118,12 @@ void ED_operatortypes_object(void)
        WM_operatortype_append(OBJECT_OT_modifier_convert);
        WM_operatortype_append(OBJECT_OT_modifier_copy);
        WM_operatortype_append(OBJECT_OT_multires_subdivide);
-       WM_operatortype_append(OBJECT_OT_modifier_mdef_bind);
+       WM_operatortype_append(OBJECT_OT_meshdeform_bind);
+       WM_operatortype_append(OBJECT_OT_hook_reset);
+       WM_operatortype_append(OBJECT_OT_hook_recenter);
+       WM_operatortype_append(OBJECT_OT_hook_select);
+       WM_operatortype_append(OBJECT_OT_hook_assign);
+       WM_operatortype_append(OBJECT_OT_explode_refresh);
 
        WM_operatortype_append(OBJECT_OT_constraint_add);
        WM_operatortype_append(OBJECT_OT_constraint_add_with_targets);
index 320574fe8b3699a540bad15b9a3f6c5165dee286..f714a291bd7357a32724b1971e15dec655afd229 100644 (file)
@@ -1044,7 +1044,6 @@ static char *windowtype_pup(void)
                   "Window type:%t"
                   "|3D View %x1"
 
-                  "|%l"
                   "|%l"
                   
                   "|Timeline %x15"
@@ -1052,7 +1051,6 @@ static char *windowtype_pup(void)
                   "|DopeSheet %x12"
                   "|NLA Editor %x13"
                   
-                  "|%l"
                   "|%l"
                   
                   "|UV/Image Editor %x6"
@@ -1062,7 +1060,6 @@ static char *windowtype_pup(void)
                   "|Node Editor %x16"
                   "|Logic Editor %x17"
                   
-                  "|%l"
                   "|%l"
                   
                   "|Properties %x4"
@@ -1070,12 +1067,10 @@ static char *windowtype_pup(void)
                   "|User Preferences %x19"
                   "|Info%x7"
                                   
-                  "|%l"
                   "|%l"
                   
                   "|File Browser %x5"
                   
-                  "|%l"
                   "|%l"
                   
                   "|Console %x18"
index 6c86c87302c51dd25d2bec64562ad1a6f697080c..3487efc4218a69631c2f94692426d599aa7a524b 100644 (file)
@@ -3442,10 +3442,5 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
 
                }
        }
-       
-       /* do not do view2d totrect set here, it's now a template */
-       
-       uiEndBlock(C, block);
-       uiDrawBlock(C, block);
 }
 
index 3349957401227b07c6f2094199bad233d0d2bdea..912d11dcc8c88225f34b709bb4db237c9954e536 100644 (file)
@@ -318,7 +318,7 @@ typedef struct UVProjectModifierData {
        ModifierData modifier;
 
        /* the objects which do the projecting */
-       struct Object *projectors[10];
+       struct Object *projectors[10]; /* MOD_UVPROJECT_MAX */
        struct Image *image;      /* the image to project */
        int flags;
        int num_projectors;
@@ -669,4 +669,6 @@ typedef struct SimpleDeformModifierData {
    coordinates or global coordinates of origin */
 #define MOD_SIMPLEDEFORM_ORIGIN_LOCAL                  (1<<0)
 
+#define MOD_UVPROJECT_MAX                              10
+
 #endif
index 9bdbc8baed70008a1a58b845d0b5024a2b8cb32a..3b0db9493501ff595026838459312e057ad03baf 100644 (file)
@@ -1173,8 +1173,14 @@ void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item
                                        defaultfound= 1;
                        }
 
-                       if(!defaultfound)
-                               eprop->defaultvalue= item[0].value;
+                       if(!defaultfound) {
+                               for(i=0; item[i].identifier; i++) {
+                                       if(item[i].identifier[0]) {
+                                               eprop->defaultvalue= item[i].value;
+                                               break;
+                                       }
+                               }
+                       }
 
                        break;
                }
index f2c8e404a52223e52232ebaa5b6176d939b05861..c080b88feafc6913491287c1bd04eef1231c3149 100644 (file)
 #include "WM_types.h"
 
 EnumPropertyItem modifier_type_items[] ={
-       {eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""},
+       {0, "", 0, "Generate", ""},
        {eModifierType_Array, "ARRAY", ICON_MOD_ARRAY, "Array", ""},
        {eModifierType_Bevel, "BEVEL", ICON_MOD_BEVEL, "Bevel", ""},
        {eModifierType_Boolean, "BOOLEAN", ICON_MOD_BOOLEAN, "Boolean", ""},
        {eModifierType_Build, "BUILD", ICON_MOD_BUILD, "Build", ""},
+       {eModifierType_Decimate, "DECIMATE", ICON_MOD_DECIM, "Decimate", ""},
+       {eModifierType_EdgeSplit, "EDGE_SPLIT", ICON_MOD_EDGESPLIT, "Edge Split", ""},
+       {eModifierType_Mask, "MASK", ICON_MOD_MASK, "Mask", ""},
+       {eModifierType_Mirror, "MIRROR", ICON_MOD_MIRROR, "Mirror", ""},
+       {eModifierType_Multires, "MULTIRES", ICON_MOD_MULTIRES, "Multiresolution", ""},
+       {eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""},
+       {eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
+       {0, "", 0, "Deformers", ""},
+       {eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""},
        {eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""},
-       {eModifierType_Cloth, "CLOTH", ICON_MOD_CLOTH, "Cloth", ""},
-       {eModifierType_Collision, "COLLISION", ICON_MOD_PHYSICS, "Collision", ""},
        {eModifierType_Curve, "CURVE", ICON_MOD_CURVE, "Curve", ""},
-       {eModifierType_Decimate, "DECIMATE", ICON_MOD_DECIM, "Decimate", ""},
        {eModifierType_Displace, "DISPLACE", ICON_MOD_DISPLACE, "Displace", ""},
-       {eModifierType_EdgeSplit, "EDGE_SPLIT", ICON_MOD_EDGESPLIT, "Edge Split", ""},
-       {eModifierType_Explode, "EXPLODE", ICON_MOD_EXPLODE, "Explode", ""},
-       {eModifierType_Fluidsim, "FLUID_SIMULATION", ICON_MOD_FLUIDSIM, "Fluid Simulation", ""},
        {eModifierType_Hook, "HOOK", ICON_HOOK, "Hook", ""},
        {eModifierType_Lattice, "LATTICE", ICON_MOD_LATTICE, "Lattice", ""},
-       {eModifierType_Mask, "MASK", ICON_MOD_MASK, "Mask", ""},
        {eModifierType_MeshDeform, "MESH_DEFORM", ICON_MOD_MESHDEFORM, "Mesh Deform", ""},
-       {eModifierType_Mirror, "MIRROR", ICON_MOD_MIRROR, "Mirror", ""},
-       {eModifierType_Multires, "MULTIRES", ICON_MOD_MULTIRES, "Multiresolution", ""},
-       {eModifierType_ParticleInstance, "PARTICLE_INSTANCE", ICON_MOD_PARTICLES, "Particle Instance", ""},
-       {eModifierType_ParticleSystem, "PARTICLE_SYSTEM", ICON_MOD_PARTICLES, "Particle System", ""},
        {eModifierType_Shrinkwrap, "SHRINKWRAP", ICON_MOD_SHRINKWRAP, "Shrinkwrap", ""},
        {eModifierType_SimpleDeform, "SIMPLE_DEFORM", ICON_MOD_SIMPLEDEFORM, "Simple Deform", ""},
+       {eModifierType_Smooth, "SMOOTH", ICON_MOD_SMOOTH, "Smooth", ""},
+       {eModifierType_Wave, "WAVE", ICON_MOD_WAVE, "Wave", ""},
+       {0, "", 0, "Physics", ""},
+       {eModifierType_Cloth, "CLOTH", ICON_MOD_CLOTH, "Cloth", ""},
+       {eModifierType_Collision, "COLLISION", ICON_MOD_PHYSICS, "Collision", ""},
+       {eModifierType_Explode, "EXPLODE", ICON_MOD_EXPLODE, "Explode", ""},
+       {eModifierType_Fluidsim, "FLUID_SIMULATION", ICON_MOD_FLUIDSIM, "Fluid Simulation", ""},
+       {eModifierType_ParticleInstance, "PARTICLE_INSTANCE", ICON_MOD_PARTICLES, "Particle Instance", ""},
+       {eModifierType_ParticleSystem, "PARTICLE_SYSTEM", ICON_MOD_PARTICLES, "Particle System", ""},
        {eModifierType_Smoke, "SMOKE", 0, "Smoke", ""},
        {eModifierType_SmokeHR, "SMOKE_HR", 0, "SmokeHR", ""},
-       {eModifierType_Smooth, "SMOOTH", ICON_MOD_SMOOTH, "Smooth", ""},
        {eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""},
-       {eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""},
        {eModifierType_Surface, "SURFACE", ICON_MOD_PHYSICS, "Surface", ""},
-       {eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""},
-       {eModifierType_Wave, "WAVE", ICON_MOD_WAVE, "Wave", ""},
        {0, NULL, 0, NULL, NULL}};
 
-
 #ifdef RNA_RUNTIME
 
 #include "BKE_context.h"
@@ -87,7 +89,7 @@ EnumPropertyItem modifier_type_items[] ={
 static void rna_UVProject_projectors_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
 {
        UVProjectModifierData *uvp= (UVProjectModifierData*)ptr->data;
-       rna_iterator_array_begin(iter, (void*)uvp->projectors, sizeof(Object*), 10, 0, NULL);
+       rna_iterator_array_begin(iter, (void*)uvp->projectors, sizeof(Object*), uvp->num_projectors, 0, NULL);
 }
 
 static StructRNA* rna_Modifier_refine(struct PointerRNA *ptr)
@@ -410,6 +412,34 @@ static PointerRNA rna_CollisionModifier_settings_get(PointerRNA *ptr)
        return rna_pointer_inherit_refine(ptr, &RNA_CollisionSettings, ob->pd);
 }
 
+static PointerRNA rna_UVProjector_object_get(PointerRNA *ptr)
+{
+       Object **ob= (Object**)ptr->data;
+       return rna_pointer_inherit_refine(ptr, &RNA_Object, *ob);
+}
+
+static void rna_UVProjector_object_set(PointerRNA *ptr, PointerRNA value)
+{
+       Object **ob= (Object**)ptr->data;
+
+    if(*ob)
+               id_us_min((ID*)*ob);
+       if(value.data)
+               id_us_plus((ID*)value.data);
+
+       *ob= value.data;
+}
+
+static void rna_UVProjectModifier_num_projectors_set(PointerRNA *ptr, int value)
+{
+       UVProjectModifierData *md= (UVProjectModifierData*)ptr->data;
+       int a;
+
+       md->num_projectors= CLAMPIS(value, 1, MOD_UVPROJECT_MAX);
+       for(a=md->num_projectors; a<MOD_UVPROJECT_MAX; a++)
+               md->projectors[a]= NULL;
+}
+
 #else
 
 static void rna_def_property_subdivision_common(StructRNA *srna, const char type[])
@@ -1150,7 +1180,7 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna)
        PropertyRNA *prop;
 
        srna= RNA_def_struct(brna, "UVProjectModifier", "Modifier");
-       RNA_def_struct_ui_text(srna, "UVProject Modifier", "UV projection modifier to sets UVs from a projector.");
+       RNA_def_struct_ui_text(srna, "UV Project Modifier", "UV projection modifier to sets UVs from a projector.");
        RNA_def_struct_sdna(srna, "UVProjectModifierData");
        RNA_def_struct_ui_icon(srna, ICON_MOD_UVPROJECT);
 
@@ -1160,9 +1190,15 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna)
        RNA_def_property_string_funcs(prop, NULL, NULL, "rna_UVProjectModifier_uvlayer_set");
        RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
 
+       prop= RNA_def_property(srna, "num_projectors", PROP_INT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Number of Projectors", "Number of projectors to use.");
+       RNA_def_property_int_funcs(prop, NULL, "rna_UVProjectModifier_num_projectors_set", NULL);
+       RNA_def_property_range(prop, 1, MOD_UVPROJECT_MAX);
+       RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
+
        prop= RNA_def_property(srna, "projectors", PROP_COLLECTION, PROP_NONE);
-       RNA_def_property_struct_type(prop, "Object");
-       RNA_def_property_collection_funcs(prop, "rna_UVProject_projectors_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_dereference_get", 0, 0, 0, 0, 0);
+       RNA_def_property_struct_type(prop, "UVProjector");
+       RNA_def_property_collection_funcs(prop, "rna_UVProject_projectors_begin", "rna_iterator_array_next", "rna_iterator_array_end", "rna_iterator_array_get", 0, 0, 0, 0, 0);
        RNA_def_property_ui_text(prop, "Projectors", "");
 
        prop= RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
@@ -1188,6 +1224,15 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_UVPROJECT_OVERRIDEIMAGE);
        RNA_def_property_ui_text(prop, "Override Image", "Override faces' current images with the given image.");
        RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
+
+       srna= RNA_def_struct(brna, "UVProjector", NULL);
+       RNA_def_struct_ui_text(srna, "UVProjector", "UV projector used by the UV project modifier.");
+
+       prop= RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "Object");
+       RNA_def_property_pointer_funcs(prop, "rna_UVProjector_object_get", "rna_UVProjector_object_set", NULL);
+       RNA_def_property_flag(prop, PROP_EDITABLE);
+       RNA_def_property_ui_text(prop, "Object", "Object to use as projector transform.");
 }
 
 static void rna_def_modifier_smooth(BlenderRNA *brna)
index 0301932aef3f40918ab9b28e5a2d126c6c6231bb..40e3efc9e46eccde35c82edd375eb23234c8cd88 100644 (file)
@@ -1144,27 +1144,28 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
                
        
        static EnumPropertyItem image_type_items[] = {
+               {0, "", 0, "Image", NULL},
                {R_PNG, "PNG", 0, "PNG", ""},
                {R_JPEG90, "JPEG", 0, "JPEG", ""},
 #ifdef WITH_OPENJPEG
                {R_JP2, "JPEG2000", 0, "JPEG 2000", ""},
 #endif         
-               {R_TIFF, "TIFF", 0, "TIFF", ""},        // XXX only with G.have_libtiff
                {R_BMP, "BMP", 0, "BMP", ""},
                {R_TARGA, "TARGA", 0, "Targa", ""},
                {R_RAWTGA, "RAWTARGA", 0, "Targa Raw", ""},
                //{R_DDS, "DDS", 0, "DDS", ""}, // XXX not yet implemented
                {R_HAMX, "HAMX", 0, "HamX", ""},
                {R_IRIS, "IRIS", 0, "Iris", ""},
-               {0, "", 0, NULL, NULL},
+               {0, "", 0, " ", NULL},
 #ifdef WITH_OPENEXR
                {R_OPENEXR, "OPENEXR", 0, "OpenEXR", ""},
                {R_MULTILAYER, "MULTILAYER", 0, "MultiLayer", ""},
 #endif
+               {R_TIFF, "TIFF", 0, "TIFF", ""},        // XXX only with G.have_libtiff
                {R_RADHDR, "RADHDR", 0, "Radiance HDR", ""},
                {R_CINEON, "CINEON", 0, "Cineon", ""},
                {R_DPX, "DPX", 0, "DPX", ""},
-               {0, "", 0, NULL, NULL},
+               {0, "", 0, "Movie", NULL},
                {R_AVIRAW, "AVIRAW", 0, "AVI Raw", ""},
                {R_AVIJPEG, "AVIJPEG", 0, "AVI JPEG", ""},
 #ifdef _WIN32
@@ -1187,7 +1188,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
 #endif
                {R_FFMPEG, "FFMPEG", 0, "FFMpeg", ""},
 #endif
-               {0, "", 0, NULL, NULL},
                {R_FRAMESERVER, "FRAMESERVER", 0, "Frame Server", ""},
                {0, NULL, 0, NULL, NULL}};
                
index 304da25017b21892aaca54a930d38d211676232b..ab8dfeabe4f65a947ed8d6b70ee5030ba6ab5b3f 100644 (file)
@@ -741,7 +741,6 @@ static void WM_OT_window_duplicate(wmOperatorType *ot)
        ot->name= "Duplicate Window";
        ot->idname= "WM_OT_window_duplicate";
        
-       ot->invoke= WM_operator_confirm;
        ot->exec= wm_window_duplicate_op;
        ot->poll= WM_operator_winactive;
 }
@@ -1035,7 +1034,6 @@ static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
     ot->name= "Toggle Fullscreen";
     ot->idname= "WM_OT_window_fullscreen_toggle";
 
-    ot->invoke= WM_operator_confirm;
     ot->exec= wm_window_fullscreen_toggle_op;
     ot->poll= WM_operator_winactive;
 }