Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / screen.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/screen.c
29  *  \ingroup bke
30  */
31
32 #ifdef WIN32
33 #  include "BLI_winstuff.h"
34 #endif
35
36 #include <string.h>
37 #include <stdio.h>
38 #include <math.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "GPU_compositing.h"
43
44 #include "DNA_scene_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_space_types.h"
47 #include "DNA_view3d_types.h"
48 #include "DNA_workspace_types.h"
49
50 #include "BLI_listbase.h"
51 #include "BLI_utildefines.h"
52 #include "BLI_rect.h"
53
54 #include "BKE_icons.h"
55 #include "BKE_idprop.h"
56 #include "BKE_screen.h"
57 #include "BKE_workspace.h"
58
59 /* ************ Spacetype/regiontype handling ************** */
60
61 /* keep global; this has to be accessible outside of windowmanager */
62 static ListBase spacetypes = {NULL, NULL};
63
64 /* not SpaceType itself */
65 static void spacetype_free(SpaceType *st)
66 {
67         ARegionType *art;
68         PanelType *pt;
69         HeaderType *ht;
70         
71         for (art = st->regiontypes.first; art; art = art->next) {
72                 BLI_freelistN(&art->drawcalls);
73
74                 for (pt = art->paneltypes.first; pt; pt = pt->next)
75                         if (pt->ext.free)
76                                 pt->ext.free(pt->ext.data);
77
78                 for (ht = art->headertypes.first; ht; ht = ht->next)
79                         if (ht->ext.free)
80                                 ht->ext.free(ht->ext.data);
81
82                 BLI_freelistN(&art->paneltypes);
83                 BLI_freelistN(&art->headertypes);
84         }
85         
86         BLI_freelistN(&st->regiontypes);
87         BLI_freelistN(&st->toolshelf);
88
89 }
90
91 void BKE_spacetypes_free(void)
92 {
93         SpaceType *st;
94         
95         for (st = spacetypes.first; st; st = st->next) {
96                 spacetype_free(st);
97         }
98         
99         BLI_freelistN(&spacetypes);
100 }
101
102 SpaceType *BKE_spacetype_from_id(int spaceid)
103 {
104         SpaceType *st;
105         
106         for (st = spacetypes.first; st; st = st->next) {
107                 if (st->spaceid == spaceid)
108                         return st;
109         }
110         return NULL;
111 }
112
113 ARegionType *BKE_regiontype_from_id(SpaceType *st, int regionid)
114 {
115         ARegionType *art;
116         
117         for (art = st->regiontypes.first; art; art = art->next)
118                 if (art->regionid == regionid)
119                         return art;
120         
121         printf("Error, region type %d missing in - name:\"%s\", id:%d\n", regionid, st->name, st->spaceid);
122         return st->regiontypes.first;
123 }
124
125
126 const ListBase *BKE_spacetypes_list(void)
127 {
128         return &spacetypes;
129 }
130
131 void BKE_spacetype_register(SpaceType *st)
132 {
133         SpaceType *stype;
134         
135         /* sanity check */
136         stype = BKE_spacetype_from_id(st->spaceid);
137         if (stype) {
138                 printf("error: redefinition of spacetype %s\n", stype->name);
139                 spacetype_free(stype);
140                 MEM_freeN(stype);
141         }
142         
143         BLI_addtail(&spacetypes, st);
144 }
145
146 bool BKE_spacetype_exists(int spaceid)
147 {
148         return BKE_spacetype_from_id(spaceid) != NULL;
149 }
150
151 /* ***************** Space handling ********************** */
152
153 void BKE_spacedata_freelist(ListBase *lb)
154 {
155         SpaceLink *sl;
156         ARegion *ar;
157         
158         for (sl = lb->first; sl; sl = sl->next) {
159                 SpaceType *st = BKE_spacetype_from_id(sl->spacetype);
160                 
161                 /* free regions for pushed spaces */
162                 for (ar = sl->regionbase.first; ar; ar = ar->next)
163                         BKE_area_region_free(st, ar);
164
165                 BLI_freelistN(&sl->regionbase);
166                 
167                 if (st && st->free) 
168                         st->free(sl);
169         }
170         
171         BLI_freelistN(lb);
172 }
173
174 ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
175 {
176         ARegion *newar = MEM_dupallocN(ar);
177         Panel *pa, *newpa, *patab;
178         
179         newar->prev = newar->next = NULL;
180         BLI_listbase_clear(&newar->handlers);
181         BLI_listbase_clear(&newar->uiblocks);
182         BLI_listbase_clear(&newar->panels_category);
183         BLI_listbase_clear(&newar->panels_category_active);
184         BLI_listbase_clear(&newar->ui_lists);
185         newar->swinid = 0;
186         newar->manipulator_map = NULL;
187         newar->regiontimer = NULL;
188         
189         /* use optional regiondata callback */
190         if (ar->regiondata) {
191                 ARegionType *art = BKE_regiontype_from_id(st, ar->regiontype);
192
193                 if (art && art->duplicate)
194                         newar->regiondata = art->duplicate(ar->regiondata);
195                 else
196                         newar->regiondata = MEM_dupallocN(ar->regiondata);
197         }
198
199         if (ar->v2d.tab_offset)
200                 newar->v2d.tab_offset = MEM_dupallocN(ar->v2d.tab_offset);
201         
202         BLI_listbase_clear(&newar->panels);
203         BLI_duplicatelist(&newar->panels, &ar->panels);
204
205         BLI_listbase_clear(&newar->ui_previews);
206         BLI_duplicatelist(&newar->ui_previews, &ar->ui_previews);
207
208         /* copy panel pointers */
209         for (newpa = newar->panels.first; newpa; newpa = newpa->next) {
210                 patab = newar->panels.first;
211                 pa = ar->panels.first;
212                 while (patab) {
213                         if (newpa->paneltab == pa) {
214                                 newpa->paneltab = patab;
215                                 break;
216                         }
217                         patab = patab->next;
218                         pa = pa->next;
219                 }
220         }
221         
222         return newar;
223 }
224
225
226 /* from lb2 to lb1, lb1 is supposed to be freed */
227 static void region_copylist(SpaceType *st, ListBase *lb1, ListBase *lb2)
228 {
229         ARegion *ar;
230         
231         /* to be sure */
232         BLI_listbase_clear(lb1);
233         
234         for (ar = lb2->first; ar; ar = ar->next) {
235                 ARegion *arnew = BKE_area_region_copy(st, ar);
236                 BLI_addtail(lb1, arnew);
237         }
238 }
239
240
241 /* lb1 should be empty */
242 void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2)
243 {
244         SpaceLink *sl;
245         
246         BLI_listbase_clear(lb1);  /* to be sure */
247         
248         for (sl = lb2->first; sl; sl = sl->next) {
249                 SpaceType *st = BKE_spacetype_from_id(sl->spacetype);
250                 
251                 if (st && st->duplicate) {
252                         SpaceLink *slnew = st->duplicate(sl);
253                         
254                         BLI_addtail(lb1, slnew);
255                         
256                         region_copylist(st, &slnew->regionbase, &sl->regionbase);
257                 }
258         }
259 }
260
261 /* facility to set locks for drawing to survive (render) threads accessing drawing data */
262 /* lock can become bitflag too */
263 /* should be replaced in future by better local data handling for threads */
264 void BKE_spacedata_draw_locks(int set)
265 {
266         SpaceType *st;
267         
268         for (st = spacetypes.first; st; st = st->next) {
269                 ARegionType *art;
270         
271                 for (art = st->regiontypes.first; art; art = art->next) {
272                         if (set) 
273                                 art->do_lock = art->lock;
274                         else 
275                                 art->do_lock = false;
276                 }
277         }
278 }
279
280 static void (*spacedata_id_remap_cb)(struct ScrArea *sa, struct SpaceLink *sl, ID *old_id, ID *new_id) = NULL;
281
282 void BKE_spacedata_callback_id_remap_set(void (*func)(ScrArea *sa, SpaceLink *sl, ID *, ID *))
283 {
284         spacedata_id_remap_cb = func;
285 }
286
287 /* UNUSED!!! */
288 void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID *id)
289 {
290         if (spacedata_id_remap_cb) {
291                 spacedata_id_remap_cb(sa, sl, id, NULL);
292         }
293 }
294
295 /**
296  * Avoid bad-level calls to #WM_manipulatormap_tag_refresh.
297  */
298 static void (*region_refresh_tag_manipulatormap_callback)(struct wmManipulatorMap *) = NULL;
299
300 void BKE_region_callback_refresh_tag_manipulatormap_set(void (*callback)(struct wmManipulatorMap *))
301 {
302         region_refresh_tag_manipulatormap_callback = callback;
303 }
304
305 void BKE_screen_manipulator_tag_refresh(struct bScreen *sc)
306 {
307         if (region_refresh_tag_manipulatormap_callback == NULL) {
308                 return;
309         }
310
311         ScrArea *sa;
312         ARegion *ar;
313         for (sa = sc->areabase.first; sa; sa = sa->next) {
314                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
315                         if (ar->manipulator_map != NULL) {
316                                 region_refresh_tag_manipulatormap_callback(ar->manipulator_map);
317                         }
318                 }
319         }
320 }
321
322 /**
323  * Avoid bad-level calls to #WM_manipulatormap_delete.
324  */
325 static void (*region_free_manipulatormap_callback)(struct wmManipulatorMap *) = NULL;
326
327 void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *))
328 {
329         region_free_manipulatormap_callback = callback;
330 }
331
332 /* not region itself */
333 void BKE_area_region_free(SpaceType *st, ARegion *ar)
334 {
335         uiList *uilst;
336
337         if (st) {
338                 ARegionType *art = BKE_regiontype_from_id(st, ar->regiontype);
339                 
340                 if (art && art->free)
341                         art->free(ar);
342                 
343                 if (ar->regiondata)
344                         printf("regiondata free error\n");
345         }
346         else if (ar->type && ar->type->free)
347                 ar->type->free(ar);
348         
349         if (ar->v2d.tab_offset) {
350                 MEM_freeN(ar->v2d.tab_offset);
351                 ar->v2d.tab_offset = NULL;
352         }
353
354         if (!BLI_listbase_is_empty(&ar->panels)) {
355                 Panel *pa, *pa_next;
356                 for (pa = ar->panels.first; pa; pa = pa_next) {
357                         pa_next = pa->next;
358                         if (pa->activedata) {
359                                 MEM_freeN(pa->activedata);
360                         }
361                         MEM_freeN(pa);
362                 }
363         }
364
365         for (uilst = ar->ui_lists.first; uilst; uilst = uilst->next) {
366                 if (uilst->dyn_data) {
367                         uiListDyn *dyn_data = uilst->dyn_data;
368                         if (dyn_data->items_filter_flags) {
369                                 MEM_freeN(dyn_data->items_filter_flags);
370                         }
371                         if (dyn_data->items_filter_neworder) {
372                                 MEM_freeN(dyn_data->items_filter_neworder);
373                         }
374                         MEM_freeN(dyn_data);
375                 }
376                 if (uilst->properties) {
377                         IDP_FreeProperty(uilst->properties);
378                         MEM_freeN(uilst->properties);
379                 }
380         }
381
382         if (ar->manipulator_map != NULL) {
383                 region_free_manipulatormap_callback(ar->manipulator_map);
384         }
385
386         BLI_freelistN(&ar->ui_lists);
387         BLI_freelistN(&ar->ui_previews);
388         BLI_freelistN(&ar->panels_category);
389         BLI_freelistN(&ar->panels_category_active);
390 }
391
392 /* not area itself */
393 void BKE_screen_area_free(ScrArea *sa)
394 {
395         SpaceType *st = BKE_spacetype_from_id(sa->spacetype);
396         ARegion *ar;
397         
398         for (ar = sa->regionbase.first; ar; ar = ar->next)
399                 BKE_area_region_free(st, ar);
400
401         BLI_freelistN(&sa->regionbase);
402         
403         BKE_spacedata_freelist(&sa->spacedata);
404         
405         BLI_freelistN(&sa->actionzones);
406 }
407
408 /** Free (or release) any data used by this screen (does not free the screen itself). */
409 void BKE_screen_free(bScreen *sc)
410 {
411         ScrArea *sa, *san;
412         ARegion *ar;
413
414         /* No animdata here. */
415         
416         for (ar = sc->regionbase.first; ar; ar = ar->next)
417                 BKE_area_region_free(NULL, ar);
418
419         BLI_freelistN(&sc->regionbase);
420         
421         for (sa = sc->areabase.first; sa; sa = san) {
422                 san = sa->next;
423                 BKE_screen_area_free(sa);
424         }
425         
426         BLI_freelistN(&sc->vertbase);
427         BLI_freelistN(&sc->edgebase);
428         BLI_freelistN(&sc->areabase);
429
430         BKE_previewimg_free(&sc->preview);
431 }
432
433 /* for depsgraph */
434 unsigned int BKE_screen_visible_layers(bScreen *screen, Scene *scene)
435 {
436         ScrArea *sa;
437         unsigned int layer = 0;
438
439         if (screen) {
440                 /* get all used view3d layers */
441                 for (sa = screen->areabase.first; sa; sa = sa->next)
442                         if (sa->spacetype == SPACE_VIEW3D)
443                                 layer |= ((View3D *)sa->spacedata.first)->lay;
444         }
445
446         if (!layer)
447                 return scene->lay;
448
449         return layer;
450 }
451
452 /* ***************** Utilities ********************** */
453
454 /* Find a region of the specified type from the given area */
455 ARegion *BKE_area_find_region_type(ScrArea *sa, int type)
456 {
457         if (sa) {
458                 ARegion *ar;
459                 
460                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
461                         if (ar->regiontype == type)
462                                 return ar;
463                 }
464         }
465         return NULL;
466 }
467
468 ARegion *BKE_area_find_region_active_win(ScrArea *sa)
469 {
470         if (sa) {
471                 ARegion *ar = BLI_findlink(&sa->regionbase, sa->region_active_win);
472                 if (ar && (ar->regiontype == RGN_TYPE_WINDOW)) {
473                         return ar;
474                 }
475
476                 /* fallback to any */
477                 return BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
478         }
479         return NULL;
480 }
481
482 ARegion *BKE_area_find_region_xy(ScrArea *sa, const int regiontype, int x, int y)
483 {
484         ARegion *ar_found = NULL;
485         if (sa) {
486                 ARegion *ar;
487                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
488                         if ((regiontype == RGN_TYPE_ANY) || (ar->regiontype == regiontype)) {
489                                 if (BLI_rcti_isect_pt(&ar->winrct, x, y)) {
490                                         ar_found = ar;
491                                         break;
492                                 }
493                         }
494                 }
495         }
496         return ar_found;
497 }
498
499 /**
500  * \note, ideally we can get the area from the context,
501  * there are a few places however where this isn't practical.
502  */
503 ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, SpaceLink *sl)
504 {
505         ScrArea *sa;
506
507         for (sa = sc->areabase.first; sa; sa = sa->next) {
508                 if (BLI_findindex(&sa->spacedata, sl) != -1) {
509                         break;
510                 }
511         }
512
513         return sa;
514 }
515
516 /**
517  * \note Using this function is generally a last resort, you really want to be
518  * using the context when you can - campbell
519  */
520 ScrArea *BKE_screen_find_big_area(bScreen *sc, const int spacetype, const short min)
521 {
522         ScrArea *sa, *big = NULL;
523         int size, maxsize = 0;
524
525         for (sa = sc->areabase.first; sa; sa = sa->next) {
526                 if ((spacetype == SPACE_TYPE_ANY) || (sa->spacetype == spacetype)) {
527                         if (min <= sa->winx && min <= sa->winy) {
528                                 size = sa->winx * sa->winy;
529                                 if (size > maxsize) {
530                                         maxsize = size;
531                                         big = sa;
532                                 }
533                         }
534                 }
535         }
536
537         return big;
538 }
539
540 ScrArea *BKE_screen_find_area_xy(bScreen *sc, const int spacetype, int x, int y)
541 {
542         ScrArea *sa, *sa_found = NULL;
543
544         for (sa = sc->areabase.first; sa; sa = sa->next) {
545                 if (BLI_rcti_isect_pt(&sa->totrct, x, y)) {
546                         if ((spacetype == SPACE_TYPE_ANY) || (sa->spacetype == spacetype)) {
547                                 sa_found = sa;
548                         }
549                         break;
550                 }
551         }
552         return sa_found;
553 }
554
555
556 /**
557  * Utility function to get the active layer to use when adding new objects.
558  */
559 unsigned int BKE_screen_view3d_layer_active_ex(const View3D *v3d, const Scene *scene, bool use_localvd)
560 {
561         unsigned int lay;
562         if ((v3d == NULL) || (v3d->scenelock && !v3d->localvd)) {
563                 lay = scene->layact;
564         }
565         else {
566                 lay = v3d->layact;
567         }
568
569         if (use_localvd) {
570                 if (v3d && v3d->localvd) {
571                         lay |= v3d->lay;
572                 }
573         }
574
575         return lay;
576 }
577 unsigned int BKE_screen_view3d_layer_active(const struct View3D *v3d, const struct Scene *scene)
578 {
579         return BKE_screen_view3d_layer_active_ex(v3d, scene, true);
580 }
581
582 /**
583  * Accumulate all visible layers on this screen.
584  */
585 unsigned int BKE_screen_view3d_layer_all(const bScreen *sc)
586 {
587         const ScrArea *sa;
588         unsigned int lay = 0;
589         for (sa = sc->areabase.first; sa; sa = sa->next) {
590                 if (sa->spacetype == SPACE_VIEW3D) {
591                         View3D *v3d = sa->spacedata.first;
592                         lay |= v3d->lay;
593                 }
594         }
595
596         return lay;
597 }
598
599 void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene)
600 {
601         int bit;
602
603         if (v3d->scenelock && v3d->localvd == NULL) {
604                 v3d->lay = scene->lay;
605                 v3d->camera = scene->camera;
606
607                 if (v3d->camera == NULL) {
608                         ARegion *ar;
609
610                         for (ar = v3d->regionbase.first; ar; ar = ar->next) {
611                                 if (ar->regiontype == RGN_TYPE_WINDOW) {
612                                         RegionView3D *rv3d = ar->regiondata;
613                                         if (rv3d->persp == RV3D_CAMOB)
614                                                 rv3d->persp = RV3D_PERSP;
615                                 }
616                         }
617                 }
618
619                 if ((v3d->lay & v3d->layact) == 0) {
620                         for (bit = 0; bit < 32; bit++) {
621                                 if (v3d->lay & (1u << bit)) {
622                                         v3d->layact = (1u << bit);
623                                         break;
624                                 }
625                         }
626                 }
627         }
628 }
629
630 void BKE_screen_view3d_scene_sync(bScreen *sc, Scene *scene)
631 {
632         /* are there cameras in the views that are not in the scene? */
633         ScrArea *sa;
634         for (sa = sc->areabase.first; sa; sa = sa->next) {
635                 SpaceLink *sl;
636                 for (sl = sa->spacedata.first; sl; sl = sl->next) {
637                         if (sl->spacetype == SPACE_VIEW3D) {
638                                 View3D *v3d = (View3D *) sl;
639                                 BKE_screen_view3d_sync(v3d, scene);
640                         }
641                 }
642         }
643 }
644
645 void BKE_screen_transform_orientation_remove(
646         const bScreen *screen, const WorkSpace *workspace, const TransformOrientation *orientation)
647 {
648         const int orientation_index = BKE_workspace_transform_orientation_get_index(workspace, orientation);
649
650         for (ScrArea *area = screen->areabase.first; area; area = area->next) {
651                 for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
652                         if (sl->spacetype == SPACE_VIEW3D) {
653                                 View3D *v3d = (View3D *)sl;
654
655                                 if (v3d->custom_orientation_index == orientation_index) {
656                                         /* could also use orientation_index-- */
657                                         v3d->twmode = V3D_MANIP_GLOBAL;
658                                         v3d->custom_orientation_index = -1;
659                                 }
660                         }
661                 }
662         }
663 }
664
665 /* magic zoom calculation, no idea what
666  * it signifies, if you find out, tell me! -zr
667  */
668
669 /* simple, its magic dude!
670  * well, to be honest, this gives a natural feeling zooming
671  * with multiple keypad presses (ton)
672  */
673 float BKE_screen_view3d_zoom_to_fac(float camzoom)
674 {
675         return powf(((float)M_SQRT2 + camzoom / 50.0f), 2.0f) / 4.0f;
676 }
677
678 float BKE_screen_view3d_zoom_from_fac(float zoomfac)
679 {
680         return ((sqrtf(4.0f * zoomfac) - (float)M_SQRT2) * 50.0f);
681 }
682
683 void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings)
684 {
685         /* currently we use DOF from the camera _only_,
686          * so we never allocate this, only copy from the Camera */
687 #if 0
688         if ((fx_settings->dof == NULL) &&
689             (fx_settings->fx_flag & GPU_FX_FLAG_DOF))
690         {
691                 GPUDOFSettings *fx_dof;
692                 fx_dof = fx_settings->dof = MEM_callocN(sizeof(GPUDOFSettings), __func__);
693         }
694 #endif
695
696         if ((fx_settings->ssao == NULL) &&
697             (fx_settings->fx_flag & GPU_FX_FLAG_SSAO))
698         {
699                 GPUSSAOSettings *fx_ssao;
700                 fx_ssao = fx_settings->ssao = MEM_callocN(sizeof(GPUSSAOSettings), __func__);
701
702                 GPU_fx_compositor_init_ssao_settings(fx_ssao);
703         }
704 }
705
706 bool BKE_screen_is_fullscreen_area(const bScreen *screen)
707 {
708         return ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL);
709 }
710
711 bool BKE_screen_is_used(const bScreen *screen)
712 {
713         return (screen->winid != 0);
714 }