4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version. The Blender
10 * Foundation also sells licenses for use in proprietary software under
11 * the Blender License. See http://www.blender.org/BL/ for information
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
40 #define snprintf _snprintf
44 #include "MEM_guardedalloc.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_space_types.h"
47 #include "DNA_scene_types.h"
49 #include "DNA_action_types.h"
50 #include "DNA_armature_types.h"
51 #include "DNA_brush_types.h"
52 #include "DNA_camera_types.h"
53 #include "DNA_color_types.h"
54 #include "DNA_constraint_types.h"
55 #include "DNA_curve_types.h"
56 #include "DNA_effect_types.h"
57 #include "DNA_group_types.h"
58 #include "DNA_key_types.h"
59 #include "DNA_lamp_types.h"
60 #include "DNA_lattice_types.h"
61 #include "DNA_material_types.h"
62 #include "DNA_meta_types.h"
63 #include "DNA_mesh_types.h"
64 #include "DNA_meshdata_types.h"
65 #include "DNA_modifier_types.h"
66 #include "DNA_nla_types.h"
67 #include "DNA_object_types.h"
68 #include "DNA_object_force.h"
69 #include "DNA_particle_types.h"
70 #include "DNA_radio_types.h"
71 #include "DNA_screen_types.h"
72 #include "DNA_texture_types.h"
73 #include "DNA_userdef_types.h"
74 #include "DNA_vfont_types.h"
75 #include "DNA_view3d_types.h"
76 #include "DNA_world_types.h"
77 #include "DNA_packedFile_types.h"
79 #include "BKE_blender.h"
80 #include "BKE_brush.h"
81 #include "BKE_curve.h"
82 #include "BKE_customdata.h"
83 #include "BKE_colortools.h"
84 #include "BKE_deform.h"
85 #include "BKE_depsgraph.h"
86 #include "BKE_global.h"
88 #include "BKE_library.h"
91 #include "BKE_modifier.h"
92 #include "BKE_packedFile.h"
93 #include "BKE_particle.h"
94 #include "BKE_scene.h"
96 #include "BLI_blenlib.h"
97 #include "BLI_arithb.h"
98 #include "BLI_vfontdata.h"
99 #include "BLI_editVert.h"
100 #include "BLI_dynstr.h"
102 #include "BSE_filesel.h"
105 #include "BIF_editarmature.h"
106 #include "BIF_editconstraint.h"
107 #include "BIF_editdeform.h"
108 #include "BIF_editfont.h"
109 #include "BIF_editkey.h"
110 #include "BIF_editmesh.h"
111 #include "BIF_editparticle.h"
112 #include "BIF_imasel.h"
113 #include "BIF_interface.h"
114 #include "BIF_meshtools.h"
115 #include "BIF_mywindow.h"
116 #include "BIF_poseobject.h"
117 #include "BIF_renderwin.h"
118 #include "BIF_resources.h"
119 #include "BIF_retopo.h"
120 #include "BIF_screen.h"
121 #include "BIF_scrarea.h"
122 #include "BIF_space.h"
123 #include "BIF_toets.h"
124 #include "BIF_toolbox.h"
125 #include "BIF_previewrender.h"
126 #include "BIF_butspace.h"
129 #include "BIF_verse.h"
132 #include "mydevice.h"
135 #include "BKE_action.h"
136 #include "BKE_anim.h"
137 #include "BKE_armature.h"
138 #include "BKE_constraint.h"
139 #include "BKE_curve.h"
140 #include "BKE_displist.h"
141 #include "BKE_DerivedMesh.h"
142 #include "BKE_effect.h"
143 #include "BKE_font.h"
144 #include "BKE_image.h"
146 #include "BKE_lattice.h"
147 #include "BKE_material.h"
148 #include "BKE_mball.h"
149 #include "BKE_mesh.h"
150 #include "BKE_object.h"
151 #include "BKE_texture.h"
152 #include "BKE_utildefines.h"
154 #include "BIF_poseobject.h"
156 #include "BDR_drawobject.h"
157 #include "BDR_editcurve.h"
158 #include "BDR_editface.h"
159 #include "BDR_editobject.h"
160 #include "BDR_sculptmode.h"
161 #include "BDR_vpaint.h"
162 #include "BDR_unwrapper.h"
164 #include "BSE_drawview.h"
165 #include "BSE_editipo.h"
166 #include "BSE_edit.h"
167 #include "BSE_filesel.h"
168 #include "BSE_headerbuttons.h"
169 #include "BSE_trans_types.h"
170 #include "BSE_view.h"
171 #include "BSE_seqaudio.h"
173 #include "RE_render_ext.h" // make_sticky
175 #include "butspace.h" // own module
176 #include "multires.h"
178 static float editbutweight= 1.0;
179 float editbutvweight= 1;
180 static int actmcol= 0, acttface= 0, acttface_rnd = 0, actmcol_rnd = 0;
182 extern ListBase editNurb;
184 /* *************************** Unicode Character Groups ****************** */
185 unicodect uctabname[125] = {
186 {"All", "All", 0x0000, 0xffff},
187 {"Basic Latin", "Basic Latin", 0x0000, 0x007f},
188 {"Latin 1 Supp", "Latin-1 Supplement", 0x0080, 0x00ff},
190 {"Latin Ext. A.", "Latin Extended-A", 0x0100, 0x017F},
191 {"Latin Ext. B.", "Latin Extended-B", 0x0180,0x024F},
192 {"Latin Ext. Add.", "Latin Extended Additional", 0x1e00, 0x1eff},
194 {"IPA Ext", "IPA Extensions", 0x0250, 0x02AF},
195 {"Spacing Mod.", "Spacing Modifier Letters", 0x02b0, 0x02ff},
197 {"Comb. Dia.", "Combining Diacritical Marks", 0x0300, 0x036F},
198 {"Greek, Coptic", "Greek and Coptic", 0x0370, 0x03ff},
199 {"Greek Ext.", "Greek Extended", 0x1f00, 0x1fff},
201 {"Cyrillic", "Cyrillic", 0x0400, 0x04ff},
202 {"Cyrillic Supp.", "Cyrillic Supplementary", 0x0500, 0x052f},
204 {"Armenian", "Armenian", 0x0530, 0x058f},
205 {"Hebrew", "Hebrew", 0x0590, 0x05ff},
208 {"Arabic", "Arabic", 0x0600, 0x06ff},
209 {"Syriac", "Syriac", 0x0700, 0x074f},
211 {"Thaana", "Thaana", 0x0780, 0x07bf},
212 {"Devanagari", "Devanagari", 0x0900, 0x097f},
214 {"Bengali", "Bengali", 0x0980, 0x09ff},
215 {"Gurmukhi", "Gurmukhi", 0x0a00, 0x0a7f},
217 {"Gujarati", "Gujarati", 0x0a80, 0x0aff},
218 {"Oriya", "Oriya", 0x0b00, 0x0b7f},
220 {"Tamil", "Tamil", 0x0b80, 0x0bff},
221 {"Tegulu", "Tegulu", 0x0c00, 0x0c7f},
223 {"Kannada", "Kannada", 0x0c80, 0x0cff},
224 {"Malayalam", "Malayalam", 0x0d00, 0x0d7f},
226 {"Sinhala", "Sinhala", 0x0d80, 0x0dff},
227 {"Thai", "Thai", 0x0e00, 0x0e7f},
229 {"Lao", "Lao", 0x0e80, 0x0eff},
230 {"Tibetan", "Tibetan", 0x0f00, 0x0fff},
232 {"Myanmar", "Myanmar", 0x1000, 0x109f},
233 {"Georgian", "Georgian", 0x10a0, 0x10ff},
235 {"Ethiopic", "Ethiopic", 0x1200, 0x137f},
237 {"Cherokee", "Cherokee", 0x13a0, 0x13ff},
238 {"Unif. Canadian", "Unified Canadian Aboriginal Syllabics", 0x1400, 0x167f},
240 {"Ogham", "Ogham", 0x1680, 0x169f},
241 {"Runic", "Runic", 0x16a0, 0x16ff},
243 {"Tagalog", "Tagalog", 0x1700, 0x171f},
244 {"Hanunoo", "Hanunoo", 0x1720, 0x173f},
246 {"Buhid", "Buhid", 0x1740, 0x175f},
247 {"Tagbanwa", "Tagbanwa", 0x1760, 0x177f},
249 {"Khmer", "Khmer", 0x1780, 0x17ff},
250 {"Khmer Symb", "Khmer Symbols", 0x19e0, 0x19ff},
252 {"Mongolian", "Mongolian", 0x1800, 0x18af},
254 {"Limbu", "Limbu", 0x1900, 0x194f},
255 {"Tai Le", "Tai Le", 0x1950, 0x197f},
257 {"Phon. Ext.", "Phonetic Extensions", 0x1d00, 0x1d7f},
260 {"Gen. Punct.", "General Punctutation", 0x2000, 0x206f},
261 {"Super, Sub", "Superscripts and Subscripts", 0x2070, 0x209f},
263 {"Curr. Symb.", "Currency Symbols", 0x20a0, 0x20cf},
264 {"Comb. Diacrit.", "Combining Diacritical Marks for Symbols", 0x20d0, 0x20ff},
266 {"Letter Symb", "Letterlike Symbols", 0x2100, 0x214f},
267 {"Numb. Forms", "Number Forms", 0x2150, 0x218f},
269 {"Arrows", "Arrows", 0x2190, 0x21ff},
270 {"Math Oper.", "Mathematical Operators", 0x2200, 0x22ff},
272 {"Misc. Tech.", "Miscellaneous Technical", 0x2300, 0x23ff},
273 {"Ctrl. Pict.", "Control Pictures", 0x2400, 0x243f},
275 {"OCR", "Optical Character Recognition", 0x2440, 0x245f},
276 {"Enc. Alpha", "Enclosed Alphanumerics", 0x2460, 0x24ff},
278 {"Bow Drawing", "Box Drawing", 0x2500, 0x257f},
279 {"BLock Elem.", "Block Elements", 0x2580, 0x259f},
281 {"Geom. Shapes", "Geometric Shapes", 0x25a0, 0x25ff},
282 {"Misc. Symb.", "Miscellaneous Symbols", 0x2600, 0x26ff},
284 {"Dingbats", "Dingbats", 0x2700, 0x27bf},
285 {"Misc. Math A", "Miscellaneous Mathematical Symbols-A", 0x27c0, 0x27ef},
287 {"Supp. Arrows-A", "Supplemental Arrows-A", 0x27f0, 0x27ff},
288 {"Braille Pat.", "Braille Patterns", 0x2800, 0x28ff},
290 {"Supp. Arrows-B", "Supplemental Arrows-B", 0x2900, 0x297f},
291 {"Misc. Math B", "Miscellaneous Mathematical Symbols-B", 0x2980, 0x29ff},
293 {"Supp. Math Op.", "Supplemental Mathematical Operators", 0x2a00, 0x2aff},
294 {"Misc. Symb.", "Miscellaneous Symbols and Arrows", 0x2b00, 0x2bff},
296 {"Kangxi Rad.", "Kangxi Radicals", 0x2f00, 0x2fdf},
298 {"Ideographic", "Ideographic Description Characters", 0x2ff0, 0x2fff},
300 {"Hiragana", "Hiragana", 0x3040, 0x309f},
301 {"Katakana", "Katakana", 0x30a0, 0x30ff},
302 {"Katakana Ext.", "Katakana Phonetic Extensions", 0x31f0, 0x31ff},
304 {"Bopomofo", "Bopomofo", 0x3100, 0x312f},
305 {"Bopomofo Ext.", "Bopomofo Extended", 0x31a0, 0x31bf},
307 {"Hangul", "Hangul Jamo", 0x1100, 0x11ff},
308 {"Hangul Comp.", "Hangul Compatibility Jamo", 0x3130, 0x318f},
309 {"Hangul Syll.", "Hangul Syllables", 0xac00, 0xd7af},
311 {"Kanbun", "Kanbun", 0x3190, 0x319f},
315 {"Yijing Hex.", "Yijing Hexagram Symbols", 0x4dc0, 0x4dff},
317 {"Yi Syllables", "Yi Syllables", 0xa000, 0xa48f},
318 {"Yi Radicals", "Yi Radicals", 0xa490, 0xa4cf},
320 {"High Surr.", "High Surrogate Area", 0xd800, 0xdbff},
322 {"Low Surr.", "Low Surrogates", 0xdc00, 0xdfff},
323 {"Priv. Use Area", "Private Use Area", 0xe000, 0xf8ff},
325 {"CJK Rad. Supp.", "CJK Radicals Supplement", 0x2e80, 0x2eff},
326 {"CJK Ideographs", "CJK Unified Ideographs", 0x4e00, 0x9faf},
327 {"CJK Ideog. Ext. A", "CJK Unified Ideographs Extension A", 0x3400, 0x4dbf},
328 {"CJK Ideog. Ext. B", "CJK Unified Ideographs Extension B", 0x20000, 0x2a6df},
329 {"CJK Symbols.", "CJK Symbols and Punctuation", 0x3000, 0x303f},
330 {"Enclosed CJK", "Enclosed CJK Letters and Months", 0x3200, 0x32ff},
331 {"CJK Comp.", "CJK Compatibility", 0x3300, 0x33ff},
332 {"CJK Comp. Ideog.", "CJK Compatibility Ideographs", 0xf900, 0xfaff},
333 {"CJK Comp. Forms", "CJK Compatibility Forms", 0xfe30, 0xfe4f},
334 {"CJK Comp. Supp.", "CJK Compatibility Ideographs Supplement", 0x2f800, 0x2fa1f},
336 {"Alpha. Pres. Forms", "Alphabetic Presentation Forms", 0xfb00, 0xfb4f},
338 {"Arabic Pres. A", "Arabic Presentation Forms-A", 0xfb50, 0xfdff},
339 {"Arabic Pres. B", "Arabic Presentation Forms-B", 0xfe70, 0xfeff},
341 {"Var. Sel.", "Variation Selectors", 0xfe00, 0xfe0f},
343 {"Comb. Half", "Combining Half Marks", 0xfe20, 0xfe2f},
345 {"Sml. From Var.", "Small Form Variants", 0xfe50, 0xfe6f},
347 {"Half, Full Forms", "Halfwidth and Fullwidth Forms", 0xff00, 0xffef},
348 {"Specials", "Specials", 0xfff0, 0xffff},
350 {"Lin. B Syllab.", "Linear B Syllabary", 0x10000, 0x1007f},
351 {"Lin. B Idog.", "Linear B Ideograms", 0x10080, 0x100ff},
353 {"Aegean Num.", "Aegean Numbers", 0x10100, 0x1013f},
354 {"Old Italic", "Old Italic", 0x10300, 0x1032f},
356 {"Gothic", "Gothic", 0x10330, 0x1034f},
357 {"Ugaritic", "Ugaritic", 0x10380, 0x1039f},
359 {"Deseret", "Deseret", 0x10400, 0x1044f},
360 {"Shavian", "Shavian", 0x10450, 0x1047f},
362 {"Osmanya", "Osmanya", 0x10480, 0x104af},
363 {"Cypriot Syll", "Cypriot Syllabary", 0x10800, 0x1083f},
365 {"Bysantine Mus.", "Bysantine Musical Symbols", 0x1d000, 0x1d0ff},
366 {"Music Symb.", "Musical Symbols", 0x1d100, 0x1d1ff},
368 {"Tai Xuan Symb", "Tai Xuan Jing Symbols", 0x1d300, 0x1d35f},
369 {"Math. Alpha Symb.", "Mathematical Alpanumeric Symbols", 0x1d400, 0x1d7ff},
372 {"Tags", "Tags", 0xe0000, 0xe007f},
373 {"Var. Supp", "Variation Selectors Supplement", 0xe0100, 0xe01ef},
375 {"Supp. Priv. A", "Supplementary Private Use Area-A", 0xf0000, 0xffffd},
376 {"Supp. Priv. B", "Supplementary Private Use Area-B", 0x100000, 0x10fffd}
380 /* *************************** static functions prototypes ****************** */
381 VFont *exist_vfont(char *str);
383 /* *************** */
385 void do_common_editbuts(unsigned short event) // old name, is a mix of object and editing events....
387 EditMesh *em = G.editMesh;
396 int a, bit, index= -1;
401 if(G.obedit && G.obedit->actcol>0) {
402 if(G.obedit->type == OB_MESH) {
403 efa= em->faces.first;
405 if(efa->f & SELECT) {
406 if(index== -1) index= efa->mat_nr;
407 else if(index!=efa->mat_nr) {
408 error("Mixed colors");
415 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
418 if( isNurbsel(nu) ) {
419 if(index== -1) index= nu->mat_nr;
420 else if(index!=nu->mat_nr) {
421 error("Mixed colors");
429 G.obedit->actcol= index+1;
430 scrarea_queue_winredraw(curarea);
435 new_material_to_objectdata(ob);
436 scrarea_queue_winredraw(curarea);
437 BIF_undo_push("New material");
438 allqueue(REDRAWBUTSSHADING, 0);
439 allqueue(REDRAWVIEW3D_Z, 0);
440 allqueue(REDRAWOOPS, 0);
443 delete_material_index();
444 scrarea_queue_winredraw(curarea);
445 BIF_undo_push("Delete material index");
446 allqueue(REDRAWBUTSSHADING, 0);
447 allqueue(REDRAWVIEW3D_Z, 0);
448 allqueue(REDRAWOOPS, 0);
451 if(G.obedit && G.obedit->actcol>0) {
452 if(G.obedit->type == OB_MESH) {
453 efa= em->faces.first;
456 efa->mat_nr= G.obedit->actcol-1;
460 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
464 nu->mat_nr= nu->charidx= G.obedit->actcol-1;
468 else if (G.obedit->type == OB_FONT) {
470 allqueue(REDRAWVIEW3D, 0);
473 allqueue(REDRAWVIEW3D_Z, 0);
474 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
475 shade_buttons_change_3d();
476 BIF_undo_push("Assign material index");
482 if(G.obedit->type == OB_MESH) {
483 if (event==B_MATSEL) {
484 editmesh_select_by_material(G.obedit->actcol-1);
486 editmesh_deselect_by_material(G.obedit->actcol-1);
488 allqueue(REDRAWVIEW3D, 0);
490 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
493 if(nu->mat_nr==G.obedit->actcol-1) {
499 if(event==B_MATSEL) {
514 a= nu->pntsu*nu->pntsv;
518 if(event==B_MATSEL) bp->f1 |= 1;
527 BIF_undo_push("Select material index");
528 allqueue(REDRAWVIEW3D, 0);
535 if(G.obedit->type == OB_MESH) hide_mesh(0);
536 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) hideNurb(0);
541 if(G.obedit->type == OB_MESH) reveal_mesh();
542 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) revealNurb();
544 else if(FACESEL_PAINT_TEST) reveal_tface();
549 if(G.obedit->type == OB_MESH) selectswap_mesh();
550 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) selectswapNurb();
554 if(ob && G.obedit==0) {
555 if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) tex_space_curve(ob->data);
564 case B_DOCENTERCURSOR:
570 if(G.obedit->type == OB_MESH) {
571 mesh_set_smooth_faces((event==B_SETSMOOTH));
574 nurb_set_smooth((event==B_SETSMOOTH));
580 if(TESTBASELIB(base)) {
581 if(base->object->type==OB_MESH) {
582 mesh_set_smooth_flag(base->object, (event==B_SETSMOOTH));
584 else if ELEM(base->object->type, OB_SURF, OB_CURVE) {
585 cu= base->object->data;
588 if(event==B_SETSMOOTH) nu->flag |= ME_SMOOTH;
589 else nu->flag &= ~ME_SMOOTH;
592 makeDispListCurveTypes(base->object, 0);
597 allqueue(REDRAWVIEW3D, 0);
599 if(event == B_SETSMOOTH) BIF_undo_push("Set Smooth");
600 else BIF_undo_push("Set Solid");
604 DAG_scene_sort(G.scene); // makes new dag
605 if(ob) ob->recalc |= OB_RECALC;
606 allqueue(REDRAWVIEW3D, 0);
613 ob->shapeflag |= OB_SHAPE_TEMPLOCK;
614 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
615 allqueue(REDRAWVIEW3D, 0);
616 allqueue(REDRAWIPO, 0);
617 allqueue(REDRAWBUTSEDIT, 0);
620 ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
621 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
622 allqueue(REDRAWVIEW3D, 0);
623 allqueue(REDRAWIPO, 0);
624 allqueue(REDRAWBUTSEDIT, 0);
628 Key *key= ob_get_key(ob);
629 if(ob->shapenr == BLI_countlist(&key->block))
632 do_common_editbuts(B_SETKEY);
637 Key *key= ob_get_key(ob);
639 ob->shapenr= BLI_countlist(&key->block);
641 do_common_editbuts(B_SETKEY);
645 allspace(REMAKEIPO, 0);
646 allqueue (REDRAWIPO, 0);
650 allqueue(REDRAWACTION, 0);
658 if(event>=B_OBLAY && event<=B_OBLAY+31) {
659 local= BASACT->lay & 0xFF000000;
660 BASACT->lay -= local;
661 if(BASACT->lay==0 || (G.qual & LR_SHIFTKEY)==0) {
664 scrarea_queue_winredraw(curarea);
666 BASACT->lay += local;
668 if( (ob->lay & G.vd->lay) && (BASACT->lay & G.vd->lay) );
669 else if( (ob->lay & G.vd->lay)==0 && (BASACT->lay & G.vd->lay)==0 );
671 allqueue(REDRAWVIEW3D, 0);
672 DAG_scene_sort(G.scene);
674 ob->lay= BASACT->lay;
680 /* *************************** MESH ******************************** */
682 static void verify_customdata_name_func(void *data1, void *data2)
684 CustomData *data= (CustomData*)data1;
685 CustomDataLayer *layer= (CustomDataLayer*)data2;
687 CustomData_set_layer_unique_name(data, layer - data->layers);
690 static void delete_customdata_layer(void *data1, void *data2)
692 Mesh *me= (Mesh*)data1;
693 CustomData *data= (G.obedit)? &G.editMesh->fdata: &me->fdata;
694 CustomDataLayer *layer= (CustomDataLayer*)data2;
695 void *actlayerdata, *rndlayerdata, *layerdata=layer->data;
696 int type= layer->type;
697 int index= CustomData_get_layer_index(data, type);
698 int i, actindex, rndindex;
700 /*ok, deleting a non-active layer needs to preserve the active layer indices.
701 to do this, we store a pointer to the .data member of both layer and the active layer,
702 (to detect if we're deleting the active layer or not), then use the active
703 layer data pointer to find where the active layer has ended up.
705 this is necassary because the deletion functions only support deleting the active
707 actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
708 rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
709 CustomData_set_layer_active(data, type, layer - &data->layers[index]);
711 /* Multires is handled seperately because the display data is separate
712 from the data stored in multires */
714 multires_delete_layer(me, &me->mr->fdata, type, layer - &data->layers[index]);
717 EM_free_data_layer(data, type);
720 CustomData_free_layer_active(data, type, me->totface);
721 mesh_update_customdata_pointers(me);
724 if(!CustomData_has_layer(data, type)) {
725 if(type == CD_MCOL && (G.f & G_VERTEXPAINT))
726 G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */
729 /*reconstruct active layer*/
730 if (actlayerdata != layerdata) {
732 actindex = CustomData_get_layer_index(data, type);
733 for (i=actindex; i<data->totlayer; i++) {
734 if (data->layers[i].data == actlayerdata) {
735 actindex = i - actindex;
741 CustomData_set_layer_active(data, type, actindex);
744 if (rndlayerdata != layerdata) {
746 rndindex = CustomData_get_layer_index(data, type);
747 for (i=rndindex; i<data->totlayer; i++) {
748 if (data->layers[i].data == rndlayerdata) {
749 rndindex = i - rndindex;
755 CustomData_set_layer_render(data, type, rndindex);
759 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
761 if(type == CD_MTFACE)
762 BIF_undo_push("Delete UV Texture");
763 else if(type == CD_MCOL)
764 BIF_undo_push("Delete Vertex Color");
766 allqueue(REDRAWVIEW3D, 0);
767 allqueue(REDRAWIMAGE, 0);
768 allqueue(REDRAWBUTSEDIT, 0);
771 static int customdata_buttons(
772 uiBlock *block, Mesh *me, CustomData *data,
773 int type, int *activep, int *renderp,
774 int setevt, int setevt_rnd, int newevt,
775 char *label, char *shortlabel, char *browsetip, char *browsetip_rnd,
776 char *newtip, char *deltip, int x, int y)
778 CustomDataLayer *layer;
780 int i, count= CustomData_number_of_layers(data, type);
782 if(count >= MAX_MTFACE) {
783 uiDefBut(block, LABEL, 0, label, x,y,220,19, 0, 0.0, 0, 0, 0, "");
786 uiDefBut(block, LABEL, 0, label, x,y,140,19, 0, 0.0, 0, 0, 0, "");
787 uiBlockBeginAlign(block);
788 uiDefBut(block, BUT, newevt, "New", x+140,y,80,19, 0,0,0,0,0, newtip);
789 uiBlockEndAlign(block);
792 y -= (count)? 24: 19;
794 uiBlockBeginAlign(block);
795 for (count=1, i=0; i<data->totlayer; i++) {
796 layer= &data->layers[i];
798 if(layer->type == type) {
799 *activep= layer->active + 1;
800 *renderp= layer->active_rnd + 1;
802 uiDefIconButI(block, ROW, setevt, ICON_VIEW3D, x,y,25,19, activep, 1.0, count, 0, 0, browsetip);
803 uiDefIconButI(block, ROW, setevt_rnd, ICON_SCENE, x+25,y,25,19, renderp, 1.0, count, 0, 0, browsetip_rnd);
804 but=uiDefBut(block, TEX, setevt, "", x+50,y,145,19, layer->name, 0.0, 31.0, 0, 0, label);
805 uiButSetFunc(but, verify_customdata_name_func, data, layer);
806 but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, deltip);
807 uiButSetFunc(but, delete_customdata_layer, me, layer);
814 uiBlockEndAlign(block);
819 static void editing_panel_mesh_type(Object *ob, Mesh *me)
827 block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_type", UI_EMBOSS, UI_HELV, curarea->win);
828 if( uiNewPanel(curarea, block, "Mesh", "Editing", 320, 0, 318, 204)==0) return;
829 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
831 uiBlockBeginAlign(block);
832 uiDefButBitS(block, TOG, ME_AUTOSMOOTH, REDRAWVIEW3D, "Auto Smooth",10,180,170,19, &me->flag, 0, 0, 0, 0, "Treats all set-smoothed faces with angles less than Degr: as 'smooth' during render");
833 uiDefButS(block, NUM, B_DIFF, "Degr:", 10,160,170,19, &me->smoothresh, 1, 80, 0, 0, "Defines maximum angle between face normals that 'Auto Smooth' will operate on");
834 uiBlockEndAlign(block);
838 uiBlockBeginAlign(block);
839 but= uiDefButBitC(block,TOG,RETOPO,B_NOP, "Retopo", 10,130,170,19, &G.scene->toolsettings->retopo_mode, 0,0,0,0, "Turn on the re-topology tool");
840 uiButSetFunc(but,retopo_toggle,ob,me);
841 if(G.scene->toolsettings->retopo_mode) {
842 but= uiDefButBitC(block,TOG,RETOPO_PAINT,B_NOP,"Paint", 10,110,55,19, &G.scene->toolsettings->retopo_mode,0,0,0,0, "Draw intersecting lines in the 3d view, ENTER creates quad or tri faces, wrapped onto other objects in the 3d view.");
843 uiButSetFunc(but,retopo_paint_toggle,ob,me);
844 but= uiDefBut(block,BUT,B_NOP,"Retopo All", 65,110,115,19, 0,0,0,0,0, "Apply the re-topology tool to all selected vertices");
845 uiButSetFunc(but,retopo_do_all_cb,ob,me);
847 uiBlockEndAlign(block);
850 uiBlockBeginAlign(block);
851 uiDefBut(block, BUT,B_DOCENTER, "Center", 10, 80, 65, 19, 0, 0, 0, 0, 0, "Shifts object data to be centered about object's origin");
852 uiDefBut(block, BUT,B_DOCENTERNEW, "Center New", 75, 80, 105, 19, 0, 0, 0, 0, 0, "Shifts object's origin to center of object data");
853 uiDefBut(block, BUT,B_DOCENTERCURSOR, "Center Cursor", 10, 60, 170, 19, 0, 0, 0, 0, 0, "Shifts object's origin to cursor location");
854 uiBlockEndAlign(block);
856 uiBlockBeginAlign(block);
857 uiDefButBitS(block, TOG, ME_TWOSIDED, REDRAWVIEW3D, "Double Sided", 10,30,170,19, &me->flag, 0, 0, 0, 0, "Render/display the mesh as double or single sided");
858 uiDefButBitS(block, TOG, ME_NOPUNOFLIP, REDRAWVIEW3D, "No V.Normal Flip", 10,10,170,19, &me->flag, 0, 0, 0, 0, "Disables flipping of vertexnormals during render");
859 uiBlockEndAlign(block);
861 uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, B_REDR, "TexMesh: ", 190,180,220,19, &me->texcomesh, "Derive texture coordinates from another mesh.");
863 if(me->msticky) val= 1.0; else val= 0.0;
864 uiDefBut(block, LABEL, 0, "Sticky", 190,155,140,19, 0, val, 0, 0, 0, "");
865 uiBlockBeginAlign(block);
866 if(me->msticky==NULL) {
867 uiDefBut(block, BUT, B_MAKESTICKY, "Make", 330,155, 80,19, 0, 0, 0, 0, 0, "Creates Sticky coordinates from the current camera view background picture");
869 else uiDefBut(block, BUT, B_DELSTICKY, "Delete", 330,155, 80,19, 0, 0, 0, 0, 0, "Deletes Sticky texture coordinates");
870 uiBlockEndAlign(block);
872 fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata;
873 yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd,
874 B_SETTFACE, B_SETTFACE_RND, B_NEWTFACE, "UV Texture", "UV Texture:",
875 "Set active UV texture", "Set rendering UV texture", "Creates a new UV texture layer",
876 "Removes the current UV texture layer", 190, 130);
878 yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd,
879 B_SETMCOL, B_SETMCOL_RND, B_NEWMCOL, "Vertex Color", "Vertex Color:",
880 "Sets active vertex color layer", "Sets rendering vertex color layer", "Creates a new vertex color layer",
881 "Removes the current vertex color layer", 190, yco-5);
884 uiNewPanelHeight(block, 204 - yco);
887 /* *************************** MODIFIERS ******************************** */
889 void do_modifier_panels(unsigned short event)
894 case B_MODIFIER_REDRAW:
895 allqueue(REDRAWBUTSEDIT, 0);
896 allqueue(REDRAWOOPS, 0);
899 case B_MODIFIER_RECALC:
900 ob->softflag |= OB_SB_RESET;
901 allqueue(REDRAWBUTSEDIT, 0);
902 allqueue(REDRAWVIEW3D, 0);
903 allqueue(REDRAWIMAGE, 0);
904 allqueue(REDRAWOOPS, 0);
905 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
906 object_handle_update(ob);
912 static void modifiers_add(void *ob_v, int type)
915 ModifierTypeInfo *mti = modifierType_getInfo(type);
917 if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
918 ModifierData *md = ob->modifiers.first;
920 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
924 BLI_insertlinkbefore(&ob->modifiers, md, modifier_new(type));
926 BLI_addtail(&ob->modifiers, modifier_new(type));
928 BIF_undo_push("Add modifier");
931 typedef struct MenuEntry {
936 static int menuEntry_compare_names(const void *entry1, const void *entry2)
938 return strcmp(((MenuEntry *)entry1)->name, ((MenuEntry *)entry2)->name);
941 static uiBlock *modifiers_add_menu(void *ob_v)
947 MenuEntry entries[NUM_MODIFIER_TYPES];
949 block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu",
950 UI_EMBOSSP, UI_HELV, curarea->win);
951 uiBlockSetButmFunc(block, modifiers_add, ob);
953 for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
954 ModifierTypeInfo *mti = modifierType_getInfo(i);
956 /* Only allow adding through appropriate other interfaces */
957 if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
959 if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
960 (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
961 entries[numEntries].name = mti->name;
962 entries[numEntries].ID = i;
968 qsort(entries, numEntries, sizeof(*entries), menuEntry_compare_names);
971 for(i = 0; i < numEntries; ++i)
972 uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name,
973 0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, "");
975 uiTextBoundsBlock(block, 50);
976 uiBlockSetDirection(block, UI_DOWN);
981 static void modifiers_del(void *ob_v, void *md_v)
986 /* It seems on rapid delete it is possible to
987 * get called twice on same modifier, so make
988 * sure it is in list.
990 for (md=ob->modifiers.first; md; md=md->next)
997 if(md->type==eModifierType_ParticleSystem){
998 ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
999 BLI_remlink(&ob->particlesystem, psmd->psys);
1000 psys_free(ob,psmd->psys);
1003 BLI_remlink(&ob->modifiers, md_v);
1005 modifier_free(md_v);
1007 BIF_undo_push("Del modifier");
1010 int mod_moveUp(void *ob_v, void *md_v)
1013 ModifierData *md = md_v;
1016 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1018 if (mti->type!=eModifierTypeType_OnlyDeform) {
1019 ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
1021 if (nmti->flags&eModifierTypeFlag_RequiresOriginalData)
1025 BLI_remlink(&ob->modifiers, md);
1026 BLI_insertlink(&ob->modifiers, md->prev->prev, md);
1032 static void modifiers_moveUp(void *ob_v, void *md_v)
1034 if( mod_moveUp( ob_v, md_v ) )
1035 error("Cannot move above a modifier requiring original data.");
1037 BIF_undo_push("Move modifier");
1040 int mod_moveDown(void *ob_v, void *md_v)
1043 ModifierData *md = md_v;
1046 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1048 if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
1049 ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
1051 if (nmti->type!=eModifierTypeType_OnlyDeform)
1055 BLI_remlink(&ob->modifiers, md);
1056 BLI_insertlink(&ob->modifiers, md->next, md);
1062 static void modifiers_moveDown(void *ob_v, void *md_v)
1064 if( mod_moveDown( ob_v, md_v ) )
1065 error("Cannot move beyond a non-deforming modifier.");
1067 BIF_undo_push("Move modifier");
1070 static void modifier_testLatticeObj(char *name, ID **idpp)
1074 for (id= G.main->object.first; id; id= id->next) {
1075 if( strcmp(name, id->name+2)==0 ) {
1076 if (((Object *)id)->type != OB_LATTICE) {
1077 error ("Lattice deform object must be a lattice");
1087 static void modifier_testCurveObj(char *name, ID **idpp)
1091 for (id= G.main->object.first; id; id= id->next) {
1092 if( strcmp(name, id->name+2)==0 ) {
1093 if (((Object *)id)->type != OB_CURVE) {
1094 error ("Curve deform object must be a curve");
1104 static void modifier_testMeshObj(char *name, ID **idpp)
1108 for (id= G.main->object.first; id; id= id->next) {
1109 /* no boolean on its own object */
1110 if(id != (ID *)OBACT) {
1111 if( strcmp(name, id->name+2)==0 ) {
1112 if (((Object *)id)->type != OB_MESH) {
1113 error ("Boolean modifier object must be a mesh");
1124 static void modifier_testArmatureObj(char *name, ID **idpp)
1128 for (id= G.main->object.first; id; id= id->next) {
1129 if( strcmp(name, id->name+2)==0 ) {
1130 if (((Object *)id)->type != OB_ARMATURE) {
1131 error ("Armature deform object must be an armature");
1141 static void modifier_testTexture(char *name, ID **idpp)
1145 for(id = G.main->tex.first; id; id = id->next) {
1146 if(strcmp(name, id->name + 2) == 0) {
1148 /* texture gets user, objects not: delete object = clear modifier */
1156 #if 0 /* this is currently unused, but could be useful in the future */
1157 static void modifier_testMaterial(char *name, ID **idpp)
1161 for(id = G.main->mat.first; id; id = id->next) {
1162 if(strcmp(name, id->name + 2) == 0) {
1171 static void modifier_testImage(char *name, ID **idpp)
1175 for(id = G.main->image.first; id; id = id->next) {
1176 if(strcmp(name, id->name + 2) == 0) {
1184 /* autocomplete callback for ID buttons */
1185 void autocomplete_image(char *str, void *arg_v)
1187 /* search if str matches the beginning of an ID struct */
1189 AutoComplete *autocpl = autocomplete_begin(str, 22);
1192 for(id = G.main->image.first; id; id = id->next)
1193 autocomplete_do_name(autocpl, id->name+2);
1195 autocomplete_end(autocpl, str);
1199 /* autocomplete callback for ID buttons */
1200 void autocomplete_meshob(char *str, void *arg_v)
1202 /* search if str matches the beginning of an ID struct */
1204 AutoComplete *autocpl = autocomplete_begin(str, 22);
1207 for(id = G.main->object.first; id; id = id->next)
1208 if(((Object *)id)->type == OB_MESH)
1209 autocomplete_do_name(autocpl, id->name+2);
1211 autocomplete_end(autocpl, str);
1214 static void modifiers_convertParticles(void *obv, void *mdv)
1217 ModifierData *md = mdv;
1218 ParticleSystem *psys;
1219 ParticleCacheKey *key, **cache;
1224 int totvert=0, totface=0, cvert=0;
1225 int totpart=0, totchild=0;
1227 if(md->type != eModifierType_ParticleSystem) return;
1229 if(G.f & G_PARTICLEEDIT) return;
1231 psys=((ParticleSystemModifierData *)md)->psys;
1233 if(psys->part->draw_as != PART_DRAW_PATH || psys->pathcache == 0) return;
1235 totpart= psys->totcached;
1236 totchild= psys->totchildcache;
1238 if(totchild && (psys->part->draw&PART_DRAW_PARENT)==0)
1242 cache= psys->pathcache;
1243 for(a=0; a<totpart; a++) {
1245 totvert+= (int)(key->col[3])+1;
1246 totface+= (int)(key->col[3]);
1249 cache= psys->childcache;
1250 for(a=0; a<totchild; a++) {
1252 totvert+= (int)(key->col[3])+1;
1253 totface+= (int)(key->col[3]);
1256 if(totvert==0) return;
1259 obn= add_object(OB_MESH);
1262 me->totvert= totvert;
1263 me->totface= totface;
1265 me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
1266 me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, totface);
1271 /* copy coordinates */
1272 cache= psys->pathcache;
1273 for(a=0; a<totpart; a++){
1275 kmax= (int)(key->col[3]);
1276 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1277 VECCOPY(mvert->co,key->co);
1286 cache=psys->childcache;
1287 for(a=0; a<totchild; a++) {
1289 kmax=(int)(key->col[3]);
1290 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1291 VECCOPY(mvert->co,key->co);
1301 static void modifiers_applyModifier(void *obv, void *mdv)
1304 ModifierData *md = mdv;
1306 Mesh *me = ob->data;
1310 error("Modifiers cannot be applied in editmode");
1312 } else if (((ID*) ob->data)->us>1) {
1313 error("Modifiers cannot be applied to multi-user data");
1317 if (md!=ob->modifiers.first) {
1318 if (!okee("Modifier is not first"))
1322 if (ob->type==OB_MESH) {
1323 if(me->mr && multires_modifier_warning()) {
1324 error("Modifier changes topology; cannot apply with multires active");
1328 error("Modifier cannot be applied to Mesh with Shape Keys");
1332 sculptmode_pmv_off(me);
1334 dm = mesh_create_derived_for_modifier(ob, md);
1336 error("Modifier is disabled or returned error, skipping apply");
1345 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
1346 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1347 Curve *cu = ob->data;
1349 float (*vertexCos)[3];
1351 if (!okee("Apply will only change CV points, not tesselated/bevel vertices"))
1354 if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) {
1355 error("Modifier is disabled, skipping apply");
1359 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
1360 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
1361 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
1365 MEM_freeN(vertexCos);
1367 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1370 error("Cannot apply modifier for this object type");
1375 BLI_remlink(&ob->modifiers, md);
1378 BIF_undo_push("Apply modifier");
1382 static void modifiers_copyModifier(void *ob_v, void *md_v)
1385 ModifierData *md = md_v;
1386 ModifierData *nmd = modifier_new(md->type);
1388 modifier_copyData(md, nmd);
1390 BLI_insertlink(&ob->modifiers, md, nmd);
1392 BIF_undo_push("Copy modifier");
1395 static void modifiers_setOnCage(void *ob_v, void *md_v)
1400 int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1402 for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1404 if( i >= cageIndex )
1405 md->mode ^= eModifierMode_OnCage;
1410 static void modifiers_clearHookOffset(void *ob_v, void *md_v)
1413 ModifierData *md = md_v;
1414 HookModifierData *hmd = (HookModifierData*) md;
1417 Mat4Invert(hmd->object->imat, hmd->object->obmat);
1418 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1419 BIF_undo_push("Clear hook offset");
1423 static void modifiers_cursorHookCenter(void *ob_v, void *md_v)
1426 ModifierData *md = md_v;
1427 HookModifierData *hmd = (HookModifierData*) md;
1430 float *curs = give_cursor();
1431 float bmat[3][3], imat[3][3];
1433 where_is_object(ob);
1435 Mat3CpyMat4(bmat, ob->obmat);
1436 Mat3Inv(imat, bmat);
1438 curs= give_cursor();
1439 hmd->cent[0]= curs[0]-ob->obmat[3][0];
1440 hmd->cent[1]= curs[1]-ob->obmat[3][1];
1441 hmd->cent[2]= curs[2]-ob->obmat[3][2];
1442 Mat3MulVecfl(imat, hmd->cent);
1444 BIF_undo_push("Hook cursor center");
1448 static void modifiers_selectHook(void *ob_v, void *md_v)
1450 ModifierData *md = md_v;
1451 HookModifierData *hmd = (HookModifierData*) md;
1456 static void modifiers_reassignHook(void *ob_v, void *md_v)
1458 ModifierData *md = md_v;
1459 HookModifierData *hmd = (HookModifierData*) md;
1461 int *indexar, tot, ok;
1464 ok= hook_getIndexArray(&tot, &indexar, name, cent);
1467 error("Requires selected vertices or active Vertex Group");
1470 MEM_freeN(hmd->indexar);
1473 VECCOPY(hmd->cent, cent);
1474 hmd->indexar = indexar;
1475 hmd->totindex = tot;
1479 static void modifiers_convertToReal(void *ob_v, void *md_v)
1482 ModifierData *md = md_v;
1483 ModifierData *nmd = modifier_new(md->type);
1485 modifier_copyData(md, nmd);
1486 nmd->mode &= ~eModifierMode_Virtual;
1488 BLI_addhead(&ob->modifiers, nmd);
1490 ob->partype = PAROBJECT;
1492 BIF_undo_push("Modifier convert to real");
1495 static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
1496 int *uvlayer_tmp, char *uvlayer_name)
1500 CustomDataLayer *layer
1501 = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
1505 totuv = CustomData_number_of_layers(data, CD_MTFACE);
1507 *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
1509 sprintf(*menu_string, "UV Layer%%t");
1510 for(i = 0; i < totuv; i++) {
1511 /* assign first layer as uvlayer_name if uvlayer_name is null. */
1512 if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
1513 sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
1514 strcat(*menu_string, strtmp);
1518 /* there is no uvlayer defined, or else it was deleted. Assign active
1519 * layer, then recalc modifiers.
1521 if(*uvlayer_tmp == -1) {
1522 if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
1524 layer = data->layers;
1525 for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
1527 if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
1529 strcpy(uvlayer_name, layer->name);
1531 /* update the modifiers */
1532 do_modifier_panels(B_MODIFIER_RECALC);
1534 /* ok we have no uv layers, so make sure menu button knows that.*/
1540 void set_displace_uvlayer(void *arg1, void *arg2)
1542 DisplaceModifierData *dmd=arg1;
1543 CustomDataLayer *layer = arg2;
1545 /*check we have UV layers*/
1546 if (dmd->uvlayer_tmp < 1) return;
1547 layer = layer + (dmd->uvlayer_tmp-1);
1549 strcpy(dmd->uvlayer_name, layer->name);
1552 void set_uvproject_uvlayer(void *arg1, void *arg2)
1554 UVProjectModifierData *umd=arg1;
1555 CustomDataLayer *layer = arg2;
1557 /*check we have UV layers*/
1558 if (umd->uvlayer_tmp < 1) return;
1559 layer = layer + (umd->uvlayer_tmp-1);
1561 strcpy(umd->uvlayer_name, layer->name);
1564 static void modifiers_bindMeshDeform(void *ob_v, void *md_v)
1566 MeshDeformModifierData *mmd = (MeshDeformModifierData*) md_v;
1567 Object *ob = (Object*)ob_v;
1570 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
1571 if(mmd->bindcos) MEM_freeN(mmd->bindcos);
1572 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1573 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1574 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1575 mmd->bindweights= NULL;
1578 mmd->dyninfluences= NULL;
1579 mmd->dynverts= NULL;
1581 mmd->totcagevert= 0;
1582 mmd->totinfluence= 0;
1586 int mode= mmd->modifier.mode;
1588 /* force modifier to run, it will call binding routine */
1590 mmd->modifier.mode |= eModifierMode_Realtime;
1592 if(ob->type == OB_MESH) {
1593 dm= mesh_create_derived_view(ob, 0);
1596 else if(ob->type == OB_LATTICE) {
1597 lattice_calc_modifiers(ob);
1601 mmd->modifier.mode= mode;
1605 void modifiers_explodeFacepa(void *arg1, void *arg2)
1607 ExplodeModifierData *emd=arg1;
1609 emd->flag |= eExplodeFlag_CalcFaces;
1612 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
1614 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1616 int isVirtual = md->mode&eModifierMode_Virtual;
1617 int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
1618 int editing = (G.obedit==ob);
1619 short height=26, width = 295, buttonWidth = width-120-10;
1622 /* rounded header */
1623 uiBlockSetCol(block, color);
1624 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1625 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0,
1626 (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, "");
1627 uiBlockSetCol(block, TH_AUTO);
1629 /* open/close icon */
1631 uiBlockSetEmboss(block, UI_EMBOSSN);
1632 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");
1635 uiBlockSetEmboss(block, UI_EMBOSS);
1638 sprintf(str, "%s parent deform", md->name);
1639 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name");
1641 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");
1642 uiButSetFunc(but, modifiers_convertToReal, ob, md);
1644 uiBlockBeginAlign(block);
1645 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");
1647 /* Softbody not allowed in this situation, enforce! */
1648 if (md->type!=eModifierType_Softbody || !(ob->pd && ob->pd->deflect)) {
1649 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");
1650 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");
1651 if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
1652 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)");
1655 uiBlockEndAlign(block);
1657 uiBlockSetEmboss(block, UI_EMBOSSR);
1659 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
1662 if (index==cageIndex) {
1663 color = TH_BUT_SETTING;
1664 icon = VICON_EDITMODE_HLT;
1665 } else if (index<cageIndex) {
1666 color = TH_BUT_NEUTRAL;
1667 icon = VICON_EDITMODE_DEHLT;
1669 color = TH_BUT_NEUTRAL;
1672 uiBlockSetCol(block, color);
1673 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");
1674 uiButSetFunc(but, modifiers_setOnCage, ob, md);
1675 uiBlockSetCol(block, TH_AUTO);
1678 uiBlockSetCol(block, TH_BUT_ACTION);
1680 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");
1681 uiButSetFunc(but, modifiers_moveUp, ob, md);
1683 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");
1684 uiButSetFunc(but, modifiers_moveDown, ob, md);
1686 uiBlockSetEmboss(block, UI_EMBOSSN);
1688 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");
1689 uiButSetFunc(but, modifiers_del, ob, md);
1690 uiBlockSetCol(block, TH_AUTO);
1693 uiBlockSetEmboss(block, UI_EMBOSS);
1695 if (isVirtual || !(md->mode&eModifierMode_Expanded)) {
1699 int lx = x + width - 60 - 15;
1701 if (md->type==eModifierType_Subsurf) {
1703 } else if (md->type==eModifierType_Lattice) {
1705 } else if (md->type==eModifierType_Curve) {
1707 } else if (md->type==eModifierType_Build) {
1709 } else if (md->type==eModifierType_Mirror) {
1711 } else if (md->type==eModifierType_EdgeSplit) {
1712 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1714 if(emd->flags & MOD_EDGESPLIT_FROMANGLE) height += 19;
1715 } else if (md->type==eModifierType_Displace) {
1716 DisplaceModifierData *dmd = (DisplaceModifierData *)md;
1718 if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
1719 dmd->texmapping == MOD_DISP_MAP_UV)
1721 } else if (md->type==eModifierType_UVProject) {
1722 height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
1723 } else if (md->type==eModifierType_Decimate) {
1725 } else if (md->type==eModifierType_Smooth) {
1727 } else if (md->type==eModifierType_Cast) {
1729 } else if (md->type==eModifierType_Wave) {
1730 WaveModifierData *wmd = (WaveModifierData *)md;
1732 if(wmd->texmapping == MOD_WAV_MAP_OBJECT ||
1733 wmd->texmapping == MOD_WAV_MAP_UV)
1735 if(wmd->flag & MOD_WAVE_NORM)
1737 } else if (md->type==eModifierType_Armature) {
1739 } else if (md->type==eModifierType_Hook) {
1740 HookModifierData *hmd = (HookModifierData*) md;
1744 if(hmd->indexar==NULL)
1746 } else if (md->type==eModifierType_Softbody) {
1748 } else if (md->type==eModifierType_Boolean) {
1750 } else if (md->type==eModifierType_Array) {
1752 } else if (md->type==eModifierType_MeshDeform) {
1753 MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
1754 height = (mmd->bindcos)? 73: 93;
1755 } else if (md->type==eModifierType_ParticleSystem) {
1757 } else if (md->type==eModifierType_ParticleInstance) {
1759 } else if (md->type==eModifierType_Explode) {
1763 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1764 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, "");
1769 uiBlockBeginAlign(block);
1770 if (md->type==eModifierType_ParticleSystem) {
1771 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");
1772 uiButSetFunc(but, modifiers_convertParticles, ob, md);
1775 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");
1776 uiButSetFunc(but, modifiers_applyModifier, ob, md);
1779 if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem) {
1780 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");
1781 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1783 uiBlockEndAlign(block);
1788 uiBlockBeginAlign(block);
1789 if (md->type==eModifierType_Subsurf) {
1790 SubsurfModifierData *smd = (SubsurfModifierData*) md;
1791 char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1792 uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu, lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1793 uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:", lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1794 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");
1796 /* Disabled until non-EM DerivedMesh implementation is complete */
1799 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");
1800 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");
1803 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");
1804 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");
1805 } else if (md->type==eModifierType_Lattice) {
1806 LatticeModifierData *lmd = (LatticeModifierData*) md;
1807 uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1808 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1809 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1810 } else if (md->type==eModifierType_Curve) {
1811 CurveModifierData *cmd = (CurveModifierData*) md;
1812 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1813 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1814 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1816 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");
1817 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");
1818 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");
1819 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");
1820 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");
1821 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");
1822 } else if (md->type==eModifierType_Build) {
1823 BuildModifierData *bmd = (BuildModifierData*) md;
1824 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");
1825 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");
1826 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.");
1827 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.");
1828 } else if (md->type==eModifierType_Mirror) {
1829 MirrorModifierData *mmd = (MirrorModifierData*) md;
1830 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");
1831 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");
1832 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");
1833 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");
1834 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");
1835 uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
1837 lx, (cy-=19), buttonWidth/2, 19,
1838 &mmd->flag, 0, 0, 0, 0,
1839 "Mirror the U texture coordinate around "
1841 uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
1843 lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
1844 &mmd->flag, 0, 0, 0, 0,
1845 "Mirror the V texture coordinate around "
1847 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1848 "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1850 "Object to use as mirror");
1852 } else if (md->type==eModifierType_EdgeSplit) {
1853 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1854 uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
1855 B_MODIFIER_RECALC, "From Edge Angle",
1856 lx, (cy -= 19), buttonWidth, 19,
1857 &emd->flags, 0, 0, 0, 0,
1858 "Split edges with high angle between faces");
1859 if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
1860 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
1861 lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
1863 "Angle above which to split edges");
1865 uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
1866 B_MODIFIER_RECALC, "From Marked As Sharp",
1867 lx, (cy -= 19), buttonWidth, 19,
1868 &emd->flags, 0, 0, 0, 0,
1869 "Split edges that are marked as sharp");
1870 } else if (md->type==eModifierType_Displace) {
1871 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
1872 but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
1873 lx, (cy -= 19), buttonWidth, 19,
1874 &dmd->defgrp_name, 0.0, 31.0, 0, 0,
1875 "Name of vertex group to displace"
1876 " (displace whole mesh if blank)");
1877 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1878 uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
1879 "Texture: ", lx, (cy -= 19), buttonWidth, 19,
1881 "Texture to use as displacement input");
1882 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
1883 lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
1885 "Material value that gives no displacement");
1886 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
1887 lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
1888 -1000, 1000, 10, 10,
1889 "Strength of displacement");
1890 sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
1891 "Z%%x%d|Y%%x%d|X%%x%d",
1892 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
1893 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
1894 uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1895 lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
1896 0.0, 1.0, 0, 0, "Displace direction");
1897 sprintf(str, "Texture Coordinates%%t"
1898 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1899 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
1900 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
1901 uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1902 lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
1904 "Texture coordinates used for displacement input");
1905 if (dmd->texmapping == MOD_DISP_MAP_UV) {
1908 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1909 : &((Mesh*)ob->data)->fdata;
1910 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
1912 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1913 lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
1914 0.0, 1.0, 0, 0, "Set the UV layer to use");
1916 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1917 uiButSetFunc(but, set_displace_uvlayer, dmd,
1920 if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
1921 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1922 "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1924 "Object to get texture coordinates from");
1926 } else if (md->type==eModifierType_UVProject) {
1927 UVProjectModifierData *umd = (UVProjectModifierData *) md;
1930 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1931 : &((Mesh*)ob->data)->fdata;
1932 build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
1934 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1935 lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
1936 0.0, 1.0, 0, 0, "Set the UV layer to use");
1937 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1938 uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
1940 uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
1941 lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
1943 "Horizontal Aspect Ratio");
1944 uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
1945 lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
1948 "Vertical Aspect Ratio");
1949 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
1950 lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
1951 1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
1952 "Number of objects to use as projectors");
1953 for(i = 0; i < umd->num_projectors; ++i) {
1954 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1955 "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1956 &umd->projectors[i],
1957 "Object to use as projector");
1959 uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
1960 "Image: ", lx, (cy -= 19), buttonWidth, 19,
1962 "Image to project (only faces with this image "
1964 uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
1965 uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
1966 B_MODIFIER_RECALC, "Override Image",
1967 lx, (cy -= 19), buttonWidth, 19,
1968 &umd->flags, 0, 0, 0, 0,
1969 "Override faces' current images with the "
1971 } else if (md->type==eModifierType_Decimate) {
1972 DecimateModifierData *dmd = (DecimateModifierData*) md;
1973 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");
1974 sprintf(str, "Face Count: %d", dmd->faceCount);
1975 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");
1976 } else if (md->type==eModifierType_Smooth) {
1977 SmoothModifierData *smd = (SmoothModifierData*) md;
1979 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");
1980 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");
1981 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");
1983 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)");
1984 uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:", lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
1985 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");
1986 } else if (md->type==eModifierType_Cast) {
1987 CastModifierData *cmd = (CastModifierData*) md;
1989 char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
1990 uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu, lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
1991 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");
1992 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");
1993 if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
1994 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");
1996 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");
1997 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)");
1998 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)");
1999 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)");
2000 if (ob->type == OB_MESH) {
2001 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");
2003 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");
2005 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");
2007 } else if (md->type==eModifierType_Wave) {
2008 WaveModifierData *wmd = (WaveModifierData*) md;
2009 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");
2010 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");
2011 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");
2012 uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals", lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
2013 if (wmd->flag & MOD_WAVE_NORM){
2014 if (ob->type==OB_MESH) {
2015 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");
2016 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");
2017 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");
2020 uiDefBut(block, LABEL, 1, "Meshes Only", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2023 uiBlockBeginAlign(block);
2025 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");
2027 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");
2028 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:", lx,(cy-=19),buttonWidth,19, &wmd->lifetime, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
2029 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:", lx,(cy-=19),buttonWidth,19, &wmd->damp, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
2031 uiBlockBeginAlign(block);
2032 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");
2033 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");
2034 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)");
2035 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");
2036 uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
2037 sprintf(str, "Texture Coordinates%%t"
2038 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2039 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
2040 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
2041 uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2042 lx, (cy -= 19), 220, 19, &wmd->texmapping,
2044 "Texture coordinates used for modulation input");
2045 if (wmd->texmapping == MOD_WAV_MAP_UV) {
2048 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2049 : &((Mesh*)ob->data)->fdata;
2050 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
2052 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2053 lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
2054 0.0, 1.0, 0, 0, "Set the UV layer to use");
2056 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2057 uiButSetFunc(but, set_displace_uvlayer, wmd,
2060 if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
2061 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2062 "Ob: ", lx, (cy -= 19), 220, 19,
2064 "Object to get texture coordinates from");
2067 uiBlockBeginAlign(block);
2068 uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:", lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
2069 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");
2070 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");
2071 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");
2072 } else if (md->type==eModifierType_Armature) {
2073 ArmatureModifierData *amd = (ArmatureModifierData*) md;
2074 uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
2076 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth-40,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence");
2077 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2078 uiDefButBitS(block, TOG, ARM_DEF_INVERT_VGROUP, B_ARM_RECALCDATA, "Inv", lx+buttonWidth-40,cy, 40, 20, &amd->deformflag, 0, 0, 0, 0, "Invert vertex group influence");
2080 uiDefButBitS(block, TOG, ARM_DEF_VGROUP, B_ARM_RECALCDATA, "Vert.Groups", lx,cy-=19,buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable VertexGroups defining deform");
2081 uiDefButBitS(block, TOG, ARM_DEF_ENVELOPE, B_ARM_RECALCDATA, "Envelopes", lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable Bone Envelopes defining deform");
2082 uiDefButBitS(block, TOG, ARM_DEF_QUATERNION, B_ARM_RECALCDATA, "Quaternion", lx,(cy-=19),buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable deform rotation interpolation with Quaternions");
2083 uiDefButBitS(block, TOG, ARM_DEF_B_BONE_REST, B_ARM_RECALCDATA, "B-Bone Rest", lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Make B-Bones deform already in rest position");
2085 uiDefButS(block, TOG, B_ARM_RECALCDATA, "MultiModifier", lx,cy-=19, buttonWidth, 20, &amd->multi, 0, 0, 0, 0, "Use same input as previous modifier, and mix results using overall vgroup");
2087 } else if (md->type==eModifierType_Hook) {
2088 HookModifierData *hmd = (HookModifierData*) md;
2089 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");
2090 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");
2091 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");
2092 if(hmd->indexar==NULL) {
2093 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
2094 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2096 uiBlockBeginAlign(block);
2097 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");
2098 uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
2099 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");
2100 uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
2103 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");
2104 uiButSetFunc(but, modifiers_selectHook, ob, md);
2105 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");
2106 uiButSetFunc(but, modifiers_reassignHook, ob, md);
2108 } else if (md->type==eModifierType_Softbody) {
2109 uiDefBut(block, LABEL, 1, "See Softbody panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2110 } else if (md->type==eModifierType_Boolean) {
2111 BooleanModifierData *bmd = (BooleanModifierData*) md;
2112 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");
2113 uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
2114 } else if (md->type==eModifierType_Array) {
2115 ArrayModifierData *amd = (ArrayModifierData*) md;
2116 float range = 10000;
2117 int cytop, halfwidth = (width - 5)/2 - 15;
2118 int halflx = lx + halfwidth + 10;
2120 uiBlockSetEmboss(block, UI_EMBOSSX);
2121 uiBlockEndAlign(block);
2123 /* length parameters */
2124 uiBlockBeginAlign(block);
2125 sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
2126 "|Fit To Curve Length%%x%d",
2127 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
2128 uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2129 lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
2130 0.0, 1.0, 0, 0, "Array length calculation method");
2131 switch(amd->fit_type)
2133 case MOD_ARR_FIXEDCOUNT:
2134 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
2135 lx, (cy -= 19), buttonWidth, 19, &amd->count,
2136 1, 1000, 0, 0, "Number of duplicates to make");
2138 case MOD_ARR_FITLENGTH:
2139 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
2140 lx, (cy -= 19), buttonWidth, 19, &amd->length,
2142 "Length to fit array within");
2144 case MOD_ARR_FITCURVE:
2145 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
2146 B_CHANGEDEP, "Ob: ",
2147 lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
2148 "Curve object to fit array length to");
2151 uiBlockEndAlign(block);
2153 /* offset parameters */
2156 uiBlockBeginAlign(block);
2157 uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
2158 "Constant Offset", lx, (cy-=19), halfwidth, 19,
2159 &amd->offset_type, 0, 0, 0, 0,
2160 "Constant offset between duplicates "
2161 "(local coordinates)");
2162 uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2163 lx, (cy-=19), halfwidth, 19,
2165 -range, range, 10, 3,
2166 "Constant component for duplicate offsets "
2167 "(local coordinates)");
2168 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2169 lx, (cy-=19), halfwidth, 19,
2171 -range, range, 10, 3,
2172 "Constant component for duplicate offsets "
2173 "(local coordinates)");
2174 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2175 lx, (cy-=19), halfwidth, 19,
2177 -range, range, 10, 3,
2178 "Constant component for duplicate offsets "
2179 "(local coordinates)");
2180 uiBlockEndAlign(block);
2183 uiBlockBeginAlign(block);
2184 uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2185 "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2186 &amd->offset_type, 0, 0, 0, 0,
2187 "Offset between duplicates relative to object width "
2188 "(local coordinates)");
2189 uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2190 halflx, (cy-=19), halfwidth, 19,
2192 -range, range, 10, 3,
2193 "Component for duplicate offsets relative to object "
2194 "width (local coordinates)");
2195 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2196 halflx, (cy-=19), halfwidth, 19,
2198 -range, range, 10, 3,
2199 "Component for duplicate offsets relative to object "
2200 "width (local coordinates)");
2201 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2202 halflx, (cy-=19), halfwidth, 19,
2204 -range, range, 10, 3,
2205 "Component for duplicate offsets relative to object "
2206 "width (local coordinates)");
2207 uiBlockEndAlign(block);
2209 /* vertex merging parameters */
2213 uiBlockBeginAlign(block);
2214 uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2216 lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2218 "Merge vertices in adjacent duplicates");
2219 uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2221 lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2224 "Merge vertices in first duplicate with vertices"
2225 " in last duplicate");
2226 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2227 lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2229 "Limit below which to merge vertices");
2233 uiBlockBeginAlign(block);
2234 uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2235 "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2236 &amd->offset_type, 0, 0, 0, 0,
2237 "Add an object transformation to the total offset");
2238 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2239 "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2241 "Object from which to take offset transformation");
2242 uiBlockEndAlign(block);
2245 but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2246 B_CHANGEDEP, "Start cap: ",
2247 lx, (cy -= 19), halfwidth, 19,
2249 "Mesh object to use as start cap");
2250 uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2251 but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2252 B_CHANGEDEP, "End cap: ",
2253 halflx, cy, halfwidth, 19,
2255 "Mesh object to use as end cap");
2256 uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2257 } else if (md->type==eModifierType_MeshDeform) {
2258 MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
2260 uiBlockBeginAlign(block);
2261 uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage");
2262 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");
2263 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2264 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");
2266 uiBlockBeginAlign(block);
2268 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
2269 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2272 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
2273 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2274 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");
2275 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, "Invert vertex group influence");
2277 uiBlockEndAlign(block);
2278 } else if (md->type==eModifierType_ParticleSystem) {
2279 uiDefBut(block, LABEL, 1, "See Particle buttons.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2280 } else if (md->type==eModifierType_ParticleInstance) {
2281 ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
2282 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
2283 uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
2284 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");
2285 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");
2286 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");
2287 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");
2288 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");
2289 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");
2290 } else if (md->type==eModifierType_Explode) {
2291 ExplodeModifierData *emd = (ExplodeModifierData*) md;
2293 char *menustr= get_vertexgroup_menustr(ob);
2294 int defCount=BLI_countlist(&ob->defbase);
2295 if(defCount==0) emd->vgroup=0;
2297 but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr, lx, (cy-=19), buttonWidth/2,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
2298 uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2301 but=uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "", lx+buttonWidth/2, cy, buttonWidth/2,19, &emd->protect, 0.0f, 1.0f, 0, 0, "Clean vertex group edges");
2302 uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2304 but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh", lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
2305 uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2307 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");
2308 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");
2309 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");
2310 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");
2313 uiBlockEndAlign(block);
2323 uiBlockSetCol(block, color);
2324 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2325 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, "");
2326 uiBlockSetCol(block, TH_AUTO);
2328 sprintf(str, "Modifier Error: %s", md->error);
2329 uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, "");
2340 static void editing_panel_modifiers(Object *ob)
2345 int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2347 block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2348 if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2350 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2351 uiNewPanelHeight(block, 204);
2353 uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2355 sprintf(str, "To: %s", ob->id.name+2);
2356 uiDefBut(block, LABEL, 1, str, 140, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2361 md = modifiers_getVirtualModifierList(ob);
2363 for (i=0; md; i++, md=md->next) {
2364 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2365 if (md->mode&eModifierMode_Virtual) i--;
2368 if(yco < 0) uiNewPanelHeight(block, 204-yco);
2371 static char *make_key_menu(Key *key, int startindex)
2375 char *str, item[64];
2377 for (kb = key->block.first; kb; kb=kb->next, index++);
2378 str= MEM_mallocN(index*40, "key string");
2382 for (kb = key->block.first; kb; kb=kb->next, index++) {
2383 sprintf (item, "|%s%%x%d", kb->name, index);
2390 static void editing_panel_shapes(Object *ob)
2398 block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2399 uiNewPanelTabbed("Modifiers", "Editing");
2400 if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2402 /* Todo check data is library here */
2403 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2405 uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" , 10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2407 key= ob_get_key(ob);
2409 /* label aligns add button */
2410 uiDefBut(block, LABEL, 0, "", 170, 180,140,20, NULL, 0, 0, 0, 0, "");
2414 uiDefButS(block, TOG, B_RELKEY, "Relative", 170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2416 kb= BLI_findlink(&key->block, ob->shapenr-1);
2419 kb= key->block.first;
2422 uiBlockBeginAlign(block);
2423 if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2424 uiDefIconButBitS(block, TOG, OB_SHAPE_LOCK, B_LOCKKEY, icon, 10,150,25,20, &ob->shapeflag, 0, 0, 0, 0, "Always show the current Shape for this Object");
2425 uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2426 uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT, 35,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2427 strp= make_key_menu(key, 1);
2428 uiDefButS(block, MENU, B_SETKEY, strp, 55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices");
2431 uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT, 75,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2433 uiDefBut(block, TEX, B_NAMEKEY, "", 95, 150, 190, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2434 uiDefIconBut(block, BUT, B_DELKEY, ICON_X, 285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2435 uiBlockEndAlign(block);
2437 if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2438 uiBlockBeginAlign(block);
2439 make_rvk_slider(block, ob, ob->shapenr-1, 10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2440 uiDefButF(block, NUM, B_REDR, "Min ", 160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2441 uiDefButF(block, NUM, B_REDR, "Max ", 235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2442 uiBlockEndAlign(block);
2444 if(key->type && ob->shapenr!=1) {
2445 uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", 10, 90, 150,19, &kb->vgroup, 0.0, 31.0, 0, 0, "Vertex Weight Group name, to blend with Basis Shape");
2447 strp= make_key_menu(key, 0);
2448 uiDefButS(block, MENU, B_MODIFIER_RECALC, strp, 160, 90, 150,19, &kb->relative, 0.0, 0.0, 0, 0, "Shape used as a relative key");
2453 uiDefButS(block, NUM, B_DIFF, "Slurph:", 10, 60, 150, 19, &(key->slurph), -500.0, 500.0, 0, 0, "Creates a delay in amount of frames in applying keypositions, first vertex goes first");
2457 /* *************************** FONT ******************************** */
2459 static short give_vfontnr(VFont *vfont)
2464 vf= G.main->vfont.first;
2466 if(vf==vfont) return nr;
2473 static VFont *give_vfontpointer(int nr) /* nr= button */
2478 vf= G.main->vfont.first;
2480 if(tel==nr) return vf;
2484 return G.main->vfont.first;
2487 VFont *exist_vfont(char *str)
2491 vf= G.main->vfont.first;
2493 if(strcmp(vf->name, str)==0) return vf;
2499 static char *give_vfontbutstr(void)
2503 char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2505 vf= G.main->vfont.first;
2507 strcpy(di, vf->name);
2508 BLI_splitdirstring(di, fi);
2513 str= MEM_callocN(len+21, "vfontbutstr");
2514 strcpy(str, "FONTS %t");
2515 vf= G.main->vfont.first;
2518 if(vf->id.us==0) strcat(str, "|0 ");
2519 else strcat(str, "| ");
2521 strcpy(di, vf->name);
2522 BLI_splitdirstring(di, fi);
2530 static void load_buts_vfont(char *name)
2535 if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2538 vf= exist_vfont(name);
2540 vf= load_vfont(name);
2543 else id_us_plus((ID *)vf);
2545 switch(cu->curinfo.flag & CU_STYLE) {
2547 if(cu->vfontb) cu->vfontb->id.us--;
2551 if(cu->vfonti) cu->vfonti->id.us--;
2554 case (CU_BOLD|CU_ITALIC):
2555 if(cu->vfontbi) cu->vfontbi->id.us--;
2559 if(cu->vfont) cu->vfont->id.us--;
2564 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2565 BIF_undo_push("Load vector font");
2566 allqueue(REDRAWVIEW3D, 0);
2567 allqueue(REDRAWBUTSEDIT, 0);
2570 static void set_unicode_text_fs(char *file)
2572 if (file > 0) paste_unicodeText(file);
2575 void do_fontbuts(unsigned short event)
2591 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2592 allqueue(REDRAWVIEW3D, 0);
2599 case B_STYLETOSELU: style = CU_UNDERLINE; break;
2600 case B_STYLETOSELB: style = CU_BOLD; break;
2601 case B_STYLETOSELI: style = CU_ITALIC; break;
2603 if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) {
2604 text_to_curve(ob, 0);
2605 makeDispListCurveTypes(ob, 0);
2606 allqueue(REDRAWVIEW3D, 0);
2608 allqueue(REDRAWBUTSEDIT, 0);
2613 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2614 allqueue(REDRAWVIEW3D, 0);
2619 if (cu->totbox < 256) {
2620 for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
2621 cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
2624 allqueue(REDRAWBUTSEDIT, 0);
2625 allqueue(REDRAWVIEW3D, 0);
2626 text_to_curve(ob, 0);
2627 makeDispListCurveTypes(ob, 0);
2630 error("Do you really need that many text frames?");
2635 if (cu->totbox > 1) {
2636 for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
2639 allqueue(REDRAWBUTSEDIT, 0);
2640 allqueue(REDRAWVIEW3D, 0);
2641 text_to_curve(ob, 0);
2642 makeDispListCurveTypes(ob, 0);
2649 vf= give_vfontpointer(G.buts->texnr);
2650 if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
2651 else strcpy(str, U.fontdir);
2653 sa= closest_bigger_area();
2654 areawinset(sa->win);
2656 activate_fileselect(FILE_LOADFONT, "SELECT FONT", str, load_buts_vfont);
2662 if(cu && cu->vfont) {
2663 if (cu->vfont->packedfile) {
2664 if (G.fileflags & G_AUTOPACK) {
2665 if (okee("Disable AutoPack ?")) {
2666 G.fileflags &= ~G_AUTOPACK;
2670 if ((G.fileflags & G_AUTOPACK) == 0) {
2671 if (unpackVFont(cu->vfont, PF_ASK) == RET_OK) {
2672 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2673 allqueue(REDRAWVIEW3D, 0);
2677 cu->vfont->packedfile = newPackedFile(cu->vfont->name);
2681 allqueue(REDRAWHEADERS, 0);
2682 allqueue(REDRAWBUTSEDIT, 0);
2686 if (!G.obedit) { error("Only in editmode!"); return; }
2687 if (G.obedit->type != OB_FONT) return;
2688 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, load_3dtext_fs);
2692 if (!G.obedit) { error("Only in editmode!"); return; }
2693 if (G.obedit->type != OB_FONT) return;
2702 vf= give_vfontpointer(G.buts->texnr);
2704 id_us_plus((ID *)vf);
2706 switch(cu->curinfo.flag & CU_STYLE) {
2708 cu->vfontb->id.us--;
2712 cu->vfonti->id.us--;
2715 case (CU_BOLD|CU_ITALIC):
2716 cu->vfontbi->id.us--;
2724 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2726 BIF_undo_push("Set vector font");
2727 allqueue(REDRAWVIEW3D, 0);
2728 allqueue(REDRAWBUTSEDIT, 0);
2738 if(G.charstart > (0xffff - 12*6))
2739 G.charstart = 0xffff - (12*6);
2740 allqueue(REDRAWBUTSEDIT, 0);
2744 G.charstart = G.charstart - (12*6);
2747 if(G.charstart < G.charmin)
2748 G.charstart = G.charmin;
2749 allqueue(REDRAWBUTSEDIT, 0);
2753 // Create new dynamic string
2754 ds = BLI_dynstr_new();
2756 // Fill the dynamic string with entries
2759 BLI_dynstr_append(ds, "|");
2760 BLI_dynstr_append(ds, uctabname[i].name);
2763 // Create the menu string from dyn string
2764 ctmenu = BLI_dynstr_get_cstring(ds);
2766 // Call the popup menu
2767 ctevt = pupmenu_col(ctmenu, 40);
2768 G.charstart = uctabname[ctevt-1].start;
2769 G.charmin = uctabname[ctevt-1].start;
2770 G.charmax = uctabname[ctevt-1].end;
2773 BLI_dynstr_free(ds);
2777 allqueue(REDRAWVIEW3D, 0);
2778 allqueue(REDRAWBUTSEDIT, 0);
2783 G.charstart = G.charstart + (12*6);
2784 if(G.charstart > (0xffff - 12*6))
2785 G.charstart = 0xffff - (12*6);
2786 if(G.charstart > G.charmax - 12*6)
2787 G.charstart = G.charmax - 12*6;
2788 allqueue(REDRAWBUTSEDIT, 0);
2792 sa= closest_bigger_area();
2793 areawinset(sa->win);
2796 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, set_unicode_text_fs);
2803 if(cu->textoncurve && cu->textoncurve->type!=OB_CURVE) {
2804 error("Only Curve Objects");
2806 allqueue(REDRAWBUTSEDIT, 0);
2808 DAG_scene_sort(G.scene); // makes new dag
2809 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2810 allqueue(REDRAWVIEW3D, 0);
2815 #ifdef INTERNATIONAL
2816 static void editing_panel_char_type(Object *ob, Curve *cu)
2820 block= uiNewBlock(&curarea->uiblocks, "editing_panel_char_type", UI_EMBOSS, UI_HELV, curarea->win);
2821 uiNewPanelTabbed("Font", "Editing");
2822 if(uiNewPanel(curarea, block, "Char", "Editing", 640, 0, 318, 204)==0)
2825 // Set the selected font
2826 G.selfont = cu->vfont;
2828 uiDefIconBut(block, BUT, B_SETUNITEXT, ICON_TEXT, 0,210,20,20, 0, 0, 0, 0, 0, "Load Unicode Text file");
2830 // Unicode categorization selection button
2831 uiDefBut(block, BUT, B_SETCAT, "Unicode Table", 22,210,226,20, 0, 0, 0, 0, 0, "Select Unicode Table");
2832 uiDefButI(block, NUM, /*B_SETUPCHAR*/ 0, "", 250,210,50,20, &G.charstart, 0, 0xffff, 0, 0, "UT");
2834 // Character selection button
2835 uiDefBut(block, CHARTAB, B_SETCHAR, "", 0, 0, 264, 200, 0, 0, 0, 0, 0, "Select character");
2837 // Buttons to change the max, min
2838 uiDefButI(block, BUT, B_SETUPCHAR, "U", 280, 185, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table up");
2839 uiDefButI(block, BUT, B_SETDOWNCHAR, "D", 280, 0, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table down");
2843 static void editing_panel_font_type(Object *ob, Curve *cu)
2847 static int packdummy = 0;
2850 block= uiNewBlock(&curarea->uiblocks, "editing_panel_font_type", UI_EMBOSS, UI_HELV, curarea->win);
2851 if(uiNewPanel(curarea, block, "Font", "Editing", 640, 0, 470, 204)==0) return;
2853 switch(cu->curinfo.flag & CU_STYLE) {
2855 G.buts->texnr= give_vfontnr(cu->vfontb);
2858 G.buts->texnr= give_vfontnr(cu->vfonti);
2860 case (CU_BOLD|CU_ITALIC):
2861 G.buts->texnr= give_vfontnr(cu->vfontbi);
2864 G.buts->texnr= give_vfontnr(cu->vfont);
2868 strp= give_vfontbutstr();
2869 // vfd= cu->vfont->data;
2871 uiDefBut(block, BUT,B_LOADFONT, "Load", 480,188,68,20, 0, 0, 0, 0, 0, "Load a new font");
2872 uiDefButS(block, MENU, B_SETFONT, strp, 550,188,220,20, &G.buts->texnr, 0, 0, 0, 0, "Change font for object");
2874 if (cu->vfont->packedfile) {