Posemode was missing a "countall" call with pose mode select/deselect all. while...
[blender.git] / source / blender / src / editmball.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
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.
13  *
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.
18  *
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.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <string.h>
34
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_arithb.h"
43
44 #include "DNA_screen_types.h"
45 #include "DNA_meta_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_view3d_types.h"
49
50 #include "BKE_utildefines.h"
51 #include "BKE_depsgraph.h"
52 #include "BKE_global.h"
53 #include "BKE_object.h"
54
55 #include "BIF_gl.h"
56 #include "BIF_graphics.h"
57 #include "BIF_screen.h"
58 #include "BIF_toolbox.h"
59 #include "BIF_space.h"
60 #include "BIF_editmode_undo.h"
61 #include "BIF_transform.h"
62
63 #include "BDR_editobject.h"
64 #include "BDR_editmball.h"
65
66 #include "BSE_edit.h"
67 #include "BSE_view.h"
68
69 #include "blendef.h"
70 #include "mydevice.h"
71
72 extern short editbutflag;
73
74 ListBase editelems= {0, 0};
75 MetaElem *lastelem;
76
77 void make_editMball()
78 {
79         MetaBall *mb;
80         MetaElem *ml, *newmb;
81
82         BLI_freelistN(&editelems);
83         lastelem= 0;
84         
85         mb= G.obedit->data;
86         ml= mb->elems.first;
87         
88         while(ml) {
89                 newmb= MEM_dupallocN(ml);
90                 BLI_addtail(&editelems, newmb);
91                 if(ml->flag & SELECT) lastelem= newmb;
92                 
93                 ml= ml->next;
94         }
95
96         allqueue(REDRAWBUTSEDIT, 0);
97
98         countall();
99 }
100
101 void load_editMball()
102 {
103         /* load mball in object */
104         MetaBall *mb;
105         MetaElem *ml, *newml;
106
107         if(G.obedit==0) return;
108         
109         mb= G.obedit->data;
110         BLI_freelistN(&(mb->elems));
111
112
113         ml= editelems.first;
114         while(ml) {
115                 newml= MEM_dupallocN(ml);
116                 BLI_addtail(&(mb->elems), newml);
117                 
118                 ml= ml->next;
119         }
120 }
121
122 void add_primitiveMball(int dummy_argument)
123 {
124         MetaElem *ml;
125         float *curs, mat[3][3], cent[3], imat[3][3], cmat[3][3];
126
127         if(G.scene->id.lib) return;
128
129         /* this function also comes from an info window */
130         if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
131         
132         check_editmode(OB_MBALL);
133
134         /* if no obedit: new object and enter editmode */
135         if(G.obedit==0) {
136                 add_object_draw(OB_MBALL);
137                 base_init_from_view3d(BASACT, G.vd);
138                 G.obedit= BASACT->object;
139                 
140                 where_is_object(G.obedit);  // need now, for imat
141                 
142                 make_editMball();
143                 setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
144         }
145         
146         /* deselect */
147         ml= editelems.first;
148         while(ml) {
149                 ml->flag &= ~SELECT;
150                 ml= ml->next;
151         }
152         
153         /* imat and centre and size */
154         Mat3CpyMat4(mat, G.obedit->obmat);
155
156         curs= give_cursor();
157         VECCOPY(cent, curs);
158         cent[0]-= G.obedit->obmat[3][0];
159         cent[1]-= G.obedit->obmat[3][1];
160         cent[2]-= G.obedit->obmat[3][2];
161
162         Mat3CpyMat4(imat, G.vd->viewmat);
163         Mat3MulVecfl(imat, cent);
164         Mat3MulMat3(cmat, imat, mat);
165         Mat3Inv(imat,cmat);
166         
167         Mat3MulVecfl(imat, cent);
168
169         ml= MEM_callocN(sizeof(MetaElem), "metaelem");
170         BLI_addtail(&editelems, ml);
171
172         ml->x= cent[0];
173         ml->y= cent[1];
174         ml->z= cent[2];
175         ml->quat[0]= 1.0;
176         ml->quat[1]= 0.0;
177         ml->quat[2]= 0.0;
178         ml->quat[3]= 0.0;
179         ml->rad= 2.0;
180         ml->s= 2.0;
181         ml->flag= SELECT | MB_SCALE_RAD;
182
183         switch(dummy_argument) {
184         case 1:
185                 ml->type = MB_BALL;
186                 ml->expx= ml->expy= ml->expz= 1.0;
187                 break;
188         case 2:
189                 ml->type = MB_TUBE;
190                 ml->expx= ml->expy= ml->expz= 1.0;
191                 break;
192         case 3:
193                 ml->type = MB_PLANE;
194                 ml->expx= ml->expy= ml->expz= 1.0;
195                 break;
196         case 4:
197                 ml->type = MB_ELIPSOID;
198                 ml->expx= 1.2f;
199                 ml->expy= 0.8f;
200                 ml->expz= 1.0;
201                 break;
202         case 5:
203                 ml->type = MB_CUBE;
204                 ml->expx= ml->expy= ml->expz= 1.0;
205                 break;
206         default:
207                 break;
208         }
209         
210         lastelem= ml;
211         
212         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);  // added ball can influence others
213                 
214         allqueue(REDRAWALL, 0);
215         BIF_undo_push("Add MetaElem");
216 }
217
218 void deselectall_mball()
219 {
220         MetaElem *ml;
221         int sel= 0;
222         
223         ml= editelems.first;
224         while(ml) {
225                 if(ml->flag & SELECT) break;
226                 ml= ml->next;
227         }
228
229         if(ml) sel= 1;
230
231         ml= editelems.first;
232         while(ml) {
233                 if(sel) ml->flag &= ~SELECT;
234                 else ml->flag |= SELECT;
235                 ml= ml->next;
236         }
237         allqueue(REDRAWVIEW3D, 0);
238         countall();
239 //      BIF_undo_push("Deselect MetaElem");
240 }
241
242 void mouse_mball()
243 {
244         static MetaElem *startelem=0;
245         MetaElem *ml, *act=0;
246         int a, hits;
247         unsigned int buffer[MAXPICKBUF];
248         
249         hits= view3d_opengl_select(buffer, MAXPICKBUF, 0, 0, 0, 0);
250
251         /* does startelem exist? */
252         ml= editelems.first;
253         while(ml) {
254                 if(ml==startelem) break;
255                 ml= ml->next;
256         }
257         if(ml==0) startelem= editelems.first;
258         
259         if(hits>0) {
260                 ml= startelem;
261                 while(ml) {
262                         
263                         for(a=0; a<hits; a++) {
264                                 /* index converted for gl stuff */
265                                 if(ml->selcol1==buffer[ 4 * a + 3 ]){
266                                         ml->flag |= MB_SCALE_RAD;
267                                         act= ml;
268                                 }
269                                 if(ml->selcol2==buffer[ 4 * a + 3 ]){
270                                         ml->flag &= ~MB_SCALE_RAD;
271                                         act= ml;
272                                 }
273
274                         }
275                         
276                         if(act) break;
277                         
278                         ml= ml->next;
279                         if(ml==0) ml= editelems.first;
280                         if(ml==startelem) break;
281                 }
282                 if(act) {
283                         if((G.qual & LR_SHIFTKEY)==0) {
284                                 deselectall_mball();
285                                 if(act->flag & SELECT) deselectall_mball();
286                                 act->flag |= SELECT;
287                         }
288                         else {
289                                 if(act->flag & SELECT) {
290                                         act->flag &= ~SELECT;
291                                 }
292                                 else act->flag |= SELECT;
293                         }
294                         lastelem= act;
295                         allqueue(REDRAWVIEW3D, 0);
296                         allqueue(REDRAWBUTSEDIT, 0);
297                 }
298         }
299         countall();
300         rightmouse_transform();
301 }
302
303 void adduplicate_mball()
304 {
305         MetaElem *ml, *newml;
306         
307         ml= editelems.last;
308         while(ml) {
309                 if(ml->flag & SELECT) {
310                         newml= MEM_dupallocN(ml);
311                         BLI_addtail(&editelems, newml);
312                         lastelem= newml;
313                         ml->flag &= ~SELECT;
314                 }
315                 ml= ml->prev;
316         }
317         
318         BIF_TransformSetUndo("Add Duplicate");
319         countall();
320         initTransform(TFM_TRANSLATION, CTX_NO_PET);
321         Transform();
322         allqueue(REDRAWBUTSEDIT, 0);
323 }
324
325 /* Delete all selected MetaElems (not MetaBall) */
326 void delete_mball()
327 {
328         MetaElem *ml, *next;
329         
330         if(okee("Erase selected")==0) return;
331         
332         ml= editelems.first;
333         while(ml) {
334                 next= ml->next;
335                 if(ml->flag & SELECT) {
336                         if(lastelem==ml) lastelem= 0;
337                         BLI_remlink(&editelems, ml);
338                         MEM_freeN(ml);
339                 }
340                 ml= next;
341         }
342         
343         DAG_scene_sort(G.scene);
344         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
345         allqueue(REDRAWVIEW3D, 0);
346         allqueue(REDRAWBUTSEDIT, 0);
347         countall();
348         BIF_undo_push("Delete MetaElem");
349 }
350
351 /* free all MetaElems from ListBase */
352 void freeMetaElemlist(ListBase *lb)
353 {
354         MetaElem *ml, *next;
355
356         if(lb==NULL) return;
357
358         ml= lb->first;
359         while(ml){
360                 next= ml->next;
361                 BLI_remlink(lb, ml);
362                 MEM_freeN(ml);
363                 ml= next;
364         }
365
366         lb->first= lb->last= NULL;
367         
368 }
369
370 /*  ************* undo for MetaBalls ************* */
371
372 static void undoMball_to_editMball(void *lbv)
373 {
374         ListBase *lb= lbv;
375         MetaElem *ml, *newml;
376         unsigned int nr, lastmlnr= 0;
377
378         /* we try to restore lastelem, which used in for example in button window */
379         for(ml= editelems.first; ml; ml= ml->next, lastmlnr++)
380                 if(lastelem==ml) break;
381
382         freeMetaElemlist(&editelems);
383
384         /* copy 'undo' MetaElems to 'edit' MetaElems */
385         ml= lb->first;
386         while(ml){
387                 newml= MEM_dupallocN(ml);
388                 BLI_addtail(&editelems, newml);
389                 ml= ml->next;
390         }
391         
392         for(nr=0, lastelem= editelems.first; lastelem; lastelem= lastelem->next, nr++)
393                 if(nr==lastmlnr) break;
394         
395         countall();
396 }
397
398 static void *editMball_to_undoMball(void)
399 {
400         ListBase *lb;
401         MetaElem *ml, *newml;
402
403         /* allocate memory for undo ListBase */
404         lb= MEM_callocN(sizeof(ListBase), "listbase undo");
405         lb->first= lb->last= NULL;
406         
407         /* copy contents of current ListBase to the undo ListBase */
408         ml= editelems.first;
409         while(ml){
410                 newml= MEM_dupallocN(ml);
411                 BLI_addtail(lb, newml);
412                 ml= ml->next;
413         }
414         
415         return lb;
416 }
417
418 /* free undo ListBase of MetaElems */
419 static void free_undoMball(void *lbv)
420 {
421         ListBase *lb= lbv;
422         
423         freeMetaElemlist(lb);
424         MEM_freeN(lb);
425 }
426
427 /* this is undo system for MetaBalls */
428 void undo_push_mball(char *name)
429 {
430         undo_editmode_push(name, free_undoMball, undoMball_to_editMball, editMball_to_undoMball);
431 }
432
433 /* Hide selected/unselected MetaElems */
434 void hide_mball(char hide)
435 {
436         MetaElem *ml;
437
438         ml= editelems.first;
439
440         while(ml){
441                 if(hide){
442                         if(!(ml->flag & SELECT))
443                                 ml->flag |= MB_HIDE;
444                 }
445                 else{
446                         if(ml->flag & SELECT)
447                                 ml->flag |= MB_HIDE;
448                 }
449                 ml= ml->next;
450         }
451
452         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
453         allqueue(REDRAWVIEW3D, 0);
454         allqueue(REDRAWBUTSEDIT, 0);
455         countall();
456         BIF_undo_push("Hide MetaElems");
457 }
458
459 /* Unhide all edited MetaElems */
460 void reveal_mball(void)
461 {
462         MetaElem *ml;
463
464         ml= editelems.first;
465
466         while(ml){
467                 ml->flag &= ~MB_HIDE;
468                 ml= ml->next;
469         }
470
471         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);     
472         allqueue(REDRAWVIEW3D, 0);
473         allqueue(REDRAWBUTSEDIT, 0);
474         countall();
475         BIF_undo_push("Unhide MetaElems");
476 }