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