updated .c files to include:
[blender.git] / source / blender / src / editoops.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 <stdlib.h>
34 #include <math.h>
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #ifndef WIN32
41 #include <unistd.h>
42 #else
43 #include <io.h>
44 #include "BLI_winstuff.h"
45 #endif   
46
47 #include "MEM_guardedalloc.h"
48
49 #include "BLI_blenlib.h"
50 #include "BLI_arithb.h"
51 #include "BLI_editVert.h"
52
53 #include "DNA_material_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_oops_types.h"
56 #include "DNA_screen_types.h"
57 #include "DNA_space_types.h"
58 #include "DNA_scene_types.h"
59
60 #include "BKE_global.h"
61 #include "BKE_scene.h"
62 #include "BKE_material.h"
63
64 #include "BIF_space.h"
65 #include "BIF_screen.h"
66 #include "BIF_editoops.h"
67 #include "BIF_editview.h"
68 #include "BIF_drawscene.h"
69 #include "BIF_mywindow.h"
70
71 #include "BDR_editobject.h"
72
73 #include "BSE_edit.h"
74 #include "BSE_drawipo.h"
75
76 #include "blendef.h"
77 #include "mydevice.h"
78
79
80 typedef struct TransOops {
81         float *loc;
82         float oldloc[2];
83 } TransOops;
84
85
86 static void oops_to_select_objects(void)
87 {
88         Oops *oops;
89         Base *base;
90         Object *ob;
91
92         if(G.soops==0) return;  
93
94         oops= G.soops->oops.first;
95         while(oops) {
96                 if(oops->hide==0) {     
97                         if(oops->type==ID_OB) {
98                                 ob= (Object *)oops->id;
99                                 if(oops->flag & SELECT) ob->flag |= SELECT;
100                                 else ob->flag &= ~SELECT;
101                         }
102                 }
103                 oops= oops->next;
104         }
105         base= FIRSTBASE;
106         while(base) {
107                 if(base->flag != base->object->flag) {
108                         base->flag= base->object->flag;
109                 }
110                 base= base->next;
111         }
112
113         allqueue(REDRAWVIEW3D, 0);
114         allqueue(REDRAWOOPS, 0);
115 }
116
117 void swap_select_all_oops(void)
118 {
119         Oops *oops;
120         int sel= 0;
121         
122         if(G.soops==0) return;  
123
124         oops= G.soops->oops.first;
125         while(oops) {
126                 if(oops->hide==0) {     
127                         if(oops->flag & SELECT) {
128                                 sel= 1;
129                                 break;
130                         }
131                 }
132                 oops= oops->next;
133         }
134
135         oops= G.soops->oops.first;
136         while(oops) {
137                 if(oops->hide==0) {     
138                         if(sel) oops->flag &= ~SELECT;
139                         else oops->flag |= SELECT;
140                 }
141                 oops= oops->next;
142         }
143         
144         oops_to_select_objects();       /* ook redr */
145         
146         G.soops->lockpoin= 0;
147 }
148
149 /* never used... check CVS 1.12 for the code */
150 /*  static void select_swap_oops(void) */
151
152 static void deselect_all_oops(void)
153 {
154         Oops *oops;
155         
156         if(G.soops==0) return;  
157
158         oops= G.soops->oops.first;
159         while(oops) {
160                 if(oops->hide==0) {     
161                         oops->flag &= ~SELECT;
162                 }
163                 oops= oops->next;
164         }
165         G.soops->lockpoin= 0;
166 }
167
168 void set_select_flag_oops(void) /* alle areas */
169 {
170         SpaceOops *so;
171         ScrArea *sa;
172         
173         sa= G.curscreen->areabase.first;
174         while(sa) {
175                 if(sa->spacetype==SPACE_OOPS) {
176                         so= sa->spacedata.first;
177                         so->flag |= SO_NEWSELECTED;
178                 }
179                 sa= sa->next;
180         }
181         if(G.soops) G.soops->lockpoin= 0;
182 }
183
184 void deselect_all_area_oops(void)       /* alle areas */
185 {
186         SpaceOops *so;
187         Oops *oops;
188         ScrArea *sa;
189         
190         sa= G.curscreen->areabase.first;
191         while(sa) {
192                 if(sa->spacetype==SPACE_OOPS) {
193                         so= sa->spacedata.first;
194                         
195                         oops= so->oops.first;
196                         while(oops) {
197                                 oops->flag &= ~SELECT;
198                                 oops= oops->next;
199                         }
200                 }
201                 sa= sa->next;
202         }
203         
204         if(G.soops) G.soops->lockpoin= 0;
205 }
206
207 void transform_oops(int mode)
208 {
209         TransOops *transmain, *tv;
210         Oops *oops;
211         float dx, dy, div, dvec[3], cent[3], min[3], max[3];
212         float sizefac, size[2], xref=1.0, yref=1.0;
213         int a, tot= 0, midtog= 0;
214         unsigned short event = 0;
215         short firsttime= 1, proj = 0, afbreek=0, xc, yc, xo, yo, xn, yn, mval[2];
216         short val;
217         char str[32];
218         
219         if(G.soops==0) return;  
220                 
221         /* welke oopsen doen mee */
222         oops= G.soops->oops.first;
223         while(oops) {
224                 if(oops->hide==0) {     
225                         if(oops->flag & SELECT) {
226                                 tot++;
227                         }
228                 }
229                 oops= oops->next;
230         }
231         
232         if(tot==0) return;
233         
234         G.moving= 1;
235         
236         INIT_MINMAX(min, max);
237         
238         tv=transmain= MEM_callocN(tot*sizeof(TransOops), "transmain");
239         oops= G.soops->oops.first;
240         while(oops) {
241                 if(oops->hide==0) {     
242                         if(oops->flag & SELECT) {
243                                 tv->loc= &oops->x;
244                                 tv->oldloc[0]= tv->loc[0];
245                                 tv->oldloc[1]= tv->loc[1];
246                                 DO_MINMAX2(tv->loc, min, max);
247                                 tv++;
248                         }
249                 }
250                 oops= oops->next;
251         }
252
253         cent[0]= (min[0]+max[0])/2.0;
254         cent[1]= (min[1]+max[1])/2.0;
255
256         ipoco_to_areaco_noclip(G.v2d, cent, mval);
257         xc= mval[0];
258         yc= mval[1];
259         
260         getmouseco_areawin(mval);
261         xo= xn= mval[0];
262         yo= yn= mval[1];
263         dvec[0]= dvec[1]= 0.0;
264
265         sizefac= sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) );
266         if(sizefac<2.0) sizefac= 2.0;
267
268         while(afbreek==0) {
269                 getmouseco_areawin(mval);
270                 if(mval[0]!=xo || mval[1]!=yo || firsttime) {
271                         
272                         if(mode=='g') {
273                         
274                                 dx= mval[0]- xo;
275                                 dy= mval[1]- yo;
276         
277                                 div= G.v2d->mask.xmax-G.v2d->mask.xmin;
278                                 dvec[0]+= (G.v2d->cur.xmax-G.v2d->cur.xmin)*(dx)/div;
279         
280                                 div= G.v2d->mask.ymax-G.v2d->mask.ymin;
281                                 dvec[1]+= (G.v2d->cur.ymax-G.v2d->cur.ymin)*(dy)/div;
282                                 
283                                 if(midtog) dvec[proj]= 0.0;
284                                 
285                                 tv= transmain;
286                                 for(a=0; a<tot; a++, tv++) {
287                                         
288                                         tv->loc[0]= tv->oldloc[0]+dvec[0];
289                                         tv->loc[1]= tv->oldloc[1]+dvec[1];
290                                                 
291                                 }
292                         
293                                 sprintf(str, "X: %.2f   Y: %.2f  ", dvec[0], dvec[1]);
294                                 headerprint(str);
295                         }
296                         else if(mode=='s') {
297                                 size[0]=size[1]= (sqrt( (float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc)) ))/sizefac;
298                                 
299                                 if(midtog) size[proj]= 1.0;
300                                 size[0]*= xref;
301                                 size[1]*= yref;
302
303                                 tv= transmain;
304                                 for(a=0; a<tot; a++, tv++) {
305                                 
306                                         tv->loc[0]= size[0]*(tv->oldloc[0]-cent[0])+ cent[0];
307                                         tv->loc[1]= size[1]*(tv->oldloc[1]-cent[1])+ cent[1];
308                                         
309                                 }
310                                 
311                                 sprintf(str, "sizeX: %.3f   sizeY: %.3f  ", size[0], size[1]);
312                                 headerprint(str);
313                         }
314                         
315
316                         xo= mval[0];
317                         yo= mval[1];
318                         
319                         force_draw();
320                         
321                         firsttime= 0;
322                         
323                 }
324                 else BIF_wait_for_statechange();
325                 
326                 while(qtest()) {
327                         event= extern_qread(&val);
328                         if(val) {
329                                 switch(event) {
330                                 case ESCKEY:
331                                 case LEFTMOUSE:
332                                 case SPACEKEY:
333                                 case RETKEY:
334                                         afbreek= 1;
335                                         break;
336                                 case MIDDLEMOUSE:
337                                         
338                                         midtog= ~midtog;
339                                         if(midtog) {
340                                                 if( abs(mval[0]-xn) > abs(mval[1]-yn)) proj= 1;
341                                                 else proj= 0;
342                                                 firsttime= 1;
343                                         }
344                                 
345                                         break;
346                                 default:
347                                         arrows_move_cursor(event);
348                                 }
349                         }
350                         if(afbreek) break;
351                 }
352         }
353         
354         if(event==ESCKEY) {
355                 tv= transmain;
356                 for(a=0; a<tot; a++, tv++) {
357                         tv->loc[0]= tv->oldloc[0];
358                         tv->loc[1]= tv->oldloc[1];
359                 }
360         }
361         MEM_freeN(transmain);
362                         
363         G.moving= 0;
364
365         scrarea_queue_redraw(curarea);
366 }
367
368 static Oops *find_nearest_oops(void)
369 {
370         Oops *oops;
371         float x, y;
372         short mval[2];
373         
374         getmouseco_areawin(mval);
375         areamouseco_to_ipoco(G.v2d, mval, &x, &y);
376         
377         oops= G.soops->oops.first;
378         while(oops) {
379                 if(oops->hide == 0) {
380                         if(oops->x <=x && oops->x+OOPSX >= x) {
381                                 if(oops->y <=y && oops->y+OOPSY >= y) {         
382                                         return oops;
383                                 }
384                         }
385                 }
386                 oops= oops->next;
387         }
388         return 0;
389 }
390
391 static void do_activate_oops(Oops *oops)
392 {
393         Base *base;
394         Object *ob;
395         
396         switch(oops->type) {
397         case ID_SCE:
398                 if(oops->id) set_scene((Scene *)oops->id);
399                 break;
400         case ID_OB:
401                 base= FIRSTBASE;
402                 while(base) {
403                         if(base->object == (Object *)oops->id) break;
404                         base= base->next;
405                 }
406                 if(base) {
407                         set_active_base(base);  /* editview.c */
408                         allqueue(REDRAWVIEW3D, 0);
409                         allqueue(REDRAWINFO, 1);
410                 }
411                 break;
412         case ID_MA:
413                 ob= OBACT;
414                 if(ob && oops->id) {
415                         assign_material(ob, (Material *)oops->id, ob->actcol);
416                         allqueue(REDRAWBUTSMAT, 0);
417                         scrarea_queue_winredraw(curarea);
418                 }
419                 break;
420                 
421         }
422 }
423
424 void mouse_select_oops(void)
425 {
426         Oops *oops;
427         extern float oopslastx, oopslasty;      /* oops.c */
428         
429         if(G.soops==0) return;  
430                 
431         /* welke oopsen doen mee */
432         oops= G.soops->oops.first;
433
434         oops= find_nearest_oops();
435         if(oops==0) return;
436         
437         if((G.qual & LR_SHIFTKEY)==0) deselect_all_oops();
438         
439         if(oops) {
440                 /* last_seq= seq; */
441                 
442                 if(G.qual==0) {
443                         oops->flag |= SELECT;
444                 }
445                 else {
446                         if(oops->flag & SELECT) {
447                                 oops->flag &= ~SELECT;
448                         }
449                         else {
450                                 oops->flag |= SELECT;
451                         }
452                 }
453                 
454                 oopslastx= oops->x;
455                 oopslasty= oops->y;
456                 
457                 if(G.qual & LR_CTRLKEY) do_activate_oops(oops);
458                 G.soops->lockpoin= oops;
459         }
460         
461         oops_to_select_objects();       /* ook redr */
462         scrarea_queue_headredraw(curarea);
463         
464         force_draw();
465         
466         std_rmouse_transform(transform_oops);
467 }
468
469 void borderselect_oops(void)
470 {
471         Oops *oops;
472         rcti rect;
473         rctf rectf, rq;
474         int val;
475         short mval[2];
476
477         if(G.soops==0) return;  
478         
479         val= get_border(&rect, 3);
480
481         if(val) {
482                 mval[0]= rect.xmin;
483                 mval[1]= rect.ymin;
484                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
485                 mval[0]= rect.xmax;
486                 mval[1]= rect.ymax;
487                 areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
488
489                 oops= G.soops->oops.first;
490                 while(oops) {
491                         if(oops->hide == 0) {
492                         
493                                 rq.xmin= oops->x;
494                                 rq.xmax= oops->x+OOPSX;
495                                 rq.ymin= oops->y;
496                                 rq.ymax= oops->y+OOPSY;
497                 
498                                 if(BLI_isect_rctf(&rq, &rectf, 0)) {
499                                         if(val==LEFTMOUSE) {
500                                                 oops->flag |= SELECT;
501                                         }
502                                         else {
503                                                 oops->flag &= ~SELECT;
504                                         }
505                                 }
506                         }
507                         oops= oops->next;
508                 }
509
510                 oops_to_select_objects();       /* ook redr */
511         }
512 }
513
514 static void select_oops_lib(ID *id)
515 {
516         Oops *oops;
517         
518         oops= G.soops->oops.first;
519         while(oops) {
520                 if(oops->hide==0) {     
521                         if(oops->id->lib== (Library *)id) oops->flag |= OOPS_DOSELECT;
522                 }
523                 oops= oops->next;
524         }
525 }
526
527 void select_linked_oops(void)
528 {
529         Oops *oops;
530         OopsLink *ol;
531         
532         if(G.soops==0) return;  
533
534         oops= G.soops->oops.first;
535         while(oops) {
536                 if(oops->hide==0) {     
537                         if(oops->flag & SELECT) {
538                                 if(oops->type==ID_LI) select_oops_lib(oops->id);
539                                 ol= oops->link.first;
540                                 while(ol) {
541                                         if(ol->to && ol->to->hide==0) ol->to->flag |= OOPS_DOSELECT;
542                                         ol= ol->next;
543                                 }
544                         }
545                 }
546                 oops= oops->next;
547         }
548         
549         oops= G.soops->oops.first;
550         while(oops) {
551                 if(oops->hide==0) {     
552                         if(oops->flag & OOPS_DOSELECT) {
553                                 oops->flag |= SELECT;
554                                 oops->flag &= ~OOPS_DOSELECT;
555                         }
556                 }
557                 oops= oops->next;
558         }
559         
560         oops_to_select_objects();       /* ook redr */
561         
562 }
563
564 void select_backlinked_oops(void)
565 {
566         Oops *oops;
567         OopsLink *ol;
568         
569         if(G.soops==0) return;  
570
571         oops= G.soops->oops.first;
572         while(oops) {
573                 if(oops->hide==0) {     
574                         if( (oops->flag & SELECT)==0) {
575                                 ol= oops->link.first;
576                                 while(ol) {
577                                         if(ol->to && ol->to->hide==0) {
578                                                 if(ol->to->flag & SELECT) oops->flag |= OOPS_DOSELECT;
579                                         }
580                                         ol= ol->next;
581                                 }
582                         }
583                 }
584                 oops= oops->next;
585         }
586         
587         oops= G.soops->oops.first;
588         while(oops) {
589                 if(oops->hide==0) {     
590                         if(oops->flag & OOPS_DOSELECT) {
591                                 oops->flag |= SELECT;
592                                 oops->flag &= ~OOPS_DOSELECT;
593                         }
594                 }
595                 oops= oops->next;
596         }
597         
598         oops_to_select_objects();       /* ook redr */
599         
600 }