2.5 UI: Modifier Template
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 21 May 2009 15:34:09 +0000 (15:34 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 21 May 2009 15:34:09 +0000 (15:34 +0000)
* template_modifier creates the modifier box, and returns a layout
  to put the buttons in.
* Only the armature modifier is now done with python code, all other
  modifiers use C code. To convert a modifier to python, remove the
  corresponding C code and create a function in DATA_PT_modifiers.
* Some modifiers still require some RNA work to get it working well,
  especially to make pointers editable. Mostly that is a matter of
  defining an own _set callback and put some of the modifier C code
  into it.
* Still various buttons that don't work, like for hooks or mesh
  deform binding.
* Fix for crashing decimate modifier (still disabled).

* Removed UI_BUT_NO_HILITE, HMENU.
* Make uiLayoutBox work with align.

19 files changed:
release/ui/buttons_data_modifier.py
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/object.c
source/blender/editors/include/ED_object.h
source/blender/editors/include/UI_interface.h
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_api.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/interface/interface_widgets.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_modifier.c
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_modifier.c
source/blender/python/intern/bpy_ui.c

index a28a978080d2515a34a6e8d111aee263246b89b6..4020c71759d646685e6afa1a13935a8b09c18a09 100644 (file)
@@ -21,26 +21,16 @@ class DATA_PT_modifiers(DataButtonsPanel):
                if not ob:
                        return
 
-               layout.row()
-               layout.item_menu_enumO("OBJECT_OT_modifier_add", "type")
+               row = layout.row()
+               row.item_menu_enumO("OBJECT_OT_modifier_add", "type")
+               row.itemL();
 
                for md in ob.modifiers:
-                       sub = layout.box()
-
-                       row = sub.row()
-                       row.itemR(md, "expanded", text="")
-                       row.itemR(md, "name", text="")
-
-                       row.itemR(md, "render", text="")
-                       row.itemR(md, "realtime", text="")
-                       row.itemR(md, "editmode", text="")
-                       row.itemR(md, "on_cage", text="")
+                       box = layout.template_modifier(context, md)
 
                        if md.expanded:
-                               sub.itemS()
-
-                               if (md.type == 'ARMATURE'):
-                                       self.armature(sub, md)
+                               if md.type == 'ARMATURE':
+                                       self.armature(box, md)
 
        def armature(self, layout, md):
                layout.itemR(md, "object")
@@ -51,9 +41,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
                flow.itemR(md, "use_vertex_groups")
                flow.itemR(md, "use_bone_envelopes")
                flow.itemR(md, "quaternion")
-               flow.itemR(md, "b_bone_rest")
                flow.itemR(md, "multi_modifier")
                
 bpy.types.register(DATA_PT_modifiers)
 
-
index 2af72d987013c3e3aa13a448c6c76e9e7e1c1798..3d71193f37a5ea6bb4384a9ddc0a3ec69f42d736 100644 (file)
@@ -85,6 +85,7 @@ struct Object *add_object(struct Scene *scene, int type);
 struct Object *copy_object(struct Object *ob);
 void expand_local_object(struct Object *ob);
 void make_local_object(struct Object *ob);
+int object_data_is_libdata(struct Object *ob);
 void set_mblur_offs(float blur);
 void set_field_offs(float field);
 void disable_speed_curve(int val);
index 6578feeeed17d8c985c7baeaab39473830eb317a..d02b660d99262c2361191838137e7d3aaa3171ee 100644 (file)
@@ -4058,17 +4058,15 @@ static void decimateModifier_copyData(ModifierData *md, ModifierData *target)
        tdmd->percent = dmd->percent;
 }
 
-//XXX
-#if 0 
 static DerivedMesh *decimateModifier_applyModifier(
                ModifierData *md, Object *ob, DerivedMesh *derivedData,
   int useRenderParams, int isFinalCalc)
 {
-       DecimateModifierData *dmd = (DecimateModifierData*) md;
+       // DecimateModifierData *dmd = (DecimateModifierData*) md;
        DerivedMesh *dm = derivedData, *result = NULL;
        MVert *mvert;
        MFace *mface;
-       LOD_Decimation_Info lod;
+       // LOD_Decimation_Info lod;
        int totvert, totface;
        int a, numTris;
 
@@ -4090,6 +4088,8 @@ static DerivedMesh *decimateModifier_applyModifier(
                goto exit;
        }
 
+       // XXX
+#if 0
        lod.vertex_buffer= MEM_mallocN(3*sizeof(float)*totvert, "vertices");
        lod.vertex_normal_buffer= MEM_mallocN(3*sizeof(float)*totvert, "normals");
        lod.triangle_index_buffer= MEM_mallocN(3*sizeof(int)*numTris, "trias");
@@ -4174,11 +4174,14 @@ static DerivedMesh *decimateModifier_applyModifier(
        MEM_freeN(lod.vertex_buffer);
        MEM_freeN(lod.vertex_normal_buffer);
        MEM_freeN(lod.triangle_index_buffer);
+#else
+       modifier_setError(md, "Modifier not working yet in 2.5.");
+       goto exit;
+#endif
 
 exit:
                return result;
 }
-#endif
 
 /* Smooth */
 
@@ -8271,7 +8274,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
                mti->flags = eModifierTypeFlag_AcceptsMesh;
                mti->initData = decimateModifier_initData;
                mti->copyData = decimateModifier_copyData;
-               //XXX mti->applyModifier = decimateModifier_applyModifier;
+               mti->applyModifier = decimateModifier_applyModifier;
 
                mti = INIT_TYPE(Smooth);
                mti->type = eModifierTypeType_OnlyDeform;
index b913651d8561e1bd25064d56d139f9b4aa8d8598..d7619010808a4f4f8ecfcd2f3e69860ac57443bb 100644 (file)
@@ -1320,6 +1320,18 @@ void make_local_object(Object *ob)
        expand_local_object(ob);
 }
 
+/* returns true if the Object data is a from an external blend file (libdata) */
+int object_data_is_libdata(Object *ob)
+{
+       if(!ob) return 0;
+       if(ob->proxy) return 0;
+       if(ob->id.lib) return 1;
+       if(!ob->data) return 0;
+       if(((ID *)ob->data)->lib) return 1;
+
+       return 0;
+}
+
 /* *************** PROXY **************** */
 
 /* when you make proxy, ensure the exposed layers are extern */
index 8ff716476adf535a059c6784f686cd0ee48769f2..1074c53bec6a67e2f3ee849a07152ddc363a69d5 100644 (file)
@@ -39,6 +39,7 @@ struct KeyBlock;
 struct Lattice;
 struct Mesh;
 struct Curve;
+struct ReportList;
 
 /* object_edit.c */
 void ED_operatortypes_object(void);
@@ -86,7 +87,13 @@ void latt_to_key(struct Lattice *lt, struct KeyBlock *kb);
 void key_to_curve(struct KeyBlock *kb, struct Curve  *cu, struct ListBase *nurb);
 void curve_to_key(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb);
 
-
+/* object_modifier.c */
+int ED_object_modifier_delete(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
+int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
+int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
+int ED_object_modifier_convert(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct ModifierData *md);
+int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct ModifierData *md);
+int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
 
 #endif /* ED_OBJECT_H */
 
index 61fd6cb0b79fcab9cf9db18c8e2a27f6931bd4b1..3a52e00b981d5bcf1f3cd9bdc7055fcdff05a080 100644 (file)
@@ -86,7 +86,7 @@ typedef struct uiLayout uiLayout;
 #define UI_BLOCK_NUMSELECT             8
 #define UI_BLOCK_ENTER_OK              16
 #define UI_BLOCK_NOSHADOW              32
-#define UI_BLOCK_NO_HILITE             64              /* XXX 2.5 not implemented */
+#define UI_BLOCK_UNUSED                        64
 #define UI_BLOCK_MOVEMOUSE_QUIT        128
 #define UI_BLOCK_KEEP_OPEN             256
 #define UI_BLOCK_POPUP                 512
@@ -127,8 +127,7 @@ typedef struct uiLayout uiLayout;
 #define UI_BUT_ALIGN_DOWN      (1<<17)
 
 #define UI_BUT_DISABLED                (1<<18)
-       /* dont draw hilite on mouse over */
-#define UI_NO_HILITE           (1<<19)
+#define UI_BUT_UNUSED          (1<<19)
 #define UI_BUT_ANIMATED                (1<<20)
 #define UI_BUT_ANIMATED_KEY    (1<<21)
 #define UI_BUT_DRIVEN          (1<<22)
@@ -188,8 +187,7 @@ typedef struct uiLayout uiLayout;
 #define ICONTOGN (34<<9)
 #define FTPREVIEW (35<<9)
 #define NUMABS (36<<9)
-#define HMENU  (37<<9)
-#define TOGBUT  (38<<9)
+#define TOGBUT  (37<<9)
 #define BUTTYPE        (63<<9)
 
 /* Drawing
@@ -560,6 +558,7 @@ uiBlock *uiLayoutFreeBlock(uiLayout *layout);
 void uiTemplateHeader(uiLayout *layout, struct bContext *C);
 void uiTemplateHeaderID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname,
        char *newop, char *openop, char *unlinkop);
+uiLayout *uiTemplateModifier(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
 
 /* items */
 void uiItemO(uiLayout *layout, char *name, int icon, char *opname);
index b4c2969c9559cb8626fb19ff3fe451c258f39e93..3ec91975a91659e1e2959c9c76ced988dbb852b4 100644 (file)
@@ -1987,7 +1987,7 @@ void uiBlockEndAlign(uiBlock *block)
 
 int ui_but_can_align(uiBut *but)
 {
-       return !ELEM(but->type, LABEL, ROUNDBOX);
+       return (but->type != LABEL);
 }
 
 static void ui_block_do_align_but(uiBlock *block, uiBut *first, int nr)
@@ -2221,8 +2221,6 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short
        }
 
        but->flag |= (block->flag & UI_BUT_ALIGN);
-       if(block->flag & UI_BLOCK_NO_HILITE)
-               but->flag |= UI_NO_HILITE;
 
        if (but->lock) {
                if (but->lockstr) {
@@ -2230,12 +2228,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short
                }
        }
 
-       if(but->type == ROUNDBOX) {
-               but->flag |= UI_NO_HILITE;
-               BLI_addhead(&block->buttons, but);
-       }
-       else
-               BLI_addtail(&block->buttons, but);
+       BLI_addtail(&block->buttons, but);
        
        if(block->curlayout)
                ui_layout_add_but(block->curlayout, but);
@@ -2999,7 +2992,7 @@ uiBut *uiDefPulldownBut(uiBlock *block, uiBlockCreateFunc func, void *arg, char
 
 uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, char *str, short x1, short y1, short x2, short y2, char *tip)
 {
-       uiBut *but= ui_def_but(block, HMENU, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
+       uiBut *but= ui_def_but(block, PULLDOWN, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
        but->menu_create_func= func;
        ui_check_but(but);
        return but;
@@ -3007,7 +3000,7 @@ uiBut *uiDefMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, char *str,
 
 uiBut *uiDefIconTextMenuBut(uiBlock *block, uiMenuCreateFunc func, void *arg, int icon, char *str, short x1, short y1, short x2, short y2, char *tip)
 {
-       uiBut *but= ui_def_but(block, HMENU, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
+       uiBut *but= ui_def_but(block, PULLDOWN, 0, str, x1, y1, x2, y2, arg, 0.0, 0.0, 0.0, 0.0, tip);
 
        but->icon= (BIFIconID) icon;
        but->flag|= UI_HAS_ICON;
index b593aef2208b8378dd514be426253fb6b40c2b8e..0aa6d9895cbd97f27a4eacda46afd8ff562e9464 100644 (file)
@@ -189,5 +189,13 @@ void RNA_api_ui_layout(StructRNA *srna)
        RNA_def_string(func, "new", "", 0, "", "Operator identifier to create a new ID block.");
        RNA_def_string(func, "open", "", 0, "", "Operator identifier to open a new ID block.");
        RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block.");
+
+       func= RNA_def_function(srna, "template_modifier", "uiTemplateModifier");
+       parm= RNA_def_pointer(func, "context", "Context", "", "Current context.");
+       RNA_def_property_flag(parm, PROP_REQUIRED);
+       parm= RNA_def_pointer(func, "data", "AnyType", "", "Modifier data.");
+       RNA_def_property_flag(parm, PROP_REQUIRED);
+       parm= RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in.");
+       RNA_def_function_return(func, parm);
 }
 
index ea5eb354b54c876aba29d399b2b150699b37ec7f..c15e4664862e41c32f4ea959208fbe683f4c4d1e 100644 (file)
@@ -431,13 +431,6 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data)
        data->applied= 1;
 }
 
-static void ui_apply_but_LABEL(bContext *C, uiBut *but, uiHandleButtonData *data)
-{
-       ui_apply_but_func(C, but);
-       data->retval= but->retval;
-       data->applied= 1;
-}
-
 static void ui_apply_but_TOG3(bContext *C, uiBut *but, uiHandleButtonData *data)
 { 
        if(but->pointype==SHO ) {
@@ -590,10 +583,6 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
                        break;
                case HSVSLI:
                        break;
-               case ROUNDBOX:  
-               case LABEL:     
-                       ui_apply_but_LABEL(C, but, data);
-                       break;
                case TOG3:      
                        ui_apply_but_TOG3(C, but, data);
                        break;
@@ -602,7 +591,6 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
                case ICONTEXTROW:
                case BLOCK:
                case PULLDOWN:
-               case HMENU:
                case COL:
                        ui_apply_but_BLOCK(C, but, data);
                        break;
@@ -630,6 +618,8 @@ static void ui_apply_button(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
                case LINK:
                case INLINK:
                        break;
+               default:
+                       break;
        }
 
        but->editstr= editstr;
@@ -1423,20 +1413,28 @@ static void ui_blockopen_begin(bContext *C, uiBut *but, uiHandleButtonData *data
        switch(but->type) {
                case BLOCK:
                case PULLDOWN:
-                       func= but->block_create_func;
-                       arg= but->poin;
-                       break;
-               case HMENU:
-                       menufunc= but->menu_create_func;
-                       arg= but->poin;
+                       if(but->menu_create_func) {
+                               menufunc= but->menu_create_func;
+                               arg= but->poin;
+                       }
+                       else {
+                               func= but->block_create_func;
+                               arg= but->poin;
+                       }
                        break;
                case MENU:
-                       data->origvalue= ui_get_but_val(but);
-                       data->value= data->origvalue;
-                       but->editval= &data->value;
+                       if(but->menu_create_func) {
+                               menufunc= but->menu_create_func;
+                               arg= but->poin;
+                       }
+                       else {
+                               data->origvalue= ui_get_but_val(but);
+                               data->value= data->origvalue;
+                               but->editval= &data->value;
 
-                       handlefunc= ui_block_func_MENU;
-                       arg= but;
+                               handlefunc= ui_block_func_MENU;
+                               arg= but;
+                       }
                        break;
                case ICONROW:
                        handlefunc= ui_block_func_ICONROW;
@@ -2698,17 +2696,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event)
                retval= ui_do_but_TEX(C, block, but, data, event);
                break;
        case MENU:
-               retval= ui_do_but_BLOCK(C, but, data, event);
-               break;
        case ICONROW:
-               retval= ui_do_but_BLOCK(C, but, data, event);
-               break;
        case ICONTEXTROW:
-               retval= ui_do_but_BLOCK(C, but, data, event);
-               break;
        case BLOCK:
        case PULLDOWN:
-       case HMENU:
                retval= ui_do_but_BLOCK(C, but, data, event);
                break;
        case BUTM:
@@ -2841,9 +2832,7 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y)
                ui_window_to_block(ar, block, &mx, &my);
 
                for(but=block->buttons.first; but; but= but->next) {
-                       if(but->flag & UI_NO_HILITE)
-                               continue;
-                       if(but->type==LABEL)
+                       if(ELEM3(but->type, LABEL, ROUNDBOX, SEPR))
                                continue;
 
                        if(ui_but_contains_pt(but, mx, my))
@@ -2896,7 +2885,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
                button_tooltip_timer_reset(but);
 
                /* automatic open pulldown block timer */
-               if(ELEM4(but->type, BLOCK, PULLDOWN, HMENU, ICONTEXTROW)) {
+               if(ELEM3(but->type, BLOCK, PULLDOWN, ICONTEXTROW)) {
                        if(!data->autoopentimer) {
                                int time;
 
@@ -3410,7 +3399,7 @@ int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu,
                                                else but= ui_but_first(block);
                                        }
 
-                                       if(but && ELEM(but->type, BLOCK, HMENU))
+                                       if(but && ELEM(but->type, BLOCK, PULLDOWN))
                                                ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE_OPEN);
                                }
 
index 13c9d09aff1a431ca461b52804193da01d777ce2..b59846738ce05a227ef6679f00c5336b43ca103c 100644 (file)
@@ -188,7 +188,7 @@ struct uiBut {
        /* BLOCK data */
        uiBlockCreateFunc block_create_func;
 
-       /* HMENU data */
+       /* PULLDOWN/MENU data */
        uiMenuCreateFunc menu_create_func;
 
        /* RNA data */
index 56183bfb314c84cf0e796c8e7963ddfc878cf731..3fa0a8849fe62c31664b668acdb1b3d91b9f8da6 100644 (file)
@@ -147,6 +147,7 @@ typedef struct uiLayoutItemSplt {
 
 typedef struct uiLayoutItemBx {
        uiLayout litem;
+       uiBut *roundbox;
 } uiLayoutItemBx;
 
 typedef struct uiLayoutItemRoot {
@@ -839,6 +840,8 @@ static void ui_item_menu(uiLayout *layout, char *name, int icon, uiMenuCreateFun
 
        if(layout->root->type == UI_LAYOUT_HEADER)
                uiBlockSetEmboss(block, UI_EMBOSS);
+       else if(layout->root->type == UI_LAYOUT_PANEL)
+               but->type= MENU;
 }
 
 void uiItemM(uiLayout *layout, bContext *C, char *name, int icon, char *menuname)
@@ -1146,12 +1149,14 @@ static void ui_litem_estimate_box(uiLayout *litem)
 
        ui_litem_estimate_column(litem);
        litem->w += 2*style->boxspace;
-       litem->h += 2*style->boxspace;
+       litem->h += style->boxspace;
 }
 
 static void ui_litem_layout_box(uiLayout *litem)
 {
+       uiLayoutItemBx *box= (uiLayoutItemBx*)litem;
        uiStyle *style= litem->root->style;
+       uiBut *but;
        int w, h;
 
        w= litem->w;
@@ -1169,10 +1174,14 @@ static void ui_litem_layout_box(uiLayout *litem)
        litem->y -= style->boxspace;
 
        if(w != 0) litem->w += 2*style->boxspace;
-       if(h != 0) litem->h += 2*style->boxspace;
+       if(h != 0) litem->h += style->boxspace;
 
        /* roundbox around the sublayout */
-       uiDefBut(litem->root->block, ROUNDBOX, 0, "", litem->x, litem->y, litem->w, litem->h, NULL, 7.0, 0.0, 3, 20, "");
+       but= box->roundbox;
+       but->x1= litem->x;
+       but->y1= litem->y;
+       but->x2= litem->x+litem->w;
+       but->y2= litem->y+litem->h;
 }
 
 /* multi-column layout, automatically flowing to the next */
@@ -1475,6 +1484,8 @@ uiLayout *uiLayoutBox(uiLayout *layout)
 
        uiBlockSetCurLayout(layout->root->block, &box->litem);
 
+       box->roundbox= uiDefBut(layout->root->block, ROUNDBOX, 0, "", 0, 0, 0, 0, NULL, 0.0, 0.0, 0, 0, "");
+
        return &box->litem;
 }
 
@@ -1564,13 +1575,21 @@ static void ui_item_align(uiLayout *litem, int nr)
 {
        uiItem *item;
        uiButtonItem *bitem;
+       uiLayoutItemBx *box;
 
-       for(item=litem->items.first; item; item=item->next) {
+       for(item=litem->items.last; item; item=item->prev) {
                if(item->type == ITEM_BUTTON) {
                        bitem= (uiButtonItem*)item;
                        if(ui_but_can_align(bitem->but))
                                bitem->but->alignnr= nr;
                }
+               else if(item->type == ITEM_LAYOUT_FREE);
+               else if(item->type == ITEM_LAYOUT_BOX) {
+                       box= (uiLayoutItemBx*)item;
+                       box->roundbox->alignnr= nr;
+                       BLI_remlink(&litem->root->block->buttons, box->roundbox);
+                       BLI_addhead(&litem->root->block->buttons, box->roundbox);
+               }
                else
                        ui_item_align((uiLayout*)item, nr);
        }
index 847c0a02ee4084ca3f69fb2913fea0e727870a25..4148f36726b26afc8a899e5dabf684c66e7e7bf8 100644 (file)
@@ -654,7 +654,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut
 
        /* if this is being created from a button */
        if(but) {
-               if(ELEM3(but->type, BLOCK, PULLDOWN, HMENU))
+               if(ELEM(but->type, BLOCK, PULLDOWN))
                        block->xofs = -2;       /* for proper alignment */
 
                /* only used for automatic toolbox, so can set the shift flag */
index 8969e2b69ae0af5cc6742608f0221cd74b5680d7..d90869a1059e0d437a8f278dec2b9eefe43e38c7 100644 (file)
@@ -236,3 +236,1431 @@ void uiTemplateHeaderID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *pr
        MEM_freeN(template);
 }
 
+/************************ Modifier Template *************************/
+
+#define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
+
+#define B_NOP                          0
+#define B_MODIFIER_RECALC      1
+#define B_MODIFIER_REDRAW      2
+#define B_CHANGEDEP                    3
+#define B_ARM_RECALCDATA       4
+
+#include <string.h>
+
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_object_force.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_bmesh.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_lattice.h"
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_report.h"
+
+#include "UI_resources.h"
+#include "ED_util.h"
+
+#include "BLI_arithb.h"
+#include "BLI_listbase.h"
+
+#include "ED_object.h"
+
+void do_modifier_panels(bContext *C, void *arg, int event)
+{
+       Scene *scene= CTX_data_scene(C);
+       Object *ob = CTX_data_active_object(C);
+
+       switch(event) {
+       case B_MODIFIER_REDRAW:
+               WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+               break;
+
+       case B_MODIFIER_RECALC:
+               WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
+               DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+               object_handle_update(scene, ob);
+               // XXX countall();
+               break;
+       }
+}
+
+static void modifiers_del(bContext *C, void *ob_v, void *md_v)
+{
+       ReportList reports;
+
+       BKE_reports_init(&reports, RPT_STORE);
+
+       if(ED_object_modifier_delete(&reports, ob_v, md_v))
+               ED_undo_push(C, "Delete modifier");
+       else
+               uiPupMenuReports(C, &reports);
+
+       BKE_reports_clear(&reports);
+}
+
+static void modifiers_moveUp(bContext *C, void *ob_v, void *md_v)
+{
+       ReportList reports;
+
+       BKE_reports_init(&reports, RPT_STORE);
+
+       if(ED_object_modifier_move_up(&reports, ob_v, md_v))
+               ED_undo_push(C, "Move modifier");
+       else
+               uiPupMenuReports(C, &reports);
+
+       BKE_reports_clear(&reports);
+}
+
+static void modifiers_moveDown(bContext *C, void *ob_v, void *md_v)
+{
+       ReportList reports;
+
+       BKE_reports_init(&reports, RPT_STORE);
+
+       if(ED_object_modifier_move_down(&reports, ob_v, md_v))
+               ED_undo_push(C, "Move modifier");
+       else
+               uiPupMenuReports(C, &reports);
+
+       BKE_reports_clear(&reports);
+}
+
+static void modifier_testLatticeObj(bContext *C, char *name, ID **idpp)
+{
+       Main *bmain= CTX_data_main(C);
+       ID *id;
+
+       for (id= bmain->object.first; id; id= id->next) {
+               if( strcmp(name, id->name+2)==0 ) {
+                       if (((Object *)id)->type != OB_LATTICE) {
+                               uiPupMenuError(C, "Lattice deform object must be a lattice");
+                               break;
+                       } 
+                       *idpp= id;
+                       return;
+               }
+       }
+       *idpp= 0;
+}
+
+static void modifier_testCurveObj(bContext *C, char *name, ID **idpp)
+{
+       Main *bmain= CTX_data_main(C);
+       ID *id;
+
+       for (id= bmain->object.first; id; id= id->next) {
+               if( strcmp(name, id->name+2)==0 ) {
+                       if (((Object *)id)->type != OB_CURVE) {
+                               uiPupMenuError(C, "Curve deform object must be a curve");
+                               break;
+                       } 
+                       *idpp= id;
+                       return;
+               }
+       }
+       *idpp= 0;
+}
+
+static void modifier_testMeshObj(bContext *C, char *name, ID **idpp)
+{
+       Main *bmain= CTX_data_main(C);
+       Object *obact= CTX_data_active_object(C);
+       ID *id;
+
+       for (id= bmain->object.first; id; id= id->next) {
+               /* no boolean on its own object */
+               if(id != (ID *)obact) {
+                       if( strcmp(name, id->name+2)==0 ) {
+                               if (((Object *)id)->type != OB_MESH) {
+                                       uiPupMenuError(C, "Boolean modifier object must be a mesh");
+                                       break;
+                               } 
+                               *idpp= id;
+                               return;
+                       }
+               }
+       }
+       *idpp= NULL;
+}
+
+static void modifier_testArmatureObj(bContext *C, char *name, ID **idpp)
+{
+       Main *bmain= CTX_data_main(C);
+       ID *id;
+
+       for (id= bmain->object.first; id; id= id->next) {
+               if( strcmp(name, id->name+2)==0 ) {
+                       if (((Object *)id)->type != OB_ARMATURE) {
+                               uiPupMenuError(C, "Armature deform object must be an armature");
+                               break;
+                       } 
+                       *idpp= id;
+                       return;
+               }
+       }
+       *idpp= 0;
+}
+
+static void modifier_testTexture(bContext *C, char *name, ID **idpp)
+{
+       Main *bmain= CTX_data_main(C);
+       ID *id;
+
+       for(id = bmain->tex.first; id; id = id->next) {
+               if(strcmp(name, id->name + 2) == 0) {
+                       *idpp = id;
+                       /* texture gets user, objects not: delete object = clear modifier */
+                       id_us_plus(id);
+                       return;
+               }
+       }
+       *idpp = 0;
+}
+
+#if 0 /* this is currently unused, but could be useful in the future */
+static void modifier_testMaterial(bContext *C, char *name, ID **idpp)
+{
+       Main *bmain= CTX_data_main(C);
+       ID *id;
+
+       for(id = bmain->mat.first; id; id = id->next) {
+               if(strcmp(name, id->name + 2) == 0) {
+                       *idpp = id;
+                       return;
+               }
+       }
+       *idpp = 0;
+}
+#endif
+
+static void modifier_testImage(bContext *C, char *name, ID **idpp)
+{
+       Main *bmain= CTX_data_main(C);
+       ID *id;
+
+       for(id = bmain->image.first; id; id = id->next) {
+               if(strcmp(name, id->name + 2) == 0) {
+                       *idpp = id;
+                       return;
+               }
+       }
+       *idpp = 0;
+}
+
+/* autocomplete callback for ID buttons */
+void autocomplete_image(bContext *C, char *str, void *arg_v)
+{
+       Main *bmain= CTX_data_main(C);
+
+       /* search if str matches the beginning of an ID struct */
+       if(str[0]) {
+               AutoComplete *autocpl = autocomplete_begin(str, 22);
+               ID *id;
+
+               for(id = bmain->image.first; id; id = id->next)
+                       autocomplete_do_name(autocpl, id->name+2);
+
+               autocomplete_end(autocpl, str);
+       }
+}
+
+/* autocomplete callback for ID buttons */
+void autocomplete_meshob(bContext *C, char *str, void *arg_v)
+{
+       Main *bmain= CTX_data_main(C);
+
+       /* search if str matches the beginning of an ID struct */
+       if(str[0]) {
+               AutoComplete *autocpl = autocomplete_begin(str, 22);
+               ID *id;
+
+               for(id = bmain->object.first; id; id = id->next)
+                       if(((Object *)id)->type == OB_MESH)
+                               autocomplete_do_name(autocpl, id->name+2);
+
+               autocomplete_end(autocpl, str);
+       }
+}
+
+static void modifiers_convertParticles(bContext *C, void *obv, void *mdv)
+{
+       Scene *scene= CTX_data_scene(C);
+       ReportList reports;
+
+       BKE_reports_init(&reports, RPT_STORE);
+
+       if(ED_object_modifier_convert(&reports, scene, obv, mdv))
+               ED_undo_push(C, "Convert particles to mesh object(s).");
+       else
+               uiPupMenuReports(C, &reports);
+
+       BKE_reports_clear(&reports);
+}
+
+static void modifiers_applyModifier(bContext *C, void *obv, void *mdv)
+{
+       Scene *scene= CTX_data_scene(C);
+       ReportList reports;
+
+       BKE_reports_init(&reports, RPT_STORE);
+
+       if(ED_object_modifier_apply(&reports, scene, obv, mdv))
+               ED_undo_push(C, "Apply modifier");
+       else
+               uiPupMenuReports(C, &reports);
+
+       BKE_reports_clear(&reports);
+}
+
+static void modifiers_copyModifier(bContext *C, void *ob_v, void *md_v)
+{
+       ReportList reports;
+
+       BKE_reports_init(&reports, RPT_STORE);
+
+       if(ED_object_modifier_copy(&reports, ob_v, md_v))
+               ED_undo_push(C, "Copy modifier");
+       else
+               uiPupMenuReports(C, &reports);
+
+       BKE_reports_clear(&reports);
+}
+
+static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
+{
+       Object *ob = ob_v;
+       ModifierData *md;
+       
+       int i, cageIndex = modifiers_getCageIndex(ob, NULL );
+
+       for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
+               if( md == md_v ) {
+                       if( i >= cageIndex )
+                               md->mode ^= eModifierMode_OnCage;
+                       break;
+               }
+}
+
+static void modifiers_clearHookOffset(bContext *C, void *ob_v, void *md_v)
+{
+       Object *ob = ob_v;
+       ModifierData *md = md_v;
+       HookModifierData *hmd = (HookModifierData*) md;
+       
+       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");
+       }
+}
+
+static void modifiers_cursorHookCenter(bContext *C, void *ob_v, void *md_v)
+{
+       /* XXX 
+       Object *ob = ob_v;
+       ModifierData *md = md_v;
+       HookModifierData *hmd = (HookModifierData*) md;
+
+       if(G.vd) {
+               float *curs = give_cursor();
+               float bmat[3][3], imat[3][3];
+
+               where_is_object(ob);
+       
+               Mat3CpyMat4(bmat, ob->obmat);
+               Mat3Inv(imat, bmat);
+
+               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);
+
+               ED_undo_push(C, "Hook cursor center");
+       }*/
+}
+
+static void modifiers_selectHook(bContext *C, void *ob_v, void *md_v)
+{
+       /* XXX ModifierData *md = md_v;
+       HookModifierData *hmd = (HookModifierData*) md;
+
+       hook_select(hmd);*/
+}
+
+static void modifiers_reassignHook(bContext *C, void *ob_v, void *md_v)
+{
+       /* XXX ModifierData *md = md_v;
+       HookModifierData *hmd = (HookModifierData*) md;
+       float cent[3];
+       int *indexar, tot, ok;
+       char name[32];
+               
+       ok= hook_getIndexArray(&tot, &indexar, name, cent);
+
+       if (!ok) {
+               uiPupMenuError(C, "Requires selected vertices or active Vertex Group");
+       } else {
+               if (hmd->indexar) {
+                       MEM_freeN(hmd->indexar);
+               }
+
+               VECCOPY(hmd->cent, cent);
+               hmd->indexar = indexar;
+               hmd->totindex = tot;
+       }*/
+}
+
+static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
+{
+       Object *ob = ob_v;
+       ModifierData *md = md_v;
+       ModifierData *nmd = modifier_new(md->type);
+
+       modifier_copyData(md, nmd);
+       nmd->mode &= ~eModifierMode_Virtual;
+
+       BLI_addhead(&ob->modifiers, nmd);
+
+       ob->partype = PAROBJECT;
+
+       ED_undo_push(C, "Modifier convert to real");
+}
+
+static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
+                                    int *uvlayer_tmp, char *uvlayer_name)
+{
+       char strtmp[38];
+       int totuv, i;
+       CustomDataLayer *layer
+                   = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
+
+       *uvlayer_tmp = -1;
+
+       totuv = CustomData_number_of_layers(data, CD_MTFACE);
+
+       *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
+                                  "menu_string");
+       sprintf(*menu_string, "UV Layer%%t");
+       for(i = 0; i < totuv; i++) {
+               /* assign first layer as uvlayer_name if uvlayer_name is null. */
+               if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
+               sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
+               strcat(*menu_string, strtmp);
+               layer++;
+       }
+
+       /* there is no uvlayer defined, or else it was deleted. Assign active
+        * layer, then recalc modifiers.
+        */
+       if(*uvlayer_tmp == -1) {
+               if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
+                       *uvlayer_tmp = 1;
+                       layer = data->layers;
+                       for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
+                           i++, layer++) {
+                               if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
+                       }
+                       strcpy(uvlayer_name, layer->name);
+
+                       /* update the modifiers */
+                       /* XXX do_modifier_panels(B_MODIFIER_RECALC);*/
+               } else {
+                       /* ok we have no uv layers, so make sure menu button knows that.*/
+                       *uvlayer_tmp = 0;
+               }
+       }
+}
+
+void set_wave_uvlayer(bContext *C, void *arg1, void *arg2)
+{
+       WaveModifierData *wmd=arg1;
+       CustomDataLayer *layer = arg2;
+
+       /*check we have UV layers*/
+       if (wmd->uvlayer_tmp < 1) return;
+       layer = layer + (wmd->uvlayer_tmp-1);
+       
+       strcpy(wmd->uvlayer_name, layer->name);
+}
+
+void set_displace_uvlayer(bContext *C, void *arg1, void *arg2)
+{
+       DisplaceModifierData *dmd=arg1;
+       CustomDataLayer *layer = arg2;
+
+       /*check we have UV layers*/
+       if (dmd->uvlayer_tmp < 1) return;
+       layer = layer + (dmd->uvlayer_tmp-1);
+       
+       strcpy(dmd->uvlayer_name, layer->name);
+}
+
+void set_uvproject_uvlayer(bContext *C, void *arg1, void *arg2)
+{
+       UVProjectModifierData *umd=arg1;
+       CustomDataLayer *layer = arg2;
+
+       /*check we have UV layers*/
+       if (umd->uvlayer_tmp < 1) return;
+       layer = layer + (umd->uvlayer_tmp-1);
+       
+       strcpy(umd->uvlayer_name, layer->name);
+}
+
+static void modifiers_bindMeshDeform(bContext *C, void *ob_v, void *md_v)
+{
+       Scene *scene= CTX_data_scene(C);
+       MeshDeformModifierData *mmd = (MeshDeformModifierData*) md_v;
+       Object *ob = (Object*)ob_v;
+
+       if(mmd->bindcos) {
+               if(mmd->bindweights) MEM_freeN(mmd->bindweights);
+               if(mmd->bindcos) MEM_freeN(mmd->bindcos);
+               if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
+               if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
+               if(mmd->dynverts) MEM_freeN(mmd->dynverts);
+               mmd->bindweights= NULL;
+               mmd->bindcos= NULL;
+               mmd->dyngrid= NULL;
+               mmd->dyninfluences= NULL;
+               mmd->dynverts= NULL;
+               mmd->totvert= 0;
+               mmd->totcagevert= 0;
+               mmd->totinfluence= 0;
+       }
+       else {
+               DerivedMesh *dm;
+               int mode= mmd->modifier.mode;
+
+               /* force modifier to run, it will call binding routine */
+               mmd->needbind= 1;
+               mmd->modifier.mode |= eModifierMode_Realtime;
+
+               if(ob->type == OB_MESH) {
+                       dm= mesh_create_derived_view(scene, ob, 0);
+                       dm->release(dm);
+               }
+               else if(ob->type == OB_LATTICE) {
+                       lattice_calc_modifiers(scene, ob);
+               }
+               else if(ob->type==OB_MBALL) {
+                       makeDispListMBall(scene, ob);
+               }
+               else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+                       makeDispListCurveTypes(scene, ob, 0);
+               }
+
+               mmd->needbind= 0;
+               mmd->modifier.mode= mode;
+       }
+}
+
+void modifiers_explodeFacepa(bContext *C, void *arg1, void *arg2)
+{
+       ExplodeModifierData *emd=arg1;
+
+       emd->flag |= eExplodeFlag_CalcFaces;
+}
+
+void modifiers_explodeDelVg(bContext *C, void *arg1, void *arg2)
+{
+       ExplodeModifierData *emd=arg1;
+       emd->vgroup = 0;
+}
+
+static int modifier_is_fluid_particles(ModifierData *md)
+{
+       if(md->type == eModifierType_ParticleSystem) {
+               if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
+                       return 1;
+       }
+       return 0;
+}
+
+static uiLayout *draw_modifier(bContext *C, uiLayout *layout, Object *ob, ModifierData *md, int index, int cageIndex, int lastCageIndex)
+{
+       Object *obedit= CTX_data_edit_object(C);
+       ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+       uiBut *but;
+       uiBlock *block;
+       uiLayout *column, *row, *result= NULL;
+       int isVirtual = md->mode&eModifierMode_Virtual;
+       int x = 0, y = 0; // XXX , color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
+       int editing = (obedit==ob);
+       short width = 295, buttonWidth = width-120-10;
+       char str[128];
+
+       column= uiLayoutColumn(layout, 1);
+
+       /* rounded header */
+       /* XXX uiBlockSetCol(block, color); */
+               /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
+       block= uiLayoutFreeBlock(uiLayoutBox(column));
+       uiBlockSetHandleFunc(block, do_modifier_panels, NULL);
+
+       //uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
+       //               (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
+       /* XXX uiBlockSetCol(block, TH_AUTO); */
+       
+       /* open/close icon */
+       if (!isVirtual) {
+               uiBlockSetEmboss(block, UI_EMBOSSN);
+               uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, B_MODIFIER_REDRAW, VICON_DISCLOSURE_TRI_RIGHT, x-10, y-2, 20, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier");
+       }
+
+       uiBlockSetEmboss(block, UI_EMBOSS);
+       
+       if (isVirtual) {
+               sprintf(str, "%s parent deform", md->name);
+               uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
+
+               but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Make Real", x+width-100, y, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Convert virtual modifier to a real modifier");
+               uiButSetFunc(but, modifiers_convertToReal, ob, md);
+       } else {
+               uiBlockBeginAlign(block);
+               uiDefBut(block, TEX, B_MODIFIER_REDRAW, "", x+10, y-1, buttonWidth-60, 19, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); 
+
+               /* Softbody not allowed in this situation, enforce! */
+               if (((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type!=eModifierType_Surface)) {
+                       uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
+                       but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
+                       if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
+                               uiDefIconButBitI(block, TOG, eModifierMode_Editmode, B_MODIFIER_RECALC, VICON_EDIT, x+10+buttonWidth-20, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)");
+                       }
+               }
+               uiBlockEndAlign(block);
+
+               /* XXX uiBlockSetEmboss(block, UI_EMBOSSR); */
+
+               if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
+                       int icon; //, color;
+
+                       if (index==cageIndex) {
+                               // XXX color = TH_BUT_SETTING;
+                               icon = VICON_EDITMODE_HLT;
+                       } else if (index<cageIndex) {
+                               // XXX color = TH_BUT_NEUTRAL;
+                               icon = VICON_EDITMODE_DEHLT;
+                       } else {
+                               // XXX color = TH_BUT_NEUTRAL;
+                               icon = ICON_BLANK1;
+                       }
+                       /* XXX uiBlockSetCol(block, color); */
+                       but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, icon, x+width-105, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode");
+                       uiButSetFunc(but, modifiers_setOnCage, ob, md);
+                       /* XXX uiBlockSetCol(block, TH_AUTO); */
+               }
+
+               /* XXX uiBlockSetCol(block, TH_BUT_ACTION); */
+
+               but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_UP, x+width-75, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Move modifier up in stack");
+               uiButSetFunc(but, modifiers_moveUp, ob, md);
+
+               but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_DOWN, x+width-75+20, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Move modifier down in stack");
+               uiButSetFunc(but, modifiers_moveDown, ob, md);
+               
+               uiBlockSetEmboss(block, UI_EMBOSSN);
+               
+               // deletion over the deflection panel
+               // fluid particle modifier can't be deleted here
+               if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && md->type!=eModifierType_Surface && !modifier_is_fluid_particles(md))
+               {
+                       but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
+                       uiButSetFunc(but, modifiers_del, ob, md);
+               }
+               /* XXX uiBlockSetCol(block, TH_AUTO); */
+       }
+
+       uiBlockSetEmboss(block, UI_EMBOSS);
+
+       if(!isVirtual && (md->mode&eModifierMode_Expanded)) {
+               int cy = y - 8;
+               int lx = x + width - 60 - 15;
+               uiLayout *box;
+
+               box= uiLayoutBox(column);
+               row= uiLayoutRow(box, 1);
+
+               y -= 18;
+
+               if (!isVirtual && (md->type!=eModifierType_Collision) && (md->type!=eModifierType_Surface)) {
+                       uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */
+
+                       uiBlockBeginAlign(block);
+                       if (md->type==eModifierType_ParticleSystem) {
+                       ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
+
+                       if(!(G.f & G_PARTICLEEDIT)) {
+                                       if(ELEM3(psys->part->draw_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache) {
+                                               but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert",        lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object");
+                                               uiButSetFunc(but, modifiers_convertParticles, ob, md);
+                                       }
+                               }
+                       }
+                       else{
+                               but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply",  lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
+                               uiButSetFunc(but, modifiers_applyModifier, ob, md);
+                       }
+                       
+                       uiBlockClearButLock(block);
+                       uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
+
+                       if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
+                               but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy",   lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
+                               uiButSetFunc(but, modifiers_copyModifier, ob, md);
+                       }
+                       uiBlockEndAlign(block);
+               }
+
+               result= uiLayoutColumn(box, 0);
+               block= uiLayoutFreeBlock(box);
+
+               lx = x + 10;
+               cy = y + 10 - 1;
+               uiBlockBeginAlign(block);
+               if (md->type==eModifierType_Subsurf) {
+                       SubsurfModifierData *smd = (SubsurfModifierData*) md;
+                       char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
+                       uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
+                       uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
+                       uiDefButS(block, NUM, B_MODIFIER_REDRAW, "Render Levels:",              lx, (cy-=19), buttonWidth,19, &smd->renderLevels, 1, 6, 0, 0, "Number subdivisions to perform when rendering");
+
+                       /* Disabled until non-EM DerivedMesh implementation is complete */
+
+                       /*
+                       uiDefButBitS(block, TOG, eSubsurfModifierFlag_Incremental, B_MODIFIER_RECALC, "Incremental", lx, (cy-=19),90,19,&smd->flags, 0, 0, 0, 0, "Use incremental calculation, even outside of mesh mode");
+                       uiDefButBitS(block, TOG, eSubsurfModifierFlag_DebugIncr, B_MODIFIER_RECALC, "Debug", lx+90, cy,buttonWidth-90,19,&smd->flags, 0, 0, 0, 0, "Visualize the subsurf incremental calculation, for debugging effect of other modifiers");
+                       */
+
+                       uiDefButBitS(block, TOG, eSubsurfModifierFlag_ControlEdges, B_MODIFIER_RECALC, "Optimal Draw", lx, (cy-=19), buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Skip drawing/rendering of interior subdivided edges");
+                       uiDefButBitS(block, TOG, eSubsurfModifierFlag_SubsurfUv, B_MODIFIER_RECALC, "Subsurf UV", lx, (cy-=19),buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Use subsurf to subdivide UVs");
+               } else if (md->type==eModifierType_Lattice) {
+                       LatticeModifierData *lmd = (LatticeModifierData*) md;
+                       uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
+                       but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
+                       uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+               } else if (md->type==eModifierType_Curve) {
+                       CurveModifierData *cmd = (CurveModifierData*) md;
+                       uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
+                       but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
+                       uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+                       
+                       uiDefButS(block, ROW,B_MODIFIER_RECALC,"X",             lx, (cy-=19), 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSX, 0, 0, "The axis that the curve deforms along");
+                       uiDefButS(block, ROW,B_MODIFIER_RECALC,"Y",             (lx+buttonWidth/6), cy, 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSY, 0, 0, "The axis that the curve deforms along");
+                       uiDefButS(block, ROW,B_MODIFIER_RECALC,"Z",             (lx+2*buttonWidth/6), cy, 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSZ, 0, 0, "The axis that the curve deforms along");
+                       uiDefButS(block, ROW,B_MODIFIER_RECALC,"-X",            (lx+3*buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGX, 0, 0, "The axis that the curve deforms along");
+                       uiDefButS(block, ROW,B_MODIFIER_RECALC,"-Y",            (lx+4*buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGY, 0, 0, "The axis that the curve deforms along");
+                       uiDefButS(block, ROW,B_MODIFIER_RECALC,"-Z",            (lx+buttonWidth-buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGZ, 0, 0, "The axis that the curve deforms along");
+               } else if (md->type==eModifierType_Build) {
+                       BuildModifierData *bmd = (BuildModifierData*) md;
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Start:", lx, (cy-=19), buttonWidth,19, &bmd->start, 1.0, MAXFRAMEF, 100, 0, "Specify the start frame of the effect");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:", lx, (cy-=19), buttonWidth,19, &bmd->length, 1.0, MAXFRAMEF, 100, 0, "Specify the total time the build effect requires");
+                       uiDefButI(block, TOG, B_MODIFIER_RECALC, "Randomize", lx, (cy-=19), buttonWidth,19, &bmd->randomize, 0, 0, 1, 0, "Randomize the faces or edges during build.");
+                       uiDefButI(block, NUM, B_MODIFIER_RECALC, "Seed:", lx, (cy-=19), buttonWidth,19, &bmd->seed, 1.0, MAXFRAMEF, 100, 0, "Specify the seed for random if used.");
+               } else if (md->type==eModifierType_Mirror) {
+                       MirrorModifierData *mmd = (MirrorModifierData*) md;
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Merge Limit:", lx, (cy-=19), buttonWidth,19, &mmd->tolerance, 0.0, 1.0, 10, 10, "Distance from axis within which mirrored vertices are merged");
+                       uiDefButBitS(block, TOG, MOD_MIR_AXIS_X, B_MODIFIER_RECALC, "X",        lx,(cy-=19),20,19, &mmd->flag, 0, 0, 0, 0, "Enable X axis mirror");
+                       uiDefButBitS(block, TOG, MOD_MIR_AXIS_Y, B_MODIFIER_RECALC, "Y",        lx+20,cy,20,19,    &mmd->flag, 0, 0, 0, 0, "Enable Y axis mirror");
+                       uiDefButBitS(block, TOG, MOD_MIR_AXIS_Z, B_MODIFIER_RECALC, "Z",        lx+40,cy,20,19,    &mmd->flag, 0, 0, 0, 0, "Enable Z axis mirror");
+                       uiDefButBitS(block, TOG, MOD_MIR_CLIPPING, B_MODIFIER_RECALC, "Do Clipping",    lx+60, cy, buttonWidth-60,19, &mmd->flag, 1, 2, 0, 0, "Prevents during Transform vertices to go through Mirror");
+                       uiDefButBitS(block, TOG, MOD_MIR_VGROUP, B_MODIFIER_RECALC, "Mirror Vgroups",   lx, (cy-=19), buttonWidth,19, &mmd->flag, 1, 2, 0, 0, "Mirror vertex groups (e.g. .R->.L)");
+                       uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
+                                    "Mirror U",
+                                    lx, (cy-=19), buttonWidth/2, 19,
+                                    &mmd->flag, 0, 0, 0, 0,
+                                    "Mirror the U texture coordinate around "
+                                    "the 0.5 point");
+                       uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
+                                    "Mirror V",
+                                    lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
+                                    &mmd->flag, 0, 0, 0, 0,
+                                    "Mirror the V texture coordinate around "
+                                    "the 0.5 point");
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
+                                      "Ob: ", lx, (cy -= 19), buttonWidth, 19,
+                                      &mmd->mirror_ob,
+                                      "Object to use as mirror");
+               } else if (md->type==eModifierType_Bevel) {
+                       BevelModifierData *bmd = (BevelModifierData*) md;
+                       /*uiDefButS(block, ROW, B_MODIFIER_RECALC, "Distance",
+                                         lx, (cy -= 19), (buttonWidth/2), 19, &bmd->val_flags,
+                                         11.0, 0, 0, 0,
+                                         "Interpret bevel value as a constant distance from each edge");
+                       uiDefButS(block, ROW, B_MODIFIER_RECALC, "Radius",
+                                         (lx+buttonWidth/2), cy, (buttonWidth - buttonWidth/2), 19, &bmd->val_flags,
+                                         11.0, BME_BEVEL_RADIUS, 0, 0,
+                                         "Interpret bevel value as a radius - smaller angles will be beveled more");*/
+                       uiBlockBeginAlign(block);
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
+                                         lx, (cy -= 19), buttonWidth, 19, &bmd->value,
+                                         0.0, 0.5, 5, 4,
+                                         "Bevel value/amount");
+                       /*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
+                                         lx, (cy -= 19), buttonWidth, 19, &bmd->res,
+                                         1, 4, 5, 2,
+                                         "Number of times to bevel");*/
+                       uiDefButBitS(block, TOG, BME_BEVEL_VERT,
+                                         B_MODIFIER_RECALC, "Only Vertices",
+                                         lx, (cy -= 19), buttonWidth, 19,
+                                         &bmd->flags, 0, 0, 0, 0,
+                                         "Bevel only verts/corners; not edges");
+                       uiBlockEndAlign(block);
+                                         
+                       uiDefBut(block, LABEL, 1, "Limit using:",       lx, (cy-=25), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
+                       uiBlockBeginAlign(block);
+                       uiDefButS(block, ROW, B_MODIFIER_RECALC, "None",
+                                         lx, (cy -= 19), (buttonWidth/3), 19, &bmd->lim_flags,
+                                         12.0, 0, 0, 0,
+                                         "Bevel the entire mesh by a constant amount");
+                       uiDefButS(block, ROW, B_MODIFIER_RECALC, "Angle",
+                                         (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->lim_flags,
+                                         12.0, BME_BEVEL_ANGLE, 0, 0,
+                                         "Only bevel edges with sharp enough angles between faces");
+                       uiDefButS(block, ROW, B_MODIFIER_RECALC, "BevWeight",
+                                         lx+(2*buttonWidth/3), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->lim_flags,
+                                         12.0, BME_BEVEL_WEIGHT, 0, 0,
+                                         "Use bevel weights to determine how much bevel is applied; apply them separately in vert/edge select mode");
+                       if ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT)) {
+                               uiDefButS(block, ROW, B_MODIFIER_RECALC, "Min",
+                                         lx, (cy -= 19), (buttonWidth/3), 19, &bmd->e_flags,
+                                         13.0, BME_BEVEL_EMIN, 0, 0,
+                                         "The sharpest edge's weight is used when weighting a vert");
+                               uiDefButS(block, ROW, B_MODIFIER_RECALC, "Average",
+                                         (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->e_flags,
+                                         13.0, 0, 0, 0,
+                                         "The edge weights are averaged when weighting a vert");
+                               uiDefButS(block, ROW, B_MODIFIER_RECALC, "Max",
+                                         (lx+2*(buttonWidth/3)), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->e_flags,
+                                         13.0, BME_BEVEL_EMAX, 0, 0,
+                                         "The largest edge's wieght is used when weighting a vert");
+                       }
+                       else if (bmd->lim_flags & BME_BEVEL_ANGLE) {
+                               uiDefButF(block, NUM, B_MODIFIER_RECALC, "Angle:",
+                                         lx, (cy -= 19), buttonWidth, 19, &bmd->bevel_angle,
+                                         0.0, 180.0, 100, 2,
+                                         "Angle above which to bevel edges");
+                       }
+               } else if (md->type==eModifierType_EdgeSplit) {
+                       EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
+                       uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
+                                    B_MODIFIER_RECALC, "From Edge Angle",
+                                    lx, (cy -= 19), buttonWidth, 19,
+                                    &emd->flags, 0, 0, 0, 0,
+                                    "Split edges with high angle between faces");
+                       if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
+                               uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
+                                         lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
+                                         0.0, 180.0, 100, 2,
+                                         "Angle above which to split edges");
+                       }
+                       uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
+                                    B_MODIFIER_RECALC, "From Marked As Sharp",
+                                    lx, (cy -= 19), buttonWidth, 19,
+                                    &emd->flags, 0, 0, 0, 0,
+                                    "Split edges that are marked as sharp");
+               } else if (md->type==eModifierType_Displace) {
+                       DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+                       but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
+                                      lx, (cy -= 19), buttonWidth, 19,
+                                      &dmd->defgrp_name, 0.0, 31.0, 0, 0,
+                                      "Name of vertex group to displace"
+                                      " (displace whole mesh if blank)");
+                       uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+                       uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
+                                      "Texture: ", lx, (cy -= 19), buttonWidth, 19,
+                                      &dmd->texture,
+                                      "Texture to use as displacement input");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
+                                 lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
+                                 0, 1, 10, 3,
+                                 "Material value that gives no displacement");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
+                                 lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
+                                 -1000, 1000, 10, 0.1,
+                                 "Strength of displacement");
+                       sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
+                               "Z%%x%d|Y%%x%d|X%%x%d",
+                               MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
+                               MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
+                       uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
+                                 lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
+                                 0.0, 1.0, 0, 0, "Displace direction");
+                       sprintf(str, "Texture Coordinates%%t"
+                               "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
+                               MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
+                               MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
+                       uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
+                                 lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
+                                 0.0, 1.0, 0, 0,
+                                 "Texture coordinates used for displacement input");
+                       if (dmd->texmapping == MOD_DISP_MAP_UV) {
+                               char *strtmp;
+                               int i;
+                               Mesh *me= (Mesh*)ob->data;
+                               CustomData *fdata = obedit? &me->edit_mesh->fdata: &me->fdata;
+                               build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
+                                                       dmd->uvlayer_name);
+                               but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
+                                     lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
+                                     0.0, 1.0, 0, 0, "Set the UV layer to use");
+                               MEM_freeN(strtmp);
+                               i = CustomData_get_layer_index(fdata, CD_MTFACE);
+                               uiButSetFunc(but, set_displace_uvlayer, dmd,
+                                            &fdata->layers[i]);
+                       }
+                       if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
+                               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
+                                              "Ob: ", lx, (cy -= 19), buttonWidth, 19,
+                                              &dmd->map_object,
+                                              "Object to get texture coordinates from");
+                       }
+               } else if (md->type==eModifierType_UVProject) {
+                       UVProjectModifierData *umd = (UVProjectModifierData *) md;
+                       int i;
+                       char *strtmp;
+                       Mesh *me= (Mesh*)ob->data;
+                       CustomData *fdata = obedit? &me->edit_mesh->fdata: &me->fdata;
+                       build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
+                                               umd->uvlayer_name);
+                       but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
+                             lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
+                             0.0, 1.0, 0, 0, "Set the UV layer to use");
+                       i = CustomData_get_layer_index(fdata, CD_MTFACE);
+                       uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
+                       MEM_freeN(strtmp);
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
+                                 lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
+                                 1, 1000, 100, 2,
+                                 "Horizontal Aspect Ratio");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
+                                 lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
+                                 &umd->aspecty,
+                                 1, 1000, 100, 2,
+                                 "Vertical Aspect Ratio");
+                       uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
+                                 lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
+                                 1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
+                                 "Number of objects to use as projectors");
+                       for(i = 0; i < umd->num_projectors; ++i) {
+                               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
+                                              "Ob: ", lx, (cy -= 19), buttonWidth, 19,
+                                              &umd->projectors[i],
+                                              "Object to use as projector");
+                       }
+                       uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
+                                      "Image: ", lx, (cy -= 19), buttonWidth, 19,
+                                      &umd->image,
+                                      "Image to project (only faces with this image "
+                                      "will be altered");
+                       uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
+                       uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
+                                    B_MODIFIER_RECALC, "Override Image",
+                                    lx, (cy -= 19), buttonWidth, 19,
+                                    &umd->flags, 0, 0, 0, 0,
+                                    "Override faces' current images with the "
+                                    "given image");
+               } else if (md->type==eModifierType_Decimate) {
+                       DecimateModifierData *dmd = (DecimateModifierData*) md;
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Ratio:",      lx,(cy-=19),buttonWidth,19, &dmd->percent, 0.0, 1.0, 10, 0, "Defines the percentage of triangles to reduce to");
+                       sprintf(str, "Face Count: %d", dmd->faceCount);
+                       uiDefBut(block, LABEL, 1, str,  lx, (cy-=19), 160,19, NULL, 0.0, 0.0, 0, 0, "Displays the current number of faces in the decimated mesh");
+               } else if (md->type==eModifierType_Mask) {
+                       MaskModifierData *mmd = (MaskModifierData *)md;
+                       
+                       sprintf(str, "Mask Mode%%t|Vertex Group%%x%d|Selected Bones%%x%d|",
+                               MOD_MASK_MODE_VGROUP,MOD_MASK_MODE_ARM);
+                       uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
+                               lx, (cy -= 19), buttonWidth, 19, &mmd->mode,
+                               0.0, 1.0, 0, 0, "How masking region is defined");
+                                         
+                       if (mmd->mode == MOD_MASK_MODE_ARM) {
+                               uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP,
+                                   "Ob: ", lx, (cy -= 19), buttonWidth, 19, &mmd->ob_arm,
+                                   "Armature to use as source of bones to mask");
+                       }
+                       else {
+                               but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", 
+                                       lx, (cy-=19), buttonWidth, 19, &mmd->vgroup, 
+                                       0.0, 31.0, 0, 0, "Vertex Group name");
+                               uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+                       }
+                       
+                       uiDefButBitI(block, TOG, MOD_MASK_INV, B_MODIFIER_RECALC, "Inverse",            
+                               lx, (cy-=19), buttonWidth, 19, &mmd->flag, 
+                               0, 0, 0, 0, "Use vertices that are not part of region defined");
+               } else if (md->type==eModifierType_Smooth) {
+                       SmoothModifierData *smd = (SmoothModifierData*) md;
+
+                       uiDefButBitS(block, TOG, MOD_SMOOTH_X, B_MODIFIER_RECALC, "X",          lx,(cy-=19),45,19, &smd->flag, 0, 0, 0, 0, "Enable X axis smoothing");
+                       uiDefButBitS(block, TOG, MOD_SMOOTH_Y, B_MODIFIER_RECALC, "Y",          lx+45,cy,45,19, &smd->flag, 0, 0, 0, 0, "Enable Y axis smoothing");
+                       uiDefButBitS(block, TOG, MOD_SMOOTH_Z, B_MODIFIER_RECALC, "Z",          lx+90,cy,45,19, &smd->flag, 0, 0, 0, 0, "Enable Z axis smoothing");
+
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth, 19, &smd->fac, -10.0, 10.0, 0.5, 0, "Define the amount of smoothing, from 0.0 to 1.0 (lower / higher values can deform the mesh)");
+                       uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
+                       but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &smd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to define which vertices are affected");
+               } else if (md->type==eModifierType_Cast) {
+                       CastModifierData *cmd = (CastModifierData*) md;
+
+                       char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
+                       uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
+                       uiDefButBitS(block, TOG, MOD_CAST_X, B_MODIFIER_RECALC, "X",            lx,(cy-=19),45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) X axis deformation");
+                       uiDefButBitS(block, TOG, MOD_CAST_Y, B_MODIFIER_RECALC, "Y",            lx+45,cy,45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) Y axis deformation");
+                       if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
+                               uiDefButBitS(block, TOG, MOD_CAST_Z, B_MODIFIER_RECALC, "Z",            lx+90,cy,45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) Z axis deformation");
+                       }
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth, 19, &cmd->fac, -10.0, 10.0, 5, 0, "Define the amount of deformation");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Radius:",     lx,(cy-=19),buttonWidth, 19, &cmd->radius, 0.0, 100.0, 10.0, 0, "Only deform vertices within this distance from the center of the effect (leave as 0 for infinite)");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Size:",       lx,(cy-=19),buttonWidth, 19, &cmd->size, 0.0, 100.0, 10.0, 0, "Size of projection shape (leave as 0 for auto)");
+                       uiDefButBitS(block, TOG, MOD_CAST_SIZE_FROM_RADIUS, B_MODIFIER_RECALC, "From radius",           lx+buttonWidth,cy,80,19, &cmd->flag, 0, 0, 0, 0, "Use radius as size of projection shape (0 = auto)");
+                       if (ob->type == OB_MESH) {
+                               but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to define which vertices are affected");
+                       }
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx,(cy-=19), buttonWidth,19, &cmd->object, "Control object: if available, its location determines the center of the effect");
+                       if(cmd->object) {
+                               uiDefButBitS(block, TOG, MOD_CAST_USE_OB_TRANSFORM, B_MODIFIER_RECALC, "Use transform",         lx+buttonWidth,cy,80,19, &cmd->flag, 0, 0, 0, 0, "Use object transform to control projection shape");
+                       }
+               } else if (md->type==eModifierType_Wave) {
+                       WaveModifierData *wmd = (WaveModifierData*) md;
+                       uiDefButBitS(block, TOG, MOD_WAVE_X, B_MODIFIER_RECALC, "X",            lx,(cy-=19),45,19, &wmd->flag, 0, 0, 0, 0, "Enable X axis motion");
+                       uiDefButBitS(block, TOG, MOD_WAVE_Y, B_MODIFIER_RECALC, "Y",            lx+45,cy,45,19, &wmd->flag, 0, 0, 0, 0, "Enable Y axis motion");
+                       uiDefButBitS(block, TOG, MOD_WAVE_CYCL, B_MODIFIER_RECALC, "Cycl",      lx+90,cy,buttonWidth-90,19, &wmd->flag, 0, 0, 0, 0, "Enable cyclic wave effect");
+                       uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
+                       if (wmd->flag & MOD_WAVE_NORM){
+                               if (ob->type==OB_MESH) {
+                                       uiDefButBitS(block, TOG, MOD_WAVE_NORM_X, B_MODIFIER_RECALC, "X",       lx,(cy-=19),buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the X normal");
+                                       uiDefButBitS(block, TOG, MOD_WAVE_NORM_Y, B_MODIFIER_RECALC, "Y",       lx+(buttonWidth/3),cy,buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the Y normal");
+                                       uiDefButBitS(block, TOG, MOD_WAVE_NORM_Z, B_MODIFIER_RECALC, "Z",       lx+(buttonWidth/3)*2,cy,buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the Z normal");
+                               }
+                               else
+                                       uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
+                       }
+
+                       uiBlockBeginAlign(block);
+                       if(wmd->speed >= 0)
+                               uiDefButF(block, NUM, B_MODIFIER_RECALC, "Time sta:",   lx,(cy-=19),buttonWidth,19, &wmd->timeoffs, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify starting frame of the wave");
+                       else
+                               uiDefButF(block, NUM, B_MODIFIER_RECALC, "Time end:",   lx,(cy-=19),buttonWidth,19, &wmd->timeoffs, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify ending frame of the wave");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff:",    lx,(cy-=19),buttonWidth,19, &wmd->falloff,  0, 100, 100, 0, "Specify the falloff radius of the waves");
+
+                       cy -= 9;
+                       uiBlockBeginAlign(block);
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Sta x:",              lx,(cy-=19),113,19, &wmd->startx, -100.0, 100.0, 100, 0, "Starting position for the X axis");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Sta y:",              lx+115,cy,105,19, &wmd->starty, -100.0, 100.0, 100, 0, "Starting position for the Y axis");
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MODIFIER_RECALC, "Ob: ", lx, (cy-=19), 220,19, &wmd->objectcenter, "Object to use as Starting Position (leave blank to disable)");
+                       uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",lx, (cy -= 19), 220, 19,&wmd->defgrp_name, 0.0, 31.0, 0, 0, "Name of vertex group with which to modulate displacement");
+                       uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
+                       sprintf(str, "Texture Coordinates%%t"
+                               "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
+                               MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
+                               MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
+                       uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
+                                 lx, (cy -= 19), 220, 19, &wmd->texmapping,
+                                 0.0, 1.0, 0, 0,
+                                 "Texture coordinates used for modulation input");
+                       if (wmd->texmapping == MOD_WAV_MAP_UV) {
+                               char *strtmp;
+                               int i;
+                               Mesh *me = (Mesh*)ob->data;
+                               CustomData *fdata = obedit? &me->edit_mesh->fdata: &me->fdata;
+                               build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
+                                                       wmd->uvlayer_name);
+                               but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
+                                     lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
+                                     0.0, 1.0, 0, 0, "Set the UV layer to use");
+                               MEM_freeN(strtmp);
+                               i = CustomData_get_layer_index(fdata, CD_MTFACE);
+                               uiButSetFunc(but, set_wave_uvlayer, wmd,
+                                            &fdata->layers[i]);
+                       }
+                       if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
+                               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
+                                              "Ob: ", lx, (cy -= 19), 220, 19,
+                                              &wmd->map_object,
+                                              "Object to get texture coordinates from");
+                       }
+                       cy -= 9;
+                       uiBlockBeginAlign(block);
+                       uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
+                       uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Height:",  lx,(cy-=19),220,19, &wmd->height, -2.0, 2.0, 0, 0, "Specify the amplitude of the wave");
+                       uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Width:",   lx,(cy-=19),220,19, &wmd->width, 0.0, 5.0, 0, 0, "Specify the width of the wave");
+                       uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Narrow:",  lx,(cy-=19),220,19, &wmd->narrow, 0.0, 10.0, 0, 0, "Specify how narrow the wave follows");
+               } else if (md->type==eModifierType_Hook) {
+                       HookModifierData *hmd = (HookModifierData*) md;
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff: ",           lx, (cy-=19), buttonWidth,19, &hmd->falloff, 0.0, 100.0, 100, 0, "If not zero, the distance from hook where influence ends");
+                       uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Force: ",          lx, (cy-=19), buttonWidth,19, &hmd->force, 0.0, 1.0, 100, 0, "Set relative force of hook");
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &hmd->object, "Parent Object for hook, also recalculates and clears offset"); 
+                       if(hmd->indexar==NULL) {
+                               but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
+                               uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+                       }
+                       uiBlockBeginAlign(block);
+                       but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Reset",          lx, (cy-=19), 80,19,                    NULL, 0.0, 0.0, 0, 0, "Recalculate and clear offset (transform) of hook");
+                       uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
+                       but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Recenter",       lx+80, cy, buttonWidth-80,19,   NULL, 0.0, 0.0, 0, 0, "Sets hook center to cursor position");
+                       uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
+
+                       if (editing) {
+                               but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Select",                 lx, (cy-=19), 80,19, NULL, 0.0, 0.0, 0, 0, "Selects effected vertices on mesh");
+                               uiButSetFunc(but, modifiers_selectHook, ob, md);
+                               but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Reassign",               lx+80, cy, buttonWidth-80,19, NULL, 0.0, 0.0, 0, 0, "Reassigns selected vertices to hook");
+                               uiButSetFunc(but, modifiers_reassignHook, ob, md);
+                       }
+               } else if (md->type==eModifierType_Softbody) {
+                       uiDefBut(block, LABEL, 1, "See Soft Body panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
+               } else if (md->type==eModifierType_Cloth) {
+                       uiDefBut(block, LABEL, 1, "See Cloth panel.",   lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
+
+               } else if (md->type==eModifierType_Collision) {
+                       uiDefBut(block, LABEL, 1, "See Collision panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
+               } else if (md->type==eModifierType_Surface) {
+                       uiDefBut(block, LABEL, 1, "See Fields panel.",  lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
+               } else if (md->type==eModifierType_Fluidsim) {
+                       uiDefBut(block, LABEL, 1, "See Fluidsim panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
+               } else if (md->type==eModifierType_Boolean) {
+                       BooleanModifierData *bmd = (BooleanModifierData*) md;
+                       uiDefButI(block, MENU, B_MODIFIER_RECALC, "Operation%t|Intersect%x0|Union%x1|Difference%x2",    lx,(cy-=19),buttonWidth,19, &bmd->operation, 0.0, 1.0, 0, 0, "Boolean operation to perform");
+                       uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
+               } else if (md->type==eModifierType_Array) {
+                       ArrayModifierData *amd = (ArrayModifierData*) md;
+                       float range = 10000;
+                       int cytop, halfwidth = (width - 5)/2 - 15;
+                       int halflx = lx + halfwidth + 10;
+
+                       // XXX uiBlockSetEmboss(block, UI_EMBOSSX);
+                       uiBlockEndAlign(block);
+
+                       /* length parameters */
+                       uiBlockBeginAlign(block);
+                       sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
+                               "|Fit To Curve Length%%x%d",
+                               MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
+                       uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
+                                 lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
+                                 0.0, 1.0, 0, 0, "Array length calculation method");
+                       switch(amd->fit_type)
+                       {
+                       case MOD_ARR_FIXEDCOUNT:
+                               uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
+                                         lx, (cy -= 19), buttonWidth, 19, &amd->count,
+                                         1, 1000, 0, 0, "Number of duplicates to make");
+                               break;
+                       case MOD_ARR_FITLENGTH:
+                               uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
+                                         lx, (cy -= 19), buttonWidth, 19, &amd->length,
+                                         0, range, 10, 2,
+                                         "Length to fit array within");
+                               break;
+                       case MOD_ARR_FITCURVE:
+                               uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
+                                              B_CHANGEDEP, "Ob: ",
+                                              lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
+                                              "Curve object to fit array length to");
+                               break;
+                       }
+                       uiBlockEndAlign(block);
+
+                       /* offset parameters */
+                       cy -= 10;
+                       cytop= cy;
+                       uiBlockBeginAlign(block);
+                       uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
+                                    "Constant Offset", lx, (cy-=19), halfwidth, 19,
+                                    &amd->offset_type, 0, 0, 0, 0,
+                                    "Constant offset between duplicates "
+                                    "(local coordinates)");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
+                                 lx, (cy-=19), halfwidth, 19,
+                                 &amd->offset[0],
+                                 -range, range, 10, 3,
+                                 "Constant component for duplicate offsets "
+                                 "(local coordinates)");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
+                                 lx, (cy-=19), halfwidth, 19,
+                                 &amd->offset[1],
+                                 -range, range, 10, 3,
+                                 "Constant component for duplicate offsets "
+                                 "(local coordinates)");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
+                                 lx, (cy-=19), halfwidth, 19,
+                                 &amd->offset[2],
+                                 -range, range, 10, 3,
+                                 "Constant component for duplicate offsets "
+                                 "(local coordinates)");
+                       uiBlockEndAlign(block);
+
+                       cy= cytop;
+                       uiBlockBeginAlign(block);
+                       uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
+                                    "Relative Offset", halflx, (cy-=19), halfwidth, 19,
+                                    &amd->offset_type, 0, 0, 0, 0,
+                                    "Offset between duplicates relative to object width "
+                                    "(local coordinates)");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
+                                 halflx, (cy-=19), halfwidth, 19,
+                                 &amd->scale[0],
+                                 -range, range, 10, 3,
+                                 "Component for duplicate offsets relative to object "
+                                 "width (local coordinates)");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
+                                 halflx, (cy-=19), halfwidth, 19,
+                                 &amd->scale[1],
+                                 -range, range, 10, 3,
+                                 "Component for duplicate offsets relative to object "
+                                 "width (local coordinates)");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
+                                 halflx, (cy-=19), halfwidth, 19,
+                                 &amd->scale[2],
+                                 -range, range, 10, 3,
+                                 "Component for duplicate offsets relative to object "
+                                 "width (local coordinates)");
+                       uiBlockEndAlign(block);
+
+                       /* vertex merging parameters */
+                       cy -= 10;
+                       cytop= cy;
+
+                       uiBlockBeginAlign(block);
+                       uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
+                                    "Merge",
+                                    lx, (cy-=19), halfwidth/2, 19, &amd->flags,
+                                    0, 0, 0, 0,
+                                    "Merge vertices in adjacent duplicates");
+                       uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
+                                    "First Last",
+                                    lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
+                                    &amd->flags,
+                                    0, 0, 0, 0,
+                                    "Merge vertices in first duplicate with vertices"
+                                    " in last duplicate");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
+                                         lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
+                                         0, 1.0f, 1, 4,
+                                         "Limit below which to merge vertices");
+
+                       /* offset ob */
+                       cy = cytop;
+                       uiBlockBeginAlign(block);
+                       uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
+                                    "Object Offset", halflx, (cy -= 19), halfwidth, 19,
+                                    &amd->offset_type, 0, 0, 0, 0,
+                                    "Add an object transformation to the total offset");
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
+                                      "Ob: ", halflx, (cy -= 19), halfwidth, 19,
+                                      &amd->offset_ob,
+                                      "Object from which to take offset transformation");
+                       uiBlockEndAlign(block);
+
+                       cy -= 10;
+                       but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
+                                            B_CHANGEDEP, "Start cap: ",
+                                            lx, (cy -= 19), halfwidth, 19,
+                                            &amd->start_cap,
+                                            "Mesh object to use as start cap");
+                       uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
+                       but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
+                                            B_CHANGEDEP, "End cap: ",
+                                            halflx, cy, halfwidth, 19,
+                                            &amd->end_cap,
+                                            "Mesh object to use as end cap");
+                       uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
+               } else if (md->type==eModifierType_MeshDeform) {
+                       MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
+
+                       uiBlockBeginAlign(block);
+                       uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage"); 
+                       but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-19), buttonWidth-40,19, &mmd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall meshdeform influence");
+                       uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+                       uiDefButBitS(block, TOG, MOD_MDEF_INVERT_VGROUP, B_MODIFIER_RECALC, "Inv", lx+buttonWidth-40, (cy-=19), 40,19, &mmd->flag, 0.0, 31.0, 0, 0, "Invert vertex group influence");
+
+                       uiBlockBeginAlign(block);
+                       if(mmd->bindcos) {
+                               but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
+                               uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
+                       }
+                       else {
+                               but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
+                               uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
+                               uiDefButS(block, NUM, B_NOP, "Precision:", lx,(cy-19), buttonWidth/2 + 20,19, &mmd->gridsize, 2, 10, 0.5, 0, "The grid size for binding");
+                               uiDefButBitS(block, TOG, MOD_MDEF_DYNAMIC_BIND, B_MODIFIER_RECALC, "Dynamic", lx+(buttonWidth+1)/2 + 20, (cy-=19), buttonWidth/2 - 20,19, &mmd->flag, 0.0, 31.0, 0, 0, "Recompute binding dynamically on top of other deformers like Shape Keys (slower and more memory consuming!)");
+                       }
+                       uiBlockEndAlign(block);
+               } else if (md->type==eModifierType_ParticleSystem) {
+                       uiDefBut(block, LABEL, 1, "See Particle buttons.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
+               } else if (md->type==eModifierType_ParticleInstance) {
+                       ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
+                       uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Parents, B_MODIFIER_RECALC, "Normal",    lx, (cy -= 19), buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances from normal particles");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Children, B_MODIFIER_RECALC, "Children", lx+buttonWidth/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances from child particles");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Path, B_MODIFIER_RECALC, "Path", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances along particle paths");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Unborn, B_MODIFIER_RECALC, "Unborn",     lx, (cy -= 19), buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are unborn");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Alive, B_MODIFIER_RECALC, "Alive",       lx+buttonWidth/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are alive");
+                       uiDefButBitS(block, TOG, eParticleInstanceFlag_Dead, B_MODIFIER_RECALC, "Dead", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are dead");
+               } else if (md->type==eModifierType_Explode) {
+                       ExplodeModifierData *emd = (ExplodeModifierData*) md;
+                       uiBut *but;
+                       char *menustr= NULL; /* XXX get_vertexgroup_menustr(ob); */
+                       int defCount=BLI_countlist(&ob->defbase);
+                       if(defCount==0) emd->vgroup=0;
+                       uiBlockBeginAlign(block);
+                       but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr,  lx, (cy-=19), buttonWidth-20,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
+                       uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
+                       MEM_freeN(menustr);
+                       
+                       but=uiDefIconBut(block, BUT, B_MODIFIER_RECALC, ICON_X, (lx+buttonWidth)-20, cy, 20,19, 0, 0, 0, 0, 0, "Disable use of vertex group");
+                       uiButSetFunc(but, modifiers_explodeDelVg, (void *)emd, (void *)NULL);
+                       
+
+                       but=uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "",     lx, (cy-=19), buttonWidth,19, &emd->protect, 0.0f, 1.0f, 0, 0, "Clean vertex group edges");
+                       uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
+
+                       but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh",  lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
+                       uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
+
+                       uiDefButBitS(block, TOG, eExplodeFlag_EdgeSplit, B_MODIFIER_RECALC, "Split Edges",      lx+buttonWidth/2, cy, buttonWidth/2,19, &emd->flag, 0, 0, 0, 0, "Split face edges for nicer shrapnel");
+                       uiDefButBitS(block, TOG, eExplodeFlag_Unborn, B_MODIFIER_RECALC, "Unborn",      lx, (cy-=19), buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are unborn");
+                       uiDefButBitS(block, TOG, eExplodeFlag_Alive, B_MODIFIER_RECALC, "Alive",        lx+buttonWidth/3, cy, buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are alive");
+                       uiDefButBitS(block, TOG, eExplodeFlag_Dead, B_MODIFIER_RECALC, "Dead",  lx+buttonWidth*2/3, cy, buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are dead");
+                       uiBlockEndAlign(block);
+               } else if (md->type==eModifierType_Shrinkwrap) {
+                       ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
+
+                       char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|projection %x1|nearest vertex %x2";
+
+                       uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &smd->target, "Target to shrink to");
+
+                       but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
+                       uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Offset:",     lx,(cy-=19),buttonWidth,19, &smd->keepDist, 0.0f, 100.0f, 1.0f, 0, "Specify distance to keep from the target");
+
+                       cy -= 3;
+                       uiDefButS(block, MENU, B_MODIFIER_RECALC, shrinktypemenu, lx,(cy-=19),buttonWidth,19, &smd->shrinkType, 0, 0, 0, 0, "Selects type of shrinkwrap algorithm for target position.");
+
+                       uiDefButC(block, NUM, B_MODIFIER_RECALC, "SS Levels:",          lx, (cy-=19), buttonWidth,19, &smd->subsurfLevels, 0, 6, 0, 0, "This indicates the number of CCSubdivisions that must be performed before extracting vertexs positions and normals");
+
+                       if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT){
+
+
+                               /* UI for projection axis */
+                               uiBlockBeginAlign(block);
+                               uiDefButC(block, ROW, B_MODIFIER_RECALC, "Normal"    , lx,(cy-=19),buttonWidth,19, &smd->projAxis, 18.0, MOD_SHRINKWRAP_PROJECT_OVER_NORMAL, 0, 0, "Projection over X axis");
+
+                               uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS, B_MODIFIER_RECALC, "X",    lx+buttonWidth/3*0,(cy-=19),buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over X axis");
+                               uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS, B_MODIFIER_RECALC, "Y",    lx+buttonWidth/3*1,cy,buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over Y axis");
+                               uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS, B_MODIFIER_RECALC, "Z",    lx+buttonWidth/3*2,cy,buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over Z axis");
+
+
+                               /* allowed directions of projection axis */
+                               uiDefButBitS(block, TOG, MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR, B_MODIFIER_RECALC, "Negative",   lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows to move the vertex in the negative direction of axis");
+                               uiDefButBitS(block, TOG, MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR, B_MODIFIER_RECALC, "Positive",   lx + buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows to move the vertex in the positive direction of axis");
+
+                               uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE, B_MODIFIER_RECALC, "Cull frontfaces",lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Controls whether a vertex can be projected to a front face on target");
+                               uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_BACKFACE,  B_MODIFIER_RECALC, "Cull backfaces",     lx+buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Controls whether a vertex can be projected to a back face on target");
+                               uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob2: ",        lx, (cy-=19), buttonWidth,19, &smd->auxTarget, "Aditional mesh to project over");
+                       }
+                       else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE){
+                               uiDefButBitS(block, TOG, MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE, B_MODIFIER_RECALC, "Above surface", lx,(cy-=19),buttonWidth,19, &smd->shrinkOpts, 0, 0, 0, 0, "Vertices are kept on the front side of faces");
+                       }
+
+                       uiBlockEndAlign(block);
+
+               } else if (md->type==eModifierType_SimpleDeform) {
+                       SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
+                       char simpledeform_modemenu[] = "Deform type%t|Twist %x1|Bend %x2|Taper %x3|Strech %x4";
+
+                       uiDefButC(block, MENU, B_MODIFIER_RECALC, simpledeform_modemenu, lx,(cy-=19),buttonWidth,19, &smd->mode, 0, 0, 0, 0, "Selects type of deform to apply to object.");
+                       
+                       but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
+                       uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+
+                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &smd->origin, "Origin of modifier space coordinates");
+                       if(smd->origin != NULL)
+                               uiDefButBitC(block, TOG, MOD_SIMPLEDEFORM_ORIGIN_LOCAL, B_MODIFIER_RECALC, "Relative",lx,(cy-=19),buttonWidth,19, &smd->originOpts, 0, 0, 0, 0, "Sets the origin of deform space to be relative to the object");
+
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth,19, &smd->factor, -10.0f, 10.0f, 0.5f, 0, "Deform Factor");
+
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Upper Limit:",        lx,(cy-=19),buttonWidth,19, &smd->limit[1], 0.0f, 1.0f, 5.0f, 0, "Upper Limit for deform");
+                       uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lower Limit:",        lx,(cy-=19),buttonWidth,19, &smd->limit[0], 0.0f, 1.0f, 5.0f, 0, "Lower Limit for deform");
+
+                       if(smd->mode == MOD_SIMPLEDEFORM_MODE_STRETCH
+                       || smd->mode == MOD_SIMPLEDEFORM_MODE_TAPER  )
+                       {
+                               uiDefButBitC(block, TOG, MOD_SIMPLEDEFORM_LOCK_AXIS_X, B_MODIFIER_RECALC, "Loc X", lx,             (cy-=19),buttonWidth/2,19, &smd->axis, 0, 0, 0, 0, "Disallow changes on the X coordinate");
+                               uiDefButBitC(block, TOG, MOD_SIMPLEDEFORM_LOCK_AXIS_Y, B_MODIFIER_RECALC, "Loc Y", lx+(buttonWidth/2), (cy),buttonWidth/2,19, &smd->axis, 0, 0, 0, 0, "Disallow changes on the Y coordinate");
+                       }
+               }
+
+               uiBlockEndAlign(block);
+       }
+
+       if (md->error) {
+
+               row = uiLayoutRow(uiLayoutBox(column), 0);
+
+               /* XXX uiBlockSetCol(block, color); */
+               uiItemL(row, md->error, ICON_ERROR);
+               /* XXX uiBlockSetCol(block, TH_AUTO); */
+       }
+
+       return result;
+}
+
+uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+       Object *ob;
+       ModifierData *md, *vmd;
+       int i, lastCageIndex, cageIndex;
+
+       /* verify we have valid data */
+       if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
+               printf("uiTemplateModifier: expected modifier on object.\n");
+               return NULL;
+       }
+
+       ob= ptr->id.data;
+       md= ptr->data;
+
+       if(!ob || !(GS(ob->id.name) == ID_OB)) {
+               printf("uiTemplateModifier: expected modifier on object.\n");
+               return NULL;
+       }
+       
+       uiBlockSetButLock(uiLayoutBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
+       
+       /* find modifier and draw it */
+       cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
+
+       // XXX virtual modifiers are not accesible for python
+       vmd = modifiers_getVirtualModifierList(ob);
+
+       for(i=0; vmd; i++, vmd=vmd->next) {
+               if(md == vmd)
+                       return draw_modifier(C, layout, ob, md, i, cageIndex, lastCageIndex);
+               else if(vmd->mode&eModifierMode_Virtual)
+                       i--;
+       }
+
+       return NULL;
+}
+
index 18b39518ee673fea087922b849341f76bb9a36c6..c243b6abdbc58646b2ab95f103f3514d103efa08 100644 (file)
@@ -1818,7 +1818,6 @@ void ui_draw_but(ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
                                break;
                                
                        case PULLDOWN:
-                       case HMENU:
                                wt= widget_type(UI_WTYPE_PULLDOWN);
                                break;
                        
index cf61c16fbe4944ee90aa5b868107b12cd35f551f..15ace3b02b17bdfaa250858ef9225ce4a05c5691 100644 (file)
@@ -203,21 +203,6 @@ void ED_base_object_activate(bContext *C, Base *base)
 }
 
 
-/*
- * Returns true if the Object data is a from an external blend file (libdata)
- */
-int object_data_is_libdata(Object *ob)
-{
-       if (!ob) return 0;
-       if (ob->proxy) return 0;
-       if (ob->id.lib) return 1;
-       if (!ob->data) return 0;
-       if (((ID *)ob->data)->lib) return 1;
-       return 0;
-}
-
-
-
 /* exported */
 void ED_object_base_init_from_view(bContext *C, Base *base)
 {
index b430cdd67bc6f16e85a8e82ed913111dc9a0700c..04bcc4e37175fa868e618108a758951ca0672c99 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "MEM_guardedalloc.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
 #include "BLI_listbase.h"
 
+#include "BKE_curve.h"
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
 #include "BKE_modifier.h"
+#include "BKE_report.h"
+#include "BKE_object.h"
+#include "BKE_particle.h"
+#include "BKE_utildefines.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
 
 #include "object_intern.h"
 
-/********************* add modifier operator ********************/
+/******************************** API ****************************/
+
+int ED_object_modifier_delete(ReportList *reports, Object *ob, ModifierData *md)
+{
+       ModifierData *obmd;
+
+       /* It seems on rapid delete it is possible to
+        * get called twice on same modifier, so make
+        * sure it is in list. */
+       for (obmd=ob->modifiers.first; obmd; obmd=obmd->next)
+               if (obmd==md)
+                       break;
+       
+       if (!obmd)
+               return 0;
+
+       if(md->type == eModifierType_ParticleSystem) {
+               ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
+
+               BLI_remlink(&ob->particlesystem, psmd->psys);
+               psys_free(ob, psmd->psys);
+       }
+
+       BLI_remlink(&ob->modifiers, md);
+
+       modifier_free(md);
+
+       return 1;
+}
+
+int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
+{
+       if(md->prev) {
+               ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+               if(mti->type!=eModifierTypeType_OnlyDeform) {
+                       ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
+
+                       if(nmti->flags&eModifierTypeFlag_RequiresOriginalData)
+                               BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data.");
+                               return 0;
+               }
+
+               BLI_remlink(&ob->modifiers, md);
+               BLI_insertlink(&ob->modifiers, md->prev->prev, md);
+       }
+
+       return 1;
+}
+
+int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md)
+{
+       if(md->next) {
+               ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+               if(mti->flags&eModifierTypeFlag_RequiresOriginalData) {
+                       ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
+
+                       if(nmti->type!=eModifierTypeType_OnlyDeform) {
+                               BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier.");
+                               return 0;
+                       }
+               }
+
+               BLI_remlink(&ob->modifiers, md);
+               BLI_insertlink(&ob->modifiers, md->next, md);
+       }
+
+       return 1;
+}
+
+int ED_object_modifier_convert(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
+{
+       Object *obn;
+       ParticleSystem *psys;
+       ParticleCacheKey *key, **cache;
+       ParticleSettings *part;
+       Mesh *me;
+       MVert *mvert;
+       MEdge *medge;
+       int a, k, kmax;
+       int totvert=0, totedge=0, cvert=0;
+       int totpart=0, totchild=0;
+
+       if(md->type != eModifierType_ParticleSystem) return 0;
+       if(G.f & G_PARTICLEEDIT) return 0;
+
+       psys=((ParticleSystemModifierData *)md)->psys;
+       part= psys->part;
+
+       if(part->draw_as == PART_DRAW_GR || part->draw_as == PART_DRAW_OB) {
+               ; // XXX make_object_duplilist_real(NULL);
+       }
+       else {
+               if(part->draw_as != PART_DRAW_PATH || psys->pathcache == 0)
+                       return 0;
+
+               totpart= psys->totcached;
+               totchild= psys->totchildcache;
+
+               if(totchild && (part->draw&PART_DRAW_PARENT)==0)
+                       totpart= 0;
+
+               /* count */
+               cache= psys->pathcache;
+               for(a=0; a<totpart; a++) {
+                       key= cache[a];
+                       totvert+= key->steps+1;
+                       totedge+= key->steps;
+               }
+
+               cache= psys->childcache;
+               for(a=0; a<totchild; a++) {
+                       key= cache[a];
+                       totvert+= key->steps+1;
+                       totedge+= key->steps;
+               }
+
+               if(totvert==0) return 0;
+
+               /* add new mesh */
+               obn= add_object(scene, OB_MESH);
+               me= obn->data;
+               
+               me->totvert= totvert;
+               me->totedge= totedge;
+               
+               me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
+               me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
+               me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
+               
+               mvert= me->mvert;
+               medge= me->medge;
+
+               /* copy coordinates */
+               cache= psys->pathcache;
+               for(a=0; a<totpart; a++) {
+                       key= cache[a];
+                       kmax= key->steps;
+                       for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
+                               VECCOPY(mvert->co,key->co);
+                               if(k) {
+                                       medge->v1= cvert-1;
+                                       medge->v2= cvert;
+                                       medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
+                                       medge++;
+                               }
+                       }
+               }
+
+               cache=psys->childcache;
+               for(a=0; a<totchild; a++) {
+                       key=cache[a];
+                       kmax=key->steps;
+                       for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
+                               VECCOPY(mvert->co,key->co);
+                               if(k) {
+                                       medge->v1=cvert-1;
+                                       medge->v2=cvert;
+                                       medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
+                                       medge++;
+                               }
+                       }
+               }
+       }
+
+       DAG_scene_sort(scene);
+
+       return 1;
+}
+
+int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
+{
+       DerivedMesh *dm;
+       Mesh *me = ob->data;
+       int converted = 0;
+
+       if (scene->obedit) {
+               BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in editmode");
+               return 0;
+       } else if (((ID*) ob->data)->us>1) {
+               BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
+               return 0;
+       }
+
+       if (md!=ob->modifiers.first)
+               BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected.");
+
+       if (ob->type==OB_MESH) {
+               if(me->key) {
+                       BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to Mesh with Shape Keys");
+                       return 0;
+               }
+       
+               mesh_pmv_off(ob, me);
+       
+               dm = mesh_create_derived_for_modifier(scene, ob, md);
+               if (!dm) {
+                       BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
+                       return 0;
+               }
+
+               DM_to_mesh(dm, me);
+               converted = 1;
+
+               dm->release(dm);
+       } 
+       else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
+               ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+               Curve *cu = ob->data;
+               int numVerts;
+               float (*vertexCos)[3];
+
+               BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tesselated/bevel vertices");
+
+               if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) {
+                       BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
+                       return 0;
+               }
+
+               vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
+               mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
+               curve_applyVertexCos(cu, &cu->nurb, vertexCos);
+
+               converted = 1;
+
+               MEM_freeN(vertexCos);
+
+               DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       }
+       else {
+               BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
+               return 0;
+       }
+
+       if (converted) {
+               BLI_remlink(&ob->modifiers, md);
+               modifier_free(md);
+
+               return 1;
+       }
+
+       return 0;
+}
+
+int ED_object_modifier_copy(ReportList *reports, Object *ob, ModifierData *md)
+{
+       ModifierData *nmd;
+       
+       nmd = modifier_new(md->type);
+       modifier_copyData(md, nmd);
+       BLI_insertlink(&ob->modifiers, md, nmd);
+
+       return 1;
+}
+
+/***************************** OPERATORS ****************************/
+
+/************************ add modifier operator *********************/
 
 static int modifier_add_exec(bContext *C, wmOperator *op)
 {
@@ -96,3 +367,76 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot)
        RNA_def_enum(ot->srna, "type", modifier_type_items, 0, "Type", "");
 }
 
+#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;
+} MenuEntry;
+
+static int menuEntry_compare_names(const void *entry1, const void *entry2)
+{
+       return strcmp(((MenuEntry *)entry1)->name, ((MenuEntry *)entry2)->name);
+}
+
+static uiBlock *modifiers_add_menu(void *ob_v)
+{
+       Object *ob = ob_v;
+       uiBlock *block;
+       int i, yco=0;
+       int numEntries = 0;
+       MenuEntry entries[NUM_MODIFIER_TYPES];
+       
+       block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu",
+                         UI_EMBOSSP, UI_HELV, curarea->win);
+       uiBlockSetButmFunc(block, modifiers_add, ob);
+
+       for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
+               ModifierTypeInfo *mti = modifierType_getInfo(i);
+
+               /* Only allow adding through appropriate other interfaces */
+               if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
+               
+               if(ELEM4(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Surface, eModifierType_Fluidsim)) continue;
+
+               if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
+                  (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
+                       entries[numEntries].name = mti->name;
+                       entries[numEntries].ID = i;
+
+                       ++numEntries;
+               }
+       }
+
+       qsort(entries, numEntries, sizeof(*entries), menuEntry_compare_names);
+
+
+       for(i = 0; i < numEntries; ++i)
+               uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name,
+                        0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, "");
+
+       uiTextBoundsBlock(block, 50);
+       uiBlockSetDirection(block, UI_DOWN);
+
+       return block;
+}
+#endif
+
index fb284aab99f446c26dac9ffde5e8b0e559413e96..dad02b2fadd7073e9f61964962f44f46b4582a3d 100644 (file)
@@ -650,6 +650,7 @@ const char *RNA_property_ui_description(PropertyRNA *prop)
 
 int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
 {
+       ID *id;
        int flag;
 
        prop= rna_ensure_property(prop);
@@ -658,8 +659,10 @@ int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
                flag= prop->editable(ptr);
        else
                flag= prop->flag;
+       
+       id= ptr->id.data;
 
-       return (flag & PROP_EDITABLE);
+       return (flag & PROP_EDITABLE) && (!id || !id->lib);
 }
 
 int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
index 3263c6d4bfc6cd4255d3a2f9bfc0929109decfb0..db07ac6865526f5da0a20c8874f6375515473602 100644 (file)
 #include "WM_types.h"
 
 EnumPropertyItem modifier_type_items[] ={
-       {eModifierType_Subsurf, "SUBSURF", "Subsurf", ""},
-       {eModifierType_Lattice, "LATTICE", "Lattice", ""},
-       {eModifierType_Curve, "CURVE", "Curve", ""},
-       {eModifierType_Build, "BUILD", "Build", ""},
-       {eModifierType_Mirror, "MIRROR", "Mirror", ""},
-       {eModifierType_Decimate, "DECIMATE", "Decimate", ""},
-       {eModifierType_Wave, "WAVE", "Wave", ""},
        {eModifierType_Armature, "ARMATURE", "Armature", ""},
-       {eModifierType_Hook, "HOOK", "Hook", ""},
-       {eModifierType_Softbody, "SOFTBODY", "Softbody", ""},
-       {eModifierType_Boolean, "BOOLEAN", "Boolean", ""},
        {eModifierType_Array, "ARRAY", "Array", ""},
-       {eModifierType_EdgeSplit, "EDGE_SPLIT", "Edge Split", ""},
-       {eModifierType_Displace, "DISPLACE", "Displace", ""},
-       {eModifierType_UVProject, "UV_PROJECT", "UV Project", ""},
-       {eModifierType_Smooth, "SMOOTH", "Smooth", ""},
+       {eModifierType_Bevel, "BEVEL", "Bevel", ""},
+       {eModifierType_Boolean, "BOOLEAN", "Boolean", ""},
+       {eModifierType_Build, "BUILD", "Build", ""},
        {eModifierType_Cast, "CAST", "Cast", ""},
-       {eModifierType_MeshDeform, "MESH_DEFORM", "Mesh Deform", ""},
-       {eModifierType_ParticleSystem, "PARTICLE_SYSTEM", "Particle System", ""},
-       {eModifierType_ParticleInstance, "PARTICLE_INSTANCE", "Particle Instance", ""},
-       {eModifierType_Explode, "EXPLODE", "Explode", ""},
        {eModifierType_Cloth, "CLOTH", "Cloth", ""},
        {eModifierType_Collision, "COLLISION", "Collision", ""},
-       {eModifierType_Bevel, "BEVEL", "Bevel", ""},
-       {eModifierType_Shrinkwrap, "SHRINKWRAP", "Shrinkwrap", ""},
+       {eModifierType_Curve, "CURVE", "Curve", ""},
+       {eModifierType_Decimate, "DECIMATE", "Decimate", ""},
+       {eModifierType_Displace, "DISPLACE", "Displace", ""},
+       {eModifierType_EdgeSplit, "EDGE_SPLIT", "Edge Split", ""},
+       {eModifierType_Explode, "EXPLODE", "Explode", ""},
        {eModifierType_Fluidsim, "FLUID_SIMULATION", "Fluid Simulation", ""},
+       {eModifierType_Hook, "HOOK", "Hook", ""},
+       {eModifierType_Lattice, "LATTICE", "Lattice", ""},
        {eModifierType_Mask, "MASK", "Mask", ""},
-       {eModifierType_SimpleDeform, "SIMPLE_DEFORM", "Simple Deform", ""},
+       {eModifierType_MeshDeform, "MESH_DEFORM", "Mesh Deform", ""},
+       {eModifierType_Mirror, "MIRROR", "Mirror", ""},
        {eModifierType_Multires, "MULTIRES", "Multires", ""},
+       {eModifierType_ParticleInstance, "PARTICLE_INSTANCE", "Particle Instance", ""},
+       {eModifierType_ParticleSystem, "PARTICLE_SYSTEM", "Particle System", ""},
+       {eModifierType_Shrinkwrap, "SHRINKWRAP", "Shrinkwrap", ""},
+       {eModifierType_SimpleDeform, "SIMPLE_DEFORM", "Simple Deform", ""},
+       {eModifierType_Smooth, "SMOOTH", "Smooth", ""},
+       {eModifierType_Softbody, "SOFTBODY", "Softbody", ""},
+       {eModifierType_Subsurf, "SUBSURF", "Subsurf", ""},
+       {eModifierType_UVProject, "UV_PROJECT", "UV Project", ""},
+       {eModifierType_Wave, "WAVE", "Wave", ""},
        {0, NULL, NULL, NULL}};
 
 
index 0f2142f4b62abab3e425ee7cb972ab8854675381..bdf656e5e57758c8340c41f16d0c22d81da2dc76 100644 (file)
@@ -406,7 +406,6 @@ PyObject *BPY_ui_module( void )
        PyModule_AddObject( mod, "BLOCK_NUMSELECT", PyLong_FromSsize_t(UI_BLOCK_NUMSELECT) );
        PyModule_AddObject( mod, "BLOCK_ENTER_OK", PyLong_FromSsize_t(UI_BLOCK_ENTER_OK) );
        PyModule_AddObject( mod, "BLOCK_NOSHADOW", PyLong_FromSsize_t(UI_BLOCK_NOSHADOW) );
-       PyModule_AddObject( mod, "BLOCK_NO_HILITE", PyLong_FromSsize_t(UI_BLOCK_NO_HILITE) );
        PyModule_AddObject( mod, "BLOCK_MOVEMOUSE_QUIT", PyLong_FromSsize_t(UI_BLOCK_MOVEMOUSE_QUIT) );
        PyModule_AddObject( mod, "BLOCK_KEEP_OPEN", PyLong_FromSsize_t(UI_BLOCK_KEEP_OPEN) );
        PyModule_AddObject( mod, "BLOCK_POPUP", PyLong_FromSsize_t(UI_BLOCK_POPUP) );