1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2008 Blender Foundation.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup spimage
22 */
23
24 #include "DNA_gpencil_types.h"
25 #include "DNA_image_types.h"
26 #include "DNA_mask_types.h"
27 #include "DNA_mesh_types.h"
28 #include "DNA_meshdata_types.h"
29 #include "DNA_object_types.h"
30 #include "DNA_scene_types.h"
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_blenlib.h"
35 #include "BLI_math.h"
36 #include "BLI_threads.h"
37
38 #include "BKE_colortools.h"
39 #include "BKE_context.h"
40 #include "BKE_editmesh.h"
41 #include "BKE_image.h"
42 #include "BKE_layer.h"
43 #include "BKE_lib_id.h"
44 #include "BKE_material.h"
45 #include "BKE_scene.h"
46 #include "BKE_screen.h"
47 #include "BKE_workspace.h"
48
49 #include "RNA_access.h"
50 #include "RNA_define.h"
51 #include "RNA_enum_types.h"
52
53 #include "DEG_depsgraph.h"
54
55 #include "IMB_imbuf_types.h"
56
57 #include "ED_image.h"
58 #include "ED_mask.h"
59 #include "ED_mesh.h"
60 #include "ED_node.h"
61 #include "ED_render.h"
62 #include "ED_screen.h"
63 #include "ED_space_api.h"
64 #include "ED_transform.h"
65 #include "ED_uvedit.h"
66
67 #include "WM_api.h"
68 #include "WM_message.h"
69 #include "WM_types.h"
70
71 #include "UI_interface.h"
72 #include "UI_resources.h"
73 #include "UI_view2d.h"
74
75 #include "GPU_batch_presets.h"
76 #include "GPU_framebuffer.h"
77 #include "GPU_viewport.h"
78
79 #include "DRW_engine.h"
80 #include "DRW_engine_types.h"
81
82 #include "image_intern.h"
83
84 /**************************** common state *****************************/
85
image_scopes_tag_refresh(ScrArea * area)86 static void image_scopes_tag_refresh(ScrArea *area)
87 {
88 SpaceImage *sima = (SpaceImage *)area->spacedata.first;
89 ARegion *region;
90
91 /* only while histogram is visible */
92 for (region = area->regionbase.first; region; region = region->next) {
93 if (region->regiontype == RGN_TYPE_TOOL_PROPS && region->flag & RGN_FLAG_HIDDEN) {
94 return;
95 }
96 }
97
98 sima->scopes.ok = 0;
99 }
100
image_user_refresh_scene(const bContext * C,SpaceImage * sima)101 static void image_user_refresh_scene(const bContext *C, SpaceImage *sima)
102 {
103 /* Update scene image user for acquiring render results. */
104 sima->iuser.scene = CTX_data_scene(C);
105
106 if (sima->image && sima->image->type == IMA_TYPE_R_RESULT) {
107 /* While rendering, prefer scene that is being rendered. */
108 Scene *render_scene = ED_render_job_get_current_scene(C);
109 if (render_scene) {
110 sima->iuser.scene = render_scene;
111 }
112 }
113
114 /* Auto switch image to show in UV editor when selection changes. */
115 ED_space_image_auto_set(C, sima);
116 }
117
118 /* ******************** default callbacks for image space ***************** */
119
image_create(const ScrArea * UNUSED (area),const Scene * UNUSED (scene))120 static SpaceLink *image_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
121 {
122 ARegion *region;
123 SpaceImage *simage;
124
125 simage = MEM_callocN(sizeof(SpaceImage), "initimage");
126 simage->spacetype = SPACE_IMAGE;
127 simage->zoom = 1.0f;
128 simage->lock = true;
129 simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS;
130 simage->uv_opacity = 1.0f;
131 simage->overlay.flag = SI_OVERLAY_SHOW_OVERLAYS;
132
133 BKE_imageuser_default(&simage->iuser);
134 simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS;
135
136 BKE_scopes_new(&simage->scopes);
137 simage->sample_line_hist.height = 100;
138
139 simage->tile_grid_shape[0] = 1;
140 simage->tile_grid_shape[1] = 1;
141
142 /* tool header */
143 region = MEM_callocN(sizeof(ARegion), "tool header for image");
144
145 BLI_addtail(&simage->regionbase, region);
146 region->regiontype = RGN_TYPE_TOOL_HEADER;
147 region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
148 region->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER;
149
150 /* header */
151 region = MEM_callocN(sizeof(ARegion), "header for image");
152
153 BLI_addtail(&simage->regionbase, region);
154 region->regiontype = RGN_TYPE_HEADER;
155 region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
156
157 /* buttons/list view */
158 region = MEM_callocN(sizeof(ARegion), "buttons for image");
159
160 BLI_addtail(&simage->regionbase, region);
161 region->regiontype = RGN_TYPE_UI;
162 region->alignment = RGN_ALIGN_RIGHT;
163 region->flag = RGN_FLAG_HIDDEN;
164
165 /* scopes/uv sculpt/paint */
166 region = MEM_callocN(sizeof(ARegion), "buttons for image");
167
168 BLI_addtail(&simage->regionbase, region);
169 region->regiontype = RGN_TYPE_TOOLS;
170 region->alignment = RGN_ALIGN_LEFT;
171 region->flag = RGN_FLAG_HIDDEN;
172
173 /* main area */
174 region = MEM_callocN(sizeof(ARegion), "main area for image");
175
176 BLI_addtail(&simage->regionbase, region);
177 region->regiontype = RGN_TYPE_WINDOW;
178
179 return (SpaceLink *)simage;
180 }
181
182 /* not spacelink itself */
image_free(SpaceLink * sl)183 static void image_free(SpaceLink *sl)
184 {
185 SpaceImage *simage = (SpaceImage *)sl;
186
187 BKE_scopes_free(&simage->scopes);
188 }
189
190 /* spacetype; init callback, add handlers */
image_init(struct wmWindowManager * UNUSED (wm),ScrArea * area)191 static void image_init(struct wmWindowManager *UNUSED(wm), ScrArea *area)
192 {
193 ListBase *lb = WM_dropboxmap_find("Image", SPACE_IMAGE, 0);
194
195 /* add drop boxes */
196 WM_event_add_dropbox_handler(&area->handlers, lb);
197 }
198
image_duplicate(SpaceLink * sl)199 static SpaceLink *image_duplicate(SpaceLink *sl)
200 {
201 SpaceImage *simagen = MEM_dupallocN(sl);
202
203 /* clear or remove stuff from old */
204
205 BKE_scopes_new(&simagen->scopes);
206
207 return (SpaceLink *)simagen;
208 }
209
image_operatortypes(void)210 static void image_operatortypes(void)
211 {
212 WM_operatortype_append(IMAGE_OT_view_all);
213 WM_operatortype_append(IMAGE_OT_view_pan);
214 WM_operatortype_append(IMAGE_OT_view_selected);
215 WM_operatortype_append(IMAGE_OT_view_center_cursor);
216 WM_operatortype_append(IMAGE_OT_view_zoom);
217 WM_operatortype_append(IMAGE_OT_view_zoom_in);
218 WM_operatortype_append(IMAGE_OT_view_zoom_out);
219 WM_operatortype_append(IMAGE_OT_view_zoom_ratio);
220 WM_operatortype_append(IMAGE_OT_view_zoom_border);
221 #ifdef WITH_INPUT_NDOF
222 WM_operatortype_append(IMAGE_OT_view_ndof);
223 #endif
224
225 WM_operatortype_append(IMAGE_OT_new);
226 WM_operatortype_append(IMAGE_OT_open);
227 WM_operatortype_append(IMAGE_OT_match_movie_length);
228 WM_operatortype_append(IMAGE_OT_replace);
229 WM_operatortype_append(IMAGE_OT_reload);
230 WM_operatortype_append(IMAGE_OT_save);
231 WM_operatortype_append(IMAGE_OT_save_as);
232 WM_operatortype_append(IMAGE_OT_save_sequence);
233 WM_operatortype_append(IMAGE_OT_save_all_modified);
234 WM_operatortype_append(IMAGE_OT_pack);
235 WM_operatortype_append(IMAGE_OT_unpack);
236
237 WM_operatortype_append(IMAGE_OT_invert);
238 WM_operatortype_append(IMAGE_OT_resize);
239
240 WM_operatortype_append(IMAGE_OT_cycle_render_slot);
241 WM_operatortype_append(IMAGE_OT_clear_render_slot);
242 WM_operatortype_append(IMAGE_OT_add_render_slot);
243 WM_operatortype_append(IMAGE_OT_remove_render_slot);
244
245 WM_operatortype_append(IMAGE_OT_sample);
246 WM_operatortype_append(IMAGE_OT_sample_line);
247 WM_operatortype_append(IMAGE_OT_curves_point_set);
248
249 WM_operatortype_append(IMAGE_OT_change_frame);
250
251 WM_operatortype_append(IMAGE_OT_read_viewlayers);
252 WM_operatortype_append(IMAGE_OT_render_border);
253 WM_operatortype_append(IMAGE_OT_clear_render_border);
254
255 WM_operatortype_append(IMAGE_OT_tile_add);
256 WM_operatortype_append(IMAGE_OT_tile_remove);
257 WM_operatortype_append(IMAGE_OT_tile_fill);
258 }
259
image_keymap(struct wmKeyConfig * keyconf)260 static void image_keymap(struct wmKeyConfig *keyconf)
261 {
262 WM_keymap_ensure(keyconf, "Image Generic", SPACE_IMAGE, 0);
263 WM_keymap_ensure(keyconf, "Image", SPACE_IMAGE, 0);
264 }
265
266 /* dropboxes */
image_drop_poll(bContext * C,wmDrag * drag,const wmEvent * event,const char ** UNUSED (r_tooltip))267 static bool image_drop_poll(bContext *C,
268 wmDrag *drag,
269 const wmEvent *event,
270 const char **UNUSED(r_tooltip))
271 {
272 ScrArea *area = CTX_wm_area(C);
273 if (ED_region_overlap_isect_any_xy(area, &event->x)) {
274 return false;
275 }
276 if (drag->type == WM_DRAG_PATH) {
277 /* rule might not work? */
278 if (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE, ICON_FILE_BLANK)) {
279 return true;
280 }
281 }
282 return false;
283 }
284
image_drop_copy(wmDrag * drag,wmDropBox * drop)285 static void image_drop_copy(wmDrag *drag, wmDropBox *drop)
286 {
287 /* copy drag path to properties */
288 RNA_string_set(drop->ptr, "filepath", drag->path);
289 }
290
291 /* area+region dropbox definition */
image_dropboxes(void)292 static void image_dropboxes(void)
293 {
294 ListBase *lb = WM_dropboxmap_find("Image", SPACE_IMAGE, 0);
295
296 WM_dropbox_add(lb, "IMAGE_OT_open", image_drop_poll, image_drop_copy);
297 }
298
299 /**
300 * \note take care not to get into feedback loop here,
301 * calling composite job causes viewer to refresh.
302 */
image_refresh(const bContext * C,ScrArea * area)303 static void image_refresh(const bContext *C, ScrArea *area)
304 {
305 Scene *scene = CTX_data_scene(C);
306 SpaceImage *sima = area->spacedata.first;
307 Image *ima;
308
309 ima = ED_space_image(sima);
310 BKE_image_user_frame_calc(ima, &sima->iuser, scene->r.cfra);
311
312 /* check if we have to set the image from the editmesh */
313 if (ima && (ima->source == IMA_SRC_VIEWER && sima->mode == SI_MODE_MASK)) {
314 if (scene->nodetree) {
315 Mask *mask = ED_space_image_get_mask(sima);
316 if (mask) {
317 ED_node_composite_job(C, scene->nodetree, scene);
318 }
319 }
320 }
321 }
322
image_listener(wmWindow * win,ScrArea * area,wmNotifier * wmn,Scene * UNUSED (scene))323 static void image_listener(wmWindow *win, ScrArea *area, wmNotifier *wmn, Scene *UNUSED(scene))
324 {
325 SpaceImage *sima = (SpaceImage *)area->spacedata.first;
326
327 /* context changes */
328 switch (wmn->category) {
329 case NC_WINDOW:
330 /* notifier comes from editing color space */
331 image_scopes_tag_refresh(area);
332 ED_area_tag_redraw(area);
333 break;
334 case NC_SCENE:
335 switch (wmn->data) {
336 case ND_FRAME:
337 image_scopes_tag_refresh(area);
338 ED_area_tag_refresh(area);
339 ED_area_tag_redraw(area);
340 break;
341 case ND_MODE:
342 if (wmn->subtype == NS_EDITMODE_MESH) {
343 ED_area_tag_refresh(area);
344 }
345 ED_area_tag_redraw(area);
346 break;
347 case ND_RENDER_RESULT:
348 case ND_RENDER_OPTIONS:
349 case ND_COMPO_RESULT:
350 if (ED_space_image_show_render(sima)) {
351 image_scopes_tag_refresh(area);
352 }
353 ED_area_tag_redraw(area);
354 break;
355 }
356 break;
357 case NC_IMAGE:
358 if (wmn->reference == sima->image || !wmn->reference) {
359 if (wmn->action != NA_PAINTING) {
360 image_scopes_tag_refresh(area);
361 ED_area_tag_refresh(area);
362 ED_area_tag_redraw(area);
363 }
364 }
365 break;
366 case NC_SPACE:
367 if (wmn->data == ND_SPACE_IMAGE) {
368 image_scopes_tag_refresh(area);
369 ED_area_tag_redraw(area);
370 }
371 break;
372 case NC_MASK: {
373 ViewLayer *view_layer = WM_window_get_active_view_layer(win);
374 Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
375 if (ED_space_image_check_show_maskedit(sima, obedit)) {
376 switch (wmn->data) {
377 case ND_SELECT:
378 ED_area_tag_redraw(area);
379 break;
380 case ND_DATA:
381 case ND_DRAW:
382 /* causes node-recalc */
383 ED_area_tag_redraw(area);
384 ED_area_tag_refresh(area);
385 break;
386 }
387 switch (wmn->action) {
388 case NA_SELECTED:
389 ED_area_tag_redraw(area);
390 break;
391 case NA_EDITED:
392 /* causes node-recalc */
393 ED_area_tag_redraw(area);
394 ED_area_tag_refresh(area);
395 break;
396 }
397 }
398 break;
399 }
400 case NC_GEOM: {
401 switch (wmn->data) {
402 case ND_DATA:
403 case ND_SELECT:
404 image_scopes_tag_refresh(area);
405 ED_area_tag_refresh(area);
406 ED_area_tag_redraw(area);
407 break;
408 }
409 break;
410 }
411 case NC_OBJECT: {
412 switch (wmn->data) {
413 case ND_TRANSFORM:
414 case ND_MODIFIER: {
415 ViewLayer *view_layer = WM_window_get_active_view_layer(win);
416 Object *ob = OBACT(view_layer);
417 if (ob && (ob == wmn->reference) && (ob->mode & OB_MODE_EDIT)) {
418 if (sima->lock && (sima->flag & SI_DRAWSHADOW)) {
419 ED_area_tag_refresh(area);
420 ED_area_tag_redraw(area);
421 }
422 }
423 break;
424 }
425 }
426
427 break;
428 }
429 case NC_ID: {
430 if (wmn->action == NA_RENAME) {
431 ED_area_tag_redraw(area);
432 }
433 break;
434 }
435 case NC_WM:
436 if (wmn->data == ND_UNDO) {
437 ED_area_tag_redraw(area);
438 ED_area_tag_refresh(area);
439 }
440 break;
441 }
442 }
443
444 const char *image_context_dir[] = {"edit_image", "edit_mask", NULL};
445
image_context(const bContext * C,const char * member,bContextDataResult * result)446 static int /*eContextResult*/ image_context(const bContext *C,
447 const char *member,
448 bContextDataResult *result)
449 {
450 SpaceImage *sima = CTX_wm_space_image(C);
451
452 if (CTX_data_dir(member)) {
453 CTX_data_dir_set(result, image_context_dir);
454 /* TODO(sybren): return CTX_RESULT_OK; */
455 }
456 else if (CTX_data_equals(member, "edit_image")) {
457 CTX_data_id_pointer_set(result, (ID *)ED_space_image(sima));
458 return CTX_RESULT_OK;
459 }
460 else if (CTX_data_equals(member, "edit_mask")) {
461 Mask *mask = ED_space_image_get_mask(sima);
462 if (mask) {
463 CTX_data_id_pointer_set(result, &mask->id);
464 }
465 return CTX_RESULT_OK;
466 }
467 return CTX_RESULT_MEMBER_NOT_FOUND;
468 }
469
IMAGE_GGT_gizmo2d(wmGizmoGroupType * gzgt)470 static void IMAGE_GGT_gizmo2d(wmGizmoGroupType *gzgt)
471 {
472 gzgt->name = "UV Transform Gizmo";
473 gzgt->idname = "IMAGE_GGT_gizmo2d";
474
475 gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP |
476 WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK);
477
478 gzgt->gzmap_params.spaceid = SPACE_IMAGE;
479 gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
480
481 ED_widgetgroup_gizmo2d_xform_callbacks_set(gzgt);
482 }
483
IMAGE_GGT_gizmo2d_translate(wmGizmoGroupType * gzgt)484 static void IMAGE_GGT_gizmo2d_translate(wmGizmoGroupType *gzgt)
485 {
486 gzgt->name = "UV Translate Gizmo";
487 gzgt->idname = "IMAGE_GGT_gizmo2d_translate";
488
489 gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP |
490 WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK);
491
492 gzgt->gzmap_params.spaceid = SPACE_IMAGE;
493 gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
494
495 ED_widgetgroup_gizmo2d_xform_no_cage_callbacks_set(gzgt);
496 }
497
IMAGE_GGT_gizmo2d_resize(wmGizmoGroupType * gzgt)498 static void IMAGE_GGT_gizmo2d_resize(wmGizmoGroupType *gzgt)
499 {
500 gzgt->name = "UV Transform Gizmo Resize";
501 gzgt->idname = "IMAGE_GGT_gizmo2d_resize";
502
503 gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP |
504 WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK);
505
506 gzgt->gzmap_params.spaceid = SPACE_IMAGE;
507 gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
508
509 ED_widgetgroup_gizmo2d_resize_callbacks_set(gzgt);
510 }
511
IMAGE_GGT_gizmo2d_rotate(wmGizmoGroupType * gzgt)512 static void IMAGE_GGT_gizmo2d_rotate(wmGizmoGroupType *gzgt)
513 {
514 gzgt->name = "UV Transform Gizmo Resize";
515 gzgt->idname = "IMAGE_GGT_gizmo2d_rotate";
516
517 gzgt->flag |= (WM_GIZMOGROUPTYPE_TOOL_FALLBACK_KEYMAP |
518 WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK);
519
520 gzgt->gzmap_params.spaceid = SPACE_IMAGE;
521 gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
522
523 ED_widgetgroup_gizmo2d_rotate_callbacks_set(gzgt);
524 }
525
IMAGE_GGT_navigate(wmGizmoGroupType * gzgt)526 static void IMAGE_GGT_navigate(wmGizmoGroupType *gzgt)
527 {
528 VIEW2D_GGT_navigate_impl(gzgt, "IMAGE_GGT_navigate");
529 }
530
image_widgets(void)531 static void image_widgets(void)
532 {
533 wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure(
534 &(const struct wmGizmoMapType_Params){SPACE_IMAGE, RGN_TYPE_WINDOW});
535
536 WM_gizmogrouptype_append(IMAGE_GGT_gizmo2d);
537 WM_gizmogrouptype_append(IMAGE_GGT_gizmo2d_translate);
538 WM_gizmogrouptype_append(IMAGE_GGT_gizmo2d_resize);
539 WM_gizmogrouptype_append(IMAGE_GGT_gizmo2d_rotate);
540
541 WM_gizmogrouptype_append_and_link(gzmap_type, IMAGE_GGT_navigate);
542 }
543
544 /************************** main region ***************************/
545
546 /* sets up the fields of the View2D from zoom and offset */
image_main_region_set_view2d(SpaceImage * sima,ARegion * region)547 static void image_main_region_set_view2d(SpaceImage *sima, ARegion *region)
548 {
549 Image *ima = ED_space_image(sima);
550
551 int width, height;
552 ED_space_image_get_size(sima, &width, &height);
553
554 float w = width;
555 float h = height;
556
557 if (ima) {
558 h *= ima->aspy / ima->aspx;
559 }
560
561 int winx = BLI_rcti_size_x(®ion->winrct) + 1;
562 int winy = BLI_rcti_size_y(®ion->winrct) + 1;
563
564 /* For region overlap, move center so image doesn't overlap header. */
565 const rcti *visible_rect = ED_region_visible_rect(region);
566 const int visible_winy = BLI_rcti_size_y(visible_rect) + 1;
567 int visible_centerx = 0;
568 int visible_centery = visible_rect->ymin + (visible_winy - winy) / 2;
569
570 region->v2d.tot.xmin = 0;
571 region->v2d.tot.ymin = 0;
572 region->v2d.tot.xmax = w;
573 region->v2d.tot.ymax = h;
574
575 region->v2d.mask.xmin = region->v2d.mask.ymin = 0;
576 region->v2d.mask.xmax = winx;
577 region->v2d.mask.ymax = winy;
578
579 /* which part of the image space do we see? */
580 float x1 = region->winrct.xmin + visible_centerx + (winx - sima->zoom * w) / 2.0f;
581 float y1 = region->winrct.ymin + visible_centery + (winy - sima->zoom * h) / 2.0f;
582
583 x1 -= sima->zoom * sima->xof;
584 y1 -= sima->zoom * sima->yof;
585
586 /* relative display right */
587 region->v2d.cur.xmin = ((region->winrct.xmin - (float)x1) / sima->zoom);
588 region->v2d.cur.xmax = region->v2d.cur.xmin + ((float)winx / sima->zoom);
589
590 /* relative display left */
591 region->v2d.cur.ymin = ((region->winrct.ymin - (float)y1) / sima->zoom);
592 region->v2d.cur.ymax = region->v2d.cur.ymin + ((float)winy / sima->zoom);
593
594 /* normalize 0.0..1.0 */
595 region->v2d.cur.xmin /= w;
596 region->v2d.cur.xmax /= w;
597 region->v2d.cur.ymin /= h;
598 region->v2d.cur.ymax /= h;
599 }
600
601 /* add handlers, stuff you only do once or on area/region changes */
image_main_region_init(wmWindowManager * wm,ARegion * region)602 static void image_main_region_init(wmWindowManager *wm, ARegion *region)
603 {
604 wmKeyMap *keymap;
605
606 /* Image space manages own v2d. */
607 // UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_STANDARD, region->winx, region->winy);
608
609 /* mask polls mode */
610 keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0);
611 WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
612
613 /* image paint polls for mode */
614 keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0);
615 WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
616
617 keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0);
618 WM_event_add_keymap_handler(®ion->handlers, keymap);
619
620 keymap = WM_keymap_ensure(wm->defaultconf, "Image Paint", 0, 0);
621 WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
622
623 keymap = WM_keymap_ensure(wm->defaultconf, "UV Editor", 0, 0);
624 WM_event_add_keymap_handler(®ion->handlers, keymap);
625
626 /* own keymaps */
627 keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
628 WM_event_add_keymap_handler(®ion->handlers, keymap);
629 keymap = WM_keymap_ensure(wm->defaultconf, "Image", SPACE_IMAGE, 0);
630 WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap);
631 }
632
image_main_region_draw(const bContext * C,ARegion * region)633 static void image_main_region_draw(const bContext *C, ARegion *region)
634 {
635 /* draw entirely, view changes should be handled here */
636 SpaceImage *sima = CTX_wm_space_image(C);
637 Object *obedit = CTX_data_edit_object(C);
638 Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
639 Mask *mask = NULL;
640 Scene *scene = CTX_data_scene(C);
641 View2D *v2d = ®ion->v2d;
642
643 /* XXX not supported yet, disabling for now */
644 scene->r.scemode &= ~R_COMP_CROP;
645
646 image_user_refresh_scene(C, sima);
647
648 /* we set view2d from own zoom and offset each time */
649 image_main_region_set_view2d(sima, region);
650
651 /* check for mask (delay draw) */
652 if (!ED_space_image_show_uvedit(sima, obedit) && sima->mode == SI_MODE_MASK) {
653 mask = ED_space_image_get_mask(sima);
654 }
655
656 /* we draw image in pixelspace */
657 DRW_draw_view(C);
658 draw_image_main_helpers(C, region);
659
660 /* Draw Meta data of the image isn't added to the DrawManager as it is
661 * used in other areas as well. */
662 if (sima->flag & SI_DRAW_METADATA) {
663 void *lock;
664 /* `ED_space_image_get_zoom` temporarily locks the image, so this needs to be done before
665 * the image is locked when calling `ED_space_image_acquire_buffer`. */
666 float zoomx, zoomy;
667 ED_space_image_get_zoom(sima, region, &zoomx, &zoomy);
668 ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
669 if (ibuf) {
670 int x, y;
671 rctf frame;
672 BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y);
673 UI_view2d_view_to_region(®ion->v2d, 0.0f, 0.0f, &x, &y);
674 ED_region_image_metadata_draw(x, y, ibuf, &frame, zoomx, zoomy);
675 ED_space_image_release_buffer(sima, ibuf, lock);
676 }
677 }
678
679 /* sample line */
680 UI_view2d_view_ortho(v2d);
681 draw_image_sample_line(sima);
682 UI_view2d_view_restore(C);
683
684 if (mask) {
685 Image *image = ED_space_image(sima);
686 int width, height, show_viewer;
687 float aspx, aspy;
688
689 show_viewer = (image && image->source == IMA_SRC_VIEWER);
690
691 if (show_viewer) {
692 /* ED_space_image_get* will acquire image buffer which requires
693 * lock here by the same reason why lock is needed in draw_image_main
694 */
695 BLI_thread_lock(LOCK_DRAW_IMAGE);
696 }
697
698 ED_space_image_get_size(sima, &width, &height);
699 ED_space_image_get_aspect(sima, &aspx, &aspy);
700
701 if (show_viewer) {
702 BLI_thread_unlock(LOCK_DRAW_IMAGE);
703 }
704
705 ED_mask_draw_region(depsgraph,
706 mask,
707 region,
708 sima->mask_info.draw_flag,
709 sima->mask_info.draw_type,
710 sima->mask_info.overlay_mode,
711 width,
712 height,
713 aspx,
714 aspy,
715 true,
716 false,
717 NULL,
718 C);
719 }
720
721 WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
722 draw_image_cache(C, region);
723 }
724
image_main_region_listener(wmWindow * UNUSED (win),ScrArea * area,ARegion * region,wmNotifier * wmn,const Scene * UNUSED (scene))725 static void image_main_region_listener(wmWindow *UNUSED(win),
726 ScrArea *area,
727 ARegion *region,
728 wmNotifier *wmn,
729 const Scene *UNUSED(scene))
730 {
731 /* context changes */
732 switch (wmn->category) {
733 case NC_GEOM:
734 if (ELEM(wmn->data, ND_DATA, ND_SELECT)) {
735 WM_gizmomap_tag_refresh(region->gizmo_map);
736 }
737 break;
738 case NC_GPENCIL:
739 if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
740 ED_region_tag_redraw(region);
741 }
742 else if (wmn->data & ND_GPENCIL_EDITMODE) {
743 ED_region_tag_redraw(region);
744 }
745 break;
746 case NC_IMAGE:
747 if (wmn->action == NA_PAINTING) {
748 ED_region_tag_redraw(region);
749 }
750 WM_gizmomap_tag_refresh(region->gizmo_map);
751 break;
752 case NC_MATERIAL:
753 if (wmn->data == ND_SHADING_LINKS) {
754 SpaceImage *sima = area->spacedata.first;
755
756 if (sima->iuser.scene && (sima->iuser.scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE)) {
757 ED_region_tag_redraw(region);
758 }
759 }
760 break;
761 case NC_SCREEN:
762 if (ELEM(wmn->data, ND_LAYER)) {
763 ED_region_tag_redraw(region);
764 }
765 break;
766 }
767 }
768
769 /* *********************** buttons region ************************ */
770
771 /* add handlers, stuff you only do once or on area/region changes */
image_buttons_region_init(wmWindowManager * wm,ARegion * region)772 static void image_buttons_region_init(wmWindowManager *wm, ARegion *region)
773 {
774 wmKeyMap *keymap;
775
776 region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
777 ED_region_panels_init(wm, region);
778
779 keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
780 WM_event_add_keymap_handler(®ion->handlers, keymap);
781 }
782
image_buttons_region_layout(const bContext * C,ARegion * region)783 static void image_buttons_region_layout(const bContext *C, ARegion *region)
784 {
785 const enum eContextObjectMode mode = CTX_data_mode_enum(C);
786 const char *contexts_base[3] = {NULL};
787
788 const char **contexts = contexts_base;
789
790 SpaceImage *sima = CTX_wm_space_image(C);
791 switch (sima->mode) {
792 case SI_MODE_VIEW:
793 break;
794 case SI_MODE_PAINT:
795 ARRAY_SET_ITEMS(contexts, ".paint_common_2d", ".imagepaint_2d");
796 break;
797 case SI_MODE_MASK:
798 break;
799 case SI_MODE_UV:
800 if (mode == CTX_MODE_EDIT_MESH) {
801 ARRAY_SET_ITEMS(contexts, ".uv_sculpt");
802 }
803 break;
804 }
805
806 ED_region_panels_layout_ex(C, region, ®ion->type->paneltypes, contexts_base, NULL);
807 }
808
image_buttons_region_draw(const bContext * C,ARegion * region)809 static void image_buttons_region_draw(const bContext *C, ARegion *region)
810 {
811 SpaceImage *sima = CTX_wm_space_image(C);
812 Scene *scene = CTX_data_scene(C);
813 void *lock;
814 /* TODO(lukas): Support tiles in scopes? */
815 ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
816 /* XXX performance regression if name of scopes category changes! */
817 PanelCategoryStack *category = UI_panel_category_active_find(region, "Scopes");
818
819 /* only update scopes if scope category is active */
820 if (category) {
821 if (ibuf) {
822 if (!sima->scopes.ok) {
823 BKE_histogram_update_sample_line(
824 &sima->sample_line_hist, ibuf, &scene->view_settings, &scene->display_settings);
825 }
826 if (sima->image->flag & IMA_VIEW_AS_RENDER) {
827 ED_space_image_scopes_update(C, sima, ibuf, true);
828 }
829 else {
830 ED_space_image_scopes_update(C, sima, ibuf, false);
831 }
832 }
833 }
834 ED_space_image_release_buffer(sima, ibuf, lock);
835
836 /* Layout handles details. */
837 ED_region_panels_draw(C, region);
838 }
839
image_buttons_region_listener(wmWindow * UNUSED (win),ScrArea * UNUSED (area),ARegion * region,wmNotifier * wmn,const Scene * UNUSED (scene))840 static void image_buttons_region_listener(wmWindow *UNUSED(win),
841 ScrArea *UNUSED(area),
842 ARegion *region,
843 wmNotifier *wmn,
844 const Scene *UNUSED(scene))
845 {
846 /* context changes */
847 switch (wmn->category) {
848 case NC_TEXTURE:
849 case NC_MATERIAL:
850 /* sending by texture render job and needed to properly update displaying
851 * brush texture icon */
852 ED_region_tag_redraw(region);
853 break;
854 case NC_SCENE:
855 switch (wmn->data) {
856 case ND_MODE:
857 case ND_RENDER_RESULT:
858 case ND_COMPO_RESULT:
859 ED_region_tag_redraw(region);
860 break;
861 }
862 break;
863 case NC_IMAGE:
864 if (wmn->action != NA_PAINTING) {
865 ED_region_tag_redraw(region);
866 }
867 break;
868 case NC_NODE:
869 ED_region_tag_redraw(region);
870 break;
871 case NC_GPENCIL:
872 if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
873 ED_region_tag_redraw(region);
874 }
875 break;
876 case NC_BRUSH:
877 if (wmn->action == NA_EDITED) {
878 ED_region_tag_redraw(region);
879 }
880 break;
881 }
882 }
883
884 /* *********************** scopes region ************************ */
885
886 /* add handlers, stuff you only do once or on area/region changes */
image_tools_region_init(wmWindowManager * wm,ARegion * region)887 static void image_tools_region_init(wmWindowManager *wm, ARegion *region)
888 {
889 wmKeyMap *keymap;
890
891 region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
892 ED_region_panels_init(wm, region);
893
894 keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
895 WM_event_add_keymap_handler(®ion->handlers, keymap);
896 }
897
image_tools_region_draw(const bContext * C,ARegion * region)898 static void image_tools_region_draw(const bContext *C, ARegion *region)
899 {
900 ED_region_panels(C, region);
901 }
902
image_tools_region_listener(wmWindow * UNUSED (win),ScrArea * UNUSED (area),ARegion * region,wmNotifier * wmn,const Scene * UNUSED (scene))903 static void image_tools_region_listener(wmWindow *UNUSED(win),
904 ScrArea *UNUSED(area),
905 ARegion *region,
906 wmNotifier *wmn,
907 const Scene *UNUSED(scene))
908 {
909 /* context changes */
910 switch (wmn->category) {
911 case NC_GPENCIL:
912 if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
913 ED_region_tag_redraw(region);
914 }
915 break;
916 case NC_BRUSH:
917 /* NA_SELECTED is used on brush changes */
918 if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) {
919 ED_region_tag_redraw(region);
920 }
921 break;
922 case NC_SCENE:
923 switch (wmn->data) {
924 case ND_MODE:
925 case ND_RENDER_RESULT:
926 case ND_COMPO_RESULT:
927 ED_region_tag_redraw(region);
928 break;
929 }
930 break;
931 case NC_IMAGE:
932 if (wmn->action != NA_PAINTING) {
933 ED_region_tag_redraw(region);
934 }
935 break;
936 case NC_NODE:
937 ED_region_tag_redraw(region);
938 break;
939 }
940 }
941
942 /************************* header region **************************/
943
944 /* add handlers, stuff you only do once or on area/region changes */
image_header_region_init(wmWindowManager * UNUSED (wm),ARegion * region)945 static void image_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
946 {
947 ED_region_header_init(region);
948 }
949
image_header_region_draw(const bContext * C,ARegion * region)950 static void image_header_region_draw(const bContext *C, ARegion *region)
951 {
952 ScrArea *area = CTX_wm_area(C);
953 SpaceImage *sima = area->spacedata.first;
954
955 image_user_refresh_scene(C, sima);
956
957 ED_region_header(C, region);
958 }
959
image_header_region_listener(wmWindow * UNUSED (win),ScrArea * UNUSED (area),ARegion * region,wmNotifier * wmn,const Scene * UNUSED (scene))960 static void image_header_region_listener(wmWindow *UNUSED(win),
961 ScrArea *UNUSED(area),
962 ARegion *region,
963 wmNotifier *wmn,
964 const Scene *UNUSED(scene))
965 {
966 /* context changes */
967 switch (wmn->category) {
968 case NC_SCENE:
969 switch (wmn->data) {
970 case ND_MODE:
971 case ND_TOOLSETTINGS:
972 ED_region_tag_redraw(region);
973 break;
974 }
975 break;
976 case NC_GEOM:
977 switch (wmn->data) {
978 case ND_DATA:
979 case ND_SELECT:
980 ED_region_tag_redraw(region);
981 break;
982 }
983 break;
984 case NC_BRUSH:
985 if (wmn->action == NA_EDITED) {
986 ED_region_tag_redraw(region);
987 }
988 break;
989 }
990 }
991
image_id_remap(ScrArea * UNUSED (area),SpaceLink * slink,ID * old_id,ID * new_id)992 static void image_id_remap(ScrArea *UNUSED(area), SpaceLink *slink, ID *old_id, ID *new_id)
993 {
994 SpaceImage *simg = (SpaceImage *)slink;
995
996 if (!ELEM(GS(old_id->name), ID_IM, ID_GD, ID_MSK)) {
997 return;
998 }
999
1000 if ((ID *)simg->image == old_id) {
1001 simg->image = (Image *)new_id;
1002 id_us_ensure_real(new_id);
1003 }
1004
1005 if ((ID *)simg->gpd == old_id) {
1006 simg->gpd = (bGPdata *)new_id;
1007 id_us_min(old_id);
1008 id_us_plus(new_id);
1009 }
1010
1011 if ((ID *)simg->mask_info.mask == old_id) {
1012 simg->mask_info.mask = (Mask *)new_id;
1013 id_us_ensure_real(new_id);
1014 }
1015 }
1016
1017 /**
1018 * \note Used for splitting out a subset of modes is more involved,
1019 * The previous non-uv-edit mode is stored so switching back to the
1020 * image doesn't always reset the sub-mode.
1021 */
image_space_subtype_get(ScrArea * area)1022 static int image_space_subtype_get(ScrArea *area)
1023 {
1024 SpaceImage *sima = area->spacedata.first;
1025 return sima->mode == SI_MODE_UV ? SI_MODE_UV : SI_MODE_VIEW;
1026 }
1027
image_space_subtype_set(ScrArea * area,int value)1028 static void image_space_subtype_set(ScrArea *area, int value)
1029 {
1030 SpaceImage *sima = area->spacedata.first;
1031 if (value == SI_MODE_UV) {
1032 if (sima->mode != SI_MODE_UV) {
1033 sima->mode_prev = sima->mode;
1034 }
1035 sima->mode = value;
1036 }
1037 else {
1038 sima->mode = sima->mode_prev;
1039 }
1040 }
1041
image_space_subtype_item_extend(bContext * UNUSED (C),EnumPropertyItem ** item,int * totitem)1042 static void image_space_subtype_item_extend(bContext *UNUSED(C),
1043 EnumPropertyItem **item,
1044 int *totitem)
1045 {
1046 RNA_enum_items_add(item, totitem, rna_enum_space_image_mode_items);
1047 }
1048
1049 /**************************** spacetype *****************************/
1050
1051 /* only called once, from space/spacetypes.c */
ED_spacetype_image(void)1052 void ED_spacetype_image(void)
1053 {
1054 SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype image");
1055 ARegionType *art;
1056
1057 st->spaceid = SPACE_IMAGE;
1058 strncpy(st->name, "Image", BKE_ST_MAXNAME);
1059
1060 st->create = image_create;
1061 st->free = image_free;
1062 st->init = image_init;
1063 st->duplicate = image_duplicate;
1064 st->operatortypes = image_operatortypes;
1065 st->keymap = image_keymap;
1066 st->dropboxes = image_dropboxes;
1067 st->refresh = image_refresh;
1068 st->listener = image_listener;
1069 st->context = image_context;
1070 st->gizmos = image_widgets;
1071 st->id_remap = image_id_remap;
1072 st->space_subtype_item_extend = image_space_subtype_item_extend;
1073 st->space_subtype_get = image_space_subtype_get;
1074 st->space_subtype_set = image_space_subtype_set;
1075
1076 /* regions: main window */
1077 art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
1078 art->regionid = RGN_TYPE_WINDOW;
1079 art->keymapflag = ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
1080 art->init = image_main_region_init;
1081 art->draw = image_main_region_draw;
1082 art->listener = image_main_region_listener;
1083 BLI_addhead(&st->regiontypes, art);
1084
1085 /* regions: listview/buttons/scopes */
1086 art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
1087 art->regionid = RGN_TYPE_UI;
1088 art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
1089 art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1090 art->listener = image_buttons_region_listener;
1091 art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
1092 art->init = image_buttons_region_init;
1093 art->layout = image_buttons_region_layout;
1094 art->draw = image_buttons_region_draw;
1095 BLI_addhead(&st->regiontypes, art);
1096
1097 ED_uvedit_buttons_register(art);
1098 image_buttons_register(art);
1099
1100 /* regions: tool(bar) */
1101 art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
1102 art->regionid = RGN_TYPE_TOOLS;
1103 art->prefsizex = 58; /* XXX */
1104 art->prefsizey = 50; /* XXX */
1105 art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
1106 art->listener = image_tools_region_listener;
1107 art->message_subscribe = ED_region_generic_tools_region_message_subscribe;
1108 art->snap_size = ED_region_generic_tools_region_snap_size;
1109 art->init = image_tools_region_init;
1110 art->draw = image_tools_region_draw;
1111 BLI_addhead(&st->regiontypes, art);
1112
1113 /* regions: tool header */
1114 art = MEM_callocN(sizeof(ARegionType), "spacetype image tool header region");
1115 art->regionid = RGN_TYPE_TOOL_HEADER;
1116 art->prefsizey = HEADERY;
1117 art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
1118 art->listener = image_header_region_listener;
1119 art->init = image_header_region_init;
1120 art->draw = image_header_region_draw;
1121 art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_header;
1122 BLI_addhead(&st->regiontypes, art);
1123
1124 /* regions: header */
1125 art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
1126 art->regionid = RGN_TYPE_HEADER;
1127 art->prefsizey = HEADERY;
1128 art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
1129 art->listener = image_header_region_listener;
1130 art->init = image_header_region_init;
1131 art->draw = image_header_region_draw;
1132
1133 BLI_addhead(&st->regiontypes, art);
1134
1135 /* regions: hud */
1136 art = ED_area_type_hud(st->spaceid);
1137 BLI_addhead(&st->regiontypes, art);
1138
1139 BKE_spacetype_register(st);
1140 }
1141