Merge branch 'ss/node'
[plumiferos.git] / source / blender / src / buttons_editing.c
blobe1bd482f2ce7bfbe826e0fca145e1899a86f04ec
1 /**
2 * $Id: buttons_editing.c 13231 2008-01-14 10:41:36Z campbellbarton $
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
12 * about this.
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 *****
33 #include <time.h>
34 #include <math.h>
35 #include <stdlib.h>
36 #include <string.h>
38 #ifdef WIN32
39 #ifndef snprintf
40 #define snprintf _snprintf
41 #endif
42 #endif
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_radio_types.h"
70 #include "DNA_screen_types.h"
71 #include "DNA_texture_types.h"
72 #include "DNA_userdef_types.h"
73 #include "DNA_vfont_types.h"
74 #include "DNA_view3d_types.h"
75 #include "DNA_world_types.h"
76 #include "DNA_packedFile_types.h"
78 #include "BKE_blender.h"
79 #include "BKE_brush.h"
80 #include "BKE_curve.h"
81 #include "BKE_customdata.h"
82 #include "BKE_colortools.h"
83 #include "BKE_deform.h"
84 #include "BKE_depsgraph.h"
85 #include "BKE_global.h"
86 #include "BKE_key.h"
87 #include "BKE_library.h"
88 #include "BKE_main.h"
89 #include "BKE_modifier.h"
90 #include "BKE_packedFile.h"
91 #include "BKE_scene.h"
93 #include "BLI_blenlib.h"
94 #include "BLI_arithb.h"
95 #include "BLI_vfontdata.h"
96 #include "BLI_editVert.h"
97 #include "BLI_dynstr.h"
99 #include "BSE_filesel.h"
101 #include "BIF_gl.h"
102 #include "BIF_editview.h"
103 #include "BIF_editarmature.h"
104 #include "BIF_editconstraint.h"
105 #include "BIF_editdeform.h"
106 #include "BIF_editfont.h"
107 #include "BIF_editkey.h"
108 #include "BIF_editmesh.h"
109 #include "BIF_interface.h"
110 #include "BIF_meshtools.h"
111 #include "BIF_mywindow.h"
112 #include "BIF_poseobject.h"
113 #include "BIF_renderwin.h"
114 #include "BIF_resources.h"
115 #include "BIF_retopo.h"
116 #include "BIF_screen.h"
117 #include "BIF_scrarea.h"
118 #include "BIF_space.h"
119 #include "BIF_toets.h"
120 #include "BIF_toolbox.h"
121 #include "BIF_previewrender.h"
122 #include "BIF_butspace.h"
124 #ifdef WITH_VERSE
125 #include "BIF_verse.h"
126 #endif
128 #include "mydevice.h"
129 #include "blendef.h"
131 #include "BKE_action.h"
132 #include "BKE_anim.h"
133 #include "BKE_armature.h"
134 #include "BKE_constraint.h"
135 #include "BKE_curve.h"
136 #include "BKE_displist.h"
137 #include "BKE_DerivedMesh.h"
138 #include "BKE_effect.h"
139 #include "BKE_font.h"
140 #include "BKE_icons.h"
141 #include "BKE_image.h"
142 #include "BKE_ipo.h"
143 #include "BKE_lattice.h"
144 #include "BKE_material.h"
145 #include "BKE_mball.h"
146 #include "BKE_mesh.h"
147 #include "BKE_object.h"
148 #include "BKE_texture.h"
149 #include "BKE_utildefines.h"
151 #include "BIF_poseobject.h"
153 #include "BDR_drawobject.h"
154 #include "BDR_editcurve.h"
155 #include "BDR_editface.h"
156 #include "BDR_editobject.h"
157 #include "BDR_sculptmode.h"
158 #include "BDR_vpaint.h"
159 #include "BDR_unwrapper.h"
161 #include "BSE_drawview.h"
162 #include "BSE_editipo.h"
163 #include "BSE_edit.h"
164 #include "BSE_filesel.h"
165 #include "BSE_headerbuttons.h"
166 #include "BSE_trans_types.h"
167 #include "BSE_view.h"
168 #include "BSE_seqaudio.h"
170 #include "RE_render_ext.h" // make_sticky
172 #include "butspace.h" // own module
173 #include "multires.h"
175 static float editbutweight= 1.0;
176 float editbutvweight= 1;
177 static int actmcol= 0, acttface= 0, acttface_rnd = 0, actmcol_rnd = 0;
179 extern ListBase editNurb;
181 /* *************************** Unicode Character Groups ****************** */
182 unicodect uctabname[125] = {
183 {"All", "All", 0x0000, 0xffff},
184 {"Basic Latin", "Basic Latin", 0x0000, 0x007f},
185 {"Latin 1 Supp", "Latin-1 Supplement", 0x0080, 0x00ff},
187 {"Latin Ext. A.", "Latin Extended-A", 0x0100, 0x017F},
188 {"Latin Ext. B.", "Latin Extended-B", 0x0180,0x024F},
189 {"Latin Ext. Add.", "Latin Extended Additional", 0x1e00, 0x1eff},
191 {"IPA Ext", "IPA Extensions", 0x0250, 0x02AF},
192 {"Spacing Mod.", "Spacing Modifier Letters", 0x02b0, 0x02ff},
194 {"Comb. Dia.", "Combining Diacritical Marks", 0x0300, 0x036F},
195 {"Greek, Coptic", "Greek and Coptic", 0x0370, 0x03ff},
196 {"Greek Ext.", "Greek Extended", 0x1f00, 0x1fff},
198 {"Cyrillic", "Cyrillic", 0x0400, 0x04ff},
199 {"Cyrillic Supp.", "Cyrillic Supplementary", 0x0500, 0x052f},
201 {"Armenian", "Armenian", 0x0530, 0x058f},
202 {"Hebrew", "Hebrew", 0x0590, 0x05ff},
205 {"Arabic", "Arabic", 0x0600, 0x06ff},
206 {"Syriac", "Syriac", 0x0700, 0x074f},
208 {"Thaana", "Thaana", 0x0780, 0x07bf},
209 {"Devanagari", "Devanagari", 0x0900, 0x097f},
211 {"Bengali", "Bengali", 0x0980, 0x09ff},
212 {"Gurmukhi", "Gurmukhi", 0x0a00, 0x0a7f},
214 {"Gujarati", "Gujarati", 0x0a80, 0x0aff},
215 {"Oriya", "Oriya", 0x0b00, 0x0b7f},
217 {"Tamil", "Tamil", 0x0b80, 0x0bff},
218 {"Tegulu", "Tegulu", 0x0c00, 0x0c7f},
220 {"Kannada", "Kannada", 0x0c80, 0x0cff},
221 {"Malayalam", "Malayalam", 0x0d00, 0x0d7f},
223 {"Sinhala", "Sinhala", 0x0d80, 0x0dff},
224 {"Thai", "Thai", 0x0e00, 0x0e7f},
226 {"Lao", "Lao", 0x0e80, 0x0eff},
227 {"Tibetan", "Tibetan", 0x0f00, 0x0fff},
229 {"Myanmar", "Myanmar", 0x1000, 0x109f},
230 {"Georgian", "Georgian", 0x10a0, 0x10ff},
232 {"Ethiopic", "Ethiopic", 0x1200, 0x137f},
234 {"Cherokee", "Cherokee", 0x13a0, 0x13ff},
235 {"Unif. Canadian", "Unified Canadian Aboriginal Syllabics", 0x1400, 0x167f},
237 {"Ogham", "Ogham", 0x1680, 0x169f},
238 {"Runic", "Runic", 0x16a0, 0x16ff},
240 {"Tagalog", "Tagalog", 0x1700, 0x171f},
241 {"Hanunoo", "Hanunoo", 0x1720, 0x173f},
243 {"Buhid", "Buhid", 0x1740, 0x175f},
244 {"Tagbanwa", "Tagbanwa", 0x1760, 0x177f},
246 {"Khmer", "Khmer", 0x1780, 0x17ff},
247 {"Khmer Symb", "Khmer Symbols", 0x19e0, 0x19ff},
249 {"Mongolian", "Mongolian", 0x1800, 0x18af},
251 {"Limbu", "Limbu", 0x1900, 0x194f},
252 {"Tai Le", "Tai Le", 0x1950, 0x197f},
254 {"Phon. Ext.", "Phonetic Extensions", 0x1d00, 0x1d7f},
257 {"Gen. Punct.", "General Punctutation", 0x2000, 0x206f},
258 {"Super, Sub", "Superscripts and Subscripts", 0x2070, 0x209f},
260 {"Curr. Symb.", "Currency Symbols", 0x20a0, 0x20cf},
261 {"Comb. Diacrit.", "Combining Diacritical Marks for Symbols", 0x20d0, 0x20ff},
263 {"Letter Symb", "Letterlike Symbols", 0x2100, 0x214f},
264 {"Numb. Forms", "Number Forms", 0x2150, 0x218f},
266 {"Arrows", "Arrows", 0x2190, 0x21ff},
267 {"Math Oper.", "Mathematical Operators", 0x2200, 0x22ff},
269 {"Misc. Tech.", "Miscellaneous Technical", 0x2300, 0x23ff},
270 {"Ctrl. Pict.", "Control Pictures", 0x2400, 0x243f},
272 {"OCR", "Optical Character Recognition", 0x2440, 0x245f},
273 {"Enc. Alpha", "Enclosed Alphanumerics", 0x2460, 0x24ff},
275 {"Bow Drawing", "Box Drawing", 0x2500, 0x257f},
276 {"BLock Elem.", "Block Elements", 0x2580, 0x259f},
278 {"Geom. Shapes", "Geometric Shapes", 0x25a0, 0x25ff},
279 {"Misc. Symb.", "Miscellaneous Symbols", 0x2600, 0x26ff},
281 {"Dingbats", "Dingbats", 0x2700, 0x27bf},
282 {"Misc. Math A", "Miscellaneous Mathematical Symbols-A", 0x27c0, 0x27ef},
284 {"Supp. Arrows-A", "Supplemental Arrows-A", 0x27f0, 0x27ff},
285 {"Braille Pat.", "Braille Patterns", 0x2800, 0x28ff},
287 {"Supp. Arrows-B", "Supplemental Arrows-B", 0x2900, 0x297f},
288 {"Misc. Math B", "Miscellaneous Mathematical Symbols-B", 0x2980, 0x29ff},
290 {"Supp. Math Op.", "Supplemental Mathematical Operators", 0x2a00, 0x2aff},
291 {"Misc. Symb.", "Miscellaneous Symbols and Arrows", 0x2b00, 0x2bff},
293 {"Kangxi Rad.", "Kangxi Radicals", 0x2f00, 0x2fdf},
295 {"Ideographic", "Ideographic Description Characters", 0x2ff0, 0x2fff},
297 {"Hiragana", "Hiragana", 0x3040, 0x309f},
298 {"Katakana", "Katakana", 0x30a0, 0x30ff},
299 {"Katakana Ext.", "Katakana Phonetic Extensions", 0x31f0, 0x31ff},
301 {"Bopomofo", "Bopomofo", 0x3100, 0x312f},
302 {"Bopomofo Ext.", "Bopomofo Extended", 0x31a0, 0x31bf},
304 {"Hangul", "Hangul Jamo", 0x1100, 0x11ff},
305 {"Hangul Comp.", "Hangul Compatibility Jamo", 0x3130, 0x318f},
306 {"Hangul Syll.", "Hangul Syllables", 0xac00, 0xd7af},
308 {"Kanbun", "Kanbun", 0x3190, 0x319f},
312 {"Yijing Hex.", "Yijing Hexagram Symbols", 0x4dc0, 0x4dff},
314 {"Yi Syllables", "Yi Syllables", 0xa000, 0xa48f},
315 {"Yi Radicals", "Yi Radicals", 0xa490, 0xa4cf},
317 {"High Surr.", "High Surrogate Area", 0xd800, 0xdbff},
319 {"Low Surr.", "Low Surrogates", 0xdc00, 0xdfff},
320 {"Priv. Use Area", "Private Use Area", 0xe000, 0xf8ff},
322 {"CJK Rad. Supp.", "CJK Radicals Supplement", 0x2e80, 0x2eff},
323 {"CJK Ideographs", "CJK Unified Ideographs", 0x4e00, 0x9faf},
324 {"CJK Ideog. Ext. A", "CJK Unified Ideographs Extension A", 0x3400, 0x4dbf},
325 {"CJK Ideog. Ext. B", "CJK Unified Ideographs Extension B", 0x20000, 0x2a6df},
326 {"CJK Symbols.", "CJK Symbols and Punctuation", 0x3000, 0x303f},
327 {"Enclosed CJK", "Enclosed CJK Letters and Months", 0x3200, 0x32ff},
328 {"CJK Comp.", "CJK Compatibility", 0x3300, 0x33ff},
329 {"CJK Comp. Ideog.", "CJK Compatibility Ideographs", 0xf900, 0xfaff},
330 {"CJK Comp. Forms", "CJK Compatibility Forms", 0xfe30, 0xfe4f},
331 {"CJK Comp. Supp.", "CJK Compatibility Ideographs Supplement", 0x2f800, 0x2fa1f},
333 {"Alpha. Pres. Forms", "Alphabetic Presentation Forms", 0xfb00, 0xfb4f},
335 {"Arabic Pres. A", "Arabic Presentation Forms-A", 0xfb50, 0xfdff},
336 {"Arabic Pres. B", "Arabic Presentation Forms-B", 0xfe70, 0xfeff},
338 {"Var. Sel.", "Variation Selectors", 0xfe00, 0xfe0f},
340 {"Comb. Half", "Combining Half Marks", 0xfe20, 0xfe2f},
342 {"Sml. From Var.", "Small Form Variants", 0xfe50, 0xfe6f},
344 {"Half, Full Forms", "Halfwidth and Fullwidth Forms", 0xff00, 0xffef},
345 {"Specials", "Specials", 0xfff0, 0xffff},
347 {"Lin. B Syllab.", "Linear B Syllabary", 0x10000, 0x1007f},
348 {"Lin. B Idog.", "Linear B Ideograms", 0x10080, 0x100ff},
350 {"Aegean Num.", "Aegean Numbers", 0x10100, 0x1013f},
351 {"Old Italic", "Old Italic", 0x10300, 0x1032f},
353 {"Gothic", "Gothic", 0x10330, 0x1034f},
354 {"Ugaritic", "Ugaritic", 0x10380, 0x1039f},
356 {"Deseret", "Deseret", 0x10400, 0x1044f},
357 {"Shavian", "Shavian", 0x10450, 0x1047f},
359 {"Osmanya", "Osmanya", 0x10480, 0x104af},
360 {"Cypriot Syll", "Cypriot Syllabary", 0x10800, 0x1083f},
362 {"Bysantine Mus.", "Bysantine Musical Symbols", 0x1d000, 0x1d0ff},
363 {"Music Symb.", "Musical Symbols", 0x1d100, 0x1d1ff},
365 {"Tai Xuan Symb", "Tai Xuan Jing Symbols", 0x1d300, 0x1d35f},
366 {"Math. Alpha Symb.", "Mathematical Alpanumeric Symbols", 0x1d400, 0x1d7ff},
369 {"Tags", "Tags", 0xe0000, 0xe007f},
370 {"Var. Supp", "Variation Selectors Supplement", 0xe0100, 0xe01ef},
372 {"Supp. Priv. A", "Supplementary Private Use Area-A", 0xf0000, 0xffffd},
373 {"Supp. Priv. B", "Supplementary Private Use Area-B", 0x100000, 0x10fffd}
377 /* *************************** static functions prototypes ****************** */
378 VFont *exist_vfont(char *str);
380 /* *************** */
382 void do_common_editbuts(unsigned short event) // old name, is a mix of object and editing events....
384 EditMesh *em = G.editMesh;
385 EditFace *efa;
386 Base *base;
387 Object *ob= OBACT;
388 Material *ma;
389 Nurb *nu;
390 Curve *cu;
391 BezTriple *bezt;
392 BPoint *bp;
393 unsigned int local;
394 int a, bit, index= -1;
396 switch(event) {
398 case B_MATWICH:
399 if(G.obedit && G.obedit->actcol>0) {
400 if(G.obedit->type == OB_MESH) {
401 for(efa= em->faces.first; efa; efa= efa->next) {
402 if(efa->f & SELECT) {
403 if(index== -1) index= efa->mat_nr;
404 else if(index!=efa->mat_nr) {
405 error("Mixed colors");
406 return;
411 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
412 nu= editNurb.first;
413 while(nu) {
414 if( isNurbsel(nu) ) {
415 if(index== -1) index= nu->mat_nr;
416 else if(index!=nu->mat_nr) {
417 error("Mixed colors");
418 return;
421 nu= nu->next;
424 if(index>=0) {
425 G.obedit->actcol= index+1;
426 scrarea_queue_winredraw(curarea);
429 break;
430 case B_MATNEW:
431 new_material_to_objectdata(ob);
432 scrarea_queue_winredraw(curarea);
433 BIF_undo_push("New material");
434 allqueue(REDRAWBUTSSHADING, 0);
435 allqueue(REDRAWVIEW3D_Z, 0);
436 allqueue(REDRAWOOPS, 0);
437 break;
438 case B_MATDEL:
439 delete_material_index();
440 scrarea_queue_winredraw(curarea);
441 BIF_undo_push("Delete material index");
442 allqueue(REDRAWBUTSSHADING, 0);
443 allqueue(REDRAWVIEW3D_Z, 0);
444 allqueue(REDRAWOOPS, 0);
445 break;
446 case B_MATASS:
447 if(G.obedit && G.obedit->actcol>0) {
448 if(G.obedit->type == OB_MESH) {
449 efa= em->faces.first;
450 while(efa) {
451 if(efa->f & SELECT)
452 efa->mat_nr= G.obedit->actcol-1;
453 efa= efa->next;
456 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
457 nu= editNurb.first;
458 while(nu) {
459 if( isNurbsel(nu) )
460 nu->mat_nr= nu->charidx= G.obedit->actcol-1;
461 nu= nu->next;
464 else if (G.obedit->type == OB_FONT) {
465 if (mat_to_sel()) {
466 allqueue(REDRAWVIEW3D, 0);
469 allqueue(REDRAWVIEW3D_Z, 0);
470 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
471 shade_buttons_change_3d();
472 BIF_undo_push("Assign material index");
474 break;
475 case B_MATASS_BROWSE:
476 /* if slot available, make that index active, and assign */
477 /* else, make new slot, and assign */
478 ma= BLI_findlink(&G.main->mat, G.buts->menunr-1);
479 if(ma) {
480 ob->actcol= find_material_index(ob, ma);
481 if(ob->actcol==0) {
482 assign_material(ob, ma, ob->totcol+1);
483 ob->actcol= ob->totcol;
486 else {
487 do_common_editbuts(B_MATNEW);
489 do_common_editbuts(B_MATASS);
490 break;
492 case B_MATCOL2:
493 ma= give_current_material(ob, ob->actcol);
494 BKE_icon_changed(BKE_icon_getid((ID *)ma));
495 allqueue(REDRAWVIEW3D, 0);
496 allqueue(REDRAWBUTSEDIT, 0);
497 break;
499 case B_MATSEL:
500 case B_MATDESEL:
501 if(G.obedit) {
502 if(G.obedit->type == OB_MESH) {
503 if (event==B_MATSEL) {
504 editmesh_select_by_material(G.obedit->actcol-1);
505 } else {
506 editmesh_deselect_by_material(G.obedit->actcol-1);
508 allqueue(REDRAWVIEW3D, 0);
510 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
511 nu= editNurb.first;
512 while(nu) {
513 if(nu->mat_nr==G.obedit->actcol-1) {
514 if(nu->bezt) {
515 a= nu->pntsu;
516 bezt= nu->bezt;
517 while(a--) {
518 if(bezt->hide==0) {
519 if(event==B_MATSEL) {
520 bezt->f1 |= 1;
521 bezt->f2 |= 1;
522 bezt->f3 |= 1;
524 else {
525 bezt->f1 &= ~1;
526 bezt->f2 &= ~1;
527 bezt->f3 &= ~1;
530 bezt++;
533 else if(nu->bp) {
534 a= nu->pntsu*nu->pntsv;
535 bp= nu->bp;
536 while(a--) {
537 if(bp->hide==0) {
538 if(event==B_MATSEL) bp->f1 |= 1;
539 else bp->f1 &= ~1;
541 bp++;
545 nu= nu->next;
547 BIF_undo_push("Select material index");
548 allqueue(REDRAWVIEW3D, 0);
551 countall();
552 break;
553 case B_HIDE:
554 if(G.obedit) {
555 if(G.obedit->type == OB_MESH) hide_mesh(0);
556 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) hideNurb(0);
558 break;
559 case B_REVEAL:
560 if(G.obedit) {
561 if(G.obedit->type == OB_MESH) reveal_mesh();
562 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) revealNurb();
564 else if(G.f & G_FACESELECT) reveal_tface();
566 break;
567 case B_SELSWAP:
568 if(G.obedit) {
569 if(G.obedit->type == OB_MESH) selectswap_mesh();
570 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) selectswapNurb();
572 break;
573 case B_AUTOTEX:
574 if(ob && G.obedit==0) {
575 if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) tex_space_curve(ob->data);
577 break;
578 case B_DOCENTER:
579 docenter(0);
580 break;
581 case B_DOCENTERNEW:
582 docenter_new();
583 break;
584 case B_DOCENTERCURSOR:
585 docenter_cursor();
586 break;
587 case B_SETSMOOTH:
588 case B_SETSOLID:
589 if(G.obedit) {
590 if(G.obedit->type == OB_MESH) {
591 mesh_set_smooth_faces((event==B_SETSMOOTH));
593 else {
594 nurb_set_smooth((event==B_SETSMOOTH));
597 else if(G.vd) {
598 base= FIRSTBASE;
599 while(base) {
600 if(TESTBASELIB(base)) {
601 if(base->object->type==OB_MESH) {
602 mesh_set_smooth_flag(base->object, (event==B_SETSMOOTH));
604 else if ELEM(base->object->type, OB_SURF, OB_CURVE) {
605 cu= base->object->data;
606 nu= cu->nurb.first;
607 while(nu) {
608 if(event==B_SETSMOOTH) nu->flag |= ME_SMOOTH;
609 else nu->flag &= ~ME_SMOOTH;
610 nu= nu->next;
612 makeDispListCurveTypes(base->object, 0);
615 base= base->next;
617 allqueue(REDRAWVIEW3D, 0);
619 if(event == B_SETSMOOTH) BIF_undo_push("Set Smooth");
620 else BIF_undo_push("Set Solid");
622 break;
623 case B_CHANGEDEP:
624 DAG_scene_sort(G.scene); // makes new dag
625 if(ob) ob->recalc |= OB_RECALC;
626 allqueue(REDRAWVIEW3D, 0);
627 break;
629 case B_ADDKEY:
630 insert_shapekey(ob);
631 break;
632 case B_SETKEY:
633 ob->shapeflag |= OB_SHAPE_TEMPLOCK;
634 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
635 allqueue(REDRAWVIEW3D, 0);
636 allqueue(REDRAWIPO, 0);
637 allqueue(REDRAWBUTSEDIT, 0);
638 break;
639 case B_LOCKKEY:
640 ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
641 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
642 allqueue(REDRAWVIEW3D, 0);
643 allqueue(REDRAWIPO, 0);
644 allqueue(REDRAWBUTSEDIT, 0);
645 break;
646 case B_NEXTKEY:
648 Key *key= ob_get_key(ob);
649 if(ob->shapenr == BLI_countlist(&key->block))
650 ob->shapenr= 1;
651 else ob->shapenr++;
652 do_common_editbuts(B_SETKEY);
653 break;
655 case B_PREVKEY:
657 Key *key= ob_get_key(ob);
658 if(ob->shapenr <= 1)
659 ob->shapenr= BLI_countlist(&key->block);
660 else ob->shapenr--;
661 do_common_editbuts(B_SETKEY);
662 break;
664 case B_NAMEKEY:
665 allspace(REMAKEIPO, 0);
666 allqueue (REDRAWIPO, 0);
667 break;
668 case B_DELKEY:
669 delete_key(OBACT);
670 allqueue(REDRAWACTION, 0);
671 break;
674 default:
675 if (G.vd==NULL)
676 break;
678 if(event>=B_OBLAY && event<=B_OBLAY+31) {
679 local= BASACT->lay & 0xFF000000;
680 BASACT->lay -= local;
681 if(BASACT->lay==0 || (G.qual & LR_SHIFTKEY)==0) {
682 bit= event-B_OBLAY;
683 BASACT->lay= 1<<bit;
684 scrarea_queue_winredraw(curarea);
686 BASACT->lay += local;
687 /* optimal redraw */
688 if( (ob->lay & G.vd->lay) && (BASACT->lay & G.vd->lay) );
689 else if( (ob->lay & G.vd->lay)==0 && (BASACT->lay & G.vd->lay)==0 );
690 else {
691 allqueue(REDRAWVIEW3D, 0);
692 DAG_scene_sort(G.scene);
694 ob->lay= BASACT->lay;
700 /* *************************** MESH ******************************** */
702 static void verify_customdata_name_func(void *data1, void *data2)
704 CustomData *data= (CustomData*)data1;
705 CustomDataLayer *layer= (CustomDataLayer*)data2;
707 CustomData_set_layer_unique_name(data, layer - data->layers);
710 static void delete_customdata_layer(void *data1, void *data2)
712 Mesh *me= (Mesh*)data1;
713 CustomData *data= (G.obedit)? &G.editMesh->fdata: &me->fdata;
714 CustomDataLayer *layer= (CustomDataLayer*)data2;
715 void *actlayerdata, *rndlayerdata, *layerdata=layer->data;
716 int type= layer->type;
717 int index= CustomData_get_layer_index(data, type);
718 int i, actindex, rndindex;
720 /*ok, deleting a non-active layer needs to preserve the active layer indices.
721 to do this, we store a pointer to the .data member of both layer and the active layer,
722 (to detect if we're deleting the active layer or not), then use the active
723 layer data pointer to find where the active layer has ended up.
725 this is necassary because the deletion functions only support deleting the active
726 layer. */
727 actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
728 rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
729 CustomData_set_layer_active(data, type, layer - &data->layers[index]);
731 /* Multires is handled seperately because the display data is separate
732 from the data stored in multires */
733 if(me && me->mr) {
734 multires_delete_layer(me, &me->mr->fdata, type, layer - &data->layers[index]);
736 else if(G.obedit) {
737 EM_free_data_layer(data, type);
739 else if(me) {
740 CustomData_free_layer_active(data, type, me->totface);
741 mesh_update_customdata_pointers(me);
744 if(!CustomData_has_layer(data, type)) {
745 if(type == CD_MCOL && (G.f & G_VERTEXPAINT))
746 G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */
747 if(type == CD_MTFACE && (G.f & G_FACESELECT))
748 set_faceselect(); /* get out of faceselect mode */
751 /*reconstruct active layer*/
752 if (actlayerdata != layerdata) {
753 /*find index. . .*/
754 actindex = CustomData_get_layer_index(data, type);
755 for (i=actindex; i<data->totlayer; i++) {
756 if (data->layers[i].data == actlayerdata) {
757 actindex = i - actindex;
758 break;
762 /*set index. . .*/
763 CustomData_set_layer_active(data, type, actindex);
766 if (rndlayerdata != layerdata) {
767 /*find index. . .*/
768 rndindex = CustomData_get_layer_index(data, type);
769 for (i=rndindex; i<data->totlayer; i++) {
770 if (data->layers[i].data == rndlayerdata) {
771 rndindex = i - rndindex;
772 break;
776 /*set index. . .*/
777 CustomData_set_layer_render(data, type, rndindex);
781 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
783 if(type == CD_MTFACE)
784 BIF_undo_push("Delete UV Texture");
785 else if(type == CD_MCOL)
786 BIF_undo_push("Delete Vertex Color");
788 allqueue(REDRAWVIEW3D, 0);
789 allqueue(REDRAWIMAGE, 0);
790 allqueue(REDRAWBUTSEDIT, 0);
793 static int customdata_buttons(
794 uiBlock *block, Mesh *me, CustomData *data,
795 int type, int *activep, int *renderp,
796 int setevt, int setevt_rnd, int newevt,
797 char *label, char *shortlabel, char *browsetip, char *browsetip_rnd,
798 char *newtip, char *deltip, int x, int y)
800 CustomDataLayer *layer;
801 uiBut *but;
802 int i, count= CustomData_number_of_layers(data, type);
804 if(count >= MAX_MTFACE) {
805 uiDefBut(block, LABEL, 0, label, x,y,220,19, 0, 0.0, 0, 0, 0, "");
807 else {
808 uiDefBut(block, LABEL, 0, label, x,y,140,19, 0, 0.0, 0, 0, 0, "");
809 uiBlockBeginAlign(block);
810 uiDefBut(block, BUT, newevt, "New", x+140,y,80,19, 0,0,0,0,0, newtip);
811 uiBlockEndAlign(block);
814 y -= (count)? 24: 19;
816 uiBlockBeginAlign(block);
817 for (count=1, i=0; i<data->totlayer; i++) {
818 layer= &data->layers[i];
820 if(layer->type == type) {
821 *activep= layer->active + 1;
822 *renderp= layer->active_rnd + 1;
824 uiDefIconButI(block, ROW, setevt, ICON_VIEW3D, x,y,25,19, activep, 1.0, count, 0, 0, browsetip);
825 uiDefIconButI(block, ROW, setevt_rnd, ICON_SCENE, x+25,y,25,19, renderp, 1.0, count, 0, 0, browsetip_rnd);
826 but=uiDefBut(block, TEX, setevt, "", x+50,y,145,19, layer->name, 0.0, 31.0, 0, 0, label);
827 uiButSetFunc(but, verify_customdata_name_func, data, layer);
828 but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, deltip);
829 uiButSetFunc(but, delete_customdata_layer, me, layer);
832 count++;
833 y -= 19;
836 uiBlockEndAlign(block);
838 return y;
841 static void editing_panel_mesh_type(Object *ob, Mesh *me)
843 uiBlock *block;
844 uiBut *but;
845 float val;
846 CustomData *fdata;
847 int yco;
849 block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_type", UI_EMBOSS, UI_HELV, curarea->win);
850 if( uiNewPanel(curarea, block, "Mesh", "Editing", 320, 0, 318, 204)==0) return;
851 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
853 uiBlockBeginAlign(block);
854 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");
855 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");
856 uiBlockEndAlign(block);
858 /* Retopo */
859 if(G.obedit) {
860 uiBlockBeginAlign(block);
861 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");
862 uiButSetFunc(but,retopo_toggle,ob,me);
863 if(G.scene->toolsettings->retopo_mode) {
864 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.");
865 uiButSetFunc(but,retopo_paint_toggle,ob,me);
866 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");
867 uiButSetFunc(but,retopo_do_all_cb,ob,me);
869 uiBlockEndAlign(block);
872 uiBlockBeginAlign(block);
873 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");
874 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");
875 uiDefBut(block, BUT,B_DOCENTERCURSOR, "Center Cursor", 10, 60, 170, 19, 0, 0, 0, 0, 0, "Shifts object's origin to cursor location");
876 uiBlockEndAlign(block);
878 uiBlockBeginAlign(block);
879 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");
880 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");
881 uiBlockEndAlign(block);
883 uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, B_REDR, "TexMesh: ", 190,180,220,19, &me->texcomesh, "Derive texture coordinates from another mesh.");
885 if(me->msticky) val= 1.0; else val= 0.0;
886 uiDefBut(block, LABEL, 0, "Sticky", 190,155,140,19, 0, val, 0, 0, 0, "");
887 uiBlockBeginAlign(block);
888 if(me->msticky==NULL) {
889 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");
891 else uiDefBut(block, BUT, B_DELSTICKY, "Delete", 330,155, 80,19, 0, 0, 0, 0, 0, "Deletes Sticky texture coordinates");
892 uiBlockEndAlign(block);
894 fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata;
895 yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd,
896 B_SETTFACE, B_SETTFACE_RND, B_NEWTFACE, "UV Texture", "UV Texture:",
897 "Set active UV texture", "Set rendering UV texture", "Creates a new UV texture layer",
898 "Removes the current UV texture layer", 190, 130);
900 yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd,
901 B_SETMCOL, B_SETMCOL_RND, B_NEWMCOL, "Vertex Color", "Vertex Color:",
902 "Sets active vertex color layer", "Sets rendering vertex color layer", "Creates a new vertex color layer",
903 "Removes the current vertex color layer", 190, yco-5);
905 if(yco < 0)
906 uiNewPanelHeight(block, 204 - yco);
909 /* *************************** MODIFIERS ******************************** */
911 void do_modifier_panels(unsigned short event)
913 Object *ob = OBACT;
915 switch(event) {
916 case B_MODIFIER_REDRAW:
917 allqueue(REDRAWBUTSEDIT, 0);
918 allqueue(REDRAWOOPS, 0);
919 break;
921 case B_MODIFIER_RECALC:
922 ob->softflag |= OB_SB_RESET;
923 allqueue(REDRAWBUTSEDIT, 0);
924 allqueue(REDRAWVIEW3D, 0);
925 allqueue(REDRAWIMAGE, 0);
926 allqueue(REDRAWOOPS, 0);
927 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
928 object_handle_update(ob);
929 countall();
930 break;
934 static void modifiers_add(void *ob_v, int type)
936 Object *ob = ob_v;
937 ModifierTypeInfo *mti = modifierType_getInfo(type);
939 if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
940 ModifierData *md = ob->modifiers.first;
942 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
943 md = md->next;
946 BLI_insertlinkbefore(&ob->modifiers, md, modifier_new(type));
947 } else {
948 BLI_addtail(&ob->modifiers, modifier_new(type));
950 BIF_undo_push("Add modifier");
953 typedef struct MenuEntry {
954 char *name;
955 int ID;
956 } MenuEntry;
958 static int menuEntry_compare_names(const void *entry1, const void *entry2)
960 return strcmp(((MenuEntry *)entry1)->name, ((MenuEntry *)entry2)->name);
963 static uiBlock *modifiers_add_menu(void *ob_v)
965 Object *ob = ob_v;
966 uiBlock *block;
967 int i, yco=0;
968 int numEntries = 0;
969 MenuEntry entries[NUM_MODIFIER_TYPES];
971 block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu",
972 UI_EMBOSSP, UI_HELV, curarea->win);
973 uiBlockSetButmFunc(block, modifiers_add, ob);
975 for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
976 ModifierTypeInfo *mti = modifierType_getInfo(i);
978 /* Only allow adding through appropriate other interfaces */
979 if(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue;
981 if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
982 (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
983 entries[numEntries].name = mti->name;
984 entries[numEntries].ID = i;
986 ++numEntries;
990 qsort(entries, numEntries, sizeof(*entries), menuEntry_compare_names);
993 for(i = 0; i < numEntries; ++i)
994 uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name,
995 0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, "");
997 uiTextBoundsBlock(block, 50);
998 uiBlockSetDirection(block, UI_DOWN);
1000 return block;
1003 static void modifiers_del(void *ob_v, void *md_v)
1005 Object *ob = ob_v;
1006 ModifierData *md;
1008 /* It seems on rapid delete it is possible to
1009 * get called twice on same modifier, so make
1010 * sure it is in list.
1012 for (md=ob->modifiers.first; md; md=md->next)
1013 if (md==md_v)
1014 break;
1016 if (!md)
1017 return;
1019 BLI_remlink(&ob->modifiers, md_v);
1021 modifier_free(md_v);
1023 BIF_undo_push("Del modifier");
1026 int mod_moveUp(void *ob_v, void *md_v)
1028 Object *ob = ob_v;
1029 ModifierData *md = md_v;
1031 if (md->prev) {
1032 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1034 if (mti->type!=eModifierTypeType_OnlyDeform) {
1035 ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
1037 if (nmti->flags&eModifierTypeFlag_RequiresOriginalData)
1038 return -1;
1041 BLI_remlink(&ob->modifiers, md);
1042 BLI_insertlink(&ob->modifiers, md->prev->prev, md);
1045 return 0;
1048 static void modifiers_moveUp(void *ob_v, void *md_v)
1050 if( mod_moveUp( ob_v, md_v ) )
1051 error("Cannot move above a modifier requiring original data.");
1052 else
1053 BIF_undo_push("Move modifier");
1056 int mod_moveDown(void *ob_v, void *md_v)
1058 Object *ob = ob_v;
1059 ModifierData *md = md_v;
1061 if (md->next) {
1062 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1064 if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
1065 ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
1067 if (nmti->type!=eModifierTypeType_OnlyDeform)
1068 return -1;
1071 BLI_remlink(&ob->modifiers, md);
1072 BLI_insertlink(&ob->modifiers, md->next, md);
1075 return 0;
1078 static void modifiers_moveDown(void *ob_v, void *md_v)
1080 if( mod_moveDown( ob_v, md_v ) )
1081 error("Cannot move beyond a non-deforming modifier.");
1082 else
1083 BIF_undo_push("Move modifier");
1086 static void modifier_testLatticeObj(char *name, ID **idpp)
1088 ID *id;
1090 for (id= G.main->object.first; id; id= id->next) {
1091 if( strcmp(name, id->name+2)==0 ) {
1092 if (((Object *)id)->type != OB_LATTICE) {
1093 error ("Lattice deform object must be a lattice");
1094 break;
1096 *idpp= id;
1097 return;
1100 *idpp= 0;
1103 static void modifier_testCurveObj(char *name, ID **idpp)
1105 ID *id;
1107 for (id= G.main->object.first; id; id= id->next) {
1108 if( strcmp(name, id->name+2)==0 ) {
1109 if (((Object *)id)->type != OB_CURVE) {
1110 error ("Curve deform object must be a curve");
1111 break;
1113 *idpp= id;
1114 return;
1117 *idpp= 0;
1120 static void modifier_testMeshObj(char *name, ID **idpp)
1122 ID *id;
1124 for (id= G.main->object.first; id; id= id->next) {
1125 /* no boolean on its own object */
1126 if(id != (ID *)OBACT) {
1127 if( strcmp(name, id->name+2)==0 ) {
1128 if (((Object *)id)->type != OB_MESH) {
1129 error ("Boolean modifier object must be a mesh");
1130 break;
1132 *idpp= id;
1133 return;
1137 *idpp= NULL;
1140 static void modifier_testArmatureObj(char *name, ID **idpp)
1142 ID *id;
1144 for (id= G.main->object.first; id; id= id->next) {
1145 if( strcmp(name, id->name+2)==0 ) {
1146 if (((Object *)id)->type != OB_ARMATURE) {
1147 error ("Armature deform object must be an armature");
1148 break;
1150 *idpp= id;
1151 return;
1154 *idpp= 0;
1157 static void modifier_testTexture(char *name, ID **idpp)
1159 ID *id;
1161 for(id = G.main->tex.first; id; id = id->next) {
1162 if(strcmp(name, id->name + 2) == 0) {
1163 *idpp = id;
1164 /* texture gets user, objects not: delete object = clear modifier */
1165 id_us_plus(id);
1166 return;
1169 *idpp = 0;
1172 #if 0 /* this is currently unused, but could be useful in the future */
1173 static void modifier_testMaterial(char *name, ID **idpp)
1175 ID *id;
1177 for(id = G.main->mat.first; id; id = id->next) {
1178 if(strcmp(name, id->name + 2) == 0) {
1179 *idpp = id;
1180 return;
1183 *idpp = 0;
1185 #endif
1187 static void modifier_testImage(char *name, ID **idpp)
1189 ID *id;
1191 for(id = G.main->image.first; id; id = id->next) {
1192 if(strcmp(name, id->name + 2) == 0) {
1193 *idpp = id;
1194 return;
1197 *idpp = 0;
1200 /* autocomplete callback for ID buttons */
1201 void autocomplete_image(char *str, void *arg_v)
1203 /* search if str matches the beginning of an ID struct */
1204 if(str[0]) {
1205 AutoComplete *autocpl = autocomplete_begin(str, 22);
1206 ID *id;
1208 for(id = G.main->image.first; id; id = id->next)
1209 autocomplete_do_name(autocpl, id->name+2);
1211 autocomplete_end(autocpl, str);
1215 /* autocomplete callback for ID buttons */
1216 void autocomplete_meshob(char *str, void *arg_v)
1218 /* search if str matches the beginning of an ID struct */
1219 if(str[0]) {
1220 AutoComplete *autocpl = autocomplete_begin(str, 22);
1221 ID *id;
1223 for(id = G.main->object.first; id; id = id->next)
1224 if(((Object *)id)->type == OB_MESH)
1225 autocomplete_do_name(autocpl, id->name+2);
1227 autocomplete_end(autocpl, str);
1231 static void modifiers_applyModifier(void *obv, void *mdv)
1233 Object *ob = obv;
1234 ModifierData *md = mdv;
1235 DerivedMesh *dm;
1236 Mesh *me = ob->data;
1237 int converted = 0;
1239 if (G.obedit) {
1240 error("Modifiers cannot be applied in editmode");
1241 return;
1242 } else if (((ID*) ob->data)->us>1) {
1243 error("Modifiers cannot be applied to multi-user data");
1244 return;
1247 if (md!=ob->modifiers.first) {
1248 if (!okee("Modifier is not first"))
1249 return;
1252 if (ob->type==OB_MESH) {
1253 if(me->mr && multires_modifier_warning()) {
1254 error("Modifier changes topology; cannot apply with multires active");
1255 return;
1257 if(me->key) {
1258 error("Modifier cannot be applied to Mesh with Shape Keys");
1259 return;
1262 sculptmode_pmv_off(me);
1264 dm = mesh_create_derived_for_modifier(ob, md);
1265 if (!dm) {
1266 error("Modifier is disabled or returned error, skipping apply");
1267 return;
1270 DM_to_mesh(dm, me);
1271 converted = 1;
1273 dm->release(dm);
1275 else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
1276 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1277 Curve *cu = ob->data;
1278 int numVerts;
1279 float (*vertexCos)[3];
1281 if (!okee("Apply will only change CV points, not tesselated/bevel vertices"))
1282 return;
1284 if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) {
1285 error("Modifier is disabled, skipping apply");
1286 return;
1289 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
1290 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
1291 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
1293 converted = 1;
1295 MEM_freeN(vertexCos);
1297 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1299 else {
1300 error("Cannot apply modifier for this object type");
1301 return;
1304 if (converted) {
1305 BLI_remlink(&ob->modifiers, md);
1306 modifier_free(md);
1308 BIF_undo_push("Apply modifier");
1312 static void modifiers_copyModifier(void *ob_v, void *md_v)
1314 Object *ob = ob_v;
1315 ModifierData *md = md_v;
1316 ModifierData *nmd = modifier_new(md->type);
1318 modifier_copyData(md, nmd);
1320 BLI_insertlink(&ob->modifiers, md, nmd);
1322 BIF_undo_push("Copy modifier");
1325 static void modifiers_setOnCage(void *ob_v, void *md_v)
1327 Object *ob = ob_v;
1328 ModifierData *md;
1330 int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1332 for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1333 if( md == md_v ) {
1334 if( i >= cageIndex )
1335 md->mode ^= eModifierMode_OnCage;
1336 break;
1340 static void modifiers_selectHookParent(void *ob_v, void *md_v)
1342 HookModifierData *hmd;
1343 Object *ob;
1344 Base *base;
1346 hmd= (HookModifierData *) md_v;
1347 ob= hmd->object;
1349 deselectall();
1350 base= FIRSTBASE;
1351 while(base) {
1352 if(base->object==ob) {
1353 if(!(base->flag & SELECT))
1354 base->flag|= SELECT;
1355 break;
1357 base= base->next;
1360 set_active_base(base);
1361 allqueue(REDRAWBUTSLOGIC, 0);
1362 allqueue(REDRAWDATASELECT, 0);
1363 allqueue(REDRAWBUTSOBJECT, 0);
1364 allqueue(REDRAWACTION, 0);
1365 allqueue(REDRAWNLA, 0);
1366 allqueue(REDRAWTIME, 0);
1367 allqueue(REDRAWHEADERS, 0);
1368 allqueue(REDRAWVIEW3D, 0);
1371 static void modifiers_clearHookOffset(void *ob_v, void *md_v)
1373 Object *ob = ob_v;
1374 ModifierData *md = md_v;
1375 HookModifierData *hmd = (HookModifierData*) md;
1377 if (hmd->object) {
1378 Mat4Invert(hmd->object->imat, hmd->object->obmat);
1379 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1380 BIF_undo_push("Clear hook offset");
1384 static void modifiers_cursorHookCenter(void *ob_v, void *md_v)
1386 Object *ob = ob_v;
1387 ModifierData *md = md_v;
1388 HookModifierData *hmd = (HookModifierData*) md;
1390 if (G.vd) {
1391 float *curs = give_cursor();
1392 float bmat[3][3], imat[3][3];
1394 where_is_object(ob);
1396 Mat3CpyMat4(bmat, ob->obmat);
1397 Mat3Inv(imat, bmat);
1399 curs= give_cursor();
1400 hmd->cent[0]= curs[0]-ob->obmat[3][0];
1401 hmd->cent[1]= curs[1]-ob->obmat[3][1];
1402 hmd->cent[2]= curs[2]-ob->obmat[3][2];
1403 Mat3MulVecfl(imat, hmd->cent);
1405 BIF_undo_push("Hook cursor center");
1409 static void modifiers_selectHook(void *ob_v, void *md_v)
1411 ModifierData *md = md_v;
1412 HookModifierData *hmd = (HookModifierData*) md;
1414 hook_select(hmd);
1417 static void modifiers_reassignHook(void *ob_v, void *md_v)
1419 ModifierData *md = md_v;
1420 HookModifierData *hmd = (HookModifierData*) md;
1421 float cent[3];
1422 int *indexar, tot, ok;
1423 char name[32];
1425 ok= hook_getIndexArray(&tot, &indexar, name, cent);
1427 if (!ok) {
1428 error("Requires selected vertices or active Vertex Group");
1429 } else {
1430 if (hmd->indexar) {
1431 MEM_freeN(hmd->indexar);
1434 VECCOPY(hmd->cent, cent);
1435 hmd->indexar = indexar;
1436 hmd->totindex = tot;
1440 static void modifiers_convertToReal(void *ob_v, void *md_v)
1442 Object *ob = ob_v;
1443 ModifierData *md = md_v;
1444 ModifierData *nmd = modifier_new(md->type);
1446 modifier_copyData(md, nmd);
1447 nmd->mode &= ~eModifierMode_Virtual;
1449 BLI_addhead(&ob->modifiers, nmd);
1451 ob->partype = PAROBJECT;
1453 BIF_undo_push("Modifier convert to real");
1456 static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
1457 int *uvlayer_tmp, char *uvlayer_name)
1459 char strtmp[38];
1460 int totuv, i;
1461 CustomDataLayer *layer
1462 = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
1464 *uvlayer_tmp = -1;
1466 totuv = CustomData_number_of_layers(data, CD_MTFACE);
1468 *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
1469 "menu_string");
1470 sprintf(*menu_string, "UV Layer%%t");
1471 for(i = 0; i < totuv; i++) {
1472 /* assign first layer as uvlayer_name if uvlayer_name is null. */
1473 if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
1474 sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
1475 strcat(*menu_string, strtmp);
1476 layer++;
1479 /* there is no uvlayer defined, or else it was deleted. Assign active
1480 * layer, then recalc modifiers.
1482 if(*uvlayer_tmp == -1) {
1483 if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
1484 *uvlayer_tmp = 1;
1485 layer = data->layers;
1486 for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
1487 i++, layer++) {
1488 if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
1490 strcpy(uvlayer_name, layer->name);
1492 /* update the modifiers */
1493 do_modifier_panels(B_MODIFIER_RECALC);
1494 } else {
1495 /* ok we have no uv layers, so make sure menu button knows that.*/
1496 *uvlayer_tmp = 0;
1501 void set_displace_uvlayer(void *arg1, void *arg2)
1503 DisplaceModifierData *dmd=arg1;
1504 CustomDataLayer *layer = arg2;
1506 /*check we have UV layers*/
1507 if (dmd->uvlayer_tmp < 1) return;
1508 layer = layer + (dmd->uvlayer_tmp-1);
1510 strcpy(dmd->uvlayer_name, layer->name);
1513 void set_uvproject_uvlayer(void *arg1, void *arg2)
1515 UVProjectModifierData *umd=arg1;
1516 CustomDataLayer *layer = arg2;
1518 /*check we have UV layers*/
1519 if (umd->uvlayer_tmp < 1) return;
1520 layer = layer + (umd->uvlayer_tmp-1);
1522 strcpy(umd->uvlayer_name, layer->name);
1525 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
1527 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1528 uiBut *but;
1529 int isVirtual = md->mode&eModifierMode_Virtual;
1530 int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
1531 int editing = (G.obedit==ob);
1532 short height=26, width = 295, buttonWidth = width-120-10;
1533 char str[128];
1535 /* rounded header */
1536 uiBlockSetCol(block, color);
1537 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1538 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0,
1539 (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, "");
1540 uiBlockSetCol(block, TH_AUTO);
1542 /* open/close icon */
1543 if (!isVirtual) {
1544 uiBlockSetEmboss(block, UI_EMBOSSN);
1545 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");
1548 uiBlockSetEmboss(block, UI_EMBOSS);
1550 if (isVirtual) {
1551 sprintf(str, "%s parent deform", md->name);
1552 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name");
1554 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");
1555 uiButSetFunc(but, modifiers_convertToReal, ob, md);
1556 } else {
1557 uiBlockBeginAlign(block);
1558 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");
1560 /* Softbody not allowed in this situation, enforce! */
1561 if (md->type!=eModifierType_Softbody || !(ob->pd && ob->pd->deflect)) {
1562 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");
1563 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");
1564 if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
1565 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)");
1568 uiBlockEndAlign(block);
1570 uiBlockSetEmboss(block, UI_EMBOSSR);
1572 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
1573 int icon, color;
1575 if (index==cageIndex) {
1576 color = TH_BUT_SETTING;
1577 icon = VICON_EDITMODE_HLT;
1578 } else if (index<cageIndex) {
1579 color = TH_BUT_NEUTRAL;
1580 icon = VICON_EDITMODE_DEHLT;
1581 } else {
1582 color = TH_BUT_NEUTRAL;
1583 icon = ICON_BLANK1;
1585 uiBlockSetCol(block, color);
1586 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");
1587 uiButSetFunc(but, modifiers_setOnCage, ob, md);
1588 uiBlockSetCol(block, TH_AUTO);
1591 uiBlockSetCol(block, TH_BUT_ACTION);
1593 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");
1594 uiButSetFunc(but, modifiers_moveUp, ob, md);
1596 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");
1597 uiButSetFunc(but, modifiers_moveDown, ob, md);
1599 uiBlockSetEmboss(block, UI_EMBOSSN);
1601 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");
1602 uiButSetFunc(but, modifiers_del, ob, md);
1603 uiBlockSetCol(block, TH_AUTO);
1606 uiBlockSetEmboss(block, UI_EMBOSS);
1608 if (isVirtual || !(md->mode&eModifierMode_Expanded)) {
1609 y -= 18;
1610 } else {
1611 int cy = y - 8;
1612 int lx = x + width - 60 - 15;
1614 if (md->type==eModifierType_Subsurf) {
1615 height = 105;
1616 } else if (md->type==eModifierType_Lattice) {
1617 height = 48;
1618 } else if (md->type==eModifierType_Curve) {
1619 height = 72;
1620 } else if (md->type==eModifierType_Build) {
1621 height = 86;
1622 } else if (md->type==eModifierType_Mirror) {
1623 height = 86;
1624 } else if (md->type==eModifierType_EdgeSplit) {
1625 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1626 height = 48;
1627 if(emd->flags & MOD_EDGESPLIT_FROMANGLE) height += 19;
1628 } else if (md->type==eModifierType_Displace) {
1629 DisplaceModifierData *dmd = (DisplaceModifierData *)md;
1630 height = 124;
1631 if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
1632 dmd->texmapping == MOD_DISP_MAP_UV)
1633 height += 19;
1634 } else if (md->type==eModifierType_UVProject) {
1635 height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
1636 } else if (md->type==eModifierType_Decimate) {
1637 height = 48;
1638 } else if (md->type==eModifierType_Smooth) {
1639 height = 86;
1640 } else if (md->type==eModifierType_Cast) {
1641 height = 143;
1642 } else if (md->type==eModifierType_Wave) {
1643 WaveModifierData *wmd = (WaveModifierData *)md;
1644 height = 294;
1645 if(wmd->texmapping == MOD_WAV_MAP_OBJECT ||
1646 wmd->texmapping == MOD_WAV_MAP_UV)
1647 height += 19;
1648 if(wmd->flag & MOD_WAVE_NORM)
1649 height += 19;
1650 } else if (md->type==eModifierType_Armature) {
1651 height = 86;
1652 } else if (md->type==eModifierType_Hook) {
1653 HookModifierData *hmd = (HookModifierData*) md;
1654 height = 86;
1655 if (editing)
1656 height += 20;
1657 if(hmd->indexar==NULL)
1658 height += 20;
1659 } else if (md->type==eModifierType_Softbody) {
1660 height = 26;
1661 } else if (md->type==eModifierType_Boolean) {
1662 height = 48;
1663 } else if (md->type==eModifierType_Array) {
1664 height = 211;
1667 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1668 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, "");
1670 y -= 18;
1672 if (!isVirtual) {
1673 uiBlockBeginAlign(block);
1674 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");
1675 uiButSetFunc(but, modifiers_applyModifier, ob, md);
1676 if (md->type!=eModifierType_Softbody) {
1677 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");
1678 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1680 if((md->type==eModifierType_Hook) && (!editing)) {
1681 but= uiDefBut(block, BUT, B_MODIFIER_SELECT_OBJ, "Select", lx, (cy-=19), 60, 19, 0, 0, 0, 0, 0, "Select Parent Object");
1682 uiButSetFunc(but, modifiers_selectHookParent, ob, md);
1684 uiBlockEndAlign(block);
1687 lx = x + 10;
1688 cy = y + 10 - 1;
1689 uiBlockBeginAlign(block);
1690 if (md->type==eModifierType_Subsurf) {
1691 SubsurfModifierData *smd = (SubsurfModifierData*) md;
1692 char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1693 uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu, lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1694 uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:", lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1695 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");
1697 /* Disabled until non-EM DerivedMesh implementation is complete */
1700 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");
1701 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");
1704 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");
1705 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");
1706 } else if (md->type==eModifierType_Lattice) {
1707 LatticeModifierData *lmd = (LatticeModifierData*) md;
1708 uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1709 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1710 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1711 } else if (md->type==eModifierType_Curve) {
1712 CurveModifierData *cmd = (CurveModifierData*) md;
1713 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1714 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1715 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1717 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");
1718 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");
1719 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");
1720 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");
1721 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");
1722 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");
1723 } else if (md->type==eModifierType_Build) {
1724 BuildModifierData *bmd = (BuildModifierData*) md;
1725 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");
1726 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");
1727 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.");
1728 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.");
1729 } else if (md->type==eModifierType_Mirror) {
1730 MirrorModifierData *mmd = (MirrorModifierData*) md;
1731 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");
1732 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");
1733 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");
1734 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");
1735 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");
1736 uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
1737 "Mirror U",
1738 lx, (cy-=19), buttonWidth/2, 19,
1739 &mmd->flag, 0, 0, 0, 0,
1740 "Mirror the U texture coordinate around "
1741 "the 0.5 point");
1742 uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
1743 "Mirror V",
1744 lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
1745 &mmd->flag, 0, 0, 0, 0,
1746 "Mirror the V texture coordinate around "
1747 "the 0.5 point");
1748 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1749 "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1750 &mmd->mirror_ob,
1751 "Object to use as mirror");
1753 } else if (md->type==eModifierType_EdgeSplit) {
1754 EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1755 uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
1756 B_MODIFIER_RECALC, "From Edge Angle",
1757 lx, (cy -= 19), buttonWidth, 19,
1758 &emd->flags, 0, 0, 0, 0,
1759 "Split edges with high angle between faces");
1760 if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
1761 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
1762 lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
1763 0.0, 180.0, 100, 2,
1764 "Angle above which to split edges");
1766 uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
1767 B_MODIFIER_RECALC, "From Marked As Sharp",
1768 lx, (cy -= 19), buttonWidth, 19,
1769 &emd->flags, 0, 0, 0, 0,
1770 "Split edges that are marked as sharp");
1771 } else if (md->type==eModifierType_Displace) {
1772 DisplaceModifierData *dmd = (DisplaceModifierData*) md;
1773 but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
1774 lx, (cy -= 19), buttonWidth, 19,
1775 &dmd->defgrp_name, 0.0, 31.0, 0, 0,
1776 "Name of vertex group to displace"
1777 " (displace whole mesh if blank)");
1778 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1779 uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
1780 "Texture: ", lx, (cy -= 19), buttonWidth, 19,
1781 &dmd->texture,
1782 "Texture to use as displacement input");
1783 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
1784 lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
1785 0, 1, 10, 3,
1786 "Material value that gives no displacement");
1787 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
1788 lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
1789 -1000, 1000, 10, 10,
1790 "Strength of displacement");
1791 sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
1792 "Z%%x%d|Y%%x%d|X%%x%d",
1793 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
1794 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
1795 uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1796 lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
1797 0.0, 1.0, 0, 0, "Displace direction");
1798 sprintf(str, "Texture Coordinates%%t"
1799 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1800 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
1801 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
1802 uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1803 lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
1804 0.0, 1.0, 0, 0,
1805 "Texture coordinates used for displacement input");
1806 if (dmd->texmapping == MOD_DISP_MAP_UV) {
1807 char *strtmp;
1808 int i;
1809 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1810 : &((Mesh*)ob->data)->fdata;
1811 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
1812 dmd->uvlayer_name);
1813 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1814 lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
1815 0.0, 1.0, 0, 0, "Set the UV layer to use");
1816 MEM_freeN(strtmp);
1817 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1818 uiButSetFunc(but, set_displace_uvlayer, dmd,
1819 &fdata->layers[i]);
1821 if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
1822 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1823 "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1824 &dmd->map_object,
1825 "Object to get texture coordinates from");
1827 } else if (md->type==eModifierType_UVProject) {
1828 UVProjectModifierData *umd = (UVProjectModifierData *) md;
1829 int i;
1830 char *strtmp;
1831 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1832 : &((Mesh*)ob->data)->fdata;
1833 build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
1834 umd->uvlayer_name);
1835 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1836 lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
1837 0.0, 1.0, 0, 0, "Set the UV layer to use");
1838 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1839 uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
1840 MEM_freeN(strtmp);
1841 uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
1842 lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
1843 1, 1000, 100, 2,
1844 "Horizontal Aspect Ratio");
1845 uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
1846 lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
1847 &umd->aspecty,
1848 1, 1000, 100, 2,
1849 "Vertical Aspect Ratio");
1850 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
1851 lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
1852 1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
1853 "Number of objects to use as projectors");
1854 for(i = 0; i < umd->num_projectors; ++i) {
1855 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1856 "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1857 &umd->projectors[i],
1858 "Object to use as projector");
1860 uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
1861 "Image: ", lx, (cy -= 19), buttonWidth, 19,
1862 &umd->image,
1863 "Image to project (only faces with this image "
1864 "will be altered");
1865 uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
1866 uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
1867 B_MODIFIER_RECALC, "Override Image",
1868 lx, (cy -= 19), buttonWidth, 19,
1869 &umd->flags, 0, 0, 0, 0,
1870 "Override faces' current images with the "
1871 "given image");
1872 } else if (md->type==eModifierType_Decimate) {
1873 DecimateModifierData *dmd = (DecimateModifierData*) md;
1874 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");
1875 sprintf(str, "Face Count: %d", dmd->faceCount);
1876 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");
1877 } else if (md->type==eModifierType_Smooth) {
1878 SmoothModifierData *smd = (SmoothModifierData*) md;
1880 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");
1881 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");
1882 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");
1884 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)");
1885 uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:", lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
1886 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");
1887 } else if (md->type==eModifierType_Cast) {
1888 CastModifierData *cmd = (CastModifierData*) md;
1890 char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
1891 uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu, lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
1892 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");
1893 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");
1894 if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
1895 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");
1897 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");
1898 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)");
1899 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)");
1900 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)");
1901 if (ob->type == OB_MESH) {
1902 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");
1904 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");
1905 if(cmd->object) {
1906 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");
1908 } else if (md->type==eModifierType_Wave) {
1909 WaveModifierData *wmd = (WaveModifierData*) md;
1910 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");
1911 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");
1912 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");
1913 uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals", lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
1914 if (wmd->flag & MOD_WAVE_NORM){
1915 if (ob->type==OB_MESH) {
1916 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");
1917 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");
1918 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");
1920 else
1921 uiDefBut(block, LABEL, 1, "Meshes Only", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1924 uiBlockBeginAlign(block);
1925 if(wmd->speed >= 0)
1926 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Time sta:", lx,(cy-=19),buttonWidth,19, &wmd->timeoffs, -1000.0, 1000.0, 100, 0, "Specify starting frame of the wave");
1927 else
1928 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Time end:", lx,(cy-=19),buttonWidth,19, &wmd->timeoffs, -1000.0, 1000.0, 100, 0, "Specify ending frame of the wave");
1929 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:", lx,(cy-=19),buttonWidth,19, &wmd->lifetime, -1000.0, 1000.0, 100, 0, "Specify the lifespan of the wave");
1930 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:", lx,(cy-=19),buttonWidth,19, &wmd->damp, -1000.0, 1000.0, 100, 0, "Specify the dampingtime of the wave");
1931 cy -= 9;
1932 uiBlockBeginAlign(block);
1933 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");
1934 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");
1935 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)");
1936 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");
1937 uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
1938 sprintf(str, "Texture Coordinates%%t"
1939 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1940 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
1941 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
1942 uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1943 lx, (cy -= 19), 220, 19, &wmd->texmapping,
1944 0.0, 1.0, 0, 0,
1945 "Texture coordinates used for modulation input");
1946 if (wmd->texmapping == MOD_WAV_MAP_UV) {
1947 char *strtmp;
1948 int i;
1949 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1950 : &((Mesh*)ob->data)->fdata;
1951 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
1952 wmd->uvlayer_name);
1953 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1954 lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
1955 0.0, 1.0, 0, 0, "Set the UV layer to use");
1956 MEM_freeN(strtmp);
1957 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1958 uiButSetFunc(but, set_displace_uvlayer, wmd,
1959 &fdata->layers[i]);
1961 if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
1962 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1963 "Ob: ", lx, (cy -= 19), 220, 19,
1964 &wmd->map_object,
1965 "Object to get texture coordinates from");
1967 cy -= 9;
1968 uiBlockBeginAlign(block);
1969 uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:", lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
1970 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");
1971 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");
1972 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");
1973 } else if (md->type==eModifierType_Armature) {
1974 ArmatureModifierData *amd = (ArmatureModifierData*) md;
1975 uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
1977 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence");
1978 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1979 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");
1980 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");
1981 uiDefButBitS(block, TOG, ARM_DEF_QUATERNION, B_ARM_RECALCDATA, "Quaternion", lx,(cy-=19),buttonWidth + 1,20, &amd->deformflag, 0, 0, 0, 0, "Enable deform rotation interpolation with Quaternions");
1984 } else if (md->type==eModifierType_Hook) {
1985 HookModifierData *hmd = (HookModifierData*) md;
1986 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");
1987 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");
1988 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");
1989 if(hmd->indexar==NULL) {
1990 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1991 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1993 uiBlockBeginAlign(block);
1994 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");
1995 uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
1996 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");
1997 uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
1999 if (editing) {
2000 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");
2001 uiButSetFunc(but, modifiers_selectHook, ob, md);
2002 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");
2003 uiButSetFunc(but, modifiers_reassignHook, ob, md);
2005 } else if (md->type==eModifierType_Softbody) {
2006 uiDefBut(block, LABEL, 1, "See Softbody panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2007 } else if (md->type==eModifierType_Boolean) {
2008 BooleanModifierData *bmd = (BooleanModifierData*) md;
2009 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");
2010 uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
2011 } else if (md->type==eModifierType_Array) {
2012 ArrayModifierData *amd = (ArrayModifierData*) md;
2013 float range = 10000;
2014 int cytop, halfwidth = (width - 5)/2 - 15;
2015 int halflx = lx + halfwidth + 10;
2017 uiBlockSetEmboss(block, UI_EMBOSSX);
2018 uiBlockEndAlign(block);
2020 /* length parameters */
2021 uiBlockBeginAlign(block);
2022 sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
2023 "|Fit To Curve Length%%x%d",
2024 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
2025 uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2026 lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
2027 0.0, 1.0, 0, 0, "Array length calculation method");
2028 switch(amd->fit_type)
2030 case MOD_ARR_FIXEDCOUNT:
2031 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
2032 lx, (cy -= 19), buttonWidth, 19, &amd->count,
2033 1, 1000, 0, 0, "Number of duplicates to make");
2034 break;
2035 case MOD_ARR_FITLENGTH:
2036 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
2037 lx, (cy -= 19), buttonWidth, 19, &amd->length,
2038 0, range, 10, 2,
2039 "Length to fit array within");
2040 break;
2041 case MOD_ARR_FITCURVE:
2042 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
2043 B_CHANGEDEP, "Ob: ",
2044 lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
2045 "Curve object to fit array length to");
2046 break;
2048 uiBlockEndAlign(block);
2050 /* offset parameters */
2051 cy -= 10;
2052 cytop= cy;
2053 uiBlockBeginAlign(block);
2054 uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
2055 "Constant Offset", lx, (cy-=19), halfwidth, 19,
2056 &amd->offset_type, 0, 0, 0, 0,
2057 "Constant offset between duplicates "
2058 "(local coordinates)");
2059 uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2060 lx, (cy-=19), halfwidth, 19,
2061 &amd->offset[0],
2062 -range, range, 10, 3,
2063 "Constant component for duplicate offsets "
2064 "(local coordinates)");
2065 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2066 lx, (cy-=19), halfwidth, 19,
2067 &amd->offset[1],
2068 -range, range, 10, 3,
2069 "Constant component for duplicate offsets "
2070 "(local coordinates)");
2071 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2072 lx, (cy-=19), halfwidth, 19,
2073 &amd->offset[2],
2074 -range, range, 10, 3,
2075 "Constant component for duplicate offsets "
2076 "(local coordinates)");
2077 uiBlockEndAlign(block);
2079 cy= cytop;
2080 uiBlockBeginAlign(block);
2081 uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2082 "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2083 &amd->offset_type, 0, 0, 0, 0,
2084 "Offset between duplicates relative to object width "
2085 "(local coordinates)");
2086 uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2087 halflx, (cy-=19), halfwidth, 19,
2088 &amd->scale[0],
2089 -range, range, 10, 3,
2090 "Component for duplicate offsets relative to object "
2091 "width (local coordinates)");
2092 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2093 halflx, (cy-=19), halfwidth, 19,
2094 &amd->scale[1],
2095 -range, range, 10, 3,
2096 "Component for duplicate offsets relative to object "
2097 "width (local coordinates)");
2098 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2099 halflx, (cy-=19), halfwidth, 19,
2100 &amd->scale[2],
2101 -range, range, 10, 3,
2102 "Component for duplicate offsets relative to object "
2103 "width (local coordinates)");
2104 uiBlockEndAlign(block);
2106 /* vertex merging parameters */
2107 cy -= 10;
2108 cytop= cy;
2110 uiBlockBeginAlign(block);
2111 uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2112 "Merge",
2113 lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2114 0, 0, 0, 0,
2115 "Merge vertices in adjacent duplicates");
2116 uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2117 "First Last",
2118 lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2119 &amd->flags,
2120 0, 0, 0, 0,
2121 "Merge vertices in first duplicate with vertices"
2122 " in last duplicate");
2123 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2124 lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2125 0, 1.0f, 1, 4,
2126 "Limit below which to merge vertices");
2128 /* offset ob */
2129 cy = cytop;
2130 uiBlockBeginAlign(block);
2131 uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2132 "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2133 &amd->offset_type, 0, 0, 0, 0,
2134 "Add an object transformation to the total offset");
2135 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2136 "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2137 &amd->offset_ob,
2138 "Object from which to take offset transformation");
2139 uiBlockEndAlign(block);
2141 cy -= 10;
2142 but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2143 B_CHANGEDEP, "Start cap: ",
2144 lx, (cy -= 19), halfwidth, 19,
2145 &amd->start_cap,
2146 "Mesh object to use as start cap");
2147 uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2148 but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2149 B_CHANGEDEP, "End cap: ",
2150 halflx, cy, halfwidth, 19,
2151 &amd->end_cap,
2152 "Mesh object to use as end cap");
2153 uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2155 uiBlockEndAlign(block);
2157 y-=height;
2160 if (md->error) {
2161 char str[512];
2163 y -= 20;
2165 uiBlockSetCol(block, color);
2166 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2167 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, "");
2168 uiBlockSetCol(block, TH_AUTO);
2170 sprintf(str, "Modifier Error: %s", md->error);
2171 uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, "");
2174 y -= 3+6;
2176 *xco = x;
2177 *yco = y;
2180 static void editing_panel_modifiers(Object *ob)
2182 ModifierData *md;
2183 uiBlock *block;
2184 char str[64];
2185 int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2187 block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2188 if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2190 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2191 uiNewPanelHeight(block, 204);
2193 uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2195 sprintf(str, "To: %s", ob->id.name+2);
2196 uiDefBut(block, LABEL, 1, str, 140, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2198 xco = 0;
2199 yco = 160;
2201 md = modifiers_getVirtualModifierList(ob);
2203 for (i=0; md; i++, md=md->next) {
2204 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2205 if (md->mode&eModifierMode_Virtual) i--;
2208 if(yco < 0) uiNewPanelHeight(block, 204-yco);
2211 static char *make_key_menu(Key *key)
2213 KeyBlock *kb;
2214 int index= 1;
2215 char *str, item[64];
2217 for (kb = key->block.first; kb; kb=kb->next, index++);
2218 str= MEM_mallocN(index*40, "key string");
2219 str[0]= 0;
2221 index= 1;
2222 for (kb = key->block.first; kb; kb=kb->next, index++) {
2223 sprintf (item, "|%s%%x%d", kb->name, index);
2224 strcat(str, item);
2227 return str;
2230 static void editing_panel_shapes(Object *ob)
2232 uiBlock *block;
2233 Key *key= NULL;
2234 KeyBlock *kb;
2235 int icon;
2236 char *strp;
2238 block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2239 uiNewPanelTabbed("Modifiers", "Editing");
2240 if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2242 /* Todo check data is library here */
2243 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2245 uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" , 10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2247 key= ob_get_key(ob);
2248 if(key==NULL) {
2249 /* label aligns add button */
2250 uiDefBut(block, LABEL, 0, "", 170, 180,140,20, NULL, 0, 0, 0, 0, "");
2251 return;
2254 uiDefButS(block, TOG, B_RELKEY, "Relative", 170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2256 kb= BLI_findlink(&key->block, ob->shapenr-1);
2257 if(kb==NULL) {
2258 ob->shapenr= 1;
2259 kb= key->block.first;
2262 uiBlockBeginAlign(block);
2263 if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2264 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");
2265 uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2266 uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT, 35,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2267 strp= make_key_menu(key);
2268 uiDefButS(block, MENU, B_SETKEY, strp, 55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
2269 MEM_freeN(strp);
2270 uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT, 75,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2271 uiClearButLock();
2272 uiDefBut(block, TEX, B_NAMEKEY, "", 95, 150, 190, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2273 uiDefIconBut(block, BUT, B_DELKEY, ICON_X, 285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2274 uiBlockEndAlign(block);
2276 if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2277 uiBlockBeginAlign(block);
2278 make_rvk_slider(block, ob, ob->shapenr-1, 10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2279 uiDefButF(block, NUM, B_REDR, "Min ", 160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2280 uiDefButF(block, NUM, B_REDR, "Max ", 235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2281 uiBlockEndAlign(block);
2283 if(key->type && ob->shapenr!=1)
2284 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");
2286 if(key->type==0)
2287 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");
2291 /* *************************** FONT ******************************** */
2293 static short give_vfontnr(VFont *vfont)
2295 VFont *vf;
2296 short nr= 1;
2298 vf= G.main->vfont.first;
2299 while(vf) {
2300 if(vf==vfont) return nr;
2301 nr++;
2302 vf= vf->id.next;
2304 return -1;
2307 static VFont *give_vfontpointer(int nr) /* nr= button */
2309 VFont *vf;
2310 short tel= 1;
2312 vf= G.main->vfont.first;
2313 while(vf) {
2314 if(tel==nr) return vf;
2315 tel++;
2316 vf= vf->id.next;
2318 return G.main->vfont.first;
2321 VFont *exist_vfont(char *str)
2323 VFont *vf;
2325 vf= G.main->vfont.first;
2326 while(vf) {
2327 if(strcmp(vf->name, str)==0) return vf;
2328 vf= vf->id.next;
2330 return 0;
2333 static char *give_vfontbutstr(void)
2335 VFont *vf;
2336 int len= 0;
2337 char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2339 vf= G.main->vfont.first;
2340 while(vf) {
2341 strcpy(di, vf->name);
2342 BLI_splitdirstring(di, fi);
2343 len+= strlen(fi)+4;
2344 vf= vf->id.next;
2347 str= MEM_callocN(len+21, "vfontbutstr");
2348 strcpy(str, "FONTS %t");
2349 vf= G.main->vfont.first;
2350 while(vf) {
2352 if(vf->id.us==0) strcat(str, "|0 ");
2353 else strcat(str, "| ");
2355 strcpy(di, vf->name);
2356 BLI_splitdirstring(di, fi);
2358 strcat(str, fi);
2359 vf= vf->id.next;
2361 return str;
2364 static void load_buts_vfont(char *name)
2366 VFont *vf;
2367 Curve *cu;
2369 if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2370 else return;
2372 vf= exist_vfont(name);
2373 if(vf==0) {
2374 vf= load_vfont(name);
2375 if(vf==0) return;
2377 else id_us_plus((ID *)vf);
2379 switch(cu->curinfo.flag & CU_STYLE) {
2380 case CU_BOLD:
2381 if(cu->vfontb) cu->vfontb->id.us--;
2382 cu->vfontb= vf;
2383 break;
2384 case CU_ITALIC:
2385 if(cu->vfonti) cu->vfonti->id.us--;
2386 cu->vfonti= vf;
2387 break;
2388 case (CU_BOLD|CU_ITALIC):
2389 if(cu->vfontbi) cu->vfontbi->id.us--;
2390 cu->vfontbi= vf;
2391 break;
2392 default:
2393 if(cu->vfont) cu->vfont->id.us--;
2394 cu->vfont= vf;
2395 break;
2398 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2399 BIF_undo_push("Load vector font");
2400 allqueue(REDRAWVIEW3D, 0);
2401 allqueue(REDRAWBUTSEDIT, 0);
2404 static void set_unicode_text_fs(char *file)
2406 if (file) paste_unicodeText(file);
2409 void do_fontbuts(unsigned short event)
2411 Curve *cu;
2412 VFont *vf;
2413 Object *ob;
2414 ScrArea *sa;
2415 char str[80];
2416 int ctevt;
2417 char *ctmenu;
2418 DynStr *ds;
2419 int i, style=0;
2421 ob= OBACT;
2423 switch(event) {
2424 case B_MAKEFONT:
2425 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2426 allqueue(REDRAWVIEW3D, 0);
2427 break;
2429 case B_STYLETOSELU:
2430 case B_STYLETOSELB:
2431 case B_STYLETOSELI:
2432 switch (event) {
2433 case B_STYLETOSELU: style = CU_UNDERLINE; break;
2434 case B_STYLETOSELB: style = CU_BOLD; break;
2435 case B_STYLETOSELI: style = CU_ITALIC; break;
2437 if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) {
2438 text_to_curve(ob, 0);
2439 makeDispListCurveTypes(ob, 0);
2440 allqueue(REDRAWVIEW3D, 0);
2442 allqueue(REDRAWBUTSEDIT, 0);
2443 break;
2445 case B_FASTFONT:
2446 if (G.obedit) {
2447 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2448 allqueue(REDRAWVIEW3D, 0);
2450 break;
2451 case B_INSTB:
2452 cu= ob->data;
2453 if (cu->totbox < 256) {
2454 for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
2455 cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
2456 cu->actbox++;
2457 cu->totbox++;
2458 allqueue(REDRAWBUTSEDIT, 0);
2459 allqueue(REDRAWVIEW3D, 0);
2460 text_to_curve(ob, 0);
2461 makeDispListCurveTypes(ob, 0);
2463 else {
2464 error("Do you really need that many text frames?");
2466 break;
2467 case B_DELTB:
2468 cu= ob->data;
2469 if (cu->totbox > 1) {
2470 for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
2471 cu->totbox--;
2472 cu->actbox--;
2473 allqueue(REDRAWBUTSEDIT, 0);
2474 allqueue(REDRAWVIEW3D, 0);
2475 text_to_curve(ob, 0);
2476 makeDispListCurveTypes(ob, 0);
2478 break;
2479 case B_TOUPPER:
2480 to_upper();
2481 break;
2482 case B_LOADFONT:
2483 vf= give_vfontpointer(G.buts->texnr);
2484 if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
2485 else strcpy(str, U.fontdir);
2487 sa= closest_bigger_area();
2488 areawinset(sa->win);
2490 activate_fileselect(FILE_SPECIAL, "SELECT FONT", str, load_buts_vfont);
2492 break;
2493 case B_PACKFONT:
2494 if (ob) {
2495 cu= ob->data;
2496 if(cu && cu->vfont) {
2497 if (cu->vfont->packedfile) {
2498 if (G.fileflags & G_AUTOPACK) {
2499 if (okee("Disable AutoPack ?")) {
2500 G.fileflags &= ~G_AUTOPACK;
2504 if ((G.fileflags & G_AUTOPACK) == 0) {
2505 if (unpackVFont(cu->vfont, PF_ASK) == RET_OK) {
2506 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2507 allqueue(REDRAWVIEW3D, 0);
2510 } else {
2511 cu->vfont->packedfile = newPackedFile(cu->vfont->name);
2515 allqueue(REDRAWHEADERS, 0);
2516 allqueue(REDRAWBUTSEDIT, 0);
2517 break;
2519 case B_LOAD3DTEXT:
2520 if (!G.obedit) { error("Only in editmode!"); return; }
2521 if (G.obedit->type != OB_FONT) return;
2522 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, load_3dtext_fs);
2523 break;
2525 case B_LOREM:
2526 if (!G.obedit) { error("Only in editmode!"); return; }
2527 if (G.obedit->type != OB_FONT) return;
2528 add_lorem();
2530 break;
2532 case B_SETFONT:
2533 if(ob) {
2534 cu= ob->data;
2536 vf= give_vfontpointer(G.buts->texnr);
2537 if(vf) {
2538 id_us_plus((ID *)vf);
2540 switch(cu->curinfo.flag & CU_STYLE) {
2541 case CU_BOLD:
2542 cu->vfontb->id.us--;
2543 cu->vfontb= vf;
2544 break;
2545 case CU_ITALIC:
2546 cu->vfonti->id.us--;
2547 cu->vfonti= vf;
2548 break;
2549 case (CU_BOLD|CU_ITALIC):
2550 cu->vfontbi->id.us--;
2551 cu->vfontbi= vf;
2552 break;
2553 default:
2554 cu->vfont->id.us--;
2555 cu->vfont= vf;
2556 break;
2558 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2560 BIF_undo_push("Set vector font");
2561 allqueue(REDRAWVIEW3D, 0);
2562 allqueue(REDRAWBUTSEDIT, 0);
2565 break;
2567 case B_SETCHAR:
2568 G.charmin = 0x0000;
2569 G.charmax = 0xffff;
2570 if(G.charstart < 0)
2571 G.charstart = 0;
2572 if(G.charstart > (0xffff - 12*6))
2573 G.charstart = 0xffff - (12*6);
2574 allqueue(REDRAWBUTSEDIT, 0);
2575 break;
2577 case B_SETUPCHAR:
2578 G.charstart = G.charstart - (12*6);
2579 if(G.charstart < 0)
2580 G.charstart = 0;
2581 if(G.charstart < G.charmin)
2582 G.charstart = G.charmin;
2583 allqueue(REDRAWBUTSEDIT, 0);
2584 break;
2586 case B_SETCAT:
2587 // Create new dynamic string
2588 ds = BLI_dynstr_new();
2590 // Fill the dynamic string with entries
2591 for(i=0;i<104;i++)
2593 BLI_dynstr_append(ds, "|");
2594 BLI_dynstr_append(ds, uctabname[i].name);
2597 // Create the menu string from dyn string
2598 ctmenu = BLI_dynstr_get_cstring(ds);
2600 // Call the popup menu
2601 ctevt = pupmenu_col(ctmenu, 40);
2602 G.charstart = uctabname[ctevt-1].start;
2603 G.charmin = uctabname[ctevt-1].start;
2604 G.charmax = uctabname[ctevt-1].end;
2606 // Free all data
2607 BLI_dynstr_free(ds);
2608 MEM_freeN(ctmenu);
2610 // And refresh
2611 allqueue(REDRAWVIEW3D, 0);
2612 allqueue(REDRAWBUTSEDIT, 0);
2614 break;
2616 case B_SETDOWNCHAR:
2617 G.charstart = G.charstart + (12*6);
2618 if(G.charstart > (0xffff - 12*6))
2619 G.charstart = 0xffff - (12*6);
2620 if(G.charstart > G.charmax - 12*6)
2621 G.charstart = G.charmax - 12*6;
2622 allqueue(REDRAWBUTSEDIT, 0);
2623 break;
2625 case B_SETUNITEXT:
2626 sa= closest_bigger_area();
2627 areawinset(sa->win);
2629 if(ob==G.obedit) {
2630 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, set_unicode_text_fs);
2632 break;
2634 case B_TEXTONCURVE:
2635 if(ob) {
2636 cu= ob->data;
2637 if(cu->textoncurve && cu->textoncurve->type!=OB_CURVE) {
2638 error("Only Curve Objects");
2639 cu->textoncurve= 0;
2640 allqueue(REDRAWBUTSEDIT, 0);
2642 DAG_scene_sort(G.scene); // makes new dag
2643 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2644 allqueue(REDRAWVIEW3D, 0);
2649 #ifdef INTERNATIONAL
2650 static void editing_panel_char_type(Object *ob, Curve *cu)
2652 uiBlock *block;
2654 block= uiNewBlock(&curarea->uiblocks, "editing_panel_char_type", UI_EMBOSS, UI_HELV, curarea->win);
2655 uiNewPanelTabbed("Font", "Editing");
2656 if(uiNewPanel(curarea, block, "Char", "Editing", 640, 0, 318, 204)==0)
2657 return;
2659 // Set the selected font
2660 G.selfont = cu->vfont;
2662 uiDefIconBut(block, BUT, B_SETUNITEXT, ICON_TEXT, 0,210,20,20, 0, 0, 0, 0, 0, "Load Unicode Text file");
2664 // Unicode categorization selection button
2665 uiDefBut(block, BUT, B_SETCAT, "Unicode Table", 22,210,226,20, 0, 0, 0, 0, 0, "Select Unicode Table");
2666 uiDefButI(block, NUM, /*B_SETUPCHAR*/ 0, "", 250,210,50,20, &G.charstart, 0, 0xffff, 0, 0, "UT");
2668 // Character selection button
2669 uiDefBut(block, CHARTAB, B_SETCHAR, "", 0, 0, 264, 200, 0, 0, 0, 0, 0, "Select character");
2671 // Buttons to change the max, min
2672 uiDefButI(block, BUT, B_SETUPCHAR, "U", 280, 185, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table up");
2673 uiDefButI(block, BUT, B_SETDOWNCHAR, "D", 280, 0, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table down");
2675 #endif
2677 static void editing_panel_font_type(Object *ob, Curve *cu)
2679 uiBlock *block;
2680 char *strp;
2681 static int packdummy = 0;
2682 char str[32];
2684 block= uiNewBlock(&curarea->uiblocks, "editing_panel_font_type", UI_EMBOSS, UI_HELV, curarea->win);
2685 if(uiNewPanel(curarea, block, "Font", "Editing", 640, 0, 470, 204)==0) return;
2687 switch(cu->curinfo.flag & CU_STYLE) {
2688 case CU_BOLD:
2689 G.buts->texnr= give_vfontnr(cu->vfontb);
2690 break;
2691 case CU_ITALIC:
2692 G.buts->texnr= give_vfontnr(cu->vfonti);
2693 break;
2694 case (CU_BOLD|CU_ITALIC):
2695 G.buts->texnr= give_vfontnr(cu->vfontbi);
2696 break;
2697 default:
2698 G.buts->texnr= give_vfontnr(cu->vfont);
2699 break;
2702 strp= give_vfontbutstr();
2703 // vfd= cu->vfont->data;
2705 uiDefBut(block, BUT,B_LOADFONT, "Load", 480,188,68,20, 0, 0, 0, 0, 0, "Load a new font");
2706 uiDefButS(block, MENU, B_SETFONT, strp, 550,188,220,20, &G.buts->texnr, 0, 0, 0, 0, "Change font for object");
2708 if (cu->vfont->packedfile) {
2709 packdummy = 1;
2710 } else {
2711 packdummy = 0;
2713 uiDefIconButI(block, TOG|BIT|0, B_PACKFONT, ICON_PACKAGE, 772,188,20,20, &packdummy, 0, 0, 0, 0, "Pack/Unpack this font");
2715 /* This doesn't work anyway */
2716 // uiDefBut(block, LABEL, 0, vfd->name, 480, 165,314,20, 0, 0, 0, 0, 0, "Postscript name of the font");
2718 uiDefBut(block, BUT, B_LOAD3DTEXT, "Insert Text", 480, 165, 90, 20, 0, 0, 0, 0, 0, "Insert text file at cursor");
2719 uiDefBut(block, BUT, B_LOREM, "Lorem", 575, 165, 70, 20, 0, 0, 0, 0, 0, "Insert a paragraph of Lorem Ipsum at cursor");
2720 uiDefButC(block, TOG|BIT|2,B_STYLETOSELU, "U", 727,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");
2721 uiBlockBeginAlign(block);
2722 uiDefButBitC(block, TOG, CU_BOLD, B_STYLETOSELB, "B", 752,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");
2723 uiDefButBitC(block, TOG, CU_ITALIC, B_STYLETOSELI, "i", 772,165,20,20, &(cu->curinfo.flag), 0, 0, 0, 0, "");
2724 uiBlockEndAlign(block);
2726 MEM_freeN(strp);
2728 uiBlockBeginAlign(block);
2729 uiDefButS(block, ROW,B_MAKEFONT, "Left", 480,135,47,20, &cu->spacemode, 0.0,0.0, 0, 0, "Left align the text from the object center");
2730 uiDefButS(block, ROW,B_MAKEFONT, "Center", 527,135,47,20, &cu->spacemode, 0.0,1.0, 0, 0, "Middle align the text from the object center");
2731 uiDefButS(block, ROW,B_MAKEFONT, "Right", 574,135,47,20, &cu->spacemode, 0.0,2.0, 0, 0, "Right align the text from the object center");
2732 uiDefButS(block, ROW,B_MAKEFONT, "Justify", 621,135,47,20, &cu->spacemode, 0.0,3.0, 0, 0, "Fill completed lines to maximum textframe width by expanding whitespace");
2733 uiDefButS(block, ROW,B_MAKEFONT, "Flush", 668,135,47,20, &cu->spacemode, 0.0,4.0, 0, 0, "Fill every line to maximum textframe width, distributing space among all characters");
2734 uiDefBut(block, BUT, B_TOUPPER, "ToUpper", 715,135,78,20, 0, 0, 0, 0, 0, "Toggle between upper and lower case in editmode");
2735 uiBlockEndAlign(block);
2736 uiDefButBitS(block, TOG, CU_FAST, B_FASTFONT, "Fast Edit", 715,105,78,20, &cu->flag, 0, 0, 0, 0, "Don't fill polygons while editing");
2738 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_TEXTONCURVE, "TextOnCurve:", 480,105,220,19, &cu->textoncurve, "Apply a deforming curve to the text");
2739 uiDefBut(block, TEX,REDRAWVIEW3D, "Ob Family:", 480,84,220,19, cu->family, 0.0, 20.0, 0, 0, "Blender uses font from selfmade objects");
2741 uiBlockBeginAlign(block);
2742 uiDefButF(block, NUM,B_MAKEFONT, "Size:", 480,56,155,20, &cu->fsize, 0.1,10.0, 10, 0, "Size of the text");
2743 uiDefButF(block, NUM,B_MAKEFONT, "Linedist:", 640,56,155,20, &cu->linedist, 0.0,10.0, 10, 0, "Distance between text lines");
2744 uiDefButF(block, NUM,B_MAKEFONT, "Word spacing:", 795,56,155,20, &cu->wordspace, 0.0,10.0, 10, 0, "Distance factor between words");
2745 uiDefButF(block, NUM,B_MAKEFONT, "Spacing:", 480,34,155,20, &cu->spacing, 0.0,10.0, 10, 0, "Spacing of individual characters");
2746 uiDefButF(block, NUM,B_MAKEFONT, "X offset:", 640,34,155,20, &cu->xof, -50.0,50.0, 10, 0, "Horizontal position from object center");
2747 uiDefButF(block, NUM,B_MAKEFONT, "UL position:", 795,34,155,20, &cu->ulpos, -0.2,0.8, 10, 0, "Vertical position of underline");
2748 uiDefButF(block, NUM,B_MAKEFONT, "Shear:", 480,12,155,20, &cu->shear, -1.0,1.0, 10, 0, "Italic angle of the characters");
2749 uiDefButF(block, NUM,B_MAKEFONT, "Y offset:", 640,12,155,20, &cu->yof, -50.0,50.0, 10, 0, "Vertical position from object center");
2750 uiDefButF(block, NUM,B_MAKEFONT, "UL height:", 795,12,155,20, &cu->ulheight, 0.01,0.5, 10, 0, "Thickness of underline");
2751 uiBlockEndAlign(block);
2753 sprintf(str, "%d TextFrame: ", cu->totbox);
2754 uiBlockBeginAlign(block);
2755 uiDefButI(block, NUM, REDRAWVIEW3D, str, 805, 188, 145, 20, &cu->actbox, 1.0, cu->totbox, 0, 10, "Textbox to show settings for");
2756 uiDefBut(block, BUT,B_INSTB, "Insert", 805, 168, 72, 20, 0, 0, 0, 0, 0, "Insert a new text frame after the current one");
2757 uiDefBut(block, BUT,B_DELTB, "Delete", 877, 168, 73, 20, 0, 0, 0, 0, 0, "Delete current text frame and shift the others up");
2758 uiDefButF(block, NUM,B_MAKEFONT, "X:", 805, 148, 72, 20, &(cu->tb[cu->actbox-1].x), -50.0, 50.0, 10, 0, "Horizontal offset of text frame");
2759 uiDefButF(block, NUM,B_MAKEFONT, "Y:", 877, 148, 73, 20, &(cu->tb[cu->actbox-1].y), -50.0, 50.0, 10, 0, "Horizontal offset of text frame");
2760 uiDefButF(block, NUM,B_MAKEFONT, "Width:", 805, 128, 145, 20, &(cu->tb[cu->actbox-1].w), 0.0, 50.0, 10, 0, "Horizontal offset of text frame");
2761 uiDefButF(block, NUM,B_MAKEFONT, "Height:", 805, 108, 145, 20, &(cu->tb[cu->actbox-1].h), 0.0, 50.0, 10, 0, "Horizontal offset of text frame");
2762 uiBlockEndAlign(block);
2766 /* *************************** CURVE ******************************** */
2769 void do_curvebuts(unsigned short event)
2771 extern Nurb *lastnu;
2772 extern ListBase editNurb; /* from editcurve */
2773 Object *ob;
2774 Curve *cu;
2775 Nurb *nu;
2777 ob= OBACT;
2778 if(ob==0) return;
2780 switch(event) {
2782 case B_CONVERTPOLY:
2783 case B_CONVERTBEZ:
2784 case B_CONVERTBSPL:
2785 case B_CONVERTCARD:
2786 case B_CONVERTNURB:
2787 if(G.obedit) {
2788 setsplinetype(event-B_CONVERTPOLY);
2789 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2790 allqueue(REDRAWVIEW3D, 0);
2792 break;
2793 case B_UNIFU:
2794 case B_ENDPU:
2795 case B_BEZU:
2796 case B_UNIFV:
2797 case B_ENDPV:
2798 case B_BEZV:
2799 if(G.obedit) {
2800 nu= editNurb.first;
2801 while(nu) {
2802 if(isNurbsel(nu)) {
2803 if((nu->type & 7)==CU_NURBS) {
2804 if(event<B_UNIFV) {
2805 nu->flagu &= 1;
2806 nu->flagu += ((event-B_UNIFU)<<1);
2807 makeknots(nu, 1, nu->flagu>>1);
2809 else if(nu->pntsv>1) {
2810 nu->flagv &= 1;
2811 nu->flagv += ((event-B_UNIFV)<<1);
2812 makeknots(nu, 2, nu->flagv>>1);
2816 nu= nu->next;
2818 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2819 allqueue(REDRAWVIEW3D, 0);
2821 break;
2822 case B_SETWEIGHT:
2823 if(G.obedit) {
2824 weightflagNurb(1, editbutweight, 0);
2825 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2826 allqueue(REDRAWVIEW3D, 0);
2828 break;
2829 case B_SETW1:
2830 editbutweight= 1.0;
2831 scrarea_queue_winredraw(curarea);
2832 break;
2833 case B_SETW2:
2834 editbutweight= sqrt(2.0)/4.0;
2835 scrarea_queue_winredraw(curarea);
2836 break;
2837 case B_SETW3:
2838 editbutweight= 0.25;
2839 scrarea_queue_winredraw(curarea);
2840 break;
2841 case B_SETW4:
2842 editbutweight= sqrt(0.5);
2843 scrarea_queue_winredraw(curarea);
2844 break;
2845 case B_SETORDER:
2846 if(G.obedit) {
2847 nu= lastnu;
2848 if(nu && (nu->type & 7)==CU_NURBS ) {
2849 if(nu->orderu>nu->pntsu) {
2850 nu->orderu= nu->pntsu;
2851 scrarea_queue_winredraw(curarea);
2853 makeknots(nu, 1, nu->flagu>>1);
2854 if(nu->orderv>nu->pntsv) {
2855 nu->orderv= nu->pntsv;
2856 scrarea_queue_winredraw(curarea);
2858 makeknots(nu, 2, nu->flagv>>1);
2860 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2861 allqueue(REDRAWVIEW3D, 0);
2863 break;
2864 case B_SUBSURFTYPE:
2865 /* fallthrough */
2866 case B_MAKEDISP:
2867 if(G.vd) {
2868 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2869 allqueue(REDRAWVIEW3D, 0);
2870 allqueue(REDRAWBUTSALL, 0);
2871 allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
2873 break;
2875 case B_SUBDIVCURVE:
2876 subdivideNurb();
2877 break;
2878 case B_SPINNURB:
2879 if( (G.obedit==NULL) || (G.obedit->type!=OB_SURF) || (G.vd==NULL) ||
2880 ((G.obedit->lay & G.vd->lay) == 0) ) return;
2881 spinNurb(0, 0);
2882 countall();
2883 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2884 allqueue(REDRAWVIEW3D, 0);
2885 break;
2886 case B_CU3D: /* allow 3D curve */
2887 if(G.obedit) {
2888 cu= G.obedit->data;
2889 nu= editNurb.first;
2890 while(nu) {
2891 nu->type &= ~CU_2D;
2892 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
2893 test2DNurb(nu);
2894 nu= nu->next;
2897 if(ob->type==OB_CURVE) {
2898 cu= ob->data;
2899 nu= cu->nurb.first;
2900 while(nu) {
2901 nu->type &= ~CU_2D;
2902 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
2903 test2DNurb(nu);
2904 nu= nu->next;
2907 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2908 allqueue(REDRAWVIEW3D, 0);
2909 break;
2910 case B_SETRESOLU:
2911 if(ob->type==OB_CURVE) {
2912 cu= ob->data;
2913 if(ob==G.obedit) nu= editNurb.first;
2914 else nu= cu->nurb.first;
2916 while(nu) {
2917 nu->resolu= cu->resolu;
2918 nu= nu->next;
2922 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2923 allqueue(REDRAWVIEW3D, 0);
2924 allqueue(REDRAWBUTSALL, 0);
2925 allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
2927 break;
2931 static void editing_panel_curve_tools(Object *ob, Curve *cu)
2933 Nurb *nu;
2934 extern ListBase editNurb; /* from editcurve */
2935 extern Nurb *lastnu;
2936 uiBlock *block;
2937 short *sp;
2939 block= uiNewBlock(&curarea->uiblocks, "editing_panel_curve_tools", UI_EMBOSS, UI_HELV, curarea->win);
2940 if(uiNewPanel(curarea, block, "Curve Tools", "Editing", 640, 0, 318, 204)==0) return;
2942 uiDefBut(block, LABEL, 0, "Make Knots",562,173,102, 18, 0, 0, 0, 0, 0, "");
2944 if(ob->type==OB_CURVE) {
2945 uiDefBut(block, LABEL, 0, "Convert", 463,173,72, 18, 0, 0, 0, 0, 0, "");
2946 uiBlockBeginAlign(block);
2947 uiDefBut(block, BUT,B_CONVERTPOLY,"Poly", 467,152,72, 18, 0, 0, 0, 0, 0, "Converts selected into regular Polygon vertices");
2948 uiDefBut(block, BUT,B_CONVERTBEZ,"Bezier", 467,132,72, 18, 0, 0, 0, 0, 0, "Converts selected to Bezier triples");
2949 uiDefBut(block, BUT,B_CONVERTNURB,"Nurb", 467,112,72, 18, 0, 0, 0, 0, 0, "Converts selected to Nurbs Points");
2951 uiBlockBeginAlign(block);
2952 uiDefBut(block, BUT,B_UNIFU,"Uniform U", 565,152,102, 18, 0, 0, 0, 0, 0, "Nurbs only; interpolated result doesn't go to end points in U");
2953 uiDefBut(block, BUT,B_UNIFV,"V", 670,152,50, 18, 0, 0, 0, 0, 0, "Nurbs only; interpolated result doesn't go to end points in V");
2954 uiDefBut(block, BUT,B_ENDPU,"Endpoint U", 565,132,102, 18, 0, 0, 0, 0, 0, "Nurbs only; interpolated result is forced to end points in U");
2955 uiDefBut(block, BUT,B_ENDPV,"V", 670,132,50, 18, 0, 0, 0, 0, 0, "Nurbs only; interpolated result is forced to end points in V");
2956 uiDefBut(block, BUT,B_BEZU,"Bezier U", 565,112,102, 18, 0, 0, 0, 0, 0, "Nurbs only; make knots array mimic a Bezier in U");
2957 uiDefBut(block, BUT,B_BEZV,"V", 670,112,50, 18, 0, 0, 0, 0, 0, "Nurbs only; make knots array mimic a Bezier in V");
2958 uiBlockEndAlign(block);
2960 uiDefBut(block, BUT,B_SETWEIGHT,"Set Weight", 465,11,95,49, 0, 0, 0, 0, 0, "Nurbs only; set weight for select points");
2962 uiBlockBeginAlign(block);
2963 uiDefButF(block, NUM,0,"Weight:", 565,36,102,22, &editbutweight, 0.01, 100.0, 10, 0, "The weight you can assign");
2964 uiDefBut(block, BUT,B_SETW1,"1.0", 670,36,50,22, 0, 0, 0, 0, 0, "");
2965 uiDefBut(block, BUT,B_SETW2,"sqrt(2)/4",565,11,55,20, 0, 0, 0, 0, 0, "");
2966 uiDefBut(block, BUT,B_SETW3,"0.25", 620,11,45,20, 0, 0, 0, 0, 0, "");
2967 uiDefBut(block, BUT,B_SETW4,"sqrt(0.5)",665,11,55,20, 0, 0, 0, 0, 0, "");
2968 uiBlockEndAlign(block);
2970 if(ob==G.obedit) {
2971 nu= lastnu;
2972 if(nu==NULL) nu= editNurb.first;
2973 if(nu) {
2974 uiBlockBeginAlign(block);
2975 sp= &(nu->orderu);
2976 uiDefButS(block, NUM, B_SETORDER, "Order U:", 565,90,102, 19, sp, 2.0, 6.0, 0, 0, "Nurbs only; the amount of control points involved");
2977 sp= &(nu->orderv);
2978 uiDefButS(block, NUM, B_SETORDER, "V:", 670,90,50, 19, sp, 2.0, 6.0, 0, 0, "Nurbs only; the amount of control points involved");
2979 sp= &(nu->resolu);
2980 uiDefButS(block, NUM, B_MAKEDISP, "Resol U:", 565,70,102, 19, sp, 1.0, 1024.0, 0, 0, "The amount of new points interpolated per control vertex pair");
2981 sp= &(nu->resolv);
2982 uiDefButS(block, NUM, B_MAKEDISP, "V:", 670,70,50, 19, sp, 1.0, 1024.0, 0, 0, "The amount of new points interpolated per control vertex pair");
2989 static void editing_panel_curve_tools1(Object *ob, Curve *cu)
2991 uiBlock *block;
2993 block= uiNewBlock(&curarea->uiblocks, "editing_panel_curve_tools1", UI_EMBOSS, UI_HELV, curarea->win);
2994 if(uiNewPanel(curarea, block, "Curve Tools1", "Editing", 960, 0, 318, 204)==0) return;
2996 uiDefBut(block, BUT, B_SUBDIVCURVE, "Subdivide", 400,180,150,20, 0, 0, 0, 0, 0, "Subdivide selected");
2997 if(ob->type==OB_SURF) {
2998 uiDefBut(block, BUT, B_SPINNURB, "Spin", 400,160,150,20, 0, 0, 0, 0, 0, "Spin selected 360 degrees");
3000 uiBlockBeginAlign(block);
3001 uiDefBut(block, BUT,B_HIDE, "Hide", 400,120,150,18, 0, 0, 0, 0, 0, "Hides selected faces");
3002 uiDefBut(block, BUT,B_REVEAL, "Reveal", 400,100,150,18, 0, 0, 0, 0, 0, "Reveals selected faces");
3003 uiDefBut(block, BUT,B_SELSWAP, "Select Swap", 400,80,150,18, 0, 0, 0, 0, 0, "Selects unselected faces, and deselects selected faces");
3004 uiBlockEndAlign(block);
3006 uiDefButF(block, NUM, REDRAWVIEW3D, "NSize:", 400, 40, 150, 19, &G.scene->editbutsize, 0.001, 1.0, 10, 0, "Normal size for drawing");
3008 if(G.obedit) {
3009 uiBut *but;
3010 uiBlockBeginAlign(block);
3011 but= uiDefButBitS(block,TOG,CU_RETOPO,B_NOP, "Retopo", 560,180,100,19, &cu->flag, 0,0,0,0, "Turn on the re-topology tool");
3012 uiButSetFunc(but,retopo_toggle,0,0);
3013 if(cu->flag & CU_RETOPO) {
3014 but= uiDefBut(block,BUT,B_NOP,"Retopo All", 560,160,100,19, 0,0,0,0,0, "Apply the re-topology tool to all selected vertices");
3015 uiButSetFunc(but,retopo_do_all_cb,0,0);
3020 /* only for bevel or taper */
3021 static void test_obcurpoin_but(char *name, ID **idpp)
3023 ID *id;
3025 for(id= G.main->object.first; id; id= id->next) {
3026 if( strcmp(name, id->name+2)==0 ) {
3027 if (((Object *)id)->type != OB_CURVE) {
3028 error ("Bevel/Taper Object must be a Curve");
3029 break;
3031 if(id == (ID *)OBACT) {
3032 error ("Cannot Bevel/Taper own Object");
3033 break;
3036 *idpp= id;
3037 return;
3040 *idpp= NULL;
3045 /* for curve, surf and font! */
3046 static void editing_panel_curve_type(Object *ob, Curve *cu)
3048 uiBlock *block;
3050 block= uiNewBlock(&curarea->uiblocks, "editing_panel_curve_type", UI_EMBOSS, UI_HELV, curarea->win);
3051 if(uiNewPanel(curarea, block, "Curve and Surface", "Editing", 320, 0, 318, 204)==0) return;
3053 uiDefButBitS(block, TOG, CU_UV_ORCO, 0, "UV Orco", 600,160,150,19, &cu->flag, 0, 0, 0, 0, "Forces to use UV coordinates for texture mapping 'orco'");
3054 if(ob->type==OB_SURF)
3055 uiDefButBitS(block, TOG, CU_NOPUNOFLIP, REDRAWVIEW3D, "No Puno Flip", 600,140,150,19, &cu->flag, 0, 0, 0, 0, "Don't flip vertex normals while render");
3057 uiBlockBeginAlign(block);
3058 uiDefBut(block, BUT,B_DOCENTER, "Center", 600, 115, 55, 19, 0, 0, 0, 0, 0, "Shifts object data to be centered about object's origin");
3059 uiDefBut(block, BUT,B_DOCENTERNEW, "Center New", 655, 115, 95, 19, 0, 0, 0, 0, 0, "Shifts object's origin to center of object data");
3060 uiDefBut(block, BUT,B_DOCENTERCURSOR, "Center Cursor", 600, 95, 150, 19, 0, 0, 0, 0, 0, "Shifts object's origin to cursor location");
3061 uiBlockEndAlign(block);
3063 if(cu->key) {
3064 /* uiDefButS(block, NUM, B_DIFF, "Slurph:", 600,25,140,19, &(cu->key->slurph), -500.0, 500.0,0,0); ,""*/
3065 uiDefButS(block, TOG, B_RELKEY, "Relative Keys", 600, 72,150,19, &cu->key->type, 0, 0, 0, 0, "");
3069 if(ob->type!=OB_SURF) {
3071 if(ob->type==OB_CURVE) {
3072 extern float prlen; // buttons_object.c, should be moved....
3073 char str[32];
3075 sprintf(str, "%.4f", prlen);
3076 uiDefBut(block, BUT, B_PRINTLEN, "PrintLen", 600,135,75,19, 0, 0, 0, 0, 0, "");
3077 uiDefBut(block, LABEL, 0, str, 675,135,75,19, 0, 1.0, 0, 0, 0, "");
3079 uiBlockBeginAlign(block);
3080 /*note, PathLen's max was MAXFRAMEF but this is a short, perhaps the pathlen should be increased later on */
3081 uiDefButS(block, NUM, B_RECALCPATH, "PathLen:", 600,50,150,19, &cu->pathlen, 1.0, 32767.0f, 0, 0, "If no speed Ipo was set, the amount of frames of the path");
3082 uiDefButBitS(block, TOG, CU_PATH, B_RECALCPATH, "CurvePath", 600,30,75,19 , &cu->flag, 0, 0, 0, 0, "Enables curve to become translation path");
3083 uiDefButBitS(block, TOG, CU_FOLLOW, REDRAWVIEW3D, "CurveFollow",675,30,75,19, &cu->flag, 0, 0, 0, 0, "Makes curve path children to rotate along path");
3084 uiDefButBitS(block, TOG, CU_STRETCH, B_CURVECHECK, "CurveStretch", 600,10,150,19, &cu->flag, 0, 0, 0, 0, "Option for curve-deform: makes deformed child to stretch along entire path");
3085 uiDefButBitS(block, TOG, CU_OFFS_PATHDIST, REDRAWVIEW3D, "PathDist Offs", 600,-10,150,19, &cu->flag, 0, 0, 0, 0, "Children will use TimeOffs value as path distance offset");
3087 uiBlockEndAlign(block);
3090 uiBlockBeginAlign(block);
3091 uiDefButS(block, NUM, B_SETRESOLU, "DefResolU:", 760,160,150,19, &cu->resolu, 1.0, 1024.0, 0, 0, "Default resolution");
3092 uiDefButS(block, NUM, B_NOP, "RenResolU", 760,140,150,19, &cu->resolu_ren, 0.0f, 1024, 0, 0, "Set resolution for rendering. A value of zero skips this operation.");
3094 uiBlockBeginAlign(block);
3095 uiDefButF(block, NUM, B_MAKEDISP, "Width:", 760,90,150,19, &cu->width, 0.0, 2.0, 1, 0, "Make interpolated result thinner or fatter");
3096 uiDefButF(block, NUM, B_MAKEDISP, "Extrude:", 760,70,150,19, &cu->ext1, 0.0, 100.0, 10, 0, "Curve extrusion size when not using a bevel object");
3097 uiDefButF(block, NUM, B_MAKEDISP, "Bevel Depth:", 760,50,150,19, &cu->ext2, 0.0, 2.0, 1, 0, "Bevel depth when not using a bevel object");
3098 uiDefButS(block, NUM, B_MAKEDISP, "BevResol:", 760,30,150,19, &cu->bevresol, 0.0, 32.0, 0, 0, "Bevel resolution when depth is non-zero and not using a bevel object");
3099 uiDefIDPoinBut(block, test_obcurpoin_but, ID_OB, B_CHANGEDEP, "BevOb:", 760,10,150,19, &cu->bevobj, "Curve object name that defines the bevel shape");
3100 uiDefIDPoinBut(block, test_obcurpoin_but, ID_OB, B_CHANGEDEP, "TaperOb:", 760,-10,150,19, &cu->taperobj, "Curve object name that defines the taper (width)");
3102 uiBlockBeginAlign(block);
3103 uiBlockSetCol(block, TH_BUT_SETTING1);
3104 uiDefButBitS(block, TOG, CU_BACK, B_MAKEDISP, "Back", 760,115,50,19, &cu->flag, 0, 0, 0, 0, "Draw filled back for extruded/beveled curves");
3105 uiDefButBitS(block, TOG, CU_FRONT, B_MAKEDISP, "Front",810,115,50,19, &cu->flag, 0, 0, 0, 0, "Draw filled front for extruded/beveled curves");
3106 uiDefButBitS(block, TOG, CU_3D, B_CU3D, "3D", 860,115,50,19, &cu->flag, 0, 0, 0, 0, "Allow Curve to be 3d, it doesn't fill then");
3111 /* *************************** CAMERA ******************************** */
3113 /* callback to handle angle to lens conversion */
3114 static void do_angletolensconversion_cb(void *lens1, void *angle1)
3116 float *lens= (float *)lens1;
3117 float *angle= (float *)angle1;
3118 float anglevalue= *angle;
3120 if(lens) {
3121 *lens= 16.0f / tan(M_PI*anglevalue/360.0f);
3124 allqueue(REDRAWVIEW3D, 0);
3127 /* callback to handle lens to angle conversion */
3128 static void do_lenstoangleconversion_cb(void *lens1, void *angle1)
3130 float *lens= (float *)lens1;
3131 float *angle= (float *)angle1;
3132 float lensvalue= *lens;
3134 if(lens) {
3135 *angle= 360.0f * atan(16.0f/lensvalue) / M_PI;
3138 allqueue(REDRAWVIEW3D, 0);
3141 static void editing_panel_camera_type(Object *ob, Camera *cam)
3143 uiBlock *block;
3144 uiBut *but;
3145 float grid=0.0;
3147 if(G.vd) grid= G.vd->grid;
3148 if(grid<1.0) grid= 1.0;
3150 block= uiNewBlock(&curarea->uiblocks, "editing_panel_camera_type", UI_EMBOSS, UI_HELV, curarea->win);
3151 if(uiNewPanel(curarea, block, "Camera", "Editing", 320, 0, 318, 204)==0) return;
3153 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
3155 uiDefBut(block, LABEL, 10, "Lens:", 10, 180, 150, 20, 0, 0.0, 0.0, 0, 0, "");
3157 if(cam->type==CAM_ORTHO) {
3158 uiDefButF(block, NUM,REDRAWVIEW3D, "Scale:",
3159 10, 160, 150, 20, &cam->ortho_scale, 0.01, 1000.0, 50, 0, "Specify the ortho scaling of the used camera");
3160 } else {
3161 if(cam->flag & CAM_ANGLETOGGLE) {
3162 but= uiDefButF(block, NUM,REDRAWVIEW3D, "Lens:",
3163 10, 160, 130, 20, &cam->angle, 7.323871, 172.847331, 100, 0, "Specify the lens of the camera in degrees");
3164 uiButSetFunc(but,do_angletolensconversion_cb, &cam->lens, &cam->angle);
3166 else {
3167 but= uiDefButF(block, NUM,REDRAWVIEW3D, "Lens:",
3168 10, 160, 130, 20, &cam->lens, 1.0, 250.0, 100, 0, "Specify the lens of the camera");
3169 uiButSetFunc(but,do_lenstoangleconversion_cb, &cam->lens, &cam->angle);
3172 uiDefButS(block, TOG|BIT|5, B_REDR, "D",
3173 140, 160, 20, 20, &cam->flag, 0, 0, 0, 0, "Use degree as the unit of the camera lens");
3176 /* qdn: focal dist. param. from yafray now enabled for Blender as well, to use with defocus composit node */
3177 uiDefButF(block, NUM, REDRAWVIEW3D, "DoFDist:", 10, 140, 150, 20 /*0, 125, 150, 20*/, &cam->YF_dofdist, 0.0, 5000.0, 50, 0, "Sets distance to point of focus (enable 'Limits' to make visible in 3Dview)");
3179 uiDefButS(block, TOG, REDRAWVIEW3D, "Orthographic",
3180 10, 115, 150, 20, &cam->type, 0, 0, 0, 0, "Render orthogonally");
3181 //10, 135, 150, 20, &cam->type, 0, 0, 0, 0, "Render orthogonally");
3183 uiDefBut(block, LABEL, 0, "Clipping:", 10, 90, 150, 20, 0, 0.0, 0.0, 0, 0, "");
3185 uiBlockBeginAlign(block);
3186 uiDefButF(block, NUM,REDRAWVIEW3D, "Start:",
3187 10, 70, 150, 20, &cam->clipsta, 0.001*grid, 100.0*grid, 10, 0, "Specify the startvalue of the the field of view");
3188 uiDefButF(block, NUM,REDRAWVIEW3D, "End:",
3189 10, 50, 150, 20, &cam->clipend, 1.0, 5000.0*grid, 100, 0, "Specify the endvalue of the the field of view");
3190 uiBlockEndAlign(block);
3192 uiDefButF(block, NUM,REDRAWVIEW3D, "Size:",
3193 170, 25, 150, 20, &cam->drawsize, 0.1*grid, 10.0, 10, 0, "The size that the camera is displayed in the 3D View (different from the object's scale)");
3195 uiDefBut(block, LABEL, 0, "Shift:", 10, 25, 150, 20, 0, 0.0, 0.0, 0, 0, "");
3197 uiBlockBeginAlign(block);
3198 uiDefButF(block, NUM,REDRAWVIEW3D, "X:",
3199 10, 5, 75, 20, &cam->shiftx, -2.0, 2.0, 1, 2, "Horizontally shifts the camera view, without changing the perspective");
3200 uiDefButF(block, NUM,REDRAWVIEW3D, "Y:",
3201 85, 5, 75, 20, &cam->shifty, -2.0, 2.0, 1, 2, "Vertically shifts the camera view, without changing the perspective");
3202 uiBlockEndAlign(block);
3204 uiDefBut(block, LABEL, 0, "Show:", 170, 180, 150, 20, 0, 0.0, 0.0, 0, 0, "");
3206 uiBlockBeginAlign(block);
3207 uiDefButS(block, TOG|BIT|0, REDRAWVIEW3D, "Limits",
3208 170, 160, 150, 20, &cam->flag, 0, 0, 0, 0, "Draw the field of view");
3209 uiDefButS(block, TOG|BIT|1, REDRAWVIEW3D, "Mist",
3210 170, 140, 150, 20, &cam->flag, 0, 0, 0, 0, "Draw a line that indicates the mist area");
3211 uiBlockEndAlign(block);
3213 uiBlockBeginAlign(block);
3214 uiDefButS(block, TOG|BIT|4, REDRAWVIEW3D, "Name",
3215 170, 115, 150, 20, &cam->flag, 0, 0, 0, 0, "Draw the active camera's name in camera view");
3216 uiDefButS(block, TOG|BIT|3, REDRAWVIEW3D, "Title Safe",
3217 170, 95, 150, 20, &cam->flag, 0, 0, 0, 0, "Draw a the title safe zone in camera view");
3218 uiBlockEndAlign(block);
3220 uiBlockBeginAlign(block);
3221 uiDefButS(block, TOG|BIT|2, REDRAWVIEW3D, "Passepartout",
3222 170, 70, 150, 20, &cam->flag, 0, 0, 0, 0, "Draw a darkened passepartout over the off-screen area in camera view");
3223 uiDefButF(block, NUMSLI, REDRAWVIEW3D, "Alpha: ",
3224 170, 50, 150, 20, &cam->passepartalpha, 0.0, 1.0, 0, 0, "The opacity (darkness) of the passepartout");
3225 uiBlockEndAlign(block);
3230 /* yafray: extra camera panel to set Depth-of-Field parameters */
3231 static void editing_panel_camera_yafraydof(Object *ob, Camera *cam)
3233 uiBlock *block;
3234 char *mst1, *mst2;
3236 block= uiNewBlock(&curarea->uiblocks, "editing_panel_camera_yafraydof", UI_EMBOSS, UI_HELV, curarea->win);
3237 uiNewPanelTabbed("Camera", "Editing");
3238 if(uiNewPanel(curarea, block, "Yafray DoF", "Editing", 320, 0, 318, 204)==0) return;
3240 uiDefButF(block, NUM, REDRAWVIEW3D, "DoFDist:", 10, 147, 180, 20, &cam->YF_dofdist, 0.0, 5000.0, 50, 0, "Sets distance to point of focus (use camera 'ShowLimits' to make visible in 3Dview)");
3241 uiDefButF(block, NUM, B_DIFF, "Aperture:", 10, 125, 180, 20, &cam->YF_aperture, 0.0, 2.0, 1, 0, "Sets lens aperture, the larger, the more blur (use small values, 0 is no DoF)");
3243 uiDefButBitS(block, TOG, CAM_YF_NO_QMC, B_DIFF, "Random sampling", 10, 90, 180, 20, &cam->flag, 0, 0, 0, 0, "Use noisy random Lens sampling instead of QMC");
3245 uiDefBut(block, LABEL, 0, "Bokeh", 10, 60, 180, 19, 0, 0.0, 0.0, 0, 0, "");
3246 mst1 = "Bokeh Type%t|Disk1%x0|Disk2%x1|Triangle%x2|Square%x3|Pentagon%x4|Hexagon%x5|Ring%x6";
3247 uiDefButS(block, MENU, B_REDR, mst1, 10, 40, 89, 20, &cam->YF_bkhtype, 0.0, 0.0, 0, 0, "Sets Bokeh type");
3249 if ((cam->YF_bkhtype!=0) && (cam->YF_bkhtype!=6)) {
3250 mst2 = "Bokeh Bias%t|Uniform%x0|Center%x1|Edge%x2";
3251 uiDefButS(block, MENU, B_REDR, mst2, 100, 40, 90, 20, &cam->YF_bkhbias, 0.0, 0.0, 0, 0, "Sets Bokeh bias");
3252 if (cam->YF_bkhtype>1)
3253 uiDefButF(block, NUM, B_DIFF, "Rotation:", 10, 15, 180, 20, &cam->YF_bkhrot, 0.0, 360.0, 100, 0, "Shape rotation amount in degrees");
3258 /* **************************** CAMERA *************************** */
3260 void do_cambuts(unsigned short event)
3262 Object *ob;
3263 Camera *cam;
3265 ob= OBACT;
3266 if (ob==0) return;
3267 cam= ob->data;
3269 switch(event) {
3270 case 0:
3272 break;
3276 /* *************************** MBALL ******************************** */
3278 void do_mballbuts(unsigned short event)
3280 switch(event) {
3281 case B_RECALCMBALL:
3282 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
3283 allqueue(REDRAWVIEW3D, 0);
3284 break;
3288 static void editing_panel_mball_type(Object *ob, MetaBall *mb)
3290 uiBlock *block;
3292 block= uiNewBlock(&curarea->uiblocks, "editing_panel_mball_type", UI_EMBOSS, UI_HELV, curarea->win);
3293 if(uiNewPanel(curarea, block, "MetaBall", "Editing", 320, 0, 318, 204)==0) return;
3295 ob= find_basis_mball(ob);
3296 mb= ob->data;
3298 uiBlockBeginAlign(block);
3299 uiDefButF(block, NUM, B_RECALCMBALL, "Wiresize:", 470,178,250,19, &mb->wiresize, 0.05, 1.0, 1, 0, "Polygonization resolution in 3d window");
3300 uiDefButF(block, NUM, B_NOP, "Rendersize:", 470,158,250,19, &mb->rendersize, 0.05, 1.0, 1, 0, "Polygonization resolution in rendering");
3301 uiDefButF(block, NUM, B_RECALCMBALL, "Threshold:", 470,138,250,19, &mb->thresh, 0.0001, 5.0, 1, 0, "Defines influence of meta elements");
3303 uiBlockBeginAlign(block);
3304 uiBlockSetCol(block, TH_BUT_SETTING1);
3305 uiDefBut(block, LABEL, 0, "Update:", 471,108,120,19, 0, 0, 0, 0, 0, "");
3306 uiDefButS(block, ROW, B_DIFF, "Always", 471, 85, 120, 19, &mb->flag, 0.0, 0.0, 0, 0, "While editing, always updates");
3307 uiDefButS(block, ROW, B_DIFF, "Half Res", 471, 65, 120, 19, &mb->flag, 0.0, 1.0, 0, 0, "While editing, updates in half resolution");
3308 uiDefButS(block, ROW, B_DIFF, "Fast", 471, 45, 120, 19, &mb->flag, 0.0, 2.0, 0, 0, "While editing, updates without polygonization");
3309 uiDefButS(block, ROW, B_DIFF, "Never", 471, 25, 120, 19, &mb->flag, 0.0, 3.0, 0, 0, "While editing, doesn't update");
3313 static void editing_panel_mball_tools(Object *ob, MetaBall *mb)
3315 extern MetaElem *lastelem;
3316 uiBlock *block;
3318 block= uiNewBlock(&curarea->uiblocks, "editing_panel_mball_tools", UI_EMBOSS, UI_HELV, curarea->win);
3319 if( uiNewPanel(curarea, block, "MetaBall tools", "Editing", 640, 0, 318, 204)==0) return;
3321 if(ob==G.obedit && lastelem) {
3322 uiBlockBeginAlign(block);
3323 uiDefButF(block, NUM, B_RECALCMBALL, "Stiffness:", 750,178,250,19, &lastelem->s, 0.0, 10.0, 1, 0, "Stiffness for active meta");
3324 if(lastelem->type!=MB_BALL)
3325 uiDefButF(block, NUM, B_RECALCMBALL, "dx:", 750,158,250,19, &lastelem->expx, 0.0, 20.0, 1, 0, "X size for active meta");
3326 if((lastelem->type!=MB_BALL)&&(lastelem->type!=MB_TUBE))
3327 uiDefButF(block, NUM, B_RECALCMBALL, "dy:", 750,138,250,19, &lastelem->expy, 0.0, 20.0, 1, 0, "Y size for active meta");
3329 if((lastelem->type==MB_CUBE)||(lastelem->type==MB_ELIPSOID))
3330 uiDefButF(block, NUM, B_RECALCMBALL, "dz:", 750,118,250,19, &lastelem->expz, 0.0, 20.0, 1, 0, "Z size for active meta");
3331 uiBlockEndAlign(block);
3333 uiDefButS(block, ROW, B_RECALCMBALL, "Ball", 753,83,60,19, &lastelem->type, 1.0, MB_BALL, 0, 0, "Draw active meta as Ball");
3334 uiBlockBeginAlign(block);
3335 uiDefButS(block, ROW, B_RECALCMBALL, "Tube", 753,62,60,19, &lastelem->type, 1.0, MB_TUBE, 0, 0, "Draw active meta as Ball");
3336 uiDefButS(block, ROW, B_RECALCMBALL, "Plane", 814,62,60,19, &lastelem->type, 1.0, MB_PLANE, 0, 0, "Draw active meta as Plane");
3337 uiDefButS(block, ROW, B_RECALCMBALL, "Elipsoid", 876,62,60,19, &lastelem->type, 1.0, MB_ELIPSOID, 0, 0, "Draw active meta as Ellipsoid");
3338 uiDefButS(block, ROW, B_RECALCMBALL, "Cube", 938,62,60,19, &lastelem->type, 1.0, MB_CUBE, 0, 0, "Draw active meta as Cube");
3339 uiBlockEndAlign(block);
3341 uiBlockBeginAlign(block);
3342 uiDefButBitS(block, TOG, MB_NEGATIVE, B_RECALCMBALL, "Negative",753,16,125,19, &lastelem->flag, 0, 0, 0, 0, "Make active meta creating holes");
3343 uiDefButBitS(block, TOG, MB_HIDE, B_RECALCMBALL, "Hide",878,16,125,19, &lastelem->flag, 0, 0, 0, 0, "Make active meta invisible");
3344 uiBlockEndAlign(block);
3351 /* *************************** LATTICE ******************************** */
3353 void do_latticebuts(unsigned short event)
3355 Object *ob;
3356 Lattice *lt;
3358 ob= OBACT;
3359 if(ob->type!=OB_LATTICE) return;
3361 switch(event) {
3362 case B_REGULARLAT:
3363 if(ob) {
3364 lt = ob->data;
3365 if(ob==G.obedit) resizelattice(editLatt, lt->opntsu, lt->opntsv, lt->opntsw, NULL);
3366 else resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, NULL);
3367 ob->softflag |= OB_SB_REDO;
3368 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
3369 allqueue(REDRAWVIEW3D, 0);
3371 case B_RESIZELAT:
3372 if(ob) {
3373 lt = ob->data;
3374 resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, ob);
3375 ob->softflag |= OB_SB_REDO;
3376 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
3377 allqueue(REDRAWVIEW3D, 0);
3379 break;
3380 case B_DRAWLAT:
3381 allqueue(REDRAWVIEW3D, 0);
3382 break;
3383 case B_LATTCHANGED:
3385 lt= ob->data;
3386 if(lt->flag & LT_OUTSIDE) outside_lattice(lt);
3388 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
3390 allqueue(REDRAWVIEW3D, 0);
3392 break;
3396 static void editing_panel_lattice_type(Object *ob, Lattice *lt)
3398 uiBlock *block;
3400 block= uiNewBlock(&curarea->uiblocks, "editing_panel_lattice_type", UI_EMBOSS, UI_HELV, curarea->win);
3401 if(uiNewPanel(curarea, block, "Lattice", "Editing", 320, 0, 318, 204)==0) return;
3404 uiSetButLock(lt->key!=0, "Not with VertexKeys");
3405 uiSetButLock(ob==G.obedit, "Unable to perform function in EditMode");
3407 uiBlockBeginAlign(block);
3409 lt->opntsu = lt->pntsu;
3410 lt->opntsv = lt->pntsv;
3411 lt->opntsw = lt->pntsw;
3413 uiDefButS(block, NUM, B_RESIZELAT, "U:", 469, 178,100,19, &lt->opntsu, 1.0, 64.0, 0, 0, "Points in U direction");
3414 uiDefButC(block, ROW, B_LATTCHANGED, "Lin", 572, 178, 40, 19, &lt->typeu, 1.0, (float)KEY_LINEAR, 0, 0, "Set Linear interpolation");
3415 uiDefButC(block, ROW, B_LATTCHANGED, "Card", 613, 178, 40, 19, &lt->typeu, 1.0, (float)KEY_CARDINAL, 0, 0, "Set Cardinal interpolation");
3416 uiDefButC(block, ROW, B_LATTCHANGED, "B", 652, 178, 40, 19, &lt->typeu, 1.0, (float)KEY_BSPLINE, 0, 0, "Set B-spline interpolation");
3418 uiDefButS(block, NUM, B_RESIZELAT, "V:", 469, 156,100,19, &lt->opntsv, 1.0, 64.0, 0, 0, "Points in V direction");
3419 uiDefButC(block, ROW, B_LATTCHANGED, "Lin", 572, 156, 40, 19, &lt->typev, 2.0, (float)KEY_LINEAR, 0, 0, "Set Linear interpolation");
3420 uiDefButC(block, ROW, B_LATTCHANGED, "Card", 613, 156, 40, 19, &lt->typev, 2.0, (float)KEY_CARDINAL, 0, 0, "Set Cardinal interpolation");
3421 uiDefButC(block, ROW, B_LATTCHANGED, "B", 652, 156, 40, 19, &lt->typev, 2.0, (float)KEY_BSPLINE, 0, 0, "Set B-spline interpolation");
3423 uiDefButS(block, NUM, B_RESIZELAT, "W:", 469, 134,100,19, &lt->opntsw, 1.0, 64.0, 0, 0, "Points in W direction");
3424 uiDefButC(block, ROW, B_LATTCHANGED, "Lin", 572, 134, 40, 19, &lt->typew, 3.0, (float)KEY_LINEAR, 0, 0, "Set Linear interpolation");
3425 uiDefButC(block, ROW, B_LATTCHANGED, "Card", 613, 134, 40, 19, &lt->typew, 3.0, (float)KEY_CARDINAL, 0, 0, "Set Cardinal interpolation");
3426 uiDefButC(block, ROW, B_LATTCHANGED, "B", 652, 134, 40, 19, &lt->typew, 3.0, (float)KEY_BSPLINE, 0, 0, "Set B-spline interpolation");
3428 uiBlockEndAlign(block);
3430 uiDefBut(block, BUT, B_REGULARLAT, "Make Regular", 469,98,102,31, 0, 0, 0, 0, 0, "Make Lattice regular");
3432 uiClearButLock();
3433 uiDefButBitS(block, TOG, LT_OUTSIDE, B_LATTCHANGED, "Outside", 571,98,122,31, &lt->flag, 0, 0, 0, 0, "Only draw, and take into account, the outer vertices");
3435 if(lt->key) {
3436 uiDefButS(block, NUM, B_DIFF, "Slurph:", 469,60,120,19, &(lt->key->slurph), -500.0, 500.0, 0, 0, "Set time value to denote 'slurph' (sequential delay) vertices with key framing");
3437 uiDefButS(block, TOG, B_RELKEY, "Relative Keys", 469,40,120,19, &lt->key->type, 0, 0, 0, 0, "Use relative keys (instead of absolute)");
3442 /* *************************** ARMATURE ******************************** */
3444 void do_armbuts(unsigned short event)
3446 Object *ob= OBACT;
3448 switch(event) {
3449 case B_ARM_RECALCDATA:
3450 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
3451 allqueue(REDRAWVIEW3D, 1);
3452 allqueue(REDRAWBUTSEDIT, 0);
3453 break;
3454 case B_ARM_STRIDE:
3455 if(ob && ob->pose) {
3456 bPoseChannel *pchan;
3457 bActionStrip *strip;
3459 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next)
3460 if(pchan->flag & POSE_STRIDE)
3461 break;
3463 /* we put the stride bone name in the strips, for lookup of action channel */
3464 for (strip=ob->nlastrips.first; strip; strip=strip->next){
3465 if(strip->flag & ACTSTRIP_USESTRIDE) {
3466 if(pchan) BLI_strncpy(strip->stridechannel, pchan->name, 32);
3467 else strip->stridechannel[0]= 0;
3470 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
3471 allqueue(REDRAWVIEW3D, 1);
3472 allqueue(REDRAWNLA, 0);
3473 allqueue(REDRAWBUTSEDIT, 0);
3475 break;
3476 case B_ARM_CALCPATHS:
3477 if (ob && ob->pose)
3478 pose_calculate_path(ob);
3479 break;
3480 case B_ARM_CLEARPATHS:
3481 if (ob && ob->pose)
3482 pose_clear_paths(ob);
3483 break;
3487 static void validate_stridebutton_cb(void *pchanv, void *poin)
3489 Object *ob= OBACT;
3490 bPoseChannel *pchan;
3492 if(ob && ob->pose) {
3493 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next){
3494 if(pchan!=pchanv)
3495 pchan->flag &= ~POSE_STRIDE;
3500 static int editbone_to_parnr (EditBone *bone)
3502 EditBone *ebone;
3503 int index;
3505 for (ebone=G.edbo.first, index=0; ebone; ebone=ebone->next, index++){
3506 if (ebone==bone)
3507 return index;
3510 return -1;
3514 /* the "IK" button in editbuttons */
3515 static void attach_bone_to_parent_cb(void *bonev, void *arg2_unused)
3517 EditBone *ebone= bonev;
3519 if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
3520 /* Attach this bone to its parent */
3521 VECCOPY(ebone->head, ebone->parent->tail);
3525 static void parnr_to_editbone(EditBone *bone)
3527 if (bone->parNr == -1){
3528 bone->parent = NULL;
3529 bone->flag &= ~BONE_CONNECTED;
3531 else{
3532 bone->parent = BLI_findlink(&G.edbo, bone->parNr);
3533 attach_bone_to_parent_cb(bone, NULL);
3537 static void parnr_to_editbone_cb(void *bonev, void *arg2_unused)
3539 EditBone *curBone= bonev;
3540 parnr_to_editbone(curBone);
3543 /* only used for showing parent of editbones */
3544 static void build_bonestring (char *string, EditBone *bone)
3546 bArmature *arm= G.obedit->data;
3547 EditBone *curBone;
3548 EditBone *pBone;
3549 int skip=0;
3550 int index, numbones, i;
3551 char (*qsort_ptr)[32] = NULL;
3552 char *s = string;
3554 /* That space is there for a reason - for no parent */
3555 s += sprintf (string, "Parent%%t| %%x%d", -1);
3557 numbones = BLI_countlist(&G.edbo);
3560 * This will hold the bone names temporarily so we can sort them
3562 if (numbones > 0)
3563 qsort_ptr = MEM_callocN (numbones * sizeof (qsort_ptr[0]),
3564 "qsort_ptr");
3566 numbones = 0;
3567 for (curBone = G.edbo.first, index=0; curBone;
3568 curBone=curBone->next, index++){
3569 /* Make sure this is a valid child */
3570 if (curBone != bone){
3571 skip=0;
3572 for (pBone=curBone->parent; pBone; pBone=pBone->parent){
3573 if (pBone==bone){
3574 skip=1;
3575 break;
3578 /* no browsing for bones in invisible layers */
3579 if ((arm->layer & curBone->layer) == 0) {
3580 /* but ensure the current parent at least shows */
3581 if(bone->parent!=curBone)
3582 skip= 1;
3585 if (skip)
3586 continue;
3588 sprintf (qsort_ptr[numbones], "|%s%%x%d", curBone->name, index);
3589 numbones++;
3592 qsort (qsort_ptr, numbones, sizeof (qsort_ptr[0]),
3593 ( int (*)(const void *, const void *) ) strcmp);
3595 for (i=0; i < numbones; ++i) {
3596 strcat(s, qsort_ptr[i]);
3599 if (qsort_ptr)
3600 MEM_freeN(qsort_ptr);
3603 /* assumes armature editmode */
3604 /* exported to drawview.c via BIF_butspace.h */
3605 void validate_editbonebutton_cb(void *bonev, void *namev)
3607 EditBone *eBone= bonev;
3608 char oldname[32], newname[32];
3610 /* need to be on the stack */
3611 BLI_strncpy(newname, eBone->name, 32);
3612 BLI_strncpy(oldname, (char *)namev, 32);
3613 /* restore */
3614 BLI_strncpy(eBone->name, oldname, 32);
3616 armature_bone_rename(G.obedit->data, oldname, newname); // editarmature.c
3617 allqueue(REDRAWALL, 0);
3620 /* assumes armature posemode */
3621 static void validate_posebonebutton_cb(void *bonev, void *namev)
3623 Bone *bone= bonev;
3624 Object *ob= OBACT;
3625 char oldname[32], newname[32];
3627 /* need to be on the stack */
3628 BLI_strncpy(newname, bone->name, 32);
3629 BLI_strncpy(oldname, (char *)namev, 32);
3630 /* restore */
3631 BLI_strncpy(bone->name, oldname, 32);
3633 armature_bone_rename(ob->data, oldname, newname); // editarmature.c
3634 allqueue(REDRAWALL, 0);
3637 static void armature_layer_cb(void *lay_v, void *value_v)
3639 short *layer= lay_v;
3640 int value= (long)value_v;
3642 if(*layer==0 || G.qual==0) *layer= value;
3643 allqueue(REDRAWBUTSEDIT, 0);
3644 allqueue(REDRAWACTION, 0);
3645 allqueue(REDRAWNLA, 0);
3648 static void editing_panel_armature_type(Object *ob, bArmature *arm)
3650 uiBlock *block;
3651 uiBut *but;
3652 int a;
3654 block= uiNewBlock(&curarea->uiblocks, "editing_panel_armature_type", UI_EMBOSS, UI_HELV, curarea->win);
3655 if(uiNewPanel(curarea, block, "Armature", "Editing", 320, 0, 318, 204)==0) return;
3657 uiDefBut(block, LABEL, 0, "Editing Options", 10,180,150,20, 0, 0, 0, 0, 0, "");
3658 uiBlockBeginAlign(block);
3659 uiDefButBitI(block, TOG, ARM_MIRROR_EDIT, B_DIFF, "X-Axis Mirror", 10, 160,100,20, &arm->flag, 0, 0, 0, 0, "Enable X-axis mirrored editing");
3660 uiDefButBitC(block, TOG, OB_DRAWXRAY,REDRAWVIEW3D, "X-Ray", 110,160,100,20, &ob->dtx, 0, 0, 0, 0, "Draw armature in front of solid objects");
3661 uiDefButBitI(block, TOG, ARM_AUTO_IK, B_DIFF, "Auto IK", 210,160,100,20, &arm->flag, 0, 0, 0, 0, "Adds temporal IK chains while grabbing Bones");
3662 uiBlockEndAlign(block);
3664 uiDefBut(block, LABEL, 0, "Display Options", 10,133,150,19, 0, 0, 0, 0, 0, "");
3666 /* layers */
3667 uiBlockBeginAlign(block);
3668 for(a=0; a<8; a++) {
3669 short dx= 18;
3670 but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 10+a*dx, 115, dx, 15, &arm->layer, 0, 0, 0, 0, "");
3671 uiButSetFunc(but, armature_layer_cb, &arm->layer, (void *)(1<<a));
3673 uiBlockBeginAlign(block);
3674 for(a=8; a<16; a++) {
3675 short dx= 18;
3676 but= uiDefButBitS(block, BUT_TOGDUAL, 1<<a, REDRAWVIEW3D, "", 18+a*dx, 115, dx, 15, &arm->layer, 0, 0, 0, 0, "");
3677 uiButSetFunc(but, armature_layer_cb, &arm->layer, (void *)(1<<a));
3679 /* quite bad here, but I don't know a better place for copy... */
3680 if(ob->pose)
3681 ob->pose->proxy_layer= arm->layer;
3683 uiBlockBeginAlign(block);
3684 uiDefButI(block, ROW, REDRAWVIEW3D, "Octahedron", 10, 87,90,20, &arm->drawtype, 0, ARM_OCTA, 0, 0, "Draw bones as octahedra");
3685 uiDefButI(block, ROW, REDRAWVIEW3D, "Stick", 100, 87,55,20, &arm->drawtype, 0, ARM_LINE, 0, 0, "Draw bones as simple 2d lines with dots");
3686 uiDefButI(block, ROW, REDRAWVIEW3D, "B-Bone", 155, 87,70,20, &arm->drawtype, 0, ARM_B_BONE, 0, 0, "Draw bones as boxes, showing subdivision and b-splines");
3687 uiDefButI(block, ROW, REDRAWVIEW3D, "Envelope", 225, 87,85,20, &arm->drawtype, 0, ARM_ENVELOPE, 0, 0, "Draw bones as extruded spheres, showing deformation influence volume");
3689 uiDefButBitI(block, TOG, ARM_DRAWAXES, REDRAWVIEW3D, "Axes", 10, 67,75,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes");
3690 uiDefButBitI(block, TOG, ARM_DRAWNAMES, REDRAWVIEW3D, "Names", 85,67,75,20, &arm->flag, 0, 0, 0, 0, "Draw bone names");
3691 uiDefButBitI(block, TOGN, ARM_NO_CUSTOM, REDRAWVIEW3D, "Shapes", 160,67,75,20, &arm->flag, 0, 0, 0, 0, "Draw custom bone shapes");
3692 uiDefButBitI(block, TOG, ARM_COLOR_CUSTOM, REDRAWVIEW3D, "Colors", 235,67,75,20, &arm->flag, 0, 0, 0, 0, "Draw custom colors");
3694 uiBlockEndAlign(block);
3696 uiDefBut(block, LABEL, 0, "Deform Options", 10,40,150,20, 0, 0, 0, 0, 0, "");
3697 uiBlockBeginAlign(block);
3698 uiDefButBitS(block, TOG, ARM_DEF_VGROUP, B_ARM_RECALCDATA, "Vertex Groups", 10, 20,100,20, &arm->deformflag, 0, 0, 0, 0, "Enable VertexGroups defining deform (not for Modifiers)");
3699 uiDefButBitS(block, TOG, ARM_DEF_ENVELOPE, B_ARM_RECALCDATA, "Envelopes", 110,20,100,20, &arm->deformflag, 0, 0, 0, 0, "Enable Bone Envelopes defining deform (not for Modifiers)");
3700 uiDefButBitS(block, TOG, ARM_DEF_QUATERNION, B_ARM_RECALCDATA, "Quaternion", 210,20,100,20, &arm->deformflag, 0, 0, 0, 0, "Enable deform rotation interpolation with Quaternions (not for Modifiers)");
3701 uiDefButBitI(block, TOG, ARM_RESTPOS, B_ARM_RECALCDATA,"Rest Position", 10,0,150,20, &arm->flag, 0, 0, 0, 0, "Show armature rest position, no posing possible");
3702 uiDefButBitI(block, TOG, ARM_DELAYDEFORM, REDRAWVIEW3D, "Delay Deform", 160,0,150,20, &arm->flag, 0, 0, 0, 0, "Don't deform children when manipulating bones in pose mode");
3703 uiBlockEndAlign(block);
3706 static void editing_panel_armature_visuals(Object *ob, bArmature *arm)
3708 uiBlock *block;
3710 block= uiNewBlock(&curarea->uiblocks, "editing_panel_armature_visuals", UI_EMBOSS, UI_HELV, curarea->win);
3711 uiNewPanelTabbed("Armature", "Editing");
3712 if(uiNewPanel(curarea, block, "Armature Visualisations", "Editing", 320, 0, 318, 204)==0) return;
3714 /* version patch for older files here (do_versions patch too complicated) */
3715 if ((arm->ghostsf == 0) || (arm->ghostef == 0)) {
3716 arm->ghostsf = CFRA - (arm->ghostep * arm->ghostsize);
3717 arm->ghostef = CFRA + (arm->ghostep * arm->ghostsize);
3719 if ((arm->pathsf == 0) || (arm->pathef == 0)) {
3720 arm->pathsf = SFRA;
3721 arm->pathef = EFRA;
3724 /* Ghost Drawing Options */
3725 uiDefBut(block, LABEL, 0, "Ghost Options", 10,180,150,20, 0, 0, 0, 0, 0, "");
3727 uiBlockBeginAlign(block);
3728 uiDefButS(block, MENU, REDRAWVIEW3D, "Ghosts %t|Around Current Frame %x0|In Range %x1",
3729 10, 160, 150, 20, &arm->ghosttype, 0, 0, 0, 0, "Choose range of Ghosts to draw for current Action");
3731 uiDefButS(block, NUM, REDRAWVIEW3D, "GStep: ", 10,140,150,20, &arm->ghostsize, 1.0f, 20.0f, 0, 0, "How many frames between Ghost instances");
3732 uiBlockEndAlign(block);
3734 uiBlockBeginAlign(block);
3735 if (arm->ghosttype == ARM_GHOST_CUR) {
3736 /* range is around current frame */
3737 uiDefButS(block, NUM, REDRAWVIEW3D, "Ghost: ", 10,110,150,20, &arm->ghostep, 0.0f, 30.0f, 0, 0, "Draw Ghosts around current frame, for current Action");
3739 else if (arm->ghosttype == ARM_GHOST_RANGE) {
3740 /* range is defined by start+end frame below */
3741 uiDefButI(block, NUM,REDRAWVIEW3D,"GSta:",10,110,150,20, &arm->ghostsf,1.0,MAXFRAMEF, 0, 0, "The start frame for Ghost display range");
3742 uiDefButI(block, NUM,REDRAWVIEW3D,"GEnd:",10,90,150,20, &arm->ghostef,arm->ghostsf,MAXFRAMEF, 0, 0, "The end frame for Ghost display range");
3744 uiBlockEndAlign(block);
3746 /* Bone Path Drawing Options */
3747 uiDefBut(block, LABEL, 0, "Bone Paths", 165,180,150,20, 0, 0, 0, 0, 0, "");
3749 uiBlockBeginAlign(block);
3750 uiDefButBitS(block, TOG, ARM_PATH_FNUMS, REDRAWVIEW3D, "Frame Nums", 170, 160, 80, 20, &arm->pathflag, 0, 0, 0, 0, "Show frame numbers on path");
3751 uiDefButS(block, NUM, REDRAWVIEW3D, "PStep:",250,160,80,20, &arm->pathsize,1,100, 10, 50, "Frames between highlighted points on bone path");
3752 uiDefButBitS(block, TOG, ARM_PATH_KFRAS, REDRAWVIEW3D, "Show Keys", 170, 140, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Show key frames on path");
3753 uiBlockEndAlign(block);
3755 uiBlockBeginAlign(block);
3756 uiDefButI(block, NUM,REDRAWVIEW3D,"PSta:",170,100,80,20, &arm->pathsf, 1.0, MAXFRAMEF, 0, 0, "The start frame for Bone Path display range");
3757 uiDefButI(block, NUM,REDRAWVIEW3D,"PEnd:",250,100,80,20, &arm->pathef, arm->pathsf, MAXFRAMEF, 0, 0, "The end frame for Bone Path display range");
3758 uiDefButBitS(block, TOG, ARM_PATH_HEADS, REDRAWVIEW3D, "Bone-Head Path", 170, 80, 160, 20, &arm->pathflag, 0, 0, 0, 0, "Calculate the Path travelled by the Bone's Head instead of Tail");
3759 uiBlockEndAlign(block);
3761 uiBlockBeginAlign(block);
3762 uiDefBut(block, BUT, B_ARM_CALCPATHS, "Calculate Paths", 170,40,160,20, 0, 0, 0, 0, 0, "(Re)calculates the paths of the selected bones");
3763 uiDefBut(block, BUT, B_ARM_CLEARPATHS, "Clear All Paths", 170,20,160,20, 0, 0, 0, 0, 0, "Clears all bone paths");
3764 uiBlockEndAlign(block);
3767 /* autocomplete callback for editbones */
3768 static void autocomplete_editbone(char *str, void *arg_v)
3770 if(G.obedit==NULL) return;
3772 /* search if str matches the beginning of an ID struct */
3773 if(str[0]) {
3774 AutoComplete *autocpl= autocomplete_begin(str, 32);
3775 EditBone *ebone;
3777 for (ebone=G.edbo.first; ebone; ebone=ebone->next)
3778 if(ebone->name!=str)
3779 autocomplete_do_name(autocpl, ebone->name);
3781 autocomplete_end(autocpl, str);
3785 static void editing_panel_armature_bones(Object *ob, bArmature *arm)
3787 uiBlock *block;
3788 uiBut *but;
3789 EditBone *curBone;
3790 char *boneString=NULL;
3791 int by=180;
3792 int index, a;
3794 /* Draw the bone name block */
3796 block= uiNewBlock(&curarea->uiblocks, "editing_panel_armature_bones", UI_EMBOSS, UI_HELV, curarea->win);
3797 if(uiNewPanel(curarea, block, "Armature Bones", "Editing", 640, 0, 318, 204)==0) return;
3799 /* this is a variable height panel, newpanel doesnt force new size on existing panels */
3800 /* so first we make it default height */
3801 uiNewPanelHeight(block, 204);
3804 uiDefBut(block, LABEL, 0, "Selected Bones", 0,by,158,18, 0, 0, 0, 0, 0, "Only show in Armature Editmode");
3805 by-=20;
3806 for (curBone=G.edbo.first, index=0; curBone; curBone=curBone->next, index++){
3807 if ((curBone->flag & BONE_SELECTED) && (curBone->layer & arm->layer)) {
3809 /* Bone naming button */
3810 but=uiDefBut(block, TEX, REDRAWVIEW3D, "BO:", -10,by,117,18, curBone->name, 0, 31, 0, 0, "Change the bone name");
3811 uiButSetFunc(but, validate_editbonebutton_cb, curBone, NULL);
3812 uiButSetCompleteFunc(but, autocomplete_editbone, (void *)OBACT);
3814 uiDefBut(block, LABEL, 0, "child of", 107,by,73,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
3816 boneString = MEM_mallocN((BLI_countlist(&G.edbo) * 64)+64, "Bone str");
3817 build_bonestring (boneString, curBone);
3819 curBone->parNr = editbone_to_parnr(curBone->parent);
3820 but = uiDefButI(block, MENU,REDRAWVIEW3D, boneString, 180,by,120,18, &curBone->parNr, 0.0, 0.0, 0.0, 0.0, "Parent");
3821 /* last arg NULL means button will put old string there */
3822 uiButSetFunc(but, parnr_to_editbone_cb, curBone, NULL);
3824 MEM_freeN(boneString);
3826 /* Connect to parent flag */
3827 if (curBone->parent){
3828 but=uiDefButBitI(block, TOG, BONE_CONNECTED, B_ARM_RECALCDATA, "Con", 300,by,32,18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Connect this Bone to Parent");
3829 uiButSetFunc(but, attach_bone_to_parent_cb, curBone, NULL);
3832 /* Segment, dist and weight buttons */
3833 uiBlockBeginAlign(block);
3834 uiDefButS(block, NUM, B_ARM_RECALCDATA, "Segm: ", -10,by-19,117,18, &curBone->segments, 1.0, 32.0, 0.0, 0.0, "Subdivisions for B-bones");
3835 uiDefButF(block, NUM,B_ARM_RECALCDATA, "Dist:", 110, by-19, 105, 18, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance");
3836 uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", 225, by-19,105, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight");
3838 /* bone types */
3839 uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge", -10,by-38,85,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
3840 uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform", 75, by-38, 85, 18, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
3841 uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 160,by-38,85,18, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
3842 uiDefButBitI(block, TOG, BONE_HIDDEN_A, REDRAWVIEW3D, "Hide", 245,by-38,85,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Edit Mode");
3844 /* layers */
3845 uiBlockBeginAlign(block);
3846 for(a=0; a<8; a++) {
3847 short dx= 21;
3848 but= uiDefButBitS(block, TOG, 1<<a, REDRAWVIEW3D, "", -10+a*dx, by-57, dx, 15, &curBone->layer, 0, 0, 0, 0, "Don't draw this layer for group-duplicators");
3849 uiButSetFunc(but, armature_layer_cb, &curBone->layer, (void *)(1<<a));
3851 uiBlockBeginAlign(block);
3852 for(a=8; a<16; a++) {
3853 short dx= 21;
3854 but= uiDefButBitS(block, TOG, 1<<a, REDRAWVIEW3D, "", -6+a*dx, by-57, dx, 15, &curBone->layer, 0, 0, 0, 0, "Don't draw this layer for group-duplicators");
3855 uiButSetFunc(but, armature_layer_cb, &curBone->layer, (void *)(1<<a));
3858 uiBlockEndAlign(block);
3859 by-=80;
3861 if(by < -200) break; // for time being... extreme long panels are very slow
3865 if(by<0) {
3866 uiNewPanelHeight(block, 204 - by);
3871 /* sets warning popup for buttons, and returns 1 for protected proxy posechannels */
3872 static int ob_arm_bone_pchan_lock(Object *ob, bArmature *arm, Bone *bone, bPoseChannel *pchan)
3874 /* ob lib case is already set globally */
3875 if(ob->id.lib)
3876 return 0;
3877 if(arm->id.lib) {
3878 if(pchan==NULL)
3879 uiSetButLock(1, ERROR_LIBDATA_MESSAGE);
3880 else if(ob->proxy && bone->layer & arm->layer_protected) {
3881 uiSetButLock(1, "Can't edit protected proxy channel");
3882 return 1;
3884 else
3885 uiClearButLock();
3887 return 0;
3890 static void editing_panel_pose_bones(Object *ob, bArmature *arm)
3892 uiBlock *block;
3893 uiBut *but;
3894 bPoseChannel *pchan;
3895 Bone *curBone;
3896 int by, a;
3897 int index, zerodof, zerolimit;
3899 /* Draw the bone name block */
3900 block= uiNewBlock(&curarea->uiblocks, "editing_panel_pose_bones", UI_EMBOSS, UI_HELV, curarea->win);
3901 if(uiNewPanel(curarea, block, "Armature Bones", "Editing", 640, 0, 318, 204)==0) return;
3903 /* this is a variable height panel, newpanel doesnt force new size on existing panels */
3904 /* so first we make it default height */
3905 uiNewPanelHeight(block, 204);
3907 uiDefBut(block, LABEL, 0, "Selected Bones", 0,180,158,18, 0, 0, 0, 0, 0, "Only show in Armature Editmode/Posemode");
3908 by= 160;
3910 for (pchan=ob->pose->chanbase.first, index=0; pchan; pchan=pchan->next, index++){
3911 curBone= pchan->bone;
3912 if ((curBone->flag & BONE_SELECTED) && (curBone->layer & arm->layer)) {
3914 if(ob_arm_bone_pchan_lock(ob, arm, curBone, pchan))
3915 uiDefBut(block, LABEL, 0, "Proxy Locked", 160, 180,150,18, NULL, 1, 0, 0, 0, "");
3917 /* Bone naming button */
3918 uiBlockBeginAlign(block);
3919 but=uiDefBut(block, TEX, REDRAWVIEW3D, "BO:", -10,by,117,19, curBone->name, 0, 24, 0, 0, "Change the bone name");
3920 uiButSetFunc(but, validate_posebonebutton_cb, curBone, NULL);
3921 uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob);
3923 /* Dist and weight buttons */
3924 uiDefButF(block, NUM,B_ARM_RECALCDATA, "Dist:", 107, by, 105, 19, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance");
3925 uiDefButF(block, NUM,B_ARM_RECALCDATA, "Weight:", 220, by, 110, 19, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight");
3927 /* Segment, ease in/out buttons */
3928 uiBlockBeginAlign(block);
3929 uiDefButS(block, NUM, B_ARM_RECALCDATA, "Segm: ", -10,by-19,117,19, &curBone->segments, 1.0, 32.0, 0.0, 0.0, "Subdivisions for B-bones");
3930 uiDefButF(block, NUM,B_ARM_RECALCDATA, "In:", 107, by-19,105, 19, &curBone->ease1, 0.0, 2.0, 10.0, 0.0, "First length of Bezier handle");
3931 uiDefButF(block, NUM,B_ARM_RECALCDATA, "Out:", 220, by-19, 110, 19, &curBone->ease2, 0.0, 2.0, 10.0, 0.0, "Second length of Bezier handle");
3933 /* bone types */
3934 uiDefButBitI(block, TOG, BONE_HINGE, B_ARM_RECALCDATA, "Hinge", -10,by-38,113,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Don't inherit rotation or scale from parent Bone");
3935 uiDefButBitI(block, TOGN, BONE_NO_DEFORM, B_ARM_RECALCDATA, "Deform", 104, by-38, 113, 19, &curBone->flag, 0.0, 0.0, 0.0, 0.0, "Indicate if Bone deforms geometry");
3936 uiDefButBitI(block, TOG, BONE_MULT_VG_ENV, B_ARM_RECALCDATA, "Mult", 217,by-38,113,19, &curBone->flag, 1.0, 32.0, 0.0, 0.0, "Multiply Bone Envelope with VertexGroup");
3937 ob_arm_bone_pchan_lock(ob, arm, curBone, pchan);
3938 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, REDRAWVIEW3D, "OB:", -10,by-57,170,19, &pchan->custom, "Object that defines custom draw type for this Bone");
3939 uiDefButF(block, COL, REDRAWVIEW3D, "", 160, by-57, 170, 29, &(pchan->custom_color[0]), 0, 0, 0, B_ARM_CUSTCOLOR, "Custom color for drawing this Bone");
3940 ob_arm_bone_pchan_lock(ob, arm, curBone, NULL);
3942 /* layers */
3943 uiBlockBeginAlign(block);
3944 for(a=0; a<8; a++) {
3945 short dx= 21;
3946 but= uiDefButBitS(block, TOG, 1<<a, REDRAWVIEW3D, "", -10+a*dx, by-76, dx, 15, &curBone->layer, 0, 0, 0, 0, "");
3947 uiButSetFunc(but, armature_layer_cb, &curBone->layer, (void *)(1<<a));
3949 uiBlockBeginAlign(block);
3950 for(a=8; a<16; a++) {
3951 short dx= 21;
3952 but= uiDefButBitS(block, TOG, 1<<a, REDRAWVIEW3D, "", -6+a*dx, by-76, dx, 15, &curBone->layer, 0, 0, 0, 0, "");
3953 uiButSetFunc(but, armature_layer_cb, &curBone->layer, (void *)(1<<a));
3955 uiBlockEndAlign(block);
3957 by-= 20;
3959 ob_arm_bone_pchan_lock(ob, arm, curBone, pchan);
3961 /* DOFs only for IK chains */
3962 zerodof = 1;
3963 zerolimit = 1;
3964 if(pose_channel_in_IK_chain(ob, pchan)) {
3966 uiBlockBeginAlign(block);
3967 uiDefButBitS(block, TOG, BONE_IK_NO_XDOF, B_ARM_RECALCDATA, "Lock X Rot", -10,by-80,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable X DoF for IK");
3968 if ((pchan->ikflag & BONE_IK_NO_XDOF)==0) {
3969 uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff X:", -10, by-100, 114, 19, &pchan->stiffness[0], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for X axis");
3970 uiDefButBitS(block, TOG, BONE_IK_XLIMIT, B_ARM_RECALCDATA, "Limit X", -10,by-120,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over X axis");
3971 if ((pchan->ikflag & BONE_IK_XLIMIT)) {
3972 uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min X:", -10, by-140, 114, 19, &pchan->limitmin[0], -180.0, 0.0, 1000, 1, "Minimum X limit");
3973 uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max X:", -10, by-160, 114, 19, &pchan->limitmax[0], 0.0, 180.0f, 1000, 1, "Maximum X limit");
3974 zerolimit = 0;
3976 zerodof = 0;
3978 uiBlockEndAlign(block);
3980 uiBlockBeginAlign(block);
3981 uiDefButBitS(block, TOG, BONE_IK_NO_YDOF, B_ARM_RECALCDATA, "Lock Y Rot", 104,by-80,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Y DoF for IK");
3982 if ((pchan->ikflag & BONE_IK_NO_YDOF)==0) {
3983 uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Y:", 104, by-100, 114, 19, &pchan->stiffness[1], 0.0, 0.99, 1.0, 0.0, "Resistance to twisting over Y axis");
3984 uiDefButBitS(block, TOG, BONE_IK_YLIMIT, B_ARM_RECALCDATA, "Limit Y", 104,by-120,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Y axis");
3985 if ((pchan->ikflag & BONE_IK_YLIMIT)) {
3986 uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min Y:", 104, by-140, 113, 19, &pchan->limitmin[1], -180.0, 0.0, 1000, 1, "Minimum Y limit");
3987 uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max Y:", 104, by-160, 113, 19, &pchan->limitmax[1], 0.0, 180.0, 1000, 1, "Maximum Y limit");
3988 zerolimit = 0;
3990 zerodof = 0;
3992 uiBlockEndAlign(block);
3994 uiBlockBeginAlign(block);
3995 uiDefButBitS(block, TOG, BONE_IK_NO_ZDOF, B_ARM_RECALCDATA, "Lock Z Rot", 217,by-80,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Z DoF for IK");
3996 if ((pchan->ikflag & BONE_IK_NO_ZDOF)==0) {
3997 uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Z:", 217, by-100, 114, 19, &pchan->stiffness[2], 0.0, 0.99, 1.0, 0.0, "Resistance to bending for Z axis");
3998 uiDefButBitS(block, TOG, BONE_IK_ZLIMIT, B_ARM_RECALCDATA, "Limit Z", 217,by-120,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Z axis");
3999 if ((pchan->ikflag & BONE_IK_ZLIMIT)) {
4000 uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min Z:", 217, by-140, 113, 19, &pchan->limitmin[2], -180.0, 0.0, 1000, 1, "Minimum Z limit");
4001 uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max Z:", 217, by-160, 113, 19, &pchan->limitmax[2], 0.0, 180.0, 1000, 1, "Maximum Z limit");
4002 zerolimit = 0;
4004 zerodof = 0;
4006 uiBlockEndAlign(block);
4008 by -= (zerodof)? 82: (zerolimit)? 142: 182;
4010 uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stretch:", -10, by, 113, 19, &pchan->ikstretch, 0.0, 1.0, 1.0, 0.0, "Allow scaling of the bone for IK");
4012 by -= 20;
4014 else {
4015 but= uiDefButBitS(block, TOG, POSE_STRIDE, B_ARM_STRIDE, "Stride Root", -10, by-80, 113, 19, &pchan->flag, 0.0, 0.0, 0, 0, "Set this PoseChannel to define the Stride distance");
4016 uiButSetFunc(but, validate_stridebutton_cb, pchan, NULL);
4018 uiDefBut(block, LABEL, 0, "(DoF only for IK chains)", 110,by-80, 190, 19, 0, 0, 0, 0, 0, "");
4019 by -= 102;
4023 if(by < -200) break; // for time being... extreme long panels are very slow
4027 if(by<0) {
4028 uiNewPanelHeight(block, 204 - by);
4034 /* *************************** MESH ******************************** */
4036 /* from this object to all objects with same ob->data */
4037 static void copy_linked_vgroup_channels(Object *ob)
4039 Base *base;
4041 for(base=FIRSTBASE; base; base= base->next) {
4042 if(base->object->type==ob->type) {
4043 if(base->object!=ob && base->object->data==ob->data) {
4044 BLI_freelistN(&base->object->defbase);
4045 duplicatelist(&base->object->defbase, &ob->defbase);
4046 base->object->actdef= ob->actdef;
4047 DAG_object_flush_update(G.scene, base->object, OB_RECALC_DATA);
4051 allqueue(REDRAWVIEW3D, 0);
4052 allqueue(REDRAWBUTSEDIT, 0);
4055 void do_vgroupbuts(unsigned short event)
4057 Object *ob= OBACT;
4059 switch(event) {
4060 case B_NEWVGROUP:
4061 add_defgroup (ob);
4062 scrarea_queue_winredraw(curarea);
4063 allqueue(REDRAWOOPS, 0);
4064 break;
4065 case B_DELVGROUP:
4066 if ((G.obedit) && (G.obedit == ob))
4067 del_defgroup (ob);
4068 else
4069 del_defgroup_in_object_mode (ob);
4070 allqueue (REDRAWVIEW3D, 1);
4071 allqueue(REDRAWOOPS, 0);
4072 BIF_undo_push("Delete vertex group");
4073 break;
4074 case B_ASSIGNVGROUP:
4075 assign_verts_defgroup ();
4076 allqueue (REDRAWVIEW3D, 1);
4077 BIF_undo_push("Assign to vertex group");
4078 break;
4079 case B_REMOVEVGROUP:
4080 remove_verts_defgroup (0);
4081 allqueue (REDRAWVIEW3D, 1);
4082 allqueue(REDRAWOOPS, 0);
4083 BIF_undo_push("Remove from vertex group");
4084 break;
4085 case B_SELVGROUP:
4086 sel_verts_defgroup(1);
4087 allqueue (REDRAWVIEW3D, 1);
4088 allqueue(REDRAWOOPS, 0);
4089 countall();
4090 break;
4091 case B_DESELVGROUP:
4092 sel_verts_defgroup(0);
4093 allqueue (REDRAWVIEW3D, 1);
4094 allqueue(REDRAWOOPS, 0);
4095 countall();
4096 break;
4097 case B_LINKEDVGROUP:
4098 copy_linked_vgroup_channels(ob);
4099 break;
4100 case B_COPYVGROUP:
4101 duplicate_defgroup (ob);
4102 scrarea_queue_winredraw (curarea);
4103 allqueue (REDRAWOOPS, 0);
4104 break;
4108 void do_meshbuts(unsigned short event)
4110 Object *ob;
4111 Mesh *me;
4112 MCol *mcol;
4113 EditMesh *em= G.editMesh;
4114 float fac;
4115 int count; /* store num of changes made to see if redraw & undo are needed*/
4116 int layernum;
4117 short randfac;
4119 ob= OBACT;
4120 if(ob && ob->type==OB_MESH) {
4122 me= get_mesh(ob);
4123 if(me==NULL) return;
4125 switch(event) {
4126 case B_DELSTICKY:
4127 if(me->msticky) {
4128 CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
4129 me->msticky= NULL;
4130 BIF_undo_push("Delete Sticky");
4132 allqueue(REDRAWBUTSEDIT, 0);
4133 break;
4134 case B_MAKESTICKY:
4135 RE_make_sticky();
4136 BIF_undo_push("Make Sticky");
4137 allqueue(REDRAWBUTSEDIT, 0);
4138 break;
4140 case B_NEWMCOL:
4141 if(G.obedit) {
4142 layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
4143 EM_add_data_layer(&em->fdata, CD_MCOL);
4144 CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
4146 else if(me) {
4147 mcol= me->mcol;
4148 layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
4150 if(mcol)
4151 CustomData_add_layer(&me->fdata, CD_MCOL, CD_DUPLICATE,
4152 mcol, me->totface);
4153 else
4154 CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC,
4155 NULL, me->totface);
4157 CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
4158 mesh_update_customdata_pointers(me);
4160 if(!mcol)
4161 shadeMeshMCol(ob, me);
4164 if (me->mr) multires_load_cols(me);
4166 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
4167 BIF_undo_push("New Vertex Color");
4168 allqueue(REDRAWVIEW3D, 0);
4169 allqueue(REDRAWBUTSEDIT, 0);
4170 break;
4171 case B_SETMCOL:
4172 if (G.obedit || me) {
4173 CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata;
4174 CustomData_set_layer_active(fdata, CD_MCOL, actmcol-1);
4175 mesh_update_customdata_pointers(me);
4177 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
4178 BIF_undo_push("Set Active Vertex Color");
4179 allqueue(REDRAWVIEW3D, 0);
4180 allqueue(REDRAWBUTSEDIT, 0);
4182 break;
4183 case B_SETMCOL_RND:
4184 if (G.obedit || me) {
4185 CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata;
4186 CustomData_set_layer_render(fdata, CD_MCOL, actmcol_rnd-1);
4188 BIF_undo_push("Set Render Vertex Color");
4189 allqueue(REDRAWBUTSEDIT, 0);
4191 break;
4193 case B_NEWTFACE:
4194 if(me)
4195 layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
4196 else
4197 layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
4199 if(me && me->mr) {
4200 multires_add_layer(me, &me->mr->fdata, CD_MTFACE, layernum);
4202 else if(G.obedit) {
4203 EM_add_data_layer(&em->fdata, CD_MTFACE);
4204 CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
4206 else if(me) {
4207 if(me->mtface)
4208 CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DUPLICATE,
4209 me->mtface, me->totface);
4210 else
4211 CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
4212 NULL, me->totface);
4214 CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
4215 mesh_update_customdata_pointers(me);
4218 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
4219 BIF_undo_push("New UV Texture");
4220 allqueue(REDRAWVIEW3D, 0);
4221 allqueue(REDRAWBUTSEDIT, 0);
4222 allqueue(REDRAWIMAGE, 0);
4223 break;
4224 case B_SETTFACE:
4225 if (G.obedit || me) {
4226 CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata;
4228 CustomData_set_layer_active(fdata, CD_MTFACE, acttface-1);
4229 mesh_update_customdata_pointers(me);
4231 /* Update first-level face data in multires */
4232 if(me && me->mr && me->mr->current != 1)
4233 CustomData_set_layer_active(&me->mr->fdata, CD_MTFACE, acttface-1);
4235 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
4236 BIF_undo_push("Set Active UV Texture");
4237 allqueue(REDRAWVIEW3D, 0);
4238 allqueue(REDRAWBUTSEDIT, 0);
4239 allqueue(REDRAWIMAGE, 0);
4241 break;
4242 case B_SETTFACE_RND:
4243 if (G.obedit || me) {
4244 CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata;
4245 CustomData_set_layer_render(fdata, CD_MTFACE, acttface_rnd-1);
4246 BIF_undo_push("Set Render UV Texture");
4247 allqueue(REDRAWBUTSEDIT, 0);
4249 break;
4251 case B_FLIPNORM:
4252 if(G.obedit) {
4253 flip_editnormals();
4254 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
4255 BIF_undo_push("Flip Normals");
4256 allqueue(REDRAWVIEW3D, 0);
4258 break;
4261 if(G.obedit==NULL || (G.obedit->type!=OB_MESH)) return;
4263 switch(event) {
4264 case B_SPIN:
4265 if( select_area(SPACE_VIEW3D)) spin_mesh(G.scene->toolsettings->step, G.scene->toolsettings->degr, 0, 0);
4266 break;
4267 case B_SPINDUP:
4268 if( select_area(SPACE_VIEW3D)) spin_mesh(G.scene->toolsettings->step, G.scene->toolsettings->degr, 0, 1);
4269 break;
4270 case B_EXTR:
4271 G.f |= G_DISABLE_OK;
4272 if( select_area(SPACE_VIEW3D)) extrude_mesh();
4273 G.f -= G_DISABLE_OK;
4274 break;
4275 case B_SCREW:
4276 if( select_area(SPACE_VIEW3D)) screw_mesh(G.scene->toolsettings->step, G.scene->toolsettings->turn);
4277 break;
4278 case B_EXTREP:
4279 if( select_area(SPACE_VIEW3D)) extrude_repeat_mesh(G.scene->toolsettings->step, G.scene->toolsettings->extr_offs);
4280 break;
4281 case B_SPLIT:
4282 G.f |= G_DISABLE_OK;
4283 split_mesh();
4284 G.f -= G_DISABLE_OK;
4285 break;
4286 case B_REMDOUB:
4287 count= removedoublesflag(1, G.scene->toolsettings->doublimit);
4288 notice("Removed: %d", count);
4289 if (count) { /* only undo and redraw if an action is taken */
4290 countall ();
4291 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
4292 allqueue(REDRAWVIEW3D, 0);
4293 BIF_undo_push("Rem Doubles");
4295 break;
4296 case B_SUBDIV:
4297 waitcursor(1);
4298 esubdivideflag(1, 0.0, G.scene->toolsettings->editbutflag,1,0);
4299 countall();
4300 waitcursor(0);
4301 allqueue(REDRAWVIEW3D, 0);
4302 BIF_undo_push("Subdivide");
4303 break;
4304 case B_FRACSUBDIV:
4305 randfac= 10;
4306 if(button(&randfac, 1, 100, "Rand fac:")==0) return;
4307 waitcursor(1);
4308 fac= -( (float)randfac )/100;
4309 esubdivideflag(1, fac, G.scene->toolsettings->editbutflag,1,0);
4310 countall();
4311 waitcursor(0);
4312 allqueue(REDRAWVIEW3D, 0);
4313 BIF_undo_push("Fractal Subdivide");
4314 break;
4315 case B_XSORT:
4316 if( select_area(SPACE_VIEW3D)) xsortvert_flag(1);
4317 break;
4318 case B_HASH:
4319 hashvert_flag(1);
4320 break;
4321 case B_TOSPHERE:
4322 vertices_to_sphere();
4323 break;
4324 case B_VERTEXNOISE:
4325 vertexnoise();
4326 break;
4327 case B_VERTEXSMOOTH:
4328 vertexsmooth();
4329 break;
4330 case B_DRAWEDGES:
4331 G.f &= ~G_DRAWCREASES;
4332 allqueue(REDRAWBUTSEDIT, 0);
4333 allqueue(REDRAWVIEW3D, 0);
4334 break;
4335 case B_DRAWCREASES:
4336 G.f &= ~G_DRAWEDGES;
4337 allqueue(REDRAWBUTSEDIT, 0);
4338 allqueue(REDRAWVIEW3D, 0);
4339 break;
4340 case B_JOINTRIA:
4341 join_triangles();
4342 break;
4345 /* WATCH IT: previous events only in editmode! */
4348 static void editing_panel_mesh_tools(Object *ob, Mesh *me)
4350 uiBlock *block;
4352 block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_tools", UI_EMBOSS, UI_HELV, curarea->win);
4353 if(uiNewPanel(curarea, block, "Mesh Tools", "Editing", 640, 0, 318, 254)==0) return;
4355 uiBlockBeginAlign(block);
4356 //uiDefButBitS(block, TOG, B_AUTOFGON, 0, "FGon", 10,195,30,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Causes 'Subdivide' To create FGon on inner edges where possible");
4357 uiDefButBitS(block, TOG, B_BEAUTY, 0, "Beauty", 10,195,53,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Causes 'Subdivide' to split faces in halves instead of quarters using long edges unless 'Short' is selected");
4358 uiDefButBitS(block, TOG, B_BEAUTY_SHORT, 0, "Short", 63,195,52,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "If Beauty is set, 'Subdivide' splits faces in halves using short edges");
4360 uiDefBut(block, BUT,B_SUBDIV,"Subdivide", 115,195,105,19, 0, 0, 0, 0, 0, "Splits selected faces into halves or quarters");
4362 uiDefButS(block, MENU, B_DIFF, "Corner Cut Type %t|Path %x0|Innervert %x1|Fan %x2",
4363 220, 195, 105, 19, &G.scene->toolsettings->cornertype , 0, 0, 0, 0, "Choose Quad Corner Cut Type");
4365 uiDefBut(block, BUT,B_VERTEXNOISE,"Noise", 10,175,78,19, 0, 0, 0, 0, 0, "Use vertex coordinate as texture coordinate");
4366 uiDefBut(block, BUT,B_HASH,"Hash", 88,175,78,19, 0, 0, 0, 0, 0, "Randomizes selected vertex sequence data");
4367 uiDefBut(block, BUT,B_XSORT,"Xsort", 166,175,78,19, 0, 0, 0, 0, 0, "Sorts selected vertex data in the X direction");
4368 uiDefBut(block, BUT,B_FRACSUBDIV, "Fractal", 244,175,81,19, 0, 0, 0, 0, 0, "Subdivides selected faces with a random factor");
4371 uiDefBut(block, BUT,B_TOSPHERE,"To Sphere", 10,155,78,19, 0, 0, 0, 0, 0, "Moves selected vertices outwards into a spherical shape");
4372 uiDefBut(block, BUT,B_VERTEXSMOOTH,"Smooth", 88,155,78,19, 0, 0, 0, 0, 0, "Flattens angles of selected faces");
4373 uiDefBut(block, BUT,B_SPLIT,"Split", 166,155,78,19, 0, 0, 0, 0, 0, "Splits selected vertices to separate sub-mesh");
4374 uiDefBut(block, BUT,B_FLIPNORM,"Flip Normals", 244,155,81,19, 0, 0, 0, 0, 0, "Toggles the direction of the selected face's normals");
4376 uiDefBut(block, BUT,B_REMDOUB,"Rem Doubles", 10,135,78,19, 0, 0, 0, 0, 0, "Removes duplicates from selected vertices");
4377 uiDefButF(block, NUM, B_DIFF, "Limit:", 88,135,117,19, &G.scene->toolsettings->doublimit, 0.0001, 1.0, 10, 0, "Specifies the max distance 'Rem Doubles' will consider vertices as 'doubled'");
4378 uiDefButF(block, NUM, B_DIFF, "Threshold:", 205,135,120,19, &G.scene->toolsettings->select_thresh, 0.0001, 1.0, 10, 0, "Tolerence for the 'Select Group' tool (Shift+G) and 'Knife Exact' (vertex snap).");
4379 uiBlockEndAlign(block);
4381 uiDefBut(block, BUT,B_EXTR,"Extrude", 10,105,315,24, 0, 0, 0, 0, 0, "Converts selected edges to faces and selects the new vertices");
4383 uiBlockBeginAlign(block);
4384 uiDefBut(block, BUT,B_SPIN, "Spin", 10,75,100,24, 0, 0, 0, 0, 0, "Extrudes the selected vertices in a circle around the cursor in the indicated viewport");
4385 uiDefBut(block, BUT,B_SPINDUP,"Spin Dup", 110,75,100,24, 0, 0, 0, 0, 0, "Creates copies of the selected vertices in a circle around the cursor in the indicated viewport");
4386 uiDefBut(block, BUT,B_SCREW,"Screw", 210,75,115,24, 0, 0, 0, 0, 0, "Activates the screw tool"); // Bish - This could use some more definition
4388 uiDefButF(block, NUM, B_DIFF, "Degr:", 10,55,100,19, &G.scene->toolsettings->degr,-360.0,360.0, 1000, 0, "Specifies the number of degrees 'Spin' revolves");
4389 uiDefButS(block, NUM, B_DIFF, "Steps:", 110,55,100,19, &G.scene->toolsettings->step,1.0,180.0, 0, 0, "Specifies the total number of 'Spin' slices");
4390 uiDefButS(block, NUM, B_DIFF, "Turns:", 210,55,115,19, &G.scene->toolsettings->turn,1.0,360.0, 0, 0, "Specifies the number of revolutions the screw turns");
4391 uiDefButBitS(block, TOG, B_KEEPORIG, B_DIFF, "Keep Original",10,35,200,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Keeps a copy of the original vertices and faces after executing tools");
4392 uiDefButBitS(block, TOG, B_CLOCKWISE, B_DIFF, "Clockwise", 210,35,115,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "Specifies the direction for 'Screw' and 'Spin'");
4394 uiBlockBeginAlign(block);
4395 uiDefBut(block, BUT,B_EXTREP, "Extrude Dup", 10,10,150,19, 0, 0, 0, 0, 0, "Creates copies of the selected vertices in a straight line away from the current viewport");
4396 uiDefButF(block, NUM, B_DIFF, "Offset:", 160,10,165,19, &G.scene->toolsettings->extr_offs, 0.01, 100.0, 100, 0, "Sets the distance between each copy for 'Extrude Dup'");
4397 uiBlockEndAlign(block);
4399 uiBlockBeginAlign(block);
4400 uiDefBut(block, BUT, B_JOINTRIA, "Join Triangles", 10, -20, 120, 19, 0, 0, 0, 0, 0, "Convert selected triangles to Quads");
4401 uiDefButF(block, NUM, B_DIFF, "Threshold", 130, -20, 195, 19, &G.scene->toolsettings->jointrilimit, 0.0, 1.0, 5, 0, "Conversion threshold for complex islands");
4402 uiDefButBitS(block, TOG, B_JOINTRIA_UV, 0, "Delimit UVs", 10, -40, 78, 19, &G.scene->toolsettings->editbutflag, 0,0,0,0, "Join pairs only where UVs match");
4403 uiDefButBitS(block, TOG, B_JOINTRIA_VCOL, 0, "Delimit Vcol", 90, -40, 78, 19, &G.scene->toolsettings->editbutflag, 0,0,0,0, "Join pairs only where Vcols match");
4404 uiDefButBitS(block, TOG, B_JOINTRIA_SHARP, 0, "Delimit Sharp", 170, -40, 78, 19, &G.scene->toolsettings->editbutflag, 0,0,0,0, "Join pairs only where edge is not sharp");
4405 uiDefButBitS(block, TOG, B_JOINTRIA_MAT, 0, "Delimit Mat", 250, -40, 74, 19, &G.scene->toolsettings->editbutflag, 0,0,0,0, "Join pairs only where material matches");
4406 uiBlockEndAlign(block);
4411 static void verify_vertexgroup_name_func(void *datav, void *data2_unused)
4413 unique_vertexgroup_name((bDeformGroup*)datav, OBACT);
4418 static void editing_panel_mesh_tools1(Object *ob, Mesh *me)
4420 uiBlock *block;
4423 block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_tools1", UI_EMBOSS, UI_HELV, curarea->win);
4424 if(uiNewPanel(curarea, block, "Mesh Tools 1", "Editing", 960, 0, 318, 204)==0) return;
4426 uiBlockBeginAlign(block);
4427 uiDefBut(block, BUT,B_SELSWAP, "Select Swap", 955, 200, 106, 19, 0, 0, 0, 0, 0, "Selects unselected faces, and deselects selected faces");
4428 uiDefBut(block, BUT,B_HIDE, "Hide", 1061, 200, 106, 19, 0, 0, 0, 0, 0, "Hides selected faces");
4429 uiDefBut(block, BUT,B_REVEAL, "Reveal", 1167, 200, 107, 19, 0, 0, 0, 0, 0, "Reveals selected faces");
4430 uiBlockEndAlign(block);
4432 uiBlockBeginAlign(block);
4433 uiDefButF(block, NUM, REDRAWVIEW3D, "NSize:", 955, 170, 150, 19, &G.scene->editbutsize, 0.001, 2.0, 10, 0, "Sets the length to use when displaying face normals");
4434 uiDefButBitI(block, TOG, G_DRAWNORMALS, REDRAWVIEW3D, "Draw Normals", 955,148,150,19, &G.f, 0, 0, 0, 0, "Displays face normals as lines");
4435 uiDefButBitI(block, TOG, G_DRAW_VNORMALS, REDRAWVIEW3D, "Draw VNormals",955,126,150,19, &G.f, 0, 0, 0, 0, "Displays vertex normals as lines");
4436 uiBlockEndAlign(block);
4438 uiBlockBeginAlign(block);
4439 uiDefButBitI(block, TOG, G_DRAWFACES, REDRAWVIEW3D, "Draw Faces", 955,88,150,19, &G.f, 0, 0, 0, 0, "Displays all faces as shades");
4440 uiDefButBitI(block, TOG, G_DRAWEDGES, REDRAWVIEW3D, "Draw Edges", 955,66,150,19, &G.f, 0, 0, 0, 0, "Displays selected edges using hilights");
4441 uiDefButBitI(block, TOG, G_DRAWCREASES, REDRAWVIEW3D, "Draw Creases", 955,44,150,19, &G.f, 0, 0, 0, 0, "Displays creases created for subsurf weighting");
4442 uiDefButBitI(block, TOG, G_DRAWSEAMS, REDRAWVIEW3D, "Draw Seams", 955,22,150,19, &G.f, 0, 0, 0, 0, "Displays UV unwrapping seams");
4443 uiDefButBitI(block, TOG, G_DRAWSHARP, REDRAWVIEW3D, "Draw Sharp", 955,0,150,19, &G.f, 0, 0, 0, 0, "Displays sharp edges, used with the EdgeSplit modifier");
4444 uiBlockEndAlign(block);
4446 /* Measurement drawing options */
4447 uiBlockBeginAlign(block);
4448 uiDefButBitI(block, TOG, G_DRAW_EDGELEN, REDRAWVIEW3D, "Edge Length", 1125,170,150,19, &G.f, 0, 0, 0, 0, "Displays selected edge lengths");
4449 uiDefButBitI(block, TOG, G_DRAW_EDGEANG, REDRAWVIEW3D, "Edge Angles", 1125,148,150,19, &G.f, 0, 0, 0, 0, "Displays the angles in the selected edges in degrees");
4450 uiDefButBitI(block, TOG, G_DRAW_FACEAREA, REDRAWVIEW3D, "Face Area", 1125,126,150,19, &G.f, 0, 0, 0, 0, "Displays the area of selected faces");
4451 #ifdef WITH_VERSE
4452 if(G.editMesh->vnode)
4453 uiDefButBitI(block, TOG, G_DRAW_VERSE_DEBUG, REDRAWVIEW3D, "Draw VDebug",1125,104,150,19, &G.f, 0, 0, 0, 0, "Displays verse debug information");
4454 #endif
4456 uiBlockEndAlign(block);
4458 uiBlockBeginAlign(block);
4459 uiDefButBitI(block, TOG, G_ALLEDGES, 0, "All Edges", 1125, 22,150,19, &G.f, 0, 0, 0, 0, "Displays all edges in object mode without optimization");
4460 uiDefButBitS(block, TOG, B_MESH_X_MIRROR, B_DIFF, "X-axis mirror",1125,0,150,19, &G.scene->toolsettings->editbutflag, 0, 0, 0, 0, "While using transforms, mirrors the transformation");
4461 uiBlockEndAlign(block);
4464 char *get_vertexgroup_menustr(Object *ob)
4466 bDeformGroup *dg;
4467 int defCount, min, index;
4468 char (*qsort_ptr)[sizeof(dg->name)+5] = NULL; // +5 for "%x99|"
4469 char *s, *menustr;
4470 int printed;
4472 defCount=BLI_countlist(&ob->defbase);
4474 if (!defCount) min=0;
4475 else min=1;
4477 if (defCount > 0) {
4479 * This will hold the group names temporarily
4480 * so we can sort them
4482 qsort_ptr = MEM_callocN (defCount * sizeof (qsort_ptr[0]),
4483 "qsort_ptr");
4484 for (index = 1, dg = ob->defbase.first; dg; index++, dg=dg->next) {
4485 printed = snprintf (qsort_ptr[index - 1], sizeof (dg->name), dg->name);
4486 snprintf (qsort_ptr[index - 1]+printed, 5+1, "%%x%d|", index); // +1 to move the \0
4489 qsort (qsort_ptr, defCount, sizeof (qsort_ptr[0]),
4490 ( int (*)(const void *, const void *) ) strcmp);
4493 s= menustr = MEM_callocN((sizeof(qsort_ptr[0]) * defCount)+30, "menustr"); // plus 30 for when defCount==0
4494 if(defCount) {
4495 for (index = 0; index < defCount; index++) {
4496 int cnt= sprintf (s, "%s", qsort_ptr[index]);
4497 if (cnt>0) s+= cnt;
4500 else strcpy(menustr, "No Vertex Groups in Object");
4502 if (qsort_ptr)
4503 MEM_freeN (qsort_ptr);
4505 return menustr;
4508 static void editing_panel_links(Object *ob)
4510 uiBlock *block;
4511 ID *id, *idfrom;
4512 int *poin, xco=143;
4513 float min;
4514 Material *ma;
4515 char str[64];
4516 uiBut *but;
4518 block= uiNewBlock(&curarea->uiblocks, "editing_panel_links", UI_EMBOSS, UI_HELV, curarea->win);
4519 if(uiNewPanel(curarea, block, "Link and Materials", "Editing", 0, 0, 318, 204)==0) return;
4521 uiSetButLock((ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
4523 buttons_active_id(&id, &idfrom);
4525 if(id) {
4526 int alone= 0;
4527 int local= 0;
4528 int browse= B_EDITBROWSE;
4530 if(ob->type==OB_MESH) {
4531 browse= B_MESHBROWSE;
4532 alone= B_MESHALONE;
4533 local= B_MESHLOCAL;
4534 uiSetButLock(G.obedit!=0, "Unable to perform function in EditMode");
4536 else if(ob->type==OB_MBALL) {
4537 alone= B_MBALLALONE;
4538 local= B_MBALLLOCAL;
4540 else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
4541 alone= B_CURVEALONE;
4542 local= B_CURVELOCAL;
4544 else if(ob->type==OB_CAMERA) {
4545 alone= B_CAMERAALONE;
4546 local= B_CAMERALOCAL;
4548 else if(ob->type==OB_LAMP) {
4549 alone= B_LAMPALONE;
4550 local= B_LAMPLOCAL;
4552 else if (ob->type==OB_ARMATURE){
4553 alone = B_ARMALONE;
4554 local = B_ARMLOCAL;
4556 else if(ob->type==OB_LATTICE) {
4557 alone= B_LATTALONE;
4558 local= B_LATTLOCAL;
4560 uiBlockSetCol(block, TH_BUT_SETTING2);
4561 xco= std_libbuttons(block, 143, 180, 0, NULL, browse, GS(id->name), 0, id, idfrom, &(G.buts->menunr), alone, local, 0, 0, B_KEEPDATA);
4562 uiBlockSetCol(block, TH_AUTO);
4564 if(ob) {
4565 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
4566 but = uiDefBut(block, TEX, B_IDNAME, "OB:", xco, 180, 454-xco, YIC, ob->id.name+2, 0.0, 21.0, 0, 0, "Active Object name.");
4567 #ifdef WITH_VERSE
4568 if(ob->vnode) uiButSetFunc(but, test_and_send_idbutton_cb, ob, ob->id.name);
4569 else uiButSetFunc(but, test_idbutton_cb, ob->id.name, NULL);
4570 #else
4571 uiButSetFunc(but, test_idbutton_cb, ob->id.name, NULL);
4572 #endif
4576 /* empty display handling, note it returns! */
4577 if (ob->type==OB_EMPTY) {
4578 uiDefBut(block, LABEL,0,"Empty Display:",
4579 xco, 154, 130,20, 0, 0, 0, 0, 0, "");
4581 uiBlockBeginAlign(block);
4582 uiDefButC(block, MENU, REDRAWVIEW3D, "Empty Drawtype%t|Arrows%x1|Single Arrow%x4|Plain Axes%x2",
4583 xco, 128, 140, 20, &ob->empty_drawtype, 0, 0, 0, 0, "The Empty 3D View display style");
4584 uiDefButF(block, NUM, REDRAWVIEW3D, "Size:",
4585 xco, 108, 140, 21, &ob->empty_drawsize, 0.01, 10.0, 1, 0, "The size to display the Empty");
4586 uiBlockEndAlign(block);
4587 return;
4590 /* vertex group... partially editmode... */
4591 if(ob->type==OB_MESH || ob->type==OB_LATTICE) {
4592 bDeformGroup *defGroup;
4593 uiBut *but;
4594 int defCount;
4596 uiDefBut(block, LABEL,0,"Vertex Groups",
4597 143,153,130,20, 0, 0, 0, 0, 0, "");
4599 defCount=BLI_countlist(&ob->defbase);
4601 if (defCount) {
4602 char *menustr= get_vertexgroup_menustr(ob);
4604 uiBlockBeginAlign(block);
4606 uiDefButS(block, MENU, B_MAKEDISP, menustr, 143, 132,18,21, (short *)&ob->actdef, 1, defCount, 0, 0, "Browses available vertex groups");
4607 MEM_freeN (menustr);
4609 if (ob->actdef){
4610 defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
4611 but= uiDefBut(block, TEX, REDRAWBUTSEDIT,"", 161,132,140-18,21, defGroup->name, 0, 31, 0, 0, "Displays current vertex group name. Click to change. (Match bone name for deformation.)");
4612 uiButSetFunc(but, verify_vertexgroup_name_func, defGroup, NULL);
4613 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
4615 uiDefButF(block, NUM, REDRAWVIEW3D, "Weight:", 143, 111, 140, 21, &editbutvweight, 0, 1, 10, 0, "Sets the current vertex group's bone deformation strength");
4617 uiBlockEndAlign(block);
4620 if (G.obedit && G.obedit==ob){
4621 uiBlockBeginAlign(block);
4622 uiDefBut(block, BUT,B_NEWVGROUP,"New", 143,90,70,21, 0, 0, 0, 0, 0, "Creates a new vertex group");
4623 uiDefBut(block, BUT,B_DELVGROUP,"Delete", 213,90,70,21, 0, 0, 0, 0, 0, "Removes the current vertex group");
4625 uiDefBut(block, BUT,B_ASSIGNVGROUP,"Assign", 143,69,70,21, 0, 0, 0, 0, 0, "Assigns selected vertices to the current vertex group");
4626 uiDefBut(block, BUT,B_REMOVEVGROUP,"Remove", 213,69,70,21, 0, 0, 0, 0, 0, "Removes selected vertices from the current vertex group");
4628 uiDefBut(block, BUT,B_SELVGROUP,"Select", 143,48,70,21, 0, 0, 0, 0, 0, "Selects vertices belonging to the current vertex group");
4629 uiDefBut(block, BUT,B_DESELVGROUP,"Desel.", 213,48,70,21, 0, 0, 0, 0, 0, "Deselects vertices belonging to the current vertex group");
4630 uiBlockEndAlign(block);
4632 else {
4633 ID *id= ob->data;
4635 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
4637 uiBlockBeginAlign (block);
4638 uiDefBut (block, BUT, B_NEWVGROUP, "New", 143, 90, 70, 21, 0, 0, 0, 0, 0, "Creates a new vertex group");
4639 uiDefBut (block, BUT, B_DELVGROUP, "Delete", 213, 90, 70, 21, 0, 0, 0, 0, 0, "Removes the current vertex group");
4640 uiDefBut (block, BUT, B_COPYVGROUP, "Copy Group", 143, 70, 140, 19, 0, 0, 0, 0, 0, "Copy Group of Vertex");
4641 uiBlockEndAlign (block);
4643 if(id->us > 1)
4644 uiDefBut(block, BUT,B_LINKEDVGROUP, "Copy To Linked", 143,50,140,20, 0, 0, 0, 0, 0, "Creates identical vertex group names in other Objects using this Object-data");
4648 /* now only objects that can be visible rendered */
4649 if ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL);
4650 else return;
4652 id= ob->data;
4653 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
4655 if(ob->type==OB_MESH) poin= &( ((Mesh *)ob->data)->texflag );
4656 else if(ob->type==OB_MBALL) poin= &( ((MetaBall *)ob->data)->texflag );
4657 else poin= &( ((Curve *)ob->data)->texflag );
4658 uiDefButBitI(block, TOG, AUTOSPACE, B_AUTOTEX, "AutoTexSpace", 143,15,140,19, poin, 0, 0, 0, 0, "Adjusts active object's texture space automatically when transforming object");
4660 sprintf(str,"%d Mat ", ob->totcol);
4661 if(ob->totcol) min= 1.0; else min= 0.0;
4662 ma= give_current_material(ob, ob->actcol);
4664 if(G.obedit) {
4665 char *str= NULL;
4666 IDnames_to_pupstring(&str, NULL, "ADD NEW %x 32767", &G.main->mat, NULL, NULL);
4667 uiDefButS(block, MENU, B_MATASS_BROWSE, str, 292,150,20,20, &G.buts->menunr, 0, 0, 0, 0, "Browses existing choices and assign");
4668 MEM_freeN(str);
4671 if(ma) uiDefBut(block, LABEL, 0, ma->id.name+2, 318,150, 103, 20, 0, 0, 0, 0, 0, "");
4673 uiBlockBeginAlign(block);
4674 if(ma) uiDefButF(block, COL, B_MATCOL2, "", 292,113,31,30, &(ma->r), 0, 0, 0, 0, "");
4675 uiDefButC(block, NUM, B_ACTCOL, str, 324,113,100,30, &ob->actcol, min, (float)(ob->totcol), 0, 0, "Displays total number of material indices and the current index");
4676 uiDefBut(block, BUT,B_MATWICH, "?", 424,113,30,30, 0, 0, 0, 0, 0, "In EditMode, sets the active material index from selected faces");
4678 uiBlockBeginAlign(block);
4679 uiDefBut(block, BUT,B_MATNEW, "New", 292,90,80,20, 0, 0, 0, 0, 0, "Adds a new Material index");
4680 uiDefBut(block, BUT,B_MATDEL, "Delete", 372,90,80,20, 0, 0, 0, 0, 0, "Deletes this Material index");
4681 uiDefBut(block, BUT,B_MATSEL, "Select", 292,70,80,20, 0, 0, 0, 0, 0, "In EditMode, selects faces that have the active index");
4682 uiDefBut(block, BUT,B_MATDESEL, "Deselect", 372,70,80,20, 0, 0, 0, 0, 0, "Deselects everything with current indexnumber");
4683 uiDefBut(block, BUT,B_MATASS, "Assign", 292,50,160,20, 0, 0, 0, 0, 0, "In EditMode, assigns the active index to selected faces");
4685 uiBlockBeginAlign(block);
4686 uiDefBut(block, BUT,B_SETSMOOTH,"Set Smooth", 292,15,80,20, 0, 0, 0, 0, 0, "In EditMode, sets 'smooth' rendering of selected faces");
4687 uiDefBut(block, BUT,B_SETSOLID, "Set Solid", 372,15,80,20, 0, 0, 0, 0, 0, "In EditMode, sets 'solid' rendering of selected faces");
4689 uiBlockEndAlign(block);
4694 void editing_panel_sculpting_tools()
4696 uiBlock *block= uiNewBlock(&curarea->uiblocks, "editing_panel_sculpting_tools", UI_EMBOSS, UI_HELV, curarea->win);
4697 if(uiNewPanel(curarea, block, "Sculpt", "Editing", 300, 0, 318, 204)==0) return;
4699 sculptmode_draw_interface_tools(block,0,200);
4702 void editing_panel_sculpting_textures()
4704 uiBlock *block= uiNewBlock(&curarea->uiblocks, "editing_panel_sculpting_textures", UI_EMBOSS, UI_HELV, curarea->win);
4705 if(uiNewPanel(curarea, block, "Brush", "Editing", 300, 0, 318, 204)==0) return;
4707 sculptmode_draw_interface_textures(block,0,200);
4710 void sculptmode_draw_interface_tools(uiBlock *block, unsigned short cx, unsigned short cy)
4712 SculptData *sd;
4713 uiBut *but;
4715 if(!G.scene) return;
4716 sd= &G.scene->sculptdata;
4718 uiBlockBeginAlign(block);
4720 uiDefBut(block,LABEL,B_NOP,"Brush",cx,cy,90,19,NULL,0,0,0,0,"");
4721 cy-= 20;
4723 uiBlockBeginAlign(block);
4724 uiDefButS(block,ROW,REDRAWBUTSEDIT,"Draw",cx,cy,67,19,&sd->brush_type,14.0,DRAW_BRUSH,0,0,"Draw lines on the model");
4725 uiDefButS(block,ROW,REDRAWBUTSEDIT,"Smooth",cx+67,cy,67,19,&sd->brush_type,14.0,SMOOTH_BRUSH,0,0,"Interactively smooth areas of the model");
4726 uiDefButS(block,ROW,REDRAWBUTSEDIT,"Pinch",cx+134,cy,67,19,&sd->brush_type,14.0,PINCH_BRUSH,0,0,"Interactively pinch areas of the model");
4727 uiDefButS(block,ROW,REDRAWBUTSEDIT,"Inflate",cx+201,cy,67,19,&sd->brush_type,14,INFLATE_BRUSH,0,0,"Push vertices along the direction of their normals");
4728 cy-= 20;
4729 uiDefButS(block,ROW,REDRAWBUTSEDIT,"Grab", cx,cy,89,19,&sd->brush_type,14,GRAB_BRUSH,0,0,"Grabs a group of vertices and moves them with the mouse");
4730 uiDefButS(block,ROW,REDRAWBUTSEDIT,"Layer", cx+89,cy,89,19,&sd->brush_type,14, LAYER_BRUSH,0,0,"Adds a layer of depth");
4731 uiDefButS(block,ROW,REDRAWBUTSEDIT,"Flatten", cx+178,cy,90,19,&sd->brush_type,14, FLATTEN_BRUSH,0,0,"Interactively flatten areas of the model");
4732 cy-= 25;
4733 uiBlockEndAlign(block);
4735 uiBlockBeginAlign(block);
4736 uiDefBut(block,LABEL,B_NOP,"Shape",cx,cy,90,19,NULL,0,0,0,0,"");
4737 cy-= 20;
4738 uiBlockBeginAlign(block);
4739 if(sd->brush_type != SMOOTH_BRUSH && sd->brush_type != GRAB_BRUSH && sd->brush_type != FLATTEN_BRUSH) {
4740 uiDefButC(block,ROW,B_NOP,"Add",cx,cy,89,19,&sculptmode_brush()->dir,15.0,1.0,0, 0,"Add depth to model [Shift]");
4741 uiDefButC(block,ROW,B_NOP,"Sub",cx+89,cy,89,19,&sculptmode_brush()->dir,15.0,2.0,0, 0,"Subtract depth from model [Shift]");
4743 if(sd->brush_type!=GRAB_BRUSH)
4744 uiDefButC(block,TOG,B_NOP,"Airbrush",cx+178,cy,89,19,&sculptmode_brush()->airbrush,0,0,0,0,"Brush makes changes without waiting for the mouse to move");
4745 cy-= 20;
4746 but= uiDefButS(block,NUMSLI,B_NOP,"Size: ",cx,cy,268,19,&sculptmode_brush()->size,1.0,200.0,0,0,"Set brush radius in pixels");
4747 cy-= 20;
4748 if(sd->brush_type!=GRAB_BRUSH)
4749 uiDefButC(block,NUMSLI,B_NOP,"Strength: ",cx,cy,268,19,&sculptmode_brush()->strength,1.0,100.0,0,0,"Set brush strength");
4750 cy-= 25;
4751 uiBlockEndAlign(block);
4753 uiBlockBeginAlign(block);
4754 uiDefBut( block,LABEL,B_NOP,"Symmetry",cx,cy,90,19,NULL,0,0,0,0,"");
4755 cy-= 20;
4756 uiBlockBeginAlign(block);
4757 uiDefButBitC(block, TOG, SYMM_X, 0, "X", cx,cy,89,19, &sd->symm, 0,0,0,0, "Mirror brush across X axis");
4758 uiDefButBitC(block, TOG, SYMM_Y, 0, "Y", cx+89,cy,89,19, &sd->symm, 0,0,0,0, "Mirror brush across Y axis");
4759 uiDefButBitC(block, TOG, SYMM_Z, 0, "Z", cx+178,cy,90,19, &sd->symm, 0,0,0,0, "Mirror brush across Z axis");
4760 uiBlockEndAlign(block);
4762 cx+= 210;
4765 void sculptmode_draw_interface_textures(uiBlock *block, unsigned short cx, unsigned short cy)
4767 SculptData *sd= sculpt_data();
4768 MTex *mtex;
4769 int i;
4770 int orig_y= cy;
4771 char *strp;
4772 uiBut *but;
4774 uiBlockBeginAlign(block);
4775 uiDefBut(block,LABEL,B_NOP,"Common",cx,cy,80,20,0,0,0,0,0,"");
4776 cy-= 20;
4778 uiBlockBeginAlign(block);
4779 uiDefButC(block,TOG,B_NOP, "Fade", cx,cy,80,19, &sd->texfade, 0,0,0,0,"Smooth the edges of the texture");
4780 cy-= 20;
4781 uiDefButS(block,NUM,B_NOP, "Space", cx,cy,80,19, &sd->spacing, 0,500,20,0,"Non-zero inserts N pixels between dots");
4782 cy-= 20;
4783 if(sd->brush_type == DRAW_BRUSH)
4784 uiDefButC(block,NUM,B_NOP, "View", cx,cy,80,19, &sculptmode_brush()->view, 0,10,20,0,"Pulls brush direction towards view");
4785 uiBlockEndAlign(block);
4787 cy= orig_y;
4788 cx+= 85;
4789 uiBlockBeginAlign(block);
4790 uiDefBut(block,LABEL,B_NOP,"Texture",cx,cy,80,20,0,0,0,0,0,"");
4791 cy-= 20;
4793 /* TEX CHANNELS */
4794 uiBlockBeginAlign(block);
4795 uiBlockSetCol(block, TH_BUT_NEUTRAL);
4796 for(i=-1; i<8; i++) {
4797 char str[64];
4798 int loos;
4799 mtex= sd->mtex[i];
4801 if(i==-1)
4802 strcpy(str, "Default");
4803 else {
4804 if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos);
4805 else strcpy(str, "");
4807 str[10]= 0;
4808 uiDefButS(block, ROW, REDRAWBUTSEDIT, str,cx, cy, 80, 20, &sd->texact, 3.0, (float)i, 0, 0, "Texture channel");
4809 cy-= 18;
4812 cy= orig_y-20;
4813 cx+= 85;
4814 mtex= sd->mtex[sd->texact];
4816 if(sd->texact == -1) {
4817 uiBlockBeginAlign(block);
4818 uiDefBut(block,LABEL,B_NOP,"",cx,cy,115,20,0,0,0,0,0,""); /* Padding */
4819 } else {
4820 ID *id= NULL;
4821 uiBlockBeginAlign(block);
4823 if(mtex && mtex->tex) id= &mtex->tex->id;
4824 IDnames_to_pupstring(&strp, NULL, "ADD NEW %x 32767", &G.main->tex, id, &G.buts->texnr);
4826 if(mtex && mtex->tex) {
4827 uiDefBut(block, TEX, B_IDNAME, "TE:",cx,cy,115,19, mtex->tex->id.name+2, 0.0, 21.0, 0, 0, "Texture name");
4828 cy-= 20;
4830 uiDefButS(block,MENU,B_SCULPT_TEXBROWSE, strp, cx,cy,20,19, &G.buts->texnr, 0,0,0,0, "Selects an existing texture or creates new");
4831 uiDefIconBut(block, BUT, B_AUTOTEXNAME, ICON_AUTO, cx+21,cy,21,20, 0, 0, 0, 0, 0, "Auto-assigns name to texture");
4833 but= uiDefBut(block, BUT, B_NOP, "Clear",cx+43, cy, 72, 20, 0, 0, 0, 0, 0, "Erases link to texture");
4834 uiButSetFunc(but,sculptmode_rem_tex,0,0);
4835 cy-= 25;
4837 uiBlockBeginAlign(block);
4838 uiDefButC(block,ROW, REDRAWBUTSEDIT, "Drag", cx, cy,39,19, &sd->texrept, 18,SCULPTREPT_DRAG,0,0,"Move the texture with the brush");
4839 uiDefButC(block,ROW, REDRAWBUTSEDIT, "Tile", cx+39,cy,39,19, &sd->texrept, 18,SCULPTREPT_TILE,0,0,"Treat the texture as a tiled image extending across the screen");
4840 uiDefButC(block,ROW, REDRAWBUTSEDIT, "3D", cx+78,cy,37,19, &sd->texrept, 18,SCULPTREPT_3D, 0,0,"Use vertex coords as texture coordinates");
4841 cy-= 20;
4843 if(sd->texrept != SCULPTREPT_3D) {
4844 uiBlockBeginAlign(block);
4845 uiDefButF(block,NUM,0, "Angle", cx,cy,115,19, &mtex->warpfac, 0,360,100,0, "Rotate texture counterclockwise");
4847 cy-= 20;
4849 if(sd->texrept != SCULPTREPT_DRAG) {
4850 uiBlockBeginAlign(block);
4851 but= uiDefIconButC(block, TOG, REDRAWBUTSEDIT, sd->texsep ? ICON_UNLOCKED : ICON_LOCKED, cx,cy,20,19, &sd->texsep,0,0,0,0, "Locks the texture sizes together");
4852 uiBlockBeginAlign(block);
4853 uiDefButF(block,NUM,B_NOP, sd->texsep ? "SizeX" : "Size", cx+20,cy,95,19, &mtex->size[0],1,1000,100,0,"Scaling factor for texture");
4854 cy-= 20;
4855 if(sd->texsep) {
4856 uiDefButF(block,NUM,B_NOP, "SizeY", cx+20,cy,95,19, &mtex->size[1],1,1000,100,0,"Scaling factor for texture");
4857 cy-= 20;
4858 if(sd->texrept == SCULPTREPT_3D)
4859 uiDefButF(block,NUM,B_NOP, "SizeZ", cx+20,cy,95,19, &mtex->size[2],1,1000,100,0,"Scaling factor for texture");
4860 cy-= 20;
4864 else {
4865 uiDefButS(block,TOG,B_SCULPT_TEXBROWSE, "Add New" ,cx, cy, 115, 19, &G.buts->texnr,-1,32767,0,0, "Adds a new texture");
4866 uiDefButS(block,MENU,B_SCULPT_TEXBROWSE, strp, cx,cy-20,20,19, &G.buts->texnr, 0,0,0,0, "Selects an existing texture or creates new");
4869 MEM_freeN(strp);
4872 uiBlockEndAlign(block);
4875 /* *************************** FACE/PAINT *************************** */
4877 void do_fpaintbuts(unsigned short event)
4879 Mesh *me;
4880 Object *ob;
4881 bDeformGroup *defGroup;
4882 MTFace *activetf, *tf;
4883 MFace *mf;
4884 MCol *activemcol;
4885 int a;
4886 SculptData *sd= &G.scene->sculptdata;
4887 ID *id, *idtest;
4888 extern VPaint Gwp; /* from vpaint */
4889 ToolSettings *settings= G.scene->toolsettings;
4890 int nr= 1;
4891 MTex *mtex;
4893 ob= OBACT;
4894 if(ob==NULL) return;
4896 switch(event) {
4898 case B_VPGAMMA:
4899 vpaint_dogamma();
4900 break;
4901 case B_COPY_TF_MODE:
4902 case B_COPY_TF_UV:
4903 case B_COPY_TF_COL:
4904 case B_COPY_TF_TEX:
4905 me= get_mesh(OBACT);
4906 activetf= get_active_tface(&activemcol);
4908 if(me && activetf) {
4909 for (a=0, tf=me->mtface, mf=me->mface; a < me->totface; a++, tf++, mf++) {
4910 if(tf!=activetf && (mf->flag & ME_FACE_SEL)) {
4911 if(event==B_COPY_TF_MODE) {
4912 tf->mode= activetf->mode;
4913 tf->transp= activetf->transp;
4915 else if(event==B_COPY_TF_UV) {
4916 memcpy(tf->uv, activetf->uv, sizeof(tf->uv));
4917 tf->tpage= activetf->tpage;
4918 tf->tile= activetf->tile;
4920 if(activetf->mode & TF_TILES) tf->mode |= TF_TILES;
4921 else tf->mode &= ~TF_TILES;
4924 else if(event==B_COPY_TF_TEX) {
4925 tf->tpage= activetf->tpage;
4926 tf->tile= activetf->tile;
4928 if(activetf->mode & TF_TILES) tf->mode |= TF_TILES;
4929 else tf->mode &= ~TF_TILES;
4931 else if(event==B_COPY_TF_COL && activemcol)
4932 memcpy(&me->mcol[a*4], activemcol, sizeof(MCol)*4);
4936 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
4937 do_shared_vertexcol(me);
4938 allqueue(REDRAWVIEW3D, 0);
4939 allqueue(REDRAWIMAGE, 0);
4941 break;
4942 case B_SET_VCOL:
4943 if(G.f & G_FACESELECT)
4944 clear_vpaint_selectedfaces();
4945 else
4946 clear_vpaint();
4947 break;
4948 case B_REDR_3D_IMA:
4949 allqueue(REDRAWVIEW3D, 0);
4950 allqueue(REDRAWIMAGE, 0);
4951 break;
4952 case B_ASSIGNMESH:
4954 test_object_materials(ob->data);
4955 allqueue(REDRAWVIEW3D, 0);
4956 allqueue(REDRAWBUTSEDIT, 0);
4957 break;
4959 case B_TFACE_HALO:
4960 activetf = get_active_tface(NULL);
4961 if(activetf) {
4962 activetf->mode &= ~TF_BILLBOARD2;
4963 allqueue(REDRAWBUTSEDIT, 0);
4965 break;
4967 case B_TFACE_BILLB:
4968 activetf = get_active_tface(NULL);
4969 if(activetf) {
4970 activetf->mode &= ~TF_BILLBOARD;
4971 allqueue(REDRAWBUTSEDIT, 0);
4973 break;
4974 case B_WEIGHT0_0:
4975 editbutvweight = 0.0f;
4976 allqueue(REDRAWBUTSEDIT, 0);
4977 allqueue(REDRAWVIEW3D, 0);
4978 break;
4980 case B_WEIGHT1_4:
4981 editbutvweight = 0.25f;
4982 allqueue(REDRAWBUTSEDIT, 0);
4983 allqueue(REDRAWVIEW3D, 0);
4984 break;
4985 case B_WEIGHT1_2:
4986 editbutvweight = 0.5f;
4987 allqueue(REDRAWBUTSEDIT, 0);
4988 allqueue(REDRAWVIEW3D, 0);
4989 break;
4990 case B_WEIGHT3_4:
4991 editbutvweight = 0.75f;
4992 allqueue(REDRAWBUTSEDIT, 0);
4993 allqueue(REDRAWVIEW3D, 0);
4994 break;
4995 case B_WEIGHT1_0:
4996 editbutvweight = 1.0f;
4997 allqueue(REDRAWBUTSEDIT, 0);
4998 allqueue(REDRAWVIEW3D, 0);
4999 break;
5001 case B_OPA1_8:
5002 Gwp.a = 0.125f;
5003 allqueue(REDRAWBUTSEDIT, 0);
5004 allqueue(REDRAWVIEW3D, 0);
5005 break;
5006 case B_OPA1_4:
5007 Gwp.a = 0.25f;
5008 allqueue(REDRAWBUTSEDIT, 0);
5009 allqueue(REDRAWVIEW3D, 0);
5010 break;
5011 case B_OPA1_2:
5012 Gwp.a = 0.5f;
5013 allqueue(REDRAWBUTSEDIT, 0);
5014 allqueue(REDRAWVIEW3D, 0);
5015 break;
5016 case B_OPA3_4:
5017 Gwp.a = 0.75f;
5018 allqueue(REDRAWBUTSEDIT, 0);
5019 allqueue(REDRAWVIEW3D, 0);
5020 break;
5021 case B_OPA1_0:
5022 Gwp.a = 1.0f;
5023 allqueue(REDRAWBUTSEDIT, 0);
5024 allqueue(REDRAWVIEW3D, 0);
5025 break;
5026 case B_CLR_WPAINT:
5027 if(!multires_level1_test()) {
5028 defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
5029 if(defGroup) {
5030 Mesh *me= ob->data;
5031 int a;
5032 for(a=0; a<me->totvert; a++)
5033 remove_vert_defgroup (ob, defGroup, a);
5034 allqueue(REDRAWVIEW3D, 0);
5035 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
5038 break;
5039 case B_SCULPT_TEXBROWSE:
5040 sd= &G.scene->sculptdata;
5042 if(G.buts->texnr== -2) {
5043 id= NULL;
5044 if(sd) {
5045 mtex= sd->mtex[sd->texact];
5046 if(mtex) id= &mtex->tex->id;
5049 activate_databrowse((ID *)id, ID_TE, 0, B_SCULPT_TEXBROWSE, &G.buts->texnr, do_global_buttons);
5050 return;
5052 if(G.buts->texnr < 0) break;
5054 if(G.buts->pin) {
5057 else if(sd && sd->texact == -1) {
5058 error("No texture channel selected");
5059 allqueue(REDRAWBUTSSHADING, 0);
5061 else if(sd && sd->texact != -1) {
5062 id= NULL;
5064 mtex= sd->mtex[sd->texact];
5065 if(mtex) id= &mtex->tex->id;
5067 idtest= G.main->tex.first;
5068 while(idtest) {
5069 if(nr==G.buts->texnr) {
5070 break;
5072 nr++;
5073 idtest= idtest->next;
5075 if(idtest==0) { /* new tex */
5076 if(id) idtest= (ID *)copy_texture((Tex *)id);
5077 else idtest= (ID *)add_texture("Tex");
5078 idtest->us--;
5080 if(idtest!=id && sd) {
5082 if(sd->mtex[sd->texact]==0) {
5083 sd->mtex[sd->texact]= add_mtex();
5084 sd->mtex[sd->texact]->texco= TEXCO_VIEW;
5085 sd->mtex[sd->texact]->size[0]=
5086 sd->mtex[sd->texact]->size[1]=
5087 sd->mtex[sd->texact]->size[2]= 100;
5088 sd->mtex[sd->texact]->warpfac= 0;
5090 sd->mtex[sd->texact]->tex= (Tex *)idtest;
5091 id_us_plus(idtest);
5092 if(id) id->us--;
5094 BIF_undo_push("Texture browse");
5095 allqueue(REDRAWBUTSEDIT, 0);
5096 allqueue(REDRAWBUTSSHADING, 0);
5097 allqueue(REDRAWIPO, 0);
5098 allqueue(REDRAWOOPS, 0);
5099 BIF_preview_changed(ID_TE);
5102 break;
5104 case B_BRUSHBROWSE:
5105 if(G.buts->menunr==-2) {
5106 activate_databrowse((ID*)settings->imapaint.brush, ID_BR, 0, B_BRUSHBROWSE, &G.buts->menunr, do_global_buttons);
5107 break;
5109 else if(G.buts->menunr < 0) break;
5111 if(brush_set_nr(&settings->imapaint.brush, G.buts->menunr)) {
5112 BIF_undo_push("Browse Brush");
5113 allqueue(REDRAWBUTSEDIT, 0);
5114 allqueue(REDRAWIMAGE, 0);
5116 break;
5117 case B_BRUSHDELETE:
5118 if(brush_delete(&settings->imapaint.brush)) {
5119 BIF_undo_push("Unlink Brush");
5120 allqueue(REDRAWBUTSEDIT, 0);
5121 allqueue(REDRAWIMAGE, 0);
5123 break;
5124 case B_BRUSHKEEPDATA:
5125 brush_toggle_fake_user(settings->imapaint.brush);
5126 allqueue(REDRAWBUTSEDIT, 0);
5127 allqueue(REDRAWIMAGE, 0);
5128 break;
5129 case B_BRUSHLOCAL:
5130 if(settings->imapaint.brush && settings->imapaint.brush->id.lib) {
5131 if(okee("Make local")) {
5132 make_local_brush(settings->imapaint.brush);
5133 allqueue(REDRAWBUTSEDIT, 0);
5134 allqueue(REDRAWIMAGE, 0);
5137 break;
5138 case B_BTEXBROWSE:
5139 if(settings->imapaint.brush) {
5140 Brush *brush= settings->imapaint.brush;
5142 if(G.buts->menunr==-2) {
5143 MTex *mtex= brush->mtex[brush->texact];
5144 ID *id= (ID*)((mtex)? mtex->tex: NULL);
5145 activate_databrowse(id, ID_TE, 0, B_BTEXBROWSE, &G.buts->menunr, do_global_buttons);
5146 break;
5148 else if(G.buts->menunr < 0) break;
5150 if(brush_texture_set_nr(brush, G.buts->menunr)) {
5151 BIF_undo_push("Browse Brush Texture");
5152 allqueue(REDRAWBUTSSHADING, 0);
5153 allqueue(REDRAWBUTSEDIT, 0);
5154 allqueue(REDRAWIMAGE, 0);
5157 break;
5158 case B_BTEXDELETE:
5159 if(settings->imapaint.brush) {
5160 if (brush_texture_delete(settings->imapaint.brush)) {
5161 BIF_undo_push("Unlink Brush Texture");
5162 allqueue(REDRAWBUTSSHADING, 0);
5163 allqueue(REDRAWBUTSEDIT, 0);
5164 allqueue(REDRAWIMAGE, 0);
5167 break;
5168 case B_BRUSHCHANGE:
5169 allqueue(REDRAWIMAGE, 0);
5170 allqueue(REDRAWBUTSEDIT, 0);
5171 break;
5175 /* -------------------- MODE: vpaint ------------------- */
5177 void weight_paint_buttons(uiBlock *block)
5179 extern VPaint Gwp; /* from vpaint */
5180 Object *ob;
5181 ob= OBACT;
5183 if(ob==NULL) return;
5185 uiBlockBeginAlign(block);
5186 uiDefButF(block, NUMSLI, REDRAWVIEW3D, "Weight:",10,160,225,19, &editbutvweight, 0, 1, 10, 0, "Sets the current vertex group's bone deformation strength");
5188 uiDefBut(block, BUT, B_WEIGHT0_0 , "0", 10,140,45,19, 0, 0, 0, 0, 0, "");
5189 uiDefBut(block, BUT, B_WEIGHT1_4 , "1/4", 55,140,45,19, 0, 0, 0, 0, 0, "");
5190 uiDefBut(block, BUT, B_WEIGHT1_2 , "1/2", 100,140,45,19, 0, 0, 0, 0, 0, "");
5191 uiDefBut(block, BUT, B_WEIGHT3_4 , "3/4", 145,140,45,19, 0, 0, 0, 0, 0, "");
5192 uiDefBut(block, BUT, B_WEIGHT1_0 , "1", 190,140,45,19, 0, 0, 0, 0, 0, "");
5194 uiDefButF(block, NUMSLI, B_NOP, "Opacity ", 10,120,225,19, &Gwp.a, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
5196 uiDefBut(block, BUT, B_OPA1_8 , "1/8", 10,100,45,19, 0, 0, 0, 0, 0, "");
5197 uiDefBut(block, BUT, B_OPA1_4 , "1/4", 55,100,45,19, 0, 0, 0, 0, 0, "");
5198 uiDefBut(block, BUT, B_OPA1_2 , "1/2", 100,100,45,19, 0, 0, 0, 0, 0, "");
5199 uiDefBut(block, BUT, B_OPA3_4 , "3/4", 145,100,45,19, 0, 0, 0, 0, 0, "");
5200 uiDefBut(block, BUT, B_OPA1_0 , "1", 190,100,45,19, 0, 0, 0, 0, 0, "");
5202 uiDefButF(block, NUMSLI, B_NOP, "Size ", 10,80,225,19, &Gwp.size, 2.0, 64.0, 0, 0, "The size of the brush");
5204 uiBlockBeginAlign(block);
5205 uiDefButS(block, ROW, B_DIFF, "Mix", 250,160,60,17, &Gwp.mode, 1.0, 0.0, 0, 0, "Mix the vertex colors");
5206 uiDefButS(block, ROW, B_DIFF, "Add", 250,142,60,17, &Gwp.mode, 1.0, 1.0, 0, 0, "Add the vertex colors");
5207 uiDefButS(block, ROW, B_DIFF, "Sub", 250,124,60,17, &Gwp.mode, 1.0, 2.0, 0, 0, "Subtract from the vertex color");
5208 uiDefButS(block, ROW, B_DIFF, "Mul", 250,106,60,17, &Gwp.mode, 1.0, 3.0, 0, 0, "Multiply the vertex color");
5209 uiDefButS(block, ROW, B_DIFF, "Filter", 250, 88,60,17, &Gwp.mode, 1.0, 4.0, 0, 0, "Mix the colors with an alpha factor");
5210 uiDefButS(block, ROW, B_DIFF, "Lighter", 250, 70,60,17, &Gwp.mode, 1.0, 5.0, 0, 0, "Paint over darker areas only");
5211 uiDefButS(block, ROW, B_DIFF, "Darker", 250, 52,60,17, &Gwp.mode, 1.0, 6.0, 0, 0, "Paint over lighter areas only");
5212 uiBlockEndAlign(block);
5214 uiDefButBitS(block, TOG, VP_SPRAY, 0, "Spray", 160,55,75,19, &Gwp.flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse");
5216 uiBlockBeginAlign(block);
5217 uiDefButBitS(block, TOG, VP_AREA, 0, "All Faces", 10,30,75,19, &Gwp.flag, 0, 0, 0, 0, "Paint on all faces inside brush (otherwise only on face under mouse cursor)");
5218 uiDefButBitS(block, TOG, VP_SOFT, 0, "Vertex Dist", 85,30,75,19, &Gwp.flag, 0, 0, 0, 0, "Use distances to vertices (instead of all vertices of face)");
5219 uiDefButBitS(block, TOGN, VP_HARD, 0, "Soft", 160,30,75,19, &Gwp.flag, 0, 0, 0, 0, "Use a soft brush");
5220 uiDefButBitS(block, TOG, VP_NORMALS, 0, "Normals", 235,30,75,19, &Gwp.flag, 0, 0, 0, 0, "Applies the vertex normal before painting");
5222 if(ob) {
5223 uiBlockBeginAlign(block);
5224 uiDefButBitS(block, TOG, VP_ONLYVGROUP, REDRAWVIEW3D, "Vgroup", 10,0,75,19, &Gwp.flag, 0, 0, 0, 0, "Only paint on vertices in the selected vertex group.");
5225 uiDefButBitS(block, TOG, VP_MIRROR_X, REDRAWVIEW3D, "X-Mirror", 85,0,75,19, &Gwp.flag, 0, 0, 0, 0, "Mirrored Paint, applying on mirrored Weight Group name");
5226 uiDefButBitC(block, TOG, OB_DRAWWIRE, REDRAWVIEW3D, "Wire", 160,0,75,19, &ob->dtx, 0, 0, 0, 0, "Displays the active object's wireframe in shaded drawing modes");
5227 uiDefBut(block, BUT, B_CLR_WPAINT, "Clear", 235,0,75,19, NULL, 0, 0, 0, 0, "Removes reference to this deform group from all vertices");
5228 uiBlockEndAlign(block);
5232 static void editing_panel_mesh_paint(void)
5234 uiBlock *block;
5236 block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_paint", UI_EMBOSS, UI_HELV, curarea->win);
5237 if(uiNewPanel(curarea, block, "Paint", "Editing", 640, 0, 318, 204)==0) return;
5240 if(G.f & G_WEIGHTPAINT) {
5241 weight_paint_buttons(block);
5243 else if(G.f & G_VERTEXPAINT) {
5244 extern VPaint Gvp; /* from vpaint */
5246 uiBlockBeginAlign(block);
5247 uiDefButF(block, NUMSLI, B_NOP, "R ", 979,160,194,19, &Gvp.r, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of red used for painting");
5248 uiDefButF(block, NUMSLI, B_NOP, "G ", 979,140,194,19, &Gvp.g, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of green used for painting");
5249 uiDefButF(block, NUMSLI, B_NOP, "B ", 979,120,194,19, &Gvp.b, 0.0, 1.0, B_VPCOLSLI, 0, "The amount of blue used for painting");
5251 uiBlockBeginAlign(block);
5252 uiDefButF(block, NUMSLI, B_NOP, "Opacity ", 979,95,194,19, &Gvp.a, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
5253 uiDefButF(block, NUMSLI, B_NOP, "Size ", 979,75,194,19, &Gvp.size, 2.0, 64.0, 0, 0, "The size of the brush");
5254 uiBlockEndAlign(block);
5256 uiDefButF(block, COL, B_REDR, "", 1176,120,28,60, &(Gvp.r), 0, 0, 0, B_VPCOLSLI, "");
5258 uiBlockBeginAlign(block);
5259 uiDefButS(block, ROW, B_DIFF, "Mix", 1212,160,63,17, &Gvp.mode, 1.0, 0.0, 0, 0, "Mix the vertex colors");
5260 uiDefButS(block, ROW, B_DIFF, "Add", 1212,142,63,17, &Gvp.mode, 1.0, 1.0, 0, 0, "Add the vertex color");
5261 uiDefButS(block, ROW, B_DIFF, "Sub", 1212, 124,63,17, &Gvp.mode, 1.0, 2.0, 0, 0, "Subtract from the vertex color");
5262 uiDefButS(block, ROW, B_DIFF, "Mul", 1212, 106,63,17, &Gvp.mode, 1.0, 3.0, 0, 0, "Multiply the vertex color");
5263 uiDefButS(block, ROW, B_DIFF, "Filter", 1212, 88,63,17, &Gvp.mode, 1.0, 4.0, 0, 0, "Mix the colors with an alpha factor");
5264 uiDefButS(block, ROW, B_DIFF, "Lighter", 1212, 70,63,17, &Gvp.mode, 1.0, 5.0, 0, 0, "Paint over darker areas only");
5265 uiDefButS(block, ROW, B_DIFF, "Darker", 1212, 52,63,17, &Gvp.mode, 1.0, 6.0, 0, 0, "Paint over lighter areas only");
5266 uiBlockEndAlign(block);
5268 uiDefBut(block, BUT, B_SET_VCOL, "Set VertCol", 979,50,81,20, 0, 0, 0, 0, 0, "Set Vertex color of selection to current (Shift+K)");
5270 uiBlockBeginAlign(block);
5271 uiDefButBitS(block, TOG, VP_AREA, 0, "All Faces", 979,25,75,19, &Gvp.flag, 0, 0, 0, 0, "Paint on all faces inside brush");
5272 uiDefButBitS(block, TOG, VP_SOFT, 0, "Vertex Dist", 1054,25,75,19, &Gvp.flag, 0, 0, 0, 0, "Use distances to vertices (instead of paint entire faces)");
5273 uiDefButBitS(block, TOG, VP_NORMALS, 0, "Normals", 1129,25,75,19, &Gvp.flag, 0, 0, 0, 0, "Applies the vertex normal before painting");
5274 uiDefButBitS(block, TOG, VP_SPRAY, 0, "Spray", 1204,25,75,19, &Gvp.flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse");
5276 uiBlockBeginAlign(block);
5277 uiDefBut(block, BUT, B_VPGAMMA, "Set", 979,0,81,19, 0, 0, 0, 0, 0, "Apply Mul and Gamma to vertex colors");
5278 uiDefButF(block, NUM, B_DIFF, "Mul:", 1061,0,112,19, &Gvp.mul, 0.1, 50.0, 10, 0, "Set the number to multiply vertex colors with");
5279 uiDefButF(block, NUM, B_DIFF, "Gamma:", 1174,0,102,19, &Gvp.gamma, 0.1, 5.0, 10, 0, "Change the clarity of the vertex colors");
5280 uiBlockEndAlign(block);
5282 else { /* texture paint */
5283 ToolSettings *settings= G.scene->toolsettings;
5284 Brush *brush= settings->imapaint.brush;
5285 ID *id;
5286 int yco, xco, butw;
5288 yco= 160;
5290 uiBlockBeginAlign(block);
5291 uiDefButS(block, ROW, B_BRUSHCHANGE, "Draw", 0 ,yco,108,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush");
5292 uiDefButS(block, ROW, B_BRUSHCHANGE, "Soften", 108 ,yco,106,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush");
5293 uiDefButS(block, ROW, B_BRUSHCHANGE, "Smear", 214,yco,106,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush");
5294 uiBlockEndAlign(block);
5295 yco -= 30;
5297 uiBlockSetCol(block, TH_BUT_SETTING2);
5298 id= (ID*)settings->imapaint.brush;
5299 xco= std_libbuttons(block, 0, yco, 0, NULL, B_BRUSHBROWSE, ID_BR, 0, id, NULL, &(G.buts->menunr), 0, B_BRUSHLOCAL, B_BRUSHDELETE, 0, B_BRUSHKEEPDATA);
5300 uiBlockSetCol(block, TH_AUTO);
5302 if(brush && !brush->id.lib) {
5303 MTex *mtex= brush->mtex[brush->texact];
5305 butw= 320-(xco+10);
5307 uiDefButS(block, MENU, B_NOP, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes");
5309 uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, B_BRUSHCHANGE, "Wrap", xco+10,yco-25,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping");
5311 uiBlockBeginAlign(block);
5312 uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, B_BRUSHCHANGE, "Airbrush", xco+10,yco-50,butw,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)");
5313 uiDefButF(block, NUM, B_NOP, "Rate ", xco+10,yco-70,butw,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush");
5314 uiBlockEndAlign(block);
5316 yco -= 25;
5318 uiBlockBeginAlign(block);
5319 uiDefButF(block, COL, B_VPCOLSLI, "", 0,yco,200,19, brush->rgb, 0, 0, 0, 0, "");
5320 uiDefButF(block, NUMSLI, B_NOP, "Opacity ", 0,yco-20,180,19, &brush->alpha, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
5321 uiDefButBitS(block, TOG|BIT, BRUSH_ALPHA_PRESSURE, B_NOP, "P", 180,yco-20,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
5322 uiDefButI(block, NUMSLI, B_NOP, "Size ", 0,yco-40,180,19, &brush->size, 1, 200, 0, 0, "The size of the brush");
5323 uiDefButBitS(block, TOG|BIT, BRUSH_SIZE_PRESSURE, B_NOP, "P", 180,yco-40,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
5324 uiDefButF(block, NUMSLI, B_NOP, "Falloff ", 0,yco-60,180,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush");
5325 uiDefButBitS(block, TOG|BIT, BRUSH_RAD_PRESSURE, B_NOP, "P", 180,yco-60,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
5326 uiDefButF(block, NUMSLI, B_NOP, "Spacing ",0,yco-80,180,19, &brush->spacing, 1.0, 100.0, 0, 0, "Repeating paint on %% of brush diameter");
5327 uiDefButBitS(block, TOG|BIT, BRUSH_SPACING_PRESSURE, B_NOP, "P", 180,yco-80,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
5328 uiBlockEndAlign(block);
5330 yco -= 110;
5332 uiBlockSetCol(block, TH_BUT_SETTING2);
5333 id= (mtex)? (ID*)mtex->tex: NULL;
5334 xco= std_libbuttons(block, 0, yco, 0, NULL, B_BTEXBROWSE, ID_TE, 0, id, NULL, &(G.buts->menunr), 0, 0, B_BTEXDELETE, 0, 0);
5335 /*uiDefButBitS(block, TOG|BIT, BRUSH_FIXED_TEX, B_BRUSHCHANGE, "Fixed", xco+5,yco,butw,19, &brush->flag, 0, 0, 0, 0, "Keep texture origin in fixed position");*/
5336 uiBlockSetCol(block, TH_AUTO);
5341 static void editing_panel_mesh_texface(void)
5343 extern VPaint Gvp; /* from vpaint */
5344 uiBlock *block;
5345 MTFace *tf;
5347 block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_texface", UI_EMBOSS, UI_HELV, curarea->win);
5348 if(uiNewPanel(curarea, block, "Texture face", "Editing", 960, 0, 318, 204)==0) return;
5350 tf = get_active_tface(NULL);
5351 if(tf) {
5352 uiBlockBeginAlign(block);
5353 uiDefButBitS(block, TOG, TF_TEX, B_REDR_3D_IMA, "Tex", 600,160,60,19, &tf->mode, 0, 0, 0, 0, "Render face with texture");
5354 uiDefButBitS(block, TOG, TF_TILES, B_REDR_3D_IMA, "Tiles", 660,160,60,19, &tf->mode, 0, 0, 0, 0, "Use tilemode for face");
5355 uiDefButBitS(block, TOG, TF_LIGHT, REDRAWVIEW3D, "Light", 720,160,60,19, &tf->mode, 0, 0, 0, 0, "Use light for face");
5356 uiDefButBitS(block, TOG, TF_INVISIBLE, REDRAWVIEW3D, "Invisible",780,160,60,19, &tf->mode, 0, 0, 0, 0, "Make face invisible");
5357 uiDefButBitS(block, TOG, TF_DYNAMIC, REDRAWVIEW3D, "Collision", 840,160,60,19, &tf->mode, 0, 0, 0, 0, "Use face for collision detection");
5359 uiBlockBeginAlign(block);
5360 uiDefButBitS(block, TOG, TF_SHAREDCOL, REDRAWVIEW3D, "Shared", 600,135,60,19, &tf->mode, 0, 0, 0, 0, "Blend vertex colors across face when vertices are shared");
5361 uiDefButBitS(block, TOG, TF_TWOSIDE, REDRAWVIEW3D, "Twoside",660,135,60,19, &tf->mode, 0, 0, 0, 0, "Render face twosided");
5362 uiDefButBitS(block, TOG, TF_OBCOL, REDRAWVIEW3D, "ObColor",720,135,60,19, &tf->mode, 0, 0, 0, 0, "Use ObColor instead of vertex colors");
5364 uiBlockBeginAlign(block);
5366 uiDefButBitS(block, TOG, TF_BILLBOARD, B_TFACE_HALO, "Halo", 600,110,60,19, &tf->mode, 0, 0, 0, 0, "Screen aligned billboard");
5367 uiDefButBitS(block, TOG, TF_BILLBOARD2, B_TFACE_BILLB, "Billboard",660,110,60,19, &tf->mode, 0, 0, 0, 0, "Billboard with Z-axis constraint");
5368 uiDefButBitS(block, TOG, TF_SHADOW, REDRAWVIEW3D, "Shadow", 720,110,60,19, &tf->mode, 0, 0, 0, 0, "Face is used for shadow");
5369 uiDefButBitS(block, TOG, TF_BMFONT, REDRAWVIEW3D, "Text", 780,110,60,19, &tf->mode, 0, 0, 0, 0, "Enable bitmap text on face");
5371 uiBlockBeginAlign(block);
5372 uiBlockSetCol(block, TH_BUT_SETTING1);
5373 uiDefButC(block, ROW, REDRAWVIEW3D, "Opaque", 600,80,60,19, &tf->transp, 2.0, 0.0, 0, 0, "Render color of textured face as color");
5374 uiDefButC(block, ROW, REDRAWVIEW3D, "Add", 660,80,60,19, &tf->transp, 2.0, 1.0, 0, 0, "Render face transparent and add color of face");
5375 uiDefButC(block, ROW, REDRAWVIEW3D, "Alpha", 720,80,60,19, &tf->transp, 2.0, 2.0, 0, 0, "Render polygon transparent, depending on alpha channel of the texture");
5377 uiBlockSetCol(block, TH_AUTO);
5379 uiBlockBeginAlign(block);
5380 uiDefButF(block, COL, B_VPCOLSLI, "", 769,40,40,28, &(Gvp.r), 0, 0, 0, 0, "");
5381 uiDefBut(block, BUT, B_SET_VCOL, "Set VertCol", 809,40,103,28, 0, 0, 0, 0, 0, "Set Vertex color of selection to current (Shift+K)");
5383 uiBlockBeginAlign(block);
5384 uiDefBut(block, BUT, B_COPY_TF_MODE, "Copy DrawMode", 600,7,117,28, 0, 0, 0, 0, 0, "Copy the drawmode from active face to selected faces");
5385 uiDefBut(block, BUT, B_COPY_TF_UV, "Copy UV+tex", 721,7,85,28, 0, 0, 0, 0, 0, "Copy UV information and textures from active face to selected faces");
5386 uiDefBut(block, BUT, B_COPY_TF_COL, "Copy VertCol", 809,7,103,28, 0, 0, 0, 0, 0, "Copy vertex colors from active face to selected faces");
5388 else
5389 uiDefBut(block,LABEL,B_NOP, "(No Active Face)", 10,200,150,19,0,0,0,0,0,"");
5393 void do_uvcalculationbuts(unsigned short event)
5395 switch(event) {
5396 case B_UVAUTO_DRAWFACES:
5397 allqueue(REDRAWVIEW3D, 0);
5398 allqueue(REDRAWIMAGE, 0);
5399 break;
5403 static void editing_panel_mesh_uvautocalculation(void)
5405 uiBlock *block;
5406 int butH= 19, butHB= 20, row= 180, butS= 10;
5408 block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_uvautocalculation", UI_EMBOSS, UI_HELV, curarea->win);
5409 /* make this a tab of "Texture face" to save screen space*/
5410 uiNewPanelTabbed("Texture face", "Editing");
5411 if(uiNewPanel(curarea, block, "UV Calculation", "Editing", 960, 0, 318, 204)==0)
5412 return;
5414 uiBlockBeginAlign(block);
5415 uiDefButBitI(block, TOG, G_DRAWFACES, B_UVAUTO_DRAWFACES, "Draw Faces", 100,row,200,butH, &G.f, 0, 0, 0, 0, "Displays all faces as shades");
5416 uiDefButBitI(block,TOG, G_DRAWEDGES, REDRAWVIEW3D,"Draw Edges",100,row-butHB,200,butH,&G.f, 2.0, 0, 0, 0, "Displays edges of visible faces");
5417 uiDefButBitI(block,TOG, G_HIDDENEDGES, REDRAWVIEW3D,"Draw Hidden Edges",100,row-2*butHB,200,butH,&G.f, 2.0, 1.0, 0, 0, "Displays edges of hidden faces");
5418 uiDefButBitI(block,TOG, G_DRAWSEAMS, REDRAWVIEW3D,"Draw Seams",100,row-3*butHB,200,butH,&G.f, 2.0, 2.0, 0, 0, "Displays UV unwrapping seams");
5419 uiBlockEndAlign(block);
5420 row-= 4*butHB+butS;
5422 uiBlockBeginAlign(block);
5423 uiDefButS(block, MENU, REDRAWBUTSEDIT, "Unwrapper%t|Conformal%x0|Angle Based%x1",100,row,200,butH, &G.scene->toolsettings->unwrapper, 0, 0, 0, 0, "Unwrap method");
5424 uiDefButBitS(block, TOG, 1, B_NOP, "Fill Holes",100,row-butHB,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0, "Fill holes to prevent internal overlaps");
5425 uiBlockEndAlign(block);
5426 row-= 2*butHB+butS;
5428 row= 180;
5430 uiBlockBeginAlign(block);
5431 uiDefButF(block, NUM,B_UVAUTO_CUBESIZE ,"Cube Size:",315,row,200,butH, &G.scene->toolsettings->uvcalc_cubesize, 0.0001, 100.0, 10, 3, "Defines the cubemap size for cube mapping");
5432 uiBlockEndAlign(block);
5433 row-= butHB+butS;
5435 uiBlockBeginAlign(block);
5436 uiDefButF(block, NUM,B_UVAUTO_CYLRADIUS ,"Cyl Radius:",315,row,200,butH, &G.scene->toolsettings->uvcalc_radius, 0.1, 100.0, 10, 3, "Defines the radius of the UV mapping cylinder");
5437 uiBlockEndAlign(block);
5438 row-= butHB+butS;
5440 uiBlockBeginAlign(block);
5441 uiDefButS(block, ROW,B_UVAUTO_FACE,"View Aligns Face",315,row,200,butH, &G.scene->toolsettings->uvcalc_mapdir,2.0, 1.0, 0.0,0.0, "View is on equator for cylindrical and spherical UV mapping");
5442 uiDefButS(block, ROW,B_UVAUTO_TOP,"VA Top",315,row-butHB,100,butH, &G.scene->toolsettings->uvcalc_mapdir,2.0, 0.0, 0.0,0.0, "View is on poles for cylindrical and spherical UV mapping");
5443 uiDefButS(block, ROW,B_UVAUTO_TOP,"Al Obj",415,row-butHB,100,butH, &G.scene->toolsettings->uvcalc_mapdir,2.0, 2.0, 0.0,0.0, "Align to object for cylindrical and spherical UV mapping");
5444 uiBlockEndAlign(block);
5445 row-= 2*butHB+butS;
5447 uiBlockBeginAlign(block);
5448 uiDefButS(block, ROW,B_UVAUTO_ALIGNX,"Polar ZX",315,row,100,butH, &G.scene->toolsettings->uvcalc_mapalign,2.0, 0.0, 0.0,0.0, "Polar 0 is X for cylindrical and spherical UV mapping");
5449 uiDefButS(block, ROW,B_UVAUTO_ALIGNY,"Polar ZY",415,row,100,butH, &G.scene->toolsettings->uvcalc_mapalign,2.0, 1.0, 0.0,0.0, "Polar 0 is Y for cylindrical and spherical UV mapping");
5450 uiBlockEndAlign(block);
5453 void editing_panel_mesh_multires()
5455 uiBlock *block;
5456 uiBut *but;
5457 Object *ob= OBACT;
5458 Mesh *me= get_mesh(ob);
5459 int cx= 100, cy= 0;
5461 block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_multires", UI_EMBOSS, UI_HELV, curarea->win);
5462 if(uiNewPanel(curarea, block, "Multires", "Editing", 500, 0, 318, 204)==0) return;
5464 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
5466 if(!me->mr) {
5467 but= uiDefBut(block,BUT,B_NOP,"Add Multires", cx,cy,268,19,0,0,0,0,0,"");
5468 uiButSetFunc(but,multires_make,ob,me);
5469 } else {
5470 char subsurfmenu[]= "Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
5472 but= uiDefBut(block,BUT,B_NOP,"Apply Multires", cx,cy,268,19,0,0,0,0,0,"Apply current multires level to mesh and the delete other levels");
5473 uiButSetFunc(but,multires_delete,ob,me);
5474 cy-= 24;
5476 uiBlockBeginAlign(block);
5477 but= uiDefBut(block,BUT,B_NOP,"Add Level", cx,cy,134,19,0,0,0,0,0,"Add a new level of subdivision at the end of the chain");
5478 uiButSetFunc(but,multires_add_level,ob,me);
5479 uiDefButC(block, MENU, B_NOP, subsurfmenu, cx + 134, cy, 134, 19, &G.scene->toolsettings->multires_subdiv_type, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
5480 cy-= 20;
5482 if(me->mr->level_count>1) {
5483 but= uiDefBut(block,BUT,B_NOP,"Del Lower", cx,cy,134,19,0,0,0,0,0,"Remove all levels of subdivision below the current one");
5484 uiButSetFunc(but,multires_del_lower,ob,me);
5485 but= uiDefBut(block,BUT,B_NOP,"Del Higher", cx+134,cy,134,19,0,0,0,0,0,"Remove all levels of subdivision above the current one");
5486 uiButSetFunc(but,multires_del_higher,ob,me);
5487 cy-= 20;
5489 but= uiDefButC(block,NUM,B_NOP,"Level: ",cx,cy,268,19,(char *)&me->mr->newlvl,1.0,me->mr->level_count,0,0,"");
5490 uiButSetFunc(but,multires_set_level_cb, ob, me);
5491 cy-= 20;
5493 but= uiDefButC(block,NUM,B_NOP,"Edges: ",cx,cy,268,19,(char *)&me->mr->edgelvl,1.0,me->mr->level_count,0,0,"Set level of edges to display");
5494 uiButSetFunc(but,multires_edge_level_update,ob,me);
5495 cy-= 20;
5496 uiBlockEndAlign(block);
5498 cy-= 5;
5499 uiDefBut(block,LABEL,B_NOP,"Rendering",cx,cy,100,19,0,0,0,0,0,"");
5500 cy-= 20;
5502 uiBlockBeginAlign(block);
5503 uiDefButC(block,NUM,B_NOP,"Pin: ",cx,cy,268,19,(char *)&me->mr->pinlvl,1.0,me->mr->level_count,0,0,"Set level to apply modifiers to during render");
5504 cy-= 20;
5506 uiDefButC(block,NUM,B_NOP,"Render: ",cx,cy,268,19,(char *)&me->mr->renderlvl,1.0,me->mr->level_count,0,0,"Set level to render");
5507 cy-= 20;
5509 if(multires_modifier_warning()) {
5510 char *tip= "One or more modifiers are enabled that modify mesh topology";
5511 uiDefIconBut(block,LABEL,B_NOP,ICON_ERROR, cx,cy,20,20, 0,0,0,0,0, tip);
5512 uiDefBut(block,LABEL,B_NOP, "Cannot use render level", cx+20,cy,180,19, 0,0,0,0,0, tip);
5517 uiBlockEndAlign(block);
5520 /* this is a mode context sensitive system */
5522 void editing_panels()
5524 Object *ob;
5525 Curve *cu;
5526 MetaBall *mb;
5527 Lattice *lt;
5528 bArmature *arm;
5529 Camera *cam;
5531 ob= OBACT;
5532 if(ob==NULL) return;
5533 uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
5535 switch(ob->type) {
5536 case OB_MESH:
5537 editing_panel_links(ob);
5538 editing_panel_mesh_type(ob, ob->data);
5539 editing_panel_modifiers(ob);
5540 editing_panel_shapes(ob);
5541 editing_panel_mesh_multires();
5542 /* modes */
5543 if(G.obedit) {
5544 editing_panel_mesh_tools(ob, ob->data);
5545 editing_panel_mesh_tools1(ob, ob->data);
5547 else if(G.f & G_SCULPTMODE) {
5548 uiNewPanelTabbed("Multires", "Editing");
5549 editing_panel_sculpting_tools();
5550 uiNewPanelTabbed("Multires", "Editing");
5551 editing_panel_sculpting_textures();
5552 } else {
5553 if(G.f & G_FACESELECT) {
5554 editing_panel_mesh_texface();
5555 editing_panel_mesh_uvautocalculation();
5557 if(G.f & (G_VERTEXPAINT | G_TEXTUREPAINT | G_WEIGHTPAINT) ) {
5558 editing_panel_mesh_paint();
5561 break;
5563 case OB_CURVE:
5564 case OB_SURF:
5565 cu= ob->data;
5566 editing_panel_links(ob);
5567 editing_panel_curve_type(ob, cu);
5568 editing_panel_modifiers(ob);
5569 // editing_panel_shapes(ob);
5570 if(G.obedit) {
5571 editing_panel_curve_tools(ob, cu);
5572 editing_panel_curve_tools1(ob, cu);
5574 break;
5576 case OB_MBALL:
5577 mb= ob->data;
5578 editing_panel_links(ob);
5579 editing_panel_mball_type(ob, mb);
5580 if(G.obedit) {
5581 editing_panel_mball_tools(ob, mb);
5583 break;
5585 case OB_FONT:
5586 cu= ob->data;
5587 editing_panel_links(ob);
5588 editing_panel_curve_type(ob, cu);
5589 editing_panel_font_type(ob, cu);
5591 #ifdef INTERNATIONAL
5592 if(G.obedit)
5594 editing_panel_char_type(ob, cu);
5596 #endif
5597 editing_panel_modifiers(ob);
5598 break;
5600 case OB_LATTICE:
5601 lt= ob->data;
5602 editing_panel_links(ob);
5603 editing_panel_lattice_type(ob, lt);
5604 editing_panel_modifiers(ob);
5605 editing_panel_shapes(ob);
5606 break;
5608 case OB_LAMP:
5609 editing_panel_links(ob);
5610 break;
5612 case OB_EMPTY:
5613 editing_panel_links(ob);
5614 break;
5616 case OB_CAMERA:
5617 cam= ob->data;
5618 editing_panel_links(ob); // no editmode!
5619 editing_panel_camera_type(ob, cam);
5620 /* yafray: extra panel for dof parameters */
5621 if (G.scene->r.renderer==R_YAFRAY) editing_panel_camera_yafraydof(ob, cam);
5622 break;
5624 case OB_ARMATURE:
5625 arm= ob->data;
5626 editing_panel_links(ob); // no editmode!
5627 editing_panel_armature_type(ob, arm);
5628 if(G.obedit) {
5629 editing_panel_armature_bones(ob, arm);
5631 else if(ob->flag & OB_POSEMODE) {
5632 editing_panel_armature_visuals(ob, arm);
5633 editing_panel_pose_bones(ob, arm);
5634 object_panel_constraint("Editing");
5636 break;
5638 uiClearButLock();