LEFT | RIGHT |
1 /* | 1 /* |
2 * ***** BEGIN GPL LICENSE BLOCK ***** | 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
3 * | 3 * |
4 * This program is free software; you can redistribute it and/or | 4 * This program is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU General Public License | 5 * modify it under the terms of the GNU General Public License |
6 * as published by the Free Software Foundation; either version 2 | 6 * as published by the Free Software Foundation; either version 2 |
7 * of the License, or (at your option) any later version. | 7 * of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 #include "UI_resources.h" | 75 #include "UI_resources.h" |
76 #include "UI_view2d.h" | 76 #include "UI_view2d.h" |
77 | 77 |
78 #include "WM_api.h" | 78 #include "WM_api.h" |
79 #include "WM_types.h" | 79 #include "WM_types.h" |
80 | 80 |
81 #include "image_intern.h" | 81 #include "image_intern.h" |
82 | 82 |
83 /******************** view navigation utilities *********************/ | 83 /******************** view navigation utilities *********************/ |
84 | 84 |
85 static void sima_zoom_set(SpaceImage *sima, ARegion *ar, float zoom) | 85 static void sima_zoom_set(SpaceImage *sima, ARegion *ar, float zoom, float locat
ion[2]) |
86 { | 86 { |
87 » float oldzoom= sima->zoom; | 87 » float oldzoom = sima->zoom; |
88 int width, height; | 88 int width, height; |
89 | 89 |
90 » sima->zoom= zoom; | 90 » sima->zoom = zoom; |
91 | 91 |
92 » if (sima->zoom > 0.1f && sima->zoom < 4.0f) | 92 » if (sima->zoom < 0.1f || sima->zoom > 4.0f) { |
93 » » return; | 93 » » /* check zoom limits */ |
| 94 » » ED_space_image_size(sima, &width, &height); |
94 | 95 |
95 » /* check zoom limits */ | 96 » » width *= sima->zoom; |
96 » ED_space_image_size(sima, &width, &height); | 97 » » height *= sima->zoom; |
97 | 98 |
98 » width *= sima->zoom; | 99 » » if ((width < 4) && (height < 4)) |
99 » height *= sima->zoom; | 100 » » » sima->zoom = oldzoom; |
| 101 » » else if ((ar->winrct.xmax - ar->winrct.xmin) <= sima->zoom) |
| 102 » » » sima->zoom = oldzoom; |
| 103 » » else if ((ar->winrct.ymax - ar->winrct.ymin) <= sima->zoom) |
| 104 » » » sima->zoom = oldzoom; |
| 105 » } |
100 | 106 |
101 » if((width < 4) && (height < 4)) | 107 » if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) && location) { |
102 » » sima->zoom= oldzoom; | 108 » » float aspx, aspy, w, h; |
103 » else if((ar->winrct.xmax - ar->winrct.xmin) <= sima->zoom) | 109 |
104 » » sima->zoom= oldzoom; | 110 » » ED_space_image_size(sima, &width, &height); |
105 » else if((ar->winrct.ymax - ar->winrct.ymin) <= sima->zoom) | 111 » » ED_space_image_aspect(sima, &aspx, &aspy); |
106 » » sima->zoom= oldzoom; | 112 |
| 113 » » w = width * aspx; |
| 114 » » h = height * aspy; |
| 115 |
| 116 » » sima->xof += ((location[0] - 0.5f) * w - sima->xof) * (sima->zoo
m - oldzoom) / sima->zoom; |
| 117 » » sima->yof += ((location[1] - 0.5f) * h - sima->yof) * (sima->zoo
m - oldzoom) / sima->zoom; |
| 118 » } |
107 } | 119 } |
108 | 120 |
109 static void sima_zoom_set_factor(SpaceImage *sima, ARegion *ar, float zoomfac) | 121 static void sima_zoom_set_factor(SpaceImage *sima, ARegion *ar, float zoomfac, f
loat location[2]) |
110 { | 122 { |
111 » sima_zoom_set(sima, ar, sima->zoom*zoomfac); | 123 » sima_zoom_set(sima, ar, sima->zoom * zoomfac, location); |
112 } | 124 } |
113 | 125 |
114 #if 0 // currently unused | 126 #if 0 // currently unused |
115 static int image_poll(bContext *C) | 127 static int image_poll(bContext *C) |
116 { | 128 { |
117 return (CTX_data_edit_image(C) != NULL); | 129 return (CTX_data_edit_image(C) != NULL); |
118 } | 130 } |
119 #endif | 131 #endif |
120 | 132 |
121 static int space_image_buffer_exists_poll(bContext *C) | 133 static int space_image_buffer_exists_poll(bContext *C) |
122 { | 134 { |
123 » SpaceImage *sima= CTX_wm_space_image(C); | 135 » SpaceImage *sima = CTX_wm_space_image(C); |
124 » if(sima && sima->spacetype==SPACE_IMAGE) | 136 » if (sima && sima->spacetype == SPACE_IMAGE) |
125 » » if(ED_space_image_has_buffer(sima)) | 137 » » if (ED_space_image_has_buffer(sima)) |
126 return 1; | 138 return 1; |
127 return 0; | 139 return 0; |
128 } | 140 } |
129 | 141 |
130 static int space_image_file_exists_poll(bContext *C) | 142 static int space_image_file_exists_poll(bContext *C) |
131 { | 143 { |
132 » if(space_image_buffer_exists_poll(C)) { | 144 » if (space_image_buffer_exists_poll(C)) { |
133 » » Main *bmain= CTX_data_main(C); | 145 » » Main *bmain = CTX_data_main(C); |
134 » » SpaceImage *sima= CTX_wm_space_image(C); | 146 » » SpaceImage *sima = CTX_wm_space_image(C); |
135 ImBuf *ibuf; | 147 ImBuf *ibuf; |
136 void *lock; | 148 void *lock; |
137 » » int ret= FALSE; | 149 » » int ret = FALSE; |
138 char name[FILE_MAX]; | 150 char name[FILE_MAX]; |
139 | 151 |
140 » » ibuf= ED_space_image_acquire_buffer(sima, &lock); | 152 » » ibuf = ED_space_image_acquire_buffer(sima, &lock); |
141 » » if(ibuf) { | 153 » » if (ibuf) { |
142 BLI_strncpy(name, ibuf->name, FILE_MAX); | 154 BLI_strncpy(name, ibuf->name, FILE_MAX); |
143 BLI_path_abs(name, bmain->name); | 155 BLI_path_abs(name, bmain->name); |
144 | 156 |
145 » » » if(BLI_exists(name) == FALSE) { | 157 » » » if (BLI_exists(name) == FALSE) { |
146 CTX_wm_operator_poll_msg_set(C, "image file not
found"); | 158 CTX_wm_operator_poll_msg_set(C, "image file not
found"); |
147 } | 159 } |
148 else if (BLI_file_is_writable(name) == FALSE) { | 160 else if (BLI_file_is_writable(name) == FALSE) { |
149 CTX_wm_operator_poll_msg_set(C, "image path can'
t be written to"); | 161 CTX_wm_operator_poll_msg_set(C, "image path can'
t be written to"); |
150 } | 162 } |
151 else { | 163 else { |
152 » » » » ret= TRUE; | 164 » » » » ret = TRUE; |
153 } | 165 } |
154 } | 166 } |
155 ED_space_image_release_buffer(sima, lock); | 167 ED_space_image_release_buffer(sima, lock); |
156 | 168 |
157 return ret; | 169 return ret; |
158 } | 170 } |
159 return 0; | 171 return 0; |
160 } | 172 } |
161 | 173 |
162 static int space_image_poll(bContext *C) | 174 static int space_image_poll(bContext *C) |
163 { | 175 { |
164 » SpaceImage *sima= CTX_wm_space_image(C); | 176 » SpaceImage *sima = CTX_wm_space_image(C); |
165 » if(sima && sima->spacetype==SPACE_IMAGE && sima->image) | 177 » if (sima && sima->spacetype == SPACE_IMAGE && sima->image) |
166 » » return 1; | |
167 return 0; | 178 return 0; |
168 } | 179 } |
169 | 180 |
170 int space_image_main_area_poll(bContext *C) | |
171 { | |
172 SpaceImage *sima= CTX_wm_space_image(C); | |
173 // XXX ARegion *ar= CTX_wm_region(C); | |
174 | |
175 if(sima) | |
176 return 1; // XXX (ar && ar->type->regionid == RGN_TYPE_WINDOW); | |
177 ········ | |
178 return 0; | |
179 } | |
180 | |
181 /* For IMAGE_OT_curves_point_set to avoid sampling when in uv smooth mode */ | |
182 int space_image_main_area_not_uv_brush_poll(bContext *C) | |
183 { | |
184 SpaceImage *sima= CTX_wm_space_image(C); | |
185 | |
186 ToolSettings *toolsettings = CTX_data_scene(C)->toolsettings; | |
187 if(sima && !toolsettings->uvsculpt) | |
188 return 1; | |
189 | |
190 return 0; | |
191 } | |
192 | |
193 static int space_image_image_sample_poll(bContext *C) | |
194 { | |
195 SpaceImage *sima= CTX_wm_space_image(C); | |
196 Object *obedit= CTX_data_edit_object(C); | |
197 ToolSettings *toolsettings = CTX_data_scene(C)->toolsettings; | |
198 | |
199 if(obedit){ | |
200 if(ED_space_image_show_uvedit(sima, obedit) && (toolsettings->us
e_uv_sculpt)) | |
201 return 0; | |
202 } | |
203 return space_image_main_area_poll(C); | |
204 } | |
205 /********************** view pan operator *********************/ | 181 /********************** view pan operator *********************/ |
206 | 182 |
207 typedef struct ViewPanData { | 183 typedef struct ViewPanData { |
208 float x, y; | |
209 float xof, yof; | |
210 int event_type; | |
211 } ViewPanData; | |
212 | |
213 static void image_view_pan_init(bContext *C, wmOperator *op, wmEvent *event) | |
214 { | |
215 SpaceImage *sima= CTX_wm_space_image(C); | |
216 ViewPanData *vpd; | |
217 | |
218 op->customdata= vpd= MEM_callocN(sizeof(ViewPanData), "ImageViewPanData"
); | |
219 WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR); | |
220 | |
221 vpd->x= event->x; | |
222 vpd->y= event->y; | |
223 vpd->xof= sima->xof; | |
224 vpd->yof= sima->yof; | |
225 vpd->event_type= event->type; | |
226 | |
227 WM_event_add_modal_handler(C, op); | |
228 } | |
229 | |
230 static void image_view_pan_exit(bContext *C, wmOperator *op, int cancel) | |
231 { | |
232 SpaceImage *sima= CTX_wm_space_image(C); | |
233 ViewPanData *vpd= op->customdata; | |
234 | |
235 if(cancel) { | |
236 sima->xof= vpd->xof; | |
237 sima->yof= vpd->yof; | |
238 ED_region_tag_redraw(CTX_wm_region(C)); | |
239 } | |
240 | |
241 WM_cursor_restore(CTX_wm_window(C)); | |
242 MEM_freeN(op->customdata); | |
243 } | |
244 | |
245 static int image_view_pan_exec(bContext *C, wmOperator *op) | |
246 { | |
247 SpaceImage *sima= CTX_wm_space_image(C); | |
248 float offset[2]; | |
249 | |
250 RNA_float_get_array(op->ptr, "offset", offset); | |
251 sima->xof += offset[0]; | |
252 sima->yof += offset[1]; | |
253 | |
254 ED_region_tag_redraw(CTX_wm_region(C)); | |
255 | |
256 /* XXX notifier? */ | |
257 #if 0 | |
258 if(image_preview_active(curarea, NULL, NULL)) { | |
259 /* recalculates new preview rect */ | |
260 scrarea_do_windraw(curarea); | |
261 image_preview_event(2); | |
262 } | |
263 #endif | |
264 ········ | |
265 return OPERATOR_FINISHED; | |
266 } | |
267 | |
268 static int image_view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
269 { | |
270 if (event->type == MOUSEPAN) { | |
271 SpaceImage *sima= CTX_wm_space_image(C); | |
272 float offset[2]; | |
273 ················ | |
274 offset[0]= (event->x - event->prevx)/sima->zoom; | |
275 offset[1]= (event->y - event->prevy)/sima->zoom; | |
276 RNA_float_set_array(op->ptr, "offset", offset); | |
277 | |
278 image_view_pan_exec(C, op); | |
279 return OPERATOR_FINISHED; | |
280 } | |
281 else { | |
282 image_view_pan_init(C, op, event); | |
283 return OPERATOR_RUNNING_MODAL; | |
284 } | |
285 } | |
286 | |
287 static int image_view_pan_modal(bContext *C, wmOperator *op, wmEvent *event) | |
288 { | |
289 SpaceImage *sima= CTX_wm_space_image(C); | |
290 ViewPanData *vpd= op->customdata; | |
291 float offset[2]; | |
292 | |
293 switch(event->type) { | |
294 case MOUSEMOVE: | |
295 sima->xof= vpd->xof; | |
296 sima->yof= vpd->yof; | |
297 offset[0]= (vpd->x - event->x)/sima->zoom; | |
298 offset[1]= (vpd->y - event->y)/sima->zoom; | |
299 RNA_float_set_array(op->ptr, "offset", offset); | |
300 image_view_pan_exec(C, op); | |
301 break; | |
302 default: | |
303 if(event->type==vpd->event_type && event->val==KM_RELEA
SE) { | |
304 image_view_pan_exit(C, op, 0); | |
305 return OPERATOR_FINISHED; | |
306 } | |
307 break; | |
308 } | |
309 | |
310 return OPERATOR_RUNNING_MODAL; | |
311 } | |
312 | |
313 static int image_view_pan_cancel(bContext *C, wmOperator *op) | |
314 { | |
315 image_view_pan_exit(C, op, 1); | |
316 return OPERATOR_CANCELLED; | |
317 } | |
318 | |
319 void IMAGE_OT_view_pan(wmOperatorType *ot) | |
320 { | |
321 /* identifiers */ | |
322 ot->name= "View Pan"; | |
323 ot->idname= "IMAGE_OT_view_pan"; | |
324 ········ | |
325 /* api callbacks */ | |
326 ot->exec= image_view_pan_exec; | |
327 ot->invoke= image_view_pan_invoke; | |
328 ot->modal= image_view_pan_modal; | |
329 ot->cancel= image_view_pan_cancel; | |
330 ot->poll= space_image_main_area_poll; | |
331 | |
332 /* flags */ | |
333 ot->flag= OPTYPE_BLOCKING; | |
334 ········ | |
335 /* properties */ | |
336 RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX, | |
337 "Offset", "Offset in floating point units, 1.0 is the width and
height of the image", -FLT_MAX, FLT_MAX); | |
338 } | |
339 | |
340 /********************** view zoom operator *********************/ | |
341 | |
342 typedef struct ViewZoomData { | |
343 float x, y; | |
344 float zoom; | |
345 int event_type; | |
346 } ViewZoomData; | |
347 | |
348 static void image_view_zoom_init(bContext *C, wmOperator *op, wmEvent *event) | |
349 { | |
350 SpaceImage *sima= CTX_wm_space_image(C); | |
351 ViewZoomData *vpd; | |
352 | |
353 op->customdata= vpd= MEM_callocN(sizeof(ViewZoomData), "ImageViewZoomDat
a"); | |
354 WM_cursor_modal(CTX_wm_window(C), BC_NSEW_SCROLLCURSOR); | |
355 | |
356 vpd->x= event->x; | |
357 vpd->y= event->y; | |
358 vpd->zoom= sima->zoom; | |
359 vpd->event_type= event->type; | |
360 ········ | |
361 WM_event_add_modal_handler(C, op); | |
362 } | |
363 | |
364 static void image_view_zoom_exit(bContext *C, wmOperator *op, int cancel) | |
365 { | |
366 SpaceImage *sima= CTX_wm_space_image(C); | |
367 ViewZoomData *vpd= op->customdata; | |
368 | |
369 if(cancel) { | |
370 sima->zoom= vpd->zoom; | |
371 ED_region_tag_redraw(CTX_wm_region(C)); | |
372 } | |
373 | |
374 WM_cursor_restore(CTX_wm_window(C)); | |
375 MEM_freeN(op->customdata); | |
376 } | |
377 | |
378 static int image_view_zoom_exec(bContext *C, wmOperator *op) | |
379 { | |
380 SpaceImage *sima= CTX_wm_space_image(C); | |
381 ARegion *ar= CTX_wm_region(C); | |
382 | |
383 sima_zoom_set_factor(sima, ar, RNA_float_get(op->ptr, "factor")); | |
384 | |
385 ED_region_tag_redraw(CTX_wm_region(C)); | |
386 | |
387 /* XXX notifier? */ | |
388 #if 0 | |
389 if(image_preview_active(curarea, NULL, NULL)) { | |
390 /* recalculates new preview rect */ | |
391 scrarea_do_windraw(curarea); | |
392 image_preview_event(2); | |
393 } | |
394 #endif | |
395 ········ | |
396 return OPERATOR_FINISHED; | |
397 } | |
398 | |
399 static int image_view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
400 { | |
401 if (event->type == MOUSEZOOM) { | |
402 SpaceImage *sima= CTX_wm_space_image(C); | |
403 ARegion *ar= CTX_wm_region(C); | |
404 float factor; | |
405 ················ | |
406 factor= 1.0f + (event->x-event->prevx+event->y-event->prevy)/300
.0f; | |
407 RNA_float_set(op->ptr, "factor", factor); | |
408 sima_zoom_set(sima, ar, sima->zoom*factor); | |
409 ED_region_tag_redraw(CTX_wm_region(C)); | |
410 ················ | |
411 return OPERATOR_FINISHED; | |
412 } | |
413 else { | |
414 image_view_zoom_init(C, op, event); | |
415 return OPERATOR_RUNNING_MODAL; | |
416 } | |
417 } | |
418 | |
419 static int image_view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event) | |
420 { | |
421 SpaceImage *sima= CTX_wm_space_image(C); | |
422 ARegion *ar= CTX_wm_region(C); | |
423 ViewZoomData *vpd= op->customdata; | |
424 float factor; | |
425 | |
426 switch(event->type) { | |
427 case MOUSEMOVE: | |
428 factor= 1.0f + (vpd->x-event->x+vpd->y-event->y)/300.0f; | |
429 RNA_float_set(op->ptr, "factor", factor); | |
430 sima_zoom_set(sima, ar, vpd->zoom*factor); | |
431 ED_region_tag_redraw(CTX_wm_region(C)); | |
432 break; | |
433 default: | |
434 if(event->type==vpd->event_type && event->val==KM_RELEAS
E) { | |
435 image_view_zoom_exit(C, op, 0); | |
436 return OPERATOR_FINISHED; | |
437 } | |
438 break; | |
439 } | |
440 | |
441 return OPERATOR_RUNNING_MODAL; | |
442 } | |
443 | |
444 static int image_view_zoom_cancel(bContext *C, wmOperator *op) | |
445 { | |
446 image_view_zoom_exit(C, op, 1); | |
447 return OPERATOR_CANCELLED; | |
448 } | |
449 | |
450 void IMAGE_OT_view_zoom(wmOperatorType *ot) | |
451 { | |
452 /* identifiers */ | |
453 ot->name= "View Zoom"; | |
454 ot->idname= "IMAGE_OT_view_zoom"; | |
455 ········ | |
456 /* api callbacks */ | |
457 ot->exec= image_view_zoom_exec; | |
458 ot->invoke= image_view_zoom_invoke; | |
459 ot->modal= image_view_zoom_modal; | |
460 ot->cancel= image_view_zoom_cancel; | |
461 ot->poll= space_image_main_area_poll; | |
462 | |
463 /* flags */ | |
464 ot->flag= OPTYPE_BLOCKING; | |
465 ········ | |
466 /* properties */ | |
467 RNA_def_float(ot->srna, "factor", 0.0f, 0.0f, FLT_MAX, | |
468 "Factor", "Zoom factor, values higher than 1.0 zoom in, lower va
lues zoom out", -FLT_MAX, FLT_MAX); | |
469 } | |
470 | |
471 /********************** NDOF operator *********************/ | |
472 | |
473 /* Combined pan/zoom from a 3D mouse device. | |
474 * Z zooms, XY pans | |
475 * "view" (not "paper") control -- user moves the viewpoint, not the image being
viewed | |
476 * that explains the negative signs in the code below | |
477 */ | |
478 | |
479 static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *
event) | |
480 { | |
481 if (event->type != NDOF_MOTION) | |
482 return OPERATOR_CANCELLED; | |
483 else { | |
484 SpaceImage *sima= CTX_wm_space_image(C); | |
485 ARegion *ar= CTX_wm_region(C); | |
486 | |
487 wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; | |
488 | |
489 float dt = ndof->dt; | |
490 /* tune these until it feels right */ | |
491 const float zoom_sensitivity = 0.5f; // 50% per second (I think) | |
492 const float pan_sensitivity = 300.f; // screen pixels per second | |
493 | |
494 float pan_x = pan_sensitivity * dt * ndof->tvec[0] / sima->zoom; | |
495 float pan_y = pan_sensitivity * dt * ndof->tvec[1] / sima->zoom; | |
496 | |
497 /* "mouse zoom" factor = 1 + (dx + dy) / 300 | |
498 * what about "ndof zoom" factor? should behave like this: | |
499 * at rest -> factor = 1 | |
500 * move forward -> factor > 1 | |
501 * move backward -> factor < 1 | |
502 */ | |
503 float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->tvec[2]
; | |
504 | |
505 if (U.ndof_flag & NDOF_ZOOM_INVERT) | |
506 zoom_factor = -zoom_factor; | |
507 | |
508 sima_zoom_set_factor(sima, ar, zoom_factor); | |
509 sima->xof += pan_x; | |
510 sima->yof += pan_y; | |
511 | |
512 ED_region_tag_redraw(ar);······· | |
513 | |
514 return OPERATOR_FINISHED; | |
515 } | |
516 } | |
517 | |
518 void IMAGE_OT_view_ndof(wmOperatorType *ot) | |
519 { | |
520 /* identifiers */ | |
521 ot->name= "NDOF Pan/Zoom"; | |
522 ot->idname= "IMAGE_OT_view_ndof"; | |
523 ········ | |
524 /* api callbacks */ | |
525 ot->invoke= image_view_ndof_invoke; | |
526 } | |
527 | |
528 /********************** view all operator *********************/ | |
529 | |
530 /* Updates the fields of the View2D member of the SpaceImage struct. | |
531 * Default behavior is to reset the position of the image and set the zoom to 1 | |
532 * If the image will not fit within the window rectangle, the zoom is adjusted *
/ | |
533 | |
534 static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op)) | |
535 { | |
536 SpaceImage *sima; | |
537 ARegion *ar; | |
538 float aspx, aspy, zoomx, zoomy, w, h; | |
539 int width, height; | |
540 | |
541 /* retrieve state */ | |
542 sima= CTX_wm_space_image(C); | |
543 ar= CTX_wm_region(C); | |
544 | |
545 ED_space_image_size(sima, &width, &height); | |
546 ED_space_image_aspect(sima, &aspx, &aspy); | |
547 | |
548 w= width*aspx; | |
549 h= height*aspy; | |
550 ········ | |
551 /* check if the image will fit in the image with zoom==1 */ | |
552 width = ar->winrct.xmax - ar->winrct.xmin + 1; | |
553 height = ar->winrct.ymax - ar->winrct.ymin + 1; | |
554 | |
555 if((w >= width || h >= height) && (width > 0 && height > 0)) { | |
556 /* find the zoom value that will fit the image in the image spac
e */ | |
557 zoomx= width/w; | |
558 zoomy= height/h; | |
559 sima_zoom_set(sima, ar, 1.0f/power_of_2(1/MIN2(zoomx, zoomy))); | |
560 } | |
561 else | |
562 sima_zoom_set(sima, ar, 1.0f); | |
563 | |
564 sima->xof= sima->yof= 0.0f; | |
565 | |
566 ED_region_tag_redraw(CTX_wm_region(C)); | |
567 ········ | |
568 return OPERATOR_FINISHED; | |
569 } | |
570 | |
571 void IMAGE_OT_view_all(wmOperatorType *ot) | |
572 { | |
573 /* identifiers */ | |
574 ot->name= "View All"; | |
575 ot->idname= "IMAGE_OT_view_all"; | |
576 ········ | |
577 /* api callbacks */ | |
578 ot->exec= image_view_all_exec; | |
579 ot->poll= space_image_main_area_poll; | |
580 } | |
581 | |
582 /********************** view selected operator *********************/ | |
583 | |
584 static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) | |
585 { | |
586 SpaceImage *sima; | |
587 ARegion *ar; | |
588 Scene *scene; | |
589 Object *obedit; | |
590 Image *ima; | |
591 float size, min[2], max[2], d[2], aspx, aspy; | |
592 int width, height; | |
593 | |
594 /* retrieve state */ | |
595 sima= CTX_wm_space_image(C); | |
596 ar= CTX_wm_region(C); | |
597 scene= (Scene*)CTX_data_scene(C); | |
598 obedit= CTX_data_edit_object(C); | |
599 | |
600 ima= ED_space_image(sima); | |
601 ED_space_image_size(sima, &width, &height); | |
602 ED_image_aspect(ima, &aspx, &aspy); | |
603 | |
604 width= width*aspx; | |
605 height= height*aspy; | |
606 | |
607 /* get bounds */ | |
608 if(!ED_uvedit_minmax(scene, ima, obedit, min, max)) | |
609 return OPERATOR_CANCELLED; | |
610 | |
611 /* adjust offset and zoom */ | |
612 sima->xof= (int)(((min[0] + max[0])*0.5f - 0.5f)*width); | |
613 sima->yof= (int)(((min[1] + max[1])*0.5f - 0.5f)*height); | |
614 | |
615 d[0]= max[0] - min[0]; | |
616 d[1]= max[1] - min[1]; | |
617 size= 0.5f*MAX2(d[0], d[1])*MAX2(width, height)/256.0f; | |
618 ········ | |
619 if(size<=0.01f) size= 0.01f; | |
620 sima_zoom_set(sima, ar, 0.7f/size); | |
621 | |
622 ED_region_tag_redraw(CTX_wm_region(C)); | |
623 ········ | |
624 return OPERATOR_FINISHED; | |
625 } | |
626 | |
627 static int image_view_selected_poll(bContext *C) | |
628 { | |
629 return (space_image_main_area_poll(C) && ED_operator_uvedit(C)); | |
630 } | |
631 | |
632 void IMAGE_OT_view_selected(wmOperatorType *ot) | |
633 { | |
634 /* identifiers */ | |
635 ot->name= "View Center"; | |
636 ot->idname= "IMAGE_OT_view_selected"; | |
637 ········ | |
638 /* api callbacks */ | |
639 ot->exec= image_view_selected_exec; | |
640 ot->poll= image_view_selected_poll; | |
641 } | |
642 | |
643 /********************** view zoom in/out operator *********************/ | |
644 | |
645 static int image_view_zoom_in_exec(bContext *C, wmOperator *UNUSED(op)) | |
646 { | |
647 SpaceImage *sima= CTX_wm_space_image(C); | |
648 ARegion *ar= CTX_wm_region(C); | |
649 | |
650 sima_zoom_set_factor(sima, ar, 1.25f); | |
651 | |
652 ED_region_tag_redraw(CTX_wm_region(C)); | |
653 ········ | |
654 return OPERATOR_FINISHED; | |
655 } | |
656 | |
657 void IMAGE_OT_view_zoom_in(wmOperatorType *ot) | |
658 { | |
659 /* identifiers */ | |
660 ot->name= "View Zoom In"; | |
661 ot->idname= "IMAGE_OT_view_zoom_in"; | |
662 ········ | |
663 /* api callbacks */ | |
664 ot->exec= image_view_zoom_in_exec; | |
665 ot->poll= space_image_main_area_poll; | |
666 } | |
667 | |
668 static int image_view_zoom_out_exec(bContext *C, wmOperator *UNUSED(op)) | |
669 { | |
670 SpaceImage *sima= CTX_wm_space_image(C); | |
671 ARegion *ar= CTX_wm_region(C); | |
672 | |
673 sima_zoom_set_factor(sima, ar, 0.8f); | |
674 | |
675 ED_region_tag_redraw(CTX_wm_region(C)); | |
676 ········ | |
677 return OPERATOR_FINISHED; | |
678 } | |
679 | |
680 void IMAGE_OT_view_zoom_out(wmOperatorType *ot) | |
681 { | |
682 /* identifiers */ | |
683 ot->name= "View Zoom Out"; | |
684 ot->idname= "IMAGE_OT_view_zoom_out"; | |
685 ········ | |
686 /* api callbacks */ | |
687 ot->exec= image_view_zoom_out_exec; | |
688 ot->poll= space_image_main_area_poll; | |
689 } | |
690 | |
691 /********************** view zoom ratio operator *********************/ | |
692 | |
693 static int image_view_zoom_ratio_exec(bContext *C, wmOperator *op) | |
694 { | |
695 SpaceImage *sima= CTX_wm_space_image(C); | |
696 ARegion *ar= CTX_wm_region(C); | |
697 | |
698 sima_zoom_set(sima, ar, RNA_float_get(op->ptr, "ratio")); | |
699 ········ | |
700 /* ensure pixel exact locations for draw */ | |
701 sima->xof= (int)sima->xof; | |
702 sima->yof= (int)sima->yof; | |
703 | |
704 /* XXX notifier? */ | |
705 #if 0 | |
706 if(image_preview_active(curarea, NULL, NULL)) { | |
707 /* recalculates new preview rect */ | |
708 scrarea_do_windraw(curarea); | |
709 image_preview_event(2); | |
710 } | |
711 #endif | |
712 | |
713 ED_region_tag_redraw(CTX_wm_region(C)); | |
714 ········ | |
715 return OPERATOR_FINISHED; | |
716 } | |
717 | |
718 void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot) | |
719 { | |
720 /* identifiers */ | |
721 ot->name= "View Zoom Ratio"; | |
722 ot->idname= "IMAGE_OT_view_zoom_ratio"; | |
723 ········ | |
724 /* api callbacks */ | |
725 ot->exec= image_view_zoom_ratio_exec; | |
726 ot->poll= space_image_main_area_poll; | |
727 ········ | |
728 /* properties */ | |
729 RNA_def_float(ot->srna, "ratio", 0.0f, 0.0f, FLT_MAX, | |
730 "Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is
zoomed out", -FLT_MAX, FLT_MAX); | |
731 } | |
732 | |
733 /**************** load/replace/save callbacks ******************/ | |
734 | |
735 /* XXX make dynamic */ | |
736 static const EnumPropertyItem image_file_type_items[] = { | |
737 {R_TARGA, "TARGA", 0, "Targa", ""}, | |
738 {R_RAWTGA, "TARGA RAW", 0, "Targa Raw", ""}, | |
739 {R_PNG, "PNG", 0, "PNG", ""}, | |
740 #ifdef WITH_DDS | |
741 {R_DDS, "DDS", 0, "DirectDraw Surface", ""}, | |
742 #endif | |
743 {R_BMP, "BMP", 0, "BMP", ""}, | |
744 {R_JPEG90, "JPEG", 0, "Jpeg", ""}, | |
745 #ifdef WITH_OPENJPEG | |
746 {R_JP2, "JPEG_2000", 0, "Jpeg 2000", ""}, | |
747 #endif | |
748 {R_IRIS, "IRIS", 0, "Iris", ""}, | |
749 #ifdef WITH_TIFF | |
750 {R_TIFF, "TIFF", 0, "Tiff", ""}, | |
751 #endif | |
752 #ifdef WITH_DDS | |
753 {R_RADHDR, "RADIANCE_HDR", 0, "Radiance HDR", ""}, | |
754 #endif | |
755 #ifdef WITH_CINEON | |
756 {R_CINEON, "CINEON", 0, "Cineon", ""}, | |
757 {R_DPX, "DPX", 0, "DPX", ""}, | |
758 #endif | |
759 #ifdef WITH_OPENEXR | |
760 {R_OPENEXR, "OPENEXR", 0, "OpenEXR", ""}, | |
761 /* saving sequences of multilayer won't work, they copy buffers */ | |
762 /*if(ima->source==IMA_SRC_SEQUENCE && ima->type==IMA_TYPE_MULTILAYER); | |
763 else*/ | |
764 {R_MULTILAYER, "MULTILAYER", 0, "MultiLayer", ""}, | |
765 #endif·· | |
766 {0, NULL, 0, NULL, NULL}}; | |
767 | |
768 static void image_filesel(bContext *C, wmOperator *op, const char *path) | |
769 { | |
770 RNA_string_set(op->ptr, "filepath", path); | |
771 WM_event_add_fileselect(C, op);· | |
772 } | |
773 | |
774 /******************** open image operator ********************/ | |
775 | |
776 static void image_open_init(bContext *C, wmOperator *op) | |
777 { | |
778 PropertyPointerRNA *pprop; | |
779 | |
780 op->customdata= pprop= MEM_callocN(sizeof(PropertyPointerRNA), "OpenProp
ertyPointerRNA"); | |
781 uiIDContextProperty(C, &pprop->ptr, &pprop->prop); | |
782 } | |
783 | |
784 static int image_open_cancel(bContext *UNUSED(C), wmOperator *op) | |
785 { | |
786 MEM_freeN(op->customdata); | |
787 op->customdata= NULL; | |
788 return OPERATOR_CANCELLED; | |
789 } | |
790 | |
791 static int image_open_exec(bContext *C, wmOperator *op) | |
792 { | |
793 SpaceImage *sima= CTX_wm_space_image(C); /* XXX other space types can ca
ll */ | |
794 Scene *scene= CTX_data_scene(C); | |
795 Object *obedit= CTX_data_edit_object(C); | |
796 ImageUser *iuser= NULL; | |
797 PropertyPointerRNA *pprop; | |
798 PointerRNA idptr; | |
799 Image *ima= NULL; | |
800 char str[FILE_MAX]; | |
801 | |
802 RNA_string_get(op->ptr, "filepath", str); | |
803 /* default to frame 1 if there's no scene in context */ | |
804 | |
805 errno= 0; | |
806 | |
807 ima= BKE_add_image_file(str); | |
808 | |
809 if(!ima) { | |
810 if(op->customdata) MEM_freeN(op->customdata); | |
811 BKE_reportf(op->reports, RPT_ERROR, "Can't read: \"%s\", %s", st
r, errno ? strerror(errno) : "Unsupported image format"); | |
812 return OPERATOR_CANCELLED; | |
813 } | |
814 ········ | |
815 if(!op->customdata) | |
816 image_open_init(C, op); | |
817 | |
818 /* hook into UI */ | |
819 pprop= op->customdata; | |
820 | |
821 if(pprop->prop) { | |
822 /* when creating new ID blocks, use is already 1, but RNA | |
823 * pointer se also increases user, so this compensates it */ | |
824 ima->id.us--; | |
825 | |
826 RNA_id_pointer_create(&ima->id, &idptr); | |
827 RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr); | |
828 RNA_property_update(C, &pprop->ptr, pprop->prop); | |
829 } | |
830 else if(sima) { | |
831 ED_space_image_set(C, sima, scene, obedit, ima); | |
832 iuser= &sima->iuser; | |
833 } | |
834 else { | |
835 Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).
data; | |
836 if(tex && tex->type==TEX_IMAGE) | |
837 iuser= &tex->iuser; | |
838 ················ | |
839 } | |
840 ········ | |
841 /* initialize because of new image */ | |
842 if(iuser) { | |
843 iuser->sfra= 1; | |
844 iuser->offset= 0; | |
845 iuser->fie_ima= 2; | |
846 } | |
847 | |
848 /* XXX unpackImage frees image buffers */ | |
849 ED_preview_kill_jobs(C); | |
850 ········ | |
851 BKE_image_signal(ima, iuser, IMA_SIGNAL_RELOAD); | |
852 WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, ima); | |
853 ········ | |
854 MEM_freeN(op->customdata); | |
855 | |
856 return OPERATOR_FINISHED; | |
857 } | |
858 | |
859 static int image_open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)
) | |
860 { | |
861 SpaceImage *sima= CTX_wm_space_image(C); /* XXX other space types can ca
ll */ | |
862 char *path=U.textudir; | |
863 Image *ima= NULL; | |
864 | |
865 if(sima) { | |
866 ima= sima->image; | |
867 } | |
868 | |
869 if (ima==NULL) { | |
870 Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).
data; | |
871 if(tex && tex->type==TEX_IMAGE) | |
872 ima= tex->ima; | |
873 } | |
874 | |
875 if(ima) | |
876 path= ima->name; | |
877 | |
878 if(RNA_property_is_set(op->ptr, "filepath")) | |
879 return image_open_exec(C, op); | |
880 ········ | |
881 image_open_init(C, op); | |
882 | |
883 image_filesel(C, op, path); | |
884 | |
885 return OPERATOR_RUNNING_MODAL; | |
886 } | |
887 | |
888 /* called by other space types too */ | |
889 void IMAGE_OT_open(wmOperatorType *ot) | |
890 { | |
891 /* identifiers */ | |
892 ot->name= "Open Image"; | |
893 ot->description= "Open image"; | |
894 ot->idname= "IMAGE_OT_open"; | |
895 ········ | |
896 /* api callbacks */ | |
897 ot->exec= image_open_exec; | |
898 ot->invoke= image_open_invoke; | |
899 ot->cancel= image_open_cancel; | |
900 | |
901 /* flags */ | |
902 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
903 | |
904 /* properties */ | |
905 WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_
SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH); | |
906 } | |
907 | |
908 /******************** replace image operator ********************/ | |
909 | |
910 static int image_replace_exec(bContext *C, wmOperator *op) | |
911 { | |
912 SpaceImage *sima= CTX_wm_space_image(C); | |
913 char str[FILE_MAX]; | |
914 | |
915 if(!sima->image) | |
916 return OPERATOR_CANCELLED; | |
917 ········ | |
918 RNA_string_get(op->ptr, "filepath", str); | |
919 BLI_strncpy(sima->image->name, str, sizeof(sima->image->name)); /* we ca
nt do much if the str is longer then 240 :/ */ | |
920 | |
921 /* XXX unpackImage frees image buffers */ | |
922 ED_preview_kill_jobs(C); | |
923 ········ | |
924 BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_RELOAD); | |
925 WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, sima->image); | |
926 | |
927 return OPERATOR_FINISHED; | |
928 } | |
929 | |
930 static int image_replace_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve
nt)) | |
931 { | |
932 SpaceImage *sima= CTX_wm_space_image(C); | |
933 | |
934 if(!sima->image) | |
935 return OPERATOR_CANCELLED; | |
936 | |
937 if(RNA_property_is_set(op->ptr, "filepath")) | |
938 return image_replace_exec(C, op); | |
939 | |
940 if(!RNA_property_is_set(op->ptr, "relative_path")) | |
941 RNA_boolean_set(op->ptr, "relative_path", (strncmp(sima->image->
name, "//", 2))==0); | |
942 | |
943 image_filesel(C, op, sima->image->name); | |
944 | |
945 return OPERATOR_RUNNING_MODAL; | |
946 } | |
947 | |
948 void IMAGE_OT_replace(wmOperatorType *ot) | |
949 { | |
950 /* identifiers */ | |
951 ot->name= "Replace Image"; | |
952 ot->idname= "IMAGE_OT_replace"; | |
953 ········ | |
954 /* api callbacks */ | |
955 ot->exec= image_replace_exec; | |
956 ot->invoke= image_replace_invoke; | |
957 ot->poll= space_image_poll; | |
958 | |
959 /* flags */ | |
960 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
961 | |
962 /* properties */ | |
963 WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_
SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH); | |
964 } | |
965 | |
966 /******************** save image as operator ********************/ | |
967 | |
968 typedef struct { | |
969 /* matching scene->r settings */ | |
970 short planes, imtype, subimtype, quality; | |
971 char filepath[FILE_MAX]; /* keep absolute */ | |
972 } SaveImageOptions; | |
973 | |
974 static void save_image_options_defaults(SaveImageOptions *simopts) | |
975 { | |
976 simopts->planes= R_PLANES24; | |
977 simopts->imtype= R_PNG; | |
978 simopts->subimtype= 0; | |
979 simopts->quality= 90; | |
980 simopts->filepath[0]= '\0'; | |
981 } | |
982 | |
983 static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
Scene *scene, const short guess_path) | |
984 { | |
985 void *lock; | |
986 ImBuf *ibuf= ED_space_image_acquire_buffer(sima, &lock); | |
987 | |
988 if(ibuf) { | |
989 Image *ima= sima->image; | |
990 | |
991 simopts->planes= ibuf->depth; | |
992 | |
993 if(ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) { | |
994 simopts->imtype= scene->r.imtype; | |
995 simopts->planes= scene->r.planes; | |
996 } | |
997 else if (ima->source == IMA_SRC_GENERATED) { | |
998 simopts->imtype= R_PNG; | |
999 } | |
1000 else { | |
1001 simopts->imtype= BKE_ftype_to_imtype(ibuf->ftype); | |
1002 } | |
1003 simopts->subimtype= scene->r.subimtype; /* XXX - this is lame, w
e need to make these available too! */ | |
1004 simopts->quality= ibuf->ftype & 0xff; | |
1005 | |
1006 BLI_strncpy(simopts->filepath, ibuf->name, sizeof(simopts->filep
ath)); | |
1007 | |
1008 /* sanitize all settings */ | |
1009 | |
1010 /* unlikely but just incase */ | |
1011 if (ELEM3(simopts->planes, R_PLANESBW, R_PLANES24, R_PLANES32) =
= 0) { | |
1012 simopts->planes= R_PLANES32; | |
1013 } | |
1014 | |
1015 /* some formats dont use quality so fallback to scenes quality *
/ | |
1016 if (simopts->quality == 0) { | |
1017 simopts->quality= scene->r.quality; | |
1018 } | |
1019 | |
1020 /* check for empty path */ | |
1021 if(guess_path && simopts->filepath[0]==0) { | |
1022 if ( (G.ima[0] == '/') && (G.ima[1] == '/') && (G.ima[2]
== '\0') ) { | |
1023 BLI_strncpy(simopts->filepath, "//untitled", FIL
E_MAX); | |
1024 } else { | |
1025 BLI_strncpy(simopts->filepath, G.ima, FILE_MAX); | |
1026 } | |
1027 BLI_path_abs(simopts->filepath, G.main->name); | |
1028 } | |
1029 } | |
1030 | |
1031 ED_space_image_release_buffer(sima, lock); | |
1032 | |
1033 return (ibuf != NULL); | |
1034 } | |
1035 | |
1036 static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op
) | |
1037 { | |
1038 if (RNA_property_is_set(op->ptr, "color_mode")) simopts->planes= RNA_enu
m_get(op->ptr, "color_mode"); | |
1039 if (RNA_property_is_set(op->ptr, "file_format")) simopts->imtype= RNA_en
um_get(op->ptr, "file_format"); | |
1040 // if (RNA_property_is_set(op->ptr, "subimtype")) simopts->subimtype= RN
A_enum_get(op->ptr, "subimtype"); // XXX | |
1041 if (RNA_property_is_set(op->ptr, "file_quality")) simopts->quality= RNA_
int_get(op->ptr, "file_quality"); | |
1042 | |
1043 if (RNA_property_is_set(op->ptr, "filepath")) { | |
1044 RNA_string_get(op->ptr, "filepath", simopts->filepath); | |
1045 BLI_path_abs(simopts->filepath, G.main->name); | |
1046 } | |
1047 } | |
1048 | |
1049 static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op) | |
1050 { | |
1051 RNA_enum_set(op->ptr, "color_mode", simopts->planes); | |
1052 RNA_enum_set(op->ptr, "file_format", simopts->imtype); | |
1053 // RNA_enum_set(op->ptr, "subimtype", simopts->subimtype); | |
1054 RNA_int_set(op->ptr, "file_quality", simopts->quality); | |
1055 | |
1056 RNA_string_set(op->ptr, "filepath", simopts->filepath); | |
1057 } | |
1058 | |
1059 /* assumes name is FILE_MAX */ | |
1060 /* ima->name and ibuf->name should end up the same */ | |
1061 static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
mageOptions *simopts, int do_newpath) | |
1062 { | |
1063 Image *ima= ED_space_image(sima); | |
1064 void *lock; | |
1065 ImBuf *ibuf= ED_space_image_acquire_buffer(sima, &lock); | |
1066 | |
1067 if (ibuf) { | |
1068 const char *relbase= ID_BLEND_PATH(CTX_data_main(C), &ima->id); | |
1069 const short relative= (RNA_struct_find_property(op->ptr, "relati
ve_path") && RNA_boolean_get(op->ptr, "relative_path")); | |
1070 const short save_copy= (RNA_struct_find_property(op->ptr, "copy"
) && RNA_boolean_get(op->ptr, "copy")); | |
1071 short ok= FALSE; | |
1072 | |
1073 /* old global to ensure a 2nd save goes to same dir */ | |
1074 BLI_strncpy(G.ima, simopts->filepath, sizeof(G.ima)); | |
1075 | |
1076 WM_cursor_wait(1); | |
1077 | |
1078 if(ima->type == IMA_TYPE_R_RESULT) { | |
1079 /* enforce user setting for RGB or RGBA, but skip BW */ | |
1080 if(simopts->planes==R_PLANES32) { | |
1081 ibuf->depth= 32; | |
1082 } | |
1083 else if(simopts->planes==R_PLANES24) { | |
1084 ibuf->depth= 24; | |
1085 } | |
1086 } | |
1087 else { | |
1088 /* TODO, better solution, if a 24bit image is painted on
to it may contain alpha */ | |
1089 if(ibuf->userflags & IB_BITMAPDIRTY) { /* it has been pa
inted onto */ | |
1090 /* checks each pixel, not ideal */ | |
1091 ibuf->depth= BKE_alphatest_ibuf(ibuf) ? 32 : 24; | |
1092 } | |
1093 } | |
1094 ················ | |
1095 if(simopts->imtype==R_MULTILAYER) { | |
1096 Scene *scene= CTX_data_scene(C); | |
1097 RenderResult *rr= BKE_image_acquire_renderresult(scene,
ima); | |
1098 if(rr) { | |
1099 RE_WriteRenderResult(op->reports, rr, simopts->f
ilepath, simopts->quality); | |
1100 ok= TRUE; | |
1101 } | |
1102 else { | |
1103 BKE_report(op->reports, RPT_ERROR, "Did not writ
e, no Multilayer Image"); | |
1104 } | |
1105 BKE_image_release_renderresult(scene, ima); | |
1106 } | |
1107 else if (BKE_write_ibuf(ibuf, simopts->filepath, simopts->imtype
, simopts->subimtype, simopts->quality)) { | |
1108 ok= TRUE; | |
1109 } | |
1110 | |
1111 if (ok) { | |
1112 if(!save_copy) { | |
1113 if(do_newpath) { | |
1114 BLI_strncpy(ibuf->name, simopts->filepat
h, sizeof(ibuf->name)); | |
1115 BLI_strncpy(ima->name, simopts->filepath
, sizeof(ima->name)); | |
1116 } | |
1117 | |
1118 ibuf->userflags &= ~IB_BITMAPDIRTY; | |
1119 | |
1120 /* change type? */ | |
1121 if(ima->type==IMA_TYPE_R_RESULT) { | |
1122 ima->type= IMA_TYPE_IMAGE; | |
1123 | |
1124 /* workaround to ensure the render resul
t buffer is no longer used | |
1125 * by this image, otherwise can crash wh
en a new render result is | |
1126 * created. */ | |
1127 if(ibuf->rect && !(ibuf->mall & IB_rect)
) | |
1128 imb_freerectImBuf(ibuf); | |
1129 if(ibuf->rect_float && !(ibuf->mall & IB
_rectfloat)) | |
1130 imb_freerectfloatImBuf(ibuf); | |
1131 if(ibuf->zbuf && !(ibuf->mall & IB_zbuf)
) | |
1132 IMB_freezbufImBuf(ibuf); | |
1133 if(ibuf->zbuf_float && !(ibuf->mall & IB
_zbuffloat)) | |
1134 IMB_freezbuffloatImBuf(ibuf); | |
1135 } | |
1136 if( ELEM(ima->source, IMA_SRC_GENERATED, IMA_SRC
_VIEWER)) { | |
1137 ima->source= IMA_SRC_FILE; | |
1138 ima->type= IMA_TYPE_IMAGE; | |
1139 } | |
1140 | |
1141 /* only image path, never ibuf */ | |
1142 if(relative) { | |
1143 BLI_path_rel(ima->name, relbase); /* onl
y after saving */ | |
1144 } | |
1145 } | |
1146 } | |
1147 else { | |
1148 BKE_reportf(op->reports, RPT_ERROR, "Couldn't write imag
e: %s", simopts->filepath); | |
1149 } | |
1150 | |
1151 | |
1152 WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, sima->image); | |
1153 | |
1154 WM_cursor_wait(0); | |
1155 } | |
1156 | |
1157 ED_space_image_release_buffer(sima, lock); | |
1158 } | |
1159 | |
1160 static int image_save_as_exec(bContext *C, wmOperator *op) | |
1161 { | |
1162 SpaceImage *sima= CTX_wm_space_image(C); | |
1163 SaveImageOptions simopts; | |
1164 | |
1165 /* just incase to initialize values, | |
1166 * these should be set on invoke or by the caller. */ | |
1167 save_image_options_defaults(&simopts); | |
1168 save_image_options_from_op(&simopts, op); | |
1169 | |
1170 save_image_doit(C, sima, op, &simopts, TRUE); | |
1171 | |
1172 return OPERATOR_FINISHED; | |
1173 } | |
1174 | |
1175 | |
1176 static int image_save_as_check(bContext *UNUSED(C), wmOperator *op) | |
1177 { | |
1178 char filepath[FILE_MAX]; | |
1179 RNA_string_get(op->ptr, "filepath", filepath); | |
1180 if(BKE_add_image_extension(filepath, RNA_enum_get(op->ptr, "file_format"
))) { | |
1181 RNA_string_set(op->ptr, "filepath", filepath); | |
1182 return TRUE; | |
1183 } | |
1184 return FALSE; | |
1185 } | |
1186 | |
1187 static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve
nt)) | |
1188 { | |
1189 SpaceImage *sima= CTX_wm_space_image(C); | |
1190 Image *ima = ED_space_image(sima); | |
1191 Scene *scene= CTX_data_scene(C); | |
1192 SaveImageOptions simopts; | |
1193 | |
1194 if(RNA_property_is_set(op->ptr, "filepath")) | |
1195 return image_save_as_exec(C, op); | |
1196 | |
1197 if (save_image_options_init(&simopts, sima, scene, TRUE) == 0) | |
1198 return OPERATOR_CANCELLED; | |
1199 save_image_options_to_op(&simopts, op); | |
1200 | |
1201 /* enable save_copy by default for render results */ | |
1202 if(ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE) && !RNA_proper
ty_is_set(op->ptr, "copy")) { | |
1203 RNA_boolean_set(op->ptr, "copy", TRUE); | |
1204 } | |
1205 | |
1206 // XXX note: we can give default menu enums to operator for this | |
1207 image_filesel(C, op, simopts.filepath); | |
1208 | |
1209 return OPERATOR_RUNNING_MODAL; | |
1210 } | |
1211 | |
1212 void IMAGE_OT_save_as(wmOperatorType *ot) | |
1213 { | |
1214 PropertyRNA *prop; | |
1215 | |
1216 /* identifiers */ | |
1217 ot->name= "Save As Image"; | |
1218 ot->idname= "IMAGE_OT_save_as"; | |
1219 ········ | |
1220 /* api callbacks */ | |
1221 ot->exec= image_save_as_exec; | |
1222 ot->check= image_save_as_check; | |
1223 ot->invoke= image_save_as_invoke; | |
1224 ot->poll= space_image_buffer_exists_poll; | |
1225 | |
1226 /* flags */ | |
1227 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1228 | |
1229 /* properties */ | |
1230 | |
1231 /* format options */ | |
1232 RNA_def_enum(ot->srna, "file_format", image_file_type_items, R_PNG, "Fil
e Type", "File type to save image as"); | |
1233 RNA_def_enum(ot->srna, "color_mode", image_color_mode_items, R_PLANES24,
"Channels", "Image channels to save"); | |
1234 prop= RNA_def_int(ot->srna, "file_quality", 90, 0, 100, "Quality", "", 0
, 100); | |
1235 RNA_def_property_subtype(prop, PROP_PERCENTAGE); | |
1236 | |
1237 WM_operator_properties_filesel(ot, FOLDERFILE|IMAGEFILE|MOVIEFILE, FILE_
SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH); | |
1238 | |
1239 RNA_def_boolean(ot->srna, "copy", 0, "Copy", "Create a new image file wi
thout modifying the current image in blender"); | |
1240 } | |
1241 | |
1242 /******************** save image operator ********************/ | |
1243 | |
1244 static int image_save_exec(bContext *C, wmOperator *op) | |
1245 { | |
1246 SpaceImage *sima= CTX_wm_space_image(C); | |
1247 Scene *scene= CTX_data_scene(C); | |
1248 SaveImageOptions simopts; | |
1249 | |
1250 if (save_image_options_init(&simopts, sima, scene, FALSE) == 0) | |
1251 return OPERATOR_CANCELLED; | |
1252 save_image_options_from_op(&simopts, op); | |
1253 | |
1254 if (BLI_exists(simopts.filepath) && BLI_file_is_writable(simopts.filepat
h)) { | |
1255 save_image_doit(C, sima, op, &simopts, FALSE); | |
1256 } | |
1257 else { | |
1258 BKE_reportf(op->reports, RPT_ERROR, "Can not save image, path '%
s' is not writable", simopts.filepath); | |
1259 return OPERATOR_CANCELLED; | |
1260 } | |
1261 | |
1262 return OPERATOR_FINISHED; | |
1263 } | |
1264 | |
1265 void IMAGE_OT_save(wmOperatorType *ot) | |
1266 { | |
1267 /* identifiers */ | |
1268 ot->name= "Save Image"; | |
1269 ot->idname= "IMAGE_OT_save"; | |
1270 ········ | |
1271 /* api callbacks */ | |
1272 ot->exec= image_save_exec; | |
1273 ot->poll= space_image_file_exists_poll; | |
1274 | |
1275 /* flags */ | |
1276 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1277 } | |
1278 | |
1279 /******************* save sequence operator ********************/ | |
1280 | |
1281 static int image_save_sequence_exec(bContext *C, wmOperator *op) | |
1282 { | |
1283 Main *bmain= CTX_data_main(C); | |
1284 SpaceImage *sima= CTX_wm_space_image(C); | |
1285 ImBuf *ibuf; | |
1286 int tot= 0; | |
1287 char di[FILE_MAX], fi[FILE_MAX]; | |
1288 ········ | |
1289 if(sima->image==NULL) | |
1290 return OPERATOR_CANCELLED; | |
1291 | |
1292 if(sima->image->source!=IMA_SRC_SEQUENCE) { | |
1293 BKE_report(op->reports, RPT_ERROR, "Can only save sequence on im
age sequences"); | |
1294 return OPERATOR_CANCELLED; | |
1295 } | |
1296 | |
1297 if(sima->image->type==IMA_TYPE_MULTILAYER) { | |
1298 BKE_report(op->reports, RPT_ERROR, "Can't save multilayer sequen
ces"); | |
1299 return OPERATOR_CANCELLED; | |
1300 } | |
1301 ········ | |
1302 /* get total */ | |
1303 for(ibuf= sima->image->ibufs.first; ibuf; ibuf= ibuf->next)· | |
1304 if(ibuf->userflags & IB_BITMAPDIRTY) | |
1305 tot++; | |
1306 ········ | |
1307 if(tot==0) { | |
1308 BKE_report(op->reports, RPT_WARNING, "No images have been change
d"); | |
1309 return OPERATOR_CANCELLED; | |
1310 } | |
1311 | |
1312 /* get a filename for menu */ | |
1313 for(ibuf= sima->image->ibufs.first; ibuf; ibuf= ibuf->next)· | |
1314 if(ibuf->userflags & IB_BITMAPDIRTY) | |
1315 break; | |
1316 ········ | |
1317 BLI_strncpy(di, ibuf->name, FILE_MAX); | |
1318 BLI_splitdirstring(di, fi); | |
1319 ········ | |
1320 BKE_reportf(op->reports, RPT_INFO, "%d Image(s) will be saved in %s", to
t, di); | |
1321 | |
1322 for(ibuf= sima->image->ibufs.first; ibuf; ibuf= ibuf->next) { | |
1323 if(ibuf->userflags & IB_BITMAPDIRTY) { | |
1324 char name[FILE_MAX]; | |
1325 BLI_strncpy(name, ibuf->name, sizeof(name)); | |
1326 ························ | |
1327 BLI_path_abs(name, bmain->name); | |
1328 | |
1329 if(0 == IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_z
buffloat)) { | |
1330 BKE_reportf(op->reports, RPT_ERROR, "Could not w
rite image %s", name); | |
1331 break; | |
1332 } | |
1333 | |
1334 BKE_reportf(op->reports, RPT_INFO, "Saved: %s\n", ibuf->
name); | |
1335 ibuf->userflags &= ~IB_BITMAPDIRTY; | |
1336 } | |
1337 } | |
1338 | |
1339 return OPERATOR_FINISHED; | |
1340 } | |
1341 | |
1342 void IMAGE_OT_save_sequence(wmOperatorType *ot) | |
1343 { | |
1344 /* identifiers */ | |
1345 ot->name= "Save Sequence"; | |
1346 ot->idname= "IMAGE_OT_save_sequence"; | |
1347 ········ | |
1348 /* api callbacks */ | |
1349 ot->exec= image_save_sequence_exec; | |
1350 ot->poll= space_image_buffer_exists_poll; | |
1351 | |
1352 /* flags */ | |
1353 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1354 } | |
1355 | |
1356 /******************** reload image operator ********************/ | |
1357 | |
1358 static int image_reload_exec(bContext *C, wmOperator *UNUSED(op)) | |
1359 { | |
1360 Image *ima= CTX_data_edit_image(C); | |
1361 SpaceImage *sima= CTX_wm_space_image(C); | |
1362 | |
1363 if(!ima) | |
1364 return OPERATOR_CANCELLED; | |
1365 | |
1366 /* XXX unpackImage frees image buffers */ | |
1367 ED_preview_kill_jobs(C); | |
1368 ········ | |
1369 // XXX other users? | |
1370 BKE_image_signal(ima, (sima)? &sima->iuser: NULL, IMA_SIGNAL_RELOAD); | |
1371 | |
1372 WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, ima); | |
1373 ········ | |
1374 return OPERATOR_FINISHED; | |
1375 } | |
1376 | |
1377 void IMAGE_OT_reload(wmOperatorType *ot) | |
1378 { | |
1379 /* identifiers */ | |
1380 ot->name= "Reload Image"; | |
1381 ot->idname= "IMAGE_OT_reload"; | |
1382 ········ | |
1383 /* api callbacks */ | |
1384 ot->exec= image_reload_exec; | |
1385 | |
1386 /* flags */ | |
1387 ot->flag= OPTYPE_REGISTER; /* no undo, image buffer is not handled by un
do */ | |
1388 } | |
1389 | |
1390 /********************** new image operator *********************/ | |
1391 | |
1392 static int image_new_exec(bContext *C, wmOperator *op) | |
1393 { | |
1394 SpaceImage *sima; | |
1395 Scene *scene; | |
1396 Object *obedit; | |
1397 Image *ima; | |
1398 PointerRNA ptr, idptr; | |
1399 PropertyRNA *prop; | |
1400 char name[MAX_ID_NAME-2]; | |
1401 float color[4]; | |
1402 int width, height, floatbuf, uvtestgrid, alpha; | |
1403 | |
1404 /* retrieve state */ | |
1405 sima= CTX_wm_space_image(C); | |
1406 scene= (Scene*)CTX_data_scene(C); | |
1407 obedit= CTX_data_edit_object(C); | |
1408 | |
1409 RNA_string_get(op->ptr, "name", name); | |
1410 width= RNA_int_get(op->ptr, "width"); | |
1411 height= RNA_int_get(op->ptr, "height"); | |
1412 floatbuf= RNA_boolean_get(op->ptr, "float"); | |
1413 uvtestgrid= RNA_boolean_get(op->ptr, "uv_test_grid"); | |
1414 RNA_float_get_array(op->ptr, "color", color); | |
1415 alpha= RNA_boolean_get(op->ptr, "alpha"); | |
1416 ········ | |
1417 if (!floatbuf && scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) | |
1418 linearrgb_to_srgb_v3_v3(color, color); | |
1419 | |
1420 if(!alpha) | |
1421 color[3]= 1.0f; | |
1422 | |
1423 ima = BKE_add_image_size(width, height, name, alpha ? 32 : 24, floatbuf,
uvtestgrid, color); | |
1424 | |
1425 if(!ima) | |
1426 return OPERATOR_CANCELLED; | |
1427 | |
1428 /* hook into UI */ | |
1429 uiIDContextProperty(C, &ptr, &prop); | |
1430 | |
1431 if(prop) { | |
1432 /* when creating new ID blocks, use is already 1, but RNA | |
1433 * pointer se also increases user, so this compensates it */ | |
1434 ima->id.us--; | |
1435 | |
1436 RNA_id_pointer_create(&ima->id, &idptr); | |
1437 RNA_property_pointer_set(&ptr, prop, idptr); | |
1438 RNA_property_update(C, &ptr, prop); | |
1439 } | |
1440 else if(sima) | |
1441 ED_space_image_set(C, sima, scene, obedit, ima); | |
1442 | |
1443 // XXX other users? | |
1444 BKE_image_signal(ima, (sima)? &sima->iuser: NULL, IMA_SIGNAL_USER_NEW_IM
AGE); | |
1445 ········ | |
1446 return OPERATOR_FINISHED; | |
1447 } | |
1448 | |
1449 /* XXX, Ton is not a fan of OK buttons but using this function to avoid undo/red
o bug while in mesh-editmode, - campbell */ | |
1450 static int image_new_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) | |
1451 { | |
1452 return WM_operator_props_dialog_popup(C, op, 300, 100); | |
1453 | |
1454 } | |
1455 | |
1456 void IMAGE_OT_new(wmOperatorType *ot) | |
1457 { | |
1458 PropertyRNA *prop; | |
1459 static float default_color[4]= {0.0f, 0.0f, 0.0f, 1.0f}; | |
1460 ········ | |
1461 /* identifiers */ | |
1462 ot->name= "New Image"; | |
1463 ot->description= "Create a new image"; | |
1464 ot->idname= "IMAGE_OT_new"; | |
1465 ········ | |
1466 /* api callbacks */ | |
1467 ot->exec= image_new_exec; | |
1468 ot->invoke= image_new_invoke; | |
1469 ········ | |
1470 /* flags */ | |
1471 ot->flag= OPTYPE_UNDO; | |
1472 | |
1473 /* properties */ | |
1474 RNA_def_string(ot->srna, "name", "untitled", MAX_ID_NAME-2, "Name", "Ima
ge datablock name"); | |
1475 RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width",
1, 16384); | |
1476 RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image heigh
t", 1, 16384); | |
1477 prop= RNA_def_float_color(ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Co
lor", "Default fill color", 0.0f, 1.0f); | |
1478 RNA_def_property_float_array_default(prop, default_color); | |
1479 RNA_def_boolean(ot->srna, "alpha", 1, "Alpha", "Create an image with an
alpha channel"); | |
1480 RNA_def_boolean(ot->srna, "uv_test_grid", 0, "UV Test Grid", "Fill the i
mage with a grid for UV map testing"); | |
1481 RNA_def_boolean(ot->srna, "float", 0, "32 bit Float", "Create image with
32 bit floating point bit depth"); | |
1482 } | |
1483 | |
1484 /********************* invert operators *********************/ | |
1485 | |
1486 static int image_invert_poll(bContext *C) | |
1487 { | |
1488 Image *ima= CTX_data_edit_image(C); | |
1489 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); | |
1490 ········ | |
1491 if( ibuf != NULL ) | |
1492 return 1; | |
1493 return 0; | |
1494 } | |
1495 | |
1496 static int image_invert_exec(bContext *C, wmOperator *op) | |
1497 { | |
1498 Image *ima= CTX_data_edit_image(C); | |
1499 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); | |
1500 | |
1501 // flags indicate if this channel should be inverted | |
1502 const short r= RNA_boolean_get(op->ptr, "invert_r"); | |
1503 const short g= RNA_boolean_get(op->ptr, "invert_g"); | |
1504 const short b= RNA_boolean_get(op->ptr, "invert_b"); | |
1505 const short a= RNA_boolean_get(op->ptr, "invert_a"); | |
1506 | |
1507 int i; | |
1508 | |
1509 if( ibuf == NULL) // TODO: this should actually never happen, but does f
or render-results -> cleanup | |
1510 return OPERATOR_CANCELLED; | |
1511 | |
1512 /* TODO: make this into an IMB_invert_channels(ibuf,r,g,b,a) method!? */ | |
1513 if (ibuf->rect_float) { | |
1514 ················ | |
1515 float *fp = (float *) ibuf->rect_float; | |
1516 for( i = ibuf->x * ibuf->y; i > 0; i--, fp+=4 ) { | |
1517 if( r ) fp[0] = 1.0f - fp[0]; | |
1518 if( g ) fp[1] = 1.0f - fp[1]; | |
1519 if( b ) fp[2] = 1.0f - fp[2]; | |
1520 if( a ) fp[3] = 1.0f - fp[3]; | |
1521 } | |
1522 | |
1523 if(ibuf->rect) { | |
1524 IMB_rect_from_float(ibuf); | |
1525 } | |
1526 } | |
1527 else if(ibuf->rect) { | |
1528 ················ | |
1529 char *cp = (char *) ibuf->rect; | |
1530 for( i = ibuf->x * ibuf->y; i > 0; i--, cp+=4 ) { | |
1531 if( r ) cp[0] = 255 - cp[0]; | |
1532 if( g ) cp[1] = 255 - cp[1]; | |
1533 if( b ) cp[2] = 255 - cp[2]; | |
1534 if( a ) cp[3] = 255 - cp[3]; | |
1535 } | |
1536 } | |
1537 else { | |
1538 return OPERATOR_CANCELLED; | |
1539 } | |
1540 | |
1541 ibuf->userflags |= IB_BITMAPDIRTY; | |
1542 if(ibuf->mipmap[0]) | |
1543 ibuf->userflags |= IB_MIPMAP_INVALID; | |
1544 | |
1545 WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, ima); | |
1546 return OPERATOR_FINISHED; | |
1547 } | |
1548 | |
1549 void IMAGE_OT_invert(wmOperatorType *ot) | |
1550 { | |
1551 /* identifiers */ | |
1552 ot->name= "Invert Channels"; | |
1553 ot->idname= "IMAGE_OT_invert"; | |
1554 ········ | |
1555 /* api callbacks */ | |
1556 ot->exec= image_invert_exec; | |
1557 ot->poll= image_invert_poll; | |
1558 ········ | |
1559 /* properties */ | |
1560 RNA_def_boolean(ot->srna, "invert_r", 0, "Red", "Invert Red Channel"); | |
1561 RNA_def_boolean(ot->srna, "invert_g", 0, "Green", "Invert Green Channel"
); | |
1562 RNA_def_boolean(ot->srna, "invert_b", 0, "Blue", "Invert Blue Channel"); | |
1563 RNA_def_boolean(ot->srna, "invert_a", 0, "Alpha", "Invert Alpha Channel"
); | |
1564 ········ | |
1565 /* flags */ | |
1566 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1567 } | |
1568 | |
1569 /********************* pack operator *********************/ | |
1570 | |
1571 static int image_pack_test(bContext *C, wmOperator *op) | |
1572 { | |
1573 Image *ima= CTX_data_edit_image(C); | |
1574 int as_png= RNA_boolean_get(op->ptr, "as_png"); | |
1575 | |
1576 if(!ima) | |
1577 return 0; | |
1578 if(!as_png && ima->packedfile) | |
1579 return 0; | |
1580 | |
1581 if(ima->source==IMA_SRC_SEQUENCE || ima->source==IMA_SRC_MOVIE) { | |
1582 BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequ
ences not supported"); | |
1583 return 0; | |
1584 } | |
1585 | |
1586 return 1; | |
1587 } | |
1588 | |
1589 static int image_pack_exec(bContext *C, wmOperator *op) | |
1590 { | |
1591 struct Main *bmain= CTX_data_main(C); | |
1592 Image *ima= CTX_data_edit_image(C); | |
1593 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); | |
1594 int as_png= RNA_boolean_get(op->ptr, "as_png"); | |
1595 | |
1596 if(!image_pack_test(C, op)) | |
1597 return OPERATOR_CANCELLED; | |
1598 ········ | |
1599 if(!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { | |
1600 BKE_report(op->reports, RPT_ERROR, "Can't pack edited image from
disk, only as internal PNG"); | |
1601 return OPERATOR_CANCELLED; | |
1602 } | |
1603 | |
1604 if(as_png) | |
1605 BKE_image_memorypack(ima); | |
1606 else | |
1607 ima->packedfile= newPackedFile(op->reports, ima->name, ID_BLEND_
PATH(bmain, &ima->id)); | |
1608 | |
1609 WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, ima); | |
1610 ········ | |
1611 return OPERATOR_FINISHED; | |
1612 } | |
1613 | |
1614 static int image_pack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)
) | |
1615 { | |
1616 Image *ima= CTX_data_edit_image(C); | |
1617 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); | |
1618 uiPopupMenu *pup; | |
1619 uiLayout *layout; | |
1620 int as_png= RNA_boolean_get(op->ptr, "as_png"); | |
1621 | |
1622 if(!image_pack_test(C, op)) | |
1623 return OPERATOR_CANCELLED; | |
1624 ········ | |
1625 if(!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { | |
1626 pup= uiPupMenuBegin(C, "OK", ICON_QUESTION); | |
1627 layout= uiPupMenuLayout(pup); | |
1628 uiItemBooleanO(layout, "Can't pack edited image from disk. Pack
as internal PNG?", ICON_NONE, op->idname, "as_png", 1); | |
1629 uiPupMenuEnd(C, pup); | |
1630 | |
1631 return OPERATOR_CANCELLED; | |
1632 } | |
1633 | |
1634 return image_pack_exec(C, op); | |
1635 } | |
1636 | |
1637 void IMAGE_OT_pack(wmOperatorType *ot) | |
1638 { | |
1639 /* identifiers */ | |
1640 ot->name= "Pack Image"; | |
1641 ot->description= "Pack an image as embedded data into the .blend file";· | |
1642 ot->idname= "IMAGE_OT_pack"; | |
1643 ········ | |
1644 /* api callbacks */ | |
1645 ot->exec= image_pack_exec; | |
1646 ot->invoke= image_pack_invoke; | |
1647 | |
1648 /* flags */ | |
1649 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1650 | |
1651 /* properties */ | |
1652 RNA_def_boolean(ot->srna, "as_png", 0, "Pack As PNG", "Pack image as los
sless PNG"); | |
1653 } | |
1654 | |
1655 /********************* unpack operator *********************/ | |
1656 | |
1657 static int image_unpack_exec(bContext *C, wmOperator *op) | |
1658 { | |
1659 Image *ima= CTX_data_edit_image(C); | |
1660 int method= RNA_enum_get(op->ptr, "method"); | |
1661 | |
1662 /* find the suppplied image by name */ | |
1663 if (RNA_property_is_set(op->ptr, "id")) { | |
1664 char imaname[MAX_ID_NAME-2]; | |
1665 RNA_string_get(op->ptr, "id", imaname); | |
1666 ima = BLI_findstring(&CTX_data_main(C)->image, imaname, offsetof
(ID, name) + 2); | |
1667 if (!ima) ima = CTX_data_edit_image(C); | |
1668 } | |
1669 ········ | |
1670 if(!ima || !ima->packedfile) | |
1671 return OPERATOR_CANCELLED; | |
1672 | |
1673 if(ima->source==IMA_SRC_SEQUENCE || ima->source==IMA_SRC_MOVIE) { | |
1674 BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image se
quences not supported"); | |
1675 return OPERATOR_CANCELLED; | |
1676 } | |
1677 | |
1678 if(G.fileflags & G_AUTOPACK) | |
1679 BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so im
age will be packed again on file save"); | |
1680 ········ | |
1681 /* XXX unpackImage frees image buffers */ | |
1682 ED_preview_kill_jobs(C); | |
1683 ········ | |
1684 unpackImage(op->reports, ima, method); | |
1685 ········ | |
1686 WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, ima); | |
1687 | |
1688 return OPERATOR_FINISHED; | |
1689 } | |
1690 | |
1691 static int image_unpack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even
t)) | |
1692 { | |
1693 Image *ima= CTX_data_edit_image(C); | |
1694 | |
1695 if(RNA_property_is_set(op->ptr, "id")) | |
1696 return image_unpack_exec(C, op); | |
1697 ················ | |
1698 if(!ima || !ima->packedfile) | |
1699 return OPERATOR_CANCELLED; | |
1700 | |
1701 if(ima->source==IMA_SRC_SEQUENCE || ima->source==IMA_SRC_MOVIE) { | |
1702 BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image se
quences not supported"); | |
1703 return OPERATOR_CANCELLED; | |
1704 } | |
1705 | |
1706 if(G.fileflags & G_AUTOPACK) | |
1707 BKE_report(op->reports, RPT_WARNING, "AutoPack is enabled, so im
age will be packed again on file save"); | |
1708 | |
1709 unpack_menu(C, "IMAGE_OT_unpack", ima->id.name+2, ima->name, "textures",
ima->packedfile); | |
1710 | |
1711 return OPERATOR_FINISHED; | |
1712 } | |
1713 | |
1714 void IMAGE_OT_unpack(wmOperatorType *ot) | |
1715 { | |
1716 /* identifiers */ | |
1717 ot->name= "Unpack Image"; | |
1718 ot->description= "Save an image packed in the .blend file to disk";· | |
1719 ot->idname= "IMAGE_OT_unpack"; | |
1720 ········ | |
1721 /* api callbacks */ | |
1722 ot->exec= image_unpack_exec; | |
1723 ot->invoke= image_unpack_invoke; | |
1724 | |
1725 /* flags */ | |
1726 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
1727 ········ | |
1728 /* properties */ | |
1729 RNA_def_enum(ot->srna, "method", unpack_method_items, PF_USE_LOCAL, "Met
hod", "How to unpack"); | |
1730 RNA_def_string(ot->srna, "id", "", MAX_ID_NAME-2, "Image Name", "Image d
atablock name to unpack"); /* XXX, weark!, will fail with library, name collisio
ns */ | |
1731 } | |
1732 | |
1733 /******************** sample image operator ********************/ | |
1734 | |
1735 typedef struct ImageSampleInfo { | |
1736 ARegionType *art; | |
1737 void *draw_handle; | |
1738 int x, y; | |
1739 int channels; | |
1740 | |
1741 char col[4]; | |
1742 float colf[4]; | |
1743 int z; | |
1744 float zf; | |
1745 | |
1746 char *colp; | |
1747 float *colfp; | |
1748 int *zp; | |
1749 float *zfp; | |
1750 | |
1751 int draw; | |
1752 } ImageSampleInfo; | |
1753 | |
1754 static void image_sample_draw(const bContext *UNUSED(C), ARegion *ar, void *arg_
info) | |
1755 { | |
1756 ImageSampleInfo *info= arg_info; | |
1757 if(info->draw) { | |
1758 /* no color management needed for images (color_manage=0) */ | |
1759 draw_image_info(ar, 0, info->channels, info->x, info->y, info->c
olp, info->colfp, info->zp, info->zfp); | |
1760 } | |
1761 } | |
1762 | |
1763 static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) | |
1764 { | |
1765 SpaceImage *sima= CTX_wm_space_image(C); | |
1766 ARegion *ar= CTX_wm_region(C); | |
1767 void *lock; | |
1768 ImBuf *ibuf= ED_space_image_acquire_buffer(sima, &lock); | |
1769 ImageSampleInfo *info= op->customdata; | |
1770 float fx, fy; | |
1771 ········ | |
1772 if(ibuf == NULL) { | |
1773 ED_space_image_release_buffer(sima, lock); | |
1774 return; | |
1775 } | |
1776 | |
1777 UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx,
&fy); | |
1778 | |
1779 if(fx>=0.0f && fy>=0.0f && fx<1.0f && fy<1.0f) { | |
1780 float *fp; | |
1781 char *cp; | |
1782 int x= (int)(fx*ibuf->x), y= (int)(fy*ibuf->y); | |
1783 | |
1784 CLAMP(x, 0, ibuf->x-1); | |
1785 CLAMP(y, 0, ibuf->y-1); | |
1786 | |
1787 info->x= x; | |
1788 info->y= y; | |
1789 info->draw= 1; | |
1790 info->channels= ibuf->channels; | |
1791 | |
1792 info->colp= NULL; | |
1793 info->colfp= NULL; | |
1794 info->zp= NULL; | |
1795 info->zfp= NULL; | |
1796 ················ | |
1797 if(ibuf->rect) { | |
1798 cp= (char *)(ibuf->rect + y*ibuf->x + x); | |
1799 | |
1800 info->col[0]= cp[0]; | |
1801 info->col[1]= cp[1]; | |
1802 info->col[2]= cp[2]; | |
1803 info->col[3]= cp[3]; | |
1804 info->colp= info->col; | |
1805 | |
1806 info->colf[0]= (float)cp[0]/255.0f; | |
1807 info->colf[1]= (float)cp[1]/255.0f; | |
1808 info->colf[2]= (float)cp[2]/255.0f; | |
1809 info->colf[3]= (float)cp[3]/255.0f; | |
1810 info->colfp= info->colf; | |
1811 } | |
1812 if(ibuf->rect_float) { | |
1813 fp= (ibuf->rect_float + (ibuf->channels)*(y*ibuf->x + x)
); | |
1814 | |
1815 info->colf[0]= fp[0]; | |
1816 info->colf[1]= fp[1]; | |
1817 info->colf[2]= fp[2]; | |
1818 info->colf[3]= fp[3]; | |
1819 info->colfp= info->colf; | |
1820 } | |
1821 | |
1822 if(ibuf->zbuf) { | |
1823 info->z= ibuf->zbuf[y*ibuf->x + x]; | |
1824 info->zp= &info->z; | |
1825 } | |
1826 if(ibuf->zbuf_float) { | |
1827 info->zf= ibuf->zbuf_float[y*ibuf->x + x]; | |
1828 info->zfp= &info->zf; | |
1829 } | |
1830 ················ | |
1831 if(sima->cumap && ibuf->channels==4) { | |
1832 /* we reuse this callback for set curves point operators
*/ | |
1833 if(RNA_struct_find_property(op->ptr, "point")) { | |
1834 int point= RNA_enum_get(op->ptr, "point"); | |
1835 | |
1836 if(point == 1) { | |
1837 curvemapping_set_black_white(sima->cumap
, NULL, info->colfp); | |
1838 if(ibuf->rect_float) | |
1839 curvemapping_do_ibuf(sima->cumap
, ibuf); | |
1840 } | |
1841 else if(point == 0) { | |
1842 curvemapping_set_black_white(sima->cumap
, info->colfp, NULL); | |
1843 if(ibuf->rect_float) | |
1844 curvemapping_do_ibuf(sima->cumap
, ibuf); | |
1845 } | |
1846 } | |
1847 } | |
1848 ································ | |
1849 // XXX node curve integration .. | |
1850 #if 0 | |
1851 { | |
1852 ScrArea *sa, *cur= curarea; | |
1853 ························ | |
1854 node_curvemap_sample(fp); /* sends global to node
editor */ | |
1855 for(sa= G.curscreen->areabase.first; sa; sa= sa->next) { | |
1856 if(sa->spacetype==SPACE_NODE) { | |
1857 areawinset(sa->win); | |
1858 scrarea_do_windraw(sa); | |
1859 } | |
1860 } | |
1861 node_curvemap_sample(NULL); /* clears global
in node editor */ | |
1862 curarea= cur; | |
1863 } | |
1864 #endif | |
1865 } | |
1866 else | |
1867 info->draw= 0; | |
1868 | |
1869 ED_space_image_release_buffer(sima, lock); | |
1870 ED_area_tag_redraw(CTX_wm_area(C)); | |
1871 } | |
1872 | |
1873 static void image_sample_exit(bContext *C, wmOperator *op) | |
1874 { | |
1875 ImageSampleInfo *info= op->customdata; | |
1876 | |
1877 ED_region_draw_cb_exit(info->art, info->draw_handle); | |
1878 ED_area_tag_redraw(CTX_wm_area(C)); | |
1879 MEM_freeN(info); | |
1880 } | |
1881 | |
1882 static int image_sample_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
1883 { | |
1884 SpaceImage *sima= CTX_wm_space_image(C); | |
1885 ARegion *ar= CTX_wm_region(C); | |
1886 ImageSampleInfo *info; | |
1887 | |
1888 if(!ED_space_image_has_buffer(sima)) | |
1889 return OPERATOR_CANCELLED; | |
1890 ········ | |
1891 info= MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo"); | |
1892 info->art= ar->type; | |
1893 info->draw_handle = ED_region_draw_cb_activate(ar->type, image_sample_dr
aw, info, REGION_DRAW_POST_PIXEL); | |
1894 op->customdata= info; | |
1895 | |
1896 image_sample_apply(C, op, event); | |
1897 | |
1898 WM_event_add_modal_handler(C, op); | |
1899 | |
1900 return OPERATOR_RUNNING_MODAL; | |
1901 } | |
1902 | |
1903 static int image_sample_modal(bContext *C, wmOperator *op, wmEvent *event) | |
1904 { | |
1905 switch(event->type) { | |
1906 case LEFTMOUSE: | |
1907 case RIGHTMOUSE: // XXX hardcoded | |
1908 image_sample_exit(C, op); | |
1909 return OPERATOR_CANCELLED; | |
1910 case MOUSEMOVE: | |
1911 image_sample_apply(C, op, event); | |
1912 break; | |
1913 } | |
1914 | |
1915 return OPERATOR_RUNNING_MODAL; | |
1916 } | |
1917 | |
1918 static int image_sample_cancel(bContext *C, wmOperator *op) | |
1919 { | |
1920 image_sample_exit(C, op); | |
1921 return OPERATOR_CANCELLED; | |
1922 } | |
1923 | |
1924 void IMAGE_OT_sample(wmOperatorType *ot) | |
1925 { | |
1926 /* identifiers */ | |
1927 ot->name= "Sample Color"; | |
1928 ot->idname= "IMAGE_OT_sample"; | |
1929 ········ | |
1930 /* api callbacks */ | |
1931 ot->invoke= image_sample_invoke; | |
1932 ot->modal= image_sample_modal; | |
1933 ot->cancel= image_sample_cancel; | |
1934 ot->poll= space_image_image_sample_poll; | |
1935 | |
1936 /* flags */ | |
1937 ot->flag= OPTYPE_BLOCKING; | |
1938 } | |
1939 | |
1940 /******************** sample line operator ********************/ | |
1941 static int image_sample_line_exec(bContext *C, wmOperator *op) | |
1942 { | |
1943 SpaceImage *sima= CTX_wm_space_image(C); | |
1944 ARegion *ar= CTX_wm_region(C); | |
1945 Scene *scene= CTX_data_scene(C); | |
1946 ········ | |
1947 int x_start= RNA_int_get(op->ptr, "xstart"); | |
1948 int y_start= RNA_int_get(op->ptr, "ystart"); | |
1949 int x_end= RNA_int_get(op->ptr, "xend"); | |
1950 int y_end= RNA_int_get(op->ptr, "yend"); | |
1951 ········ | |
1952 void *lock; | |
1953 ImBuf *ibuf= ED_space_image_acquire_buffer(sima, &lock); | |
1954 Histogram *hist= &sima->sample_line_hist; | |
1955 ········ | |
1956 float x1f, y1f, x2f, y2f; | |
1957 int x1, y1, x2, y2; | |
1958 int i, x, y; | |
1959 float *fp; | |
1960 float rgb[3]; | |
1961 unsigned char *cp; | |
1962 ········ | |
1963 if (ibuf == NULL) { | |
1964 ED_space_image_release_buffer(sima, lock); | |
1965 return OPERATOR_CANCELLED; | |
1966 } | |
1967 /* hmmmm */ | |
1968 if (ibuf->channels < 3) { | |
1969 ED_space_image_release_buffer(sima, lock); | |
1970 return OPERATOR_CANCELLED; | |
1971 } | |
1972 ········ | |
1973 UI_view2d_region_to_view(&ar->v2d, x_start, y_start, &x1f, &y1f); | |
1974 UI_view2d_region_to_view(&ar->v2d, x_end, y_end, &x2f, &y2f); | |
1975 x1= 0.5f+ x1f*ibuf->x; | |
1976 x2= 0.5f+ x2f*ibuf->x; | |
1977 y1= 0.5f+ y1f*ibuf->y; | |
1978 y2= 0.5f+ y2f*ibuf->y; | |
1979 ········ | |
1980 hist->channels = 3; | |
1981 hist->x_resolution = 256; | |
1982 hist->xmax = 1.0f; | |
1983 hist->ymax = 1.0f; | |
1984 ········ | |
1985 for (i=0; i<256; i++) { | |
1986 x= (int)(0.5f + x1 + (float)i*(x2-x1)/255.0f); | |
1987 y= (int)(0.5f + y1 + (float)i*(y2-y1)/255.0f); | |
1988 ················ | |
1989 if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) { | |
1990 hist->data_luma[i] = hist->data_r[i] = hist->data_g[i]=
hist->data_b[i] = 0.0f; | |
1991 } else { | |
1992 if (ibuf->rect_float) { | |
1993 fp= (ibuf->rect_float + (ibuf->channels)*(y*ibuf
->x + x)); | |
1994 | |
1995 if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT
) | |
1996 linearrgb_to_srgb_v3_v3(rgb, fp); | |
1997 else | |
1998 copy_v3_v3(rgb, fp); | |
1999 | |
2000 hist->data_r[i] = rgb[0]; | |
2001 hist->data_g[i] = rgb[1]; | |
2002 hist->data_b[i] = rgb[2]; | |
2003 hist->data_luma[i] = (0.299f*rgb[0] + 0.587f*rgb
[1] + 0.114f*rgb[2]); | |
2004 } | |
2005 else if (ibuf->rect) { | |
2006 cp= (unsigned char *)(ibuf->rect + y*ibuf->x + x
); | |
2007 hist->data_r[i] = (float)cp[0]/255.0f; | |
2008 hist->data_g[i] = (float)cp[1]/255.0f; | |
2009 hist->data_b[i] = (float)cp[2]/255.0f; | |
2010 hist->data_luma[i] = (0.299f*cp[0] + 0.587f*cp[1
] + 0.114f*cp[2])/255; | |
2011 } | |
2012 } | |
2013 } | |
2014 ········ | |
2015 ED_space_image_release_buffer(sima, lock); | |
2016 ········ | |
2017 ED_area_tag_redraw(CTX_wm_area(C)); | |
2018 ········ | |
2019 return OPERATOR_FINISHED; | |
2020 } | |
2021 | |
2022 static int image_sample_line_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
2023 { | |
2024 SpaceImage *sima= CTX_wm_space_image(C); | |
2025 ········ | |
2026 if(!ED_space_image_has_buffer(sima)) | |
2027 return OPERATOR_CANCELLED; | |
2028 ········ | |
2029 return WM_gesture_straightline_invoke(C, op, event); | |
2030 } | |
2031 | |
2032 void IMAGE_OT_sample_line(wmOperatorType *ot) | |
2033 { | |
2034 /* identifiers */ | |
2035 ot->name= "Sample Line"; | |
2036 ot->idname= "IMAGE_OT_sample_line"; | |
2037 ········ | |
2038 /* api callbacks */ | |
2039 ot->invoke= image_sample_line_invoke; | |
2040 ot->modal= WM_gesture_straightline_modal; | |
2041 ot->exec= image_sample_line_exec; | |
2042 ot->poll= space_image_main_area_poll; | |
2043 ot->cancel= WM_gesture_straightline_cancel; | |
2044 ········ | |
2045 /* flags */ | |
2046 ot->flag= 0; /* no undo/register since this operates on the space */ | |
2047 ········ | |
2048 WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT); | |
2049 } | |
2050 | |
2051 /******************** set curve point operator ********************/ | |
2052 | |
2053 void IMAGE_OT_curves_point_set(wmOperatorType *ot) | |
2054 { | |
2055 static EnumPropertyItem point_items[]= { | |
2056 {0, "BLACK_POINT", 0, "Black Point", ""}, | |
2057 {1, "WHITE_POINT", 0, "White Point", ""}, | |
2058 {0, NULL, 0, NULL, NULL}}; | |
2059 | |
2060 /* identifiers */ | |
2061 ot->name= "Set Curves Point"; | |
2062 ot->idname= "IMAGE_OT_curves_point_set"; | |
2063 | |
2064 /* flags */ | |
2065 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2066 ········ | |
2067 /* api callbacks */ | |
2068 ot->invoke= image_sample_invoke; | |
2069 ot->modal= image_sample_modal; | |
2070 ot->cancel= image_sample_cancel; | |
2071 ot->poll= space_image_main_area_not_uv_brush_poll; | |
2072 | |
2073 /* properties */ | |
2074 RNA_def_enum(ot->srna, "point", point_items, 0, "Point", "Set black poin
t or white point for curves"); | |
2075 } | |
2076 | |
2077 /******************** record composite operator *********************/ | |
2078 | |
2079 typedef struct RecordCompositeData { | |
2080 wmTimer *timer; | |
2081 int old_cfra; | |
2082 int sfra, efra; | |
2083 } RecordCompositeData; | |
2084 | |
2085 static int image_record_composite_apply(bContext *C, wmOperator *op) | |
2086 { | |
2087 SpaceImage *sima= CTX_wm_space_image(C); | |
2088 RecordCompositeData *rcd= op->customdata; | |
2089 Scene *scene= CTX_data_scene(C); | |
2090 ImBuf *ibuf; | |
2091 ········ | |
2092 WM_timecursor(CTX_wm_window(C), scene->r.cfra); | |
2093 | |
2094 // XXX scene->nodetree->test_break= blender_test_break; | |
2095 // XXX scene->nodetree->test_break= NULL; | |
2096 ········ | |
2097 BKE_image_all_free_anim_ibufs(scene->r.cfra); | |
2098 ntreeCompositTagAnimated(scene->nodetree); | |
2099 ntreeCompositExecTree(scene->nodetree, &scene->r, scene->r.cfra != rcd->
old_cfra); /* 1 is no previews */ | |
2100 | |
2101 ED_area_tag_redraw(CTX_wm_area(C)); | |
2102 ········ | |
2103 ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); | |
2104 /* save memory in flipbooks */ | |
2105 if(ibuf) | |
2106 imb_freerectfloatImBuf(ibuf); | |
2107 ········ | |
2108 scene->r.cfra++; | |
2109 | |
2110 return (scene->r.cfra <= rcd->efra); | |
2111 } | |
2112 | |
2113 static int image_record_composite_init(bContext *C, wmOperator *op) | |
2114 { | |
2115 SpaceImage *sima= CTX_wm_space_image(C); | |
2116 Scene *scene= CTX_data_scene(C); | |
2117 RecordCompositeData *rcd; | |
2118 | |
2119 if(sima->iuser.frames < 2) | |
2120 return 0; | |
2121 if(scene->nodetree == NULL) | |
2122 return 0; | |
2123 ········ | |
2124 op->customdata= rcd= MEM_callocN(sizeof(RecordCompositeData), "ImageReco
rdCompositeData"); | |
2125 | |
2126 rcd->old_cfra= scene->r.cfra; | |
2127 rcd->sfra= sima->iuser.sfra; | |
2128 rcd->efra= sima->iuser.sfra + sima->iuser.frames-1; | |
2129 scene->r.cfra= rcd->sfra; | |
2130 | |
2131 return 1; | |
2132 } | |
2133 | |
2134 static void image_record_composite_exit(bContext *C, wmOperator *op) | |
2135 { | |
2136 Scene *scene= CTX_data_scene(C); | |
2137 SpaceImage *sima= CTX_wm_space_image(C); | |
2138 RecordCompositeData *rcd= op->customdata; | |
2139 | |
2140 scene->r.cfra= rcd->old_cfra; | |
2141 | |
2142 WM_cursor_restore(CTX_wm_window(C)); | |
2143 | |
2144 if(rcd->timer) | |
2145 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rcd->
timer); | |
2146 | |
2147 WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, sima->image); | |
2148 | |
2149 // XXX play_anim(0); | |
2150 // XXX allqueue(REDRAWNODE, 1); | |
2151 | |
2152 MEM_freeN(rcd); | |
2153 } | |
2154 | |
2155 static int image_record_composite_exec(bContext *C, wmOperator *op) | |
2156 { | |
2157 if(!image_record_composite_init(C, op)) | |
2158 return OPERATOR_CANCELLED; | |
2159 ········ | |
2160 while(image_record_composite_apply(C, op)) | |
2161 ; | |
2162 ········ | |
2163 image_record_composite_exit(C, op); | |
2164 ········ | |
2165 return OPERATOR_FINISHED; | |
2166 } | |
2167 | |
2168 static int image_record_composite_invoke(bContext *C, wmOperator *op, wmEvent *U
NUSED(event)) | |
2169 { | |
2170 RecordCompositeData *rcd; | |
2171 ········ | |
2172 if(!image_record_composite_init(C, op)) | |
2173 return OPERATOR_CANCELLED; | |
2174 | |
2175 rcd= op->customdata; | |
2176 rcd->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIME
R, 0.0f); | |
2177 WM_event_add_modal_handler(C, op); | |
2178 | |
2179 if(!image_record_composite_apply(C, op)) | |
2180 return OPERATOR_FINISHED; | |
2181 | |
2182 return OPERATOR_RUNNING_MODAL; | |
2183 } | |
2184 | |
2185 static int image_record_composite_modal(bContext *C, wmOperator *op, wmEvent *ev
ent) | |
2186 { | |
2187 RecordCompositeData *rcd= op->customdata; | |
2188 | |
2189 switch(event->type) { | |
2190 case TIMER: | |
2191 if(rcd->timer == event->customdata) { | |
2192 if(!image_record_composite_apply(C, op)) { | |
2193 image_record_composite_exit(C, op); | |
2194 return OPERATOR_FINISHED; | |
2195 } | |
2196 } | |
2197 break; | |
2198 case ESCKEY: | |
2199 image_record_composite_exit(C, op); | |
2200 return OPERATOR_FINISHED; | |
2201 } | |
2202 | |
2203 return OPERATOR_RUNNING_MODAL; | |
2204 } | |
2205 | |
2206 static int image_record_composite_cancel(bContext *C, wmOperator *op) | |
2207 { | |
2208 image_record_composite_exit(C, op); | |
2209 return OPERATOR_CANCELLED; | |
2210 } | |
2211 | |
2212 void IMAGE_OT_record_composite(wmOperatorType *ot) | |
2213 { | |
2214 /* identifiers */ | |
2215 ot->name= "Record Composite"; | |
2216 ot->idname= "IMAGE_OT_record_composite"; | |
2217 ········ | |
2218 /* api callbacks */ | |
2219 ot->exec= image_record_composite_exec; | |
2220 ot->invoke= image_record_composite_invoke; | |
2221 ot->modal= image_record_composite_modal; | |
2222 ot->cancel= image_record_composite_cancel; | |
2223 ot->poll= space_image_buffer_exists_poll; | |
2224 } | |
2225 | |
2226 /********************* cycle render slot operator *********************/ | |
2227 | |
2228 static int image_cycle_render_slot_poll(bContext *C) | |
2229 { | |
2230 Image *ima= CTX_data_edit_image(C); | |
2231 | |
2232 return (ima && ima->type == IMA_TYPE_R_RESULT); | |
2233 } | |
2234 | |
2235 static int image_cycle_render_slot_exec(bContext *C, wmOperator *op) | |
2236 { | |
2237 Image *ima= CTX_data_edit_image(C); | |
2238 int a, slot, cur= ima->render_slot; | |
2239 const short use_reverse= RNA_boolean_get(op->ptr, "reverse"); | |
2240 | |
2241 for(a=1; a<IMA_MAX_RENDER_SLOT; a++) { | |
2242 slot= (cur + (use_reverse ? -a:a))%IMA_MAX_RENDER_SLOT; | |
2243 if(slot<0) slot+=IMA_MAX_RENDER_SLOT; | |
2244 | |
2245 if(ima->renders[slot] || slot == ima->last_render_slot) { | |
2246 ima->render_slot= slot; | |
2247 break; | |
2248 } | |
2249 else if((slot - 1) == ima->last_render_slot && slot < IMA_MAX_RE
NDER_SLOT) { | |
2250 ima->render_slot= slot; | |
2251 break; | |
2252 } | |
2253 } | |
2254 | |
2255 if(a == IMA_MAX_RENDER_SLOT) | |
2256 ima->render_slot= ((cur == 1)? 0: 1); | |
2257 ········ | |
2258 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL); | |
2259 | |
2260 /* no undo push for browsing existing */ | |
2261 if(ima->renders[ima->render_slot] || ima->render_slot==ima->last_render_
slot) | |
2262 return OPERATOR_CANCELLED; | |
2263 ········ | |
2264 return OPERATOR_FINISHED; | |
2265 } | |
2266 | |
2267 void IMAGE_OT_cycle_render_slot(wmOperatorType *ot) | |
2268 { | |
2269 /* identifiers */ | |
2270 ot->name= "Cycle Render Slot"; | |
2271 ot->idname= "IMAGE_OT_cycle_render_slot"; | |
2272 ········ | |
2273 /* api callbacks */ | |
2274 ot->exec= image_cycle_render_slot_exec; | |
2275 ot->poll= image_cycle_render_slot_poll; | |
2276 | |
2277 /* flags */ | |
2278 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; | |
2279 | |
2280 RNA_def_boolean(ot->srna, "reverse", 0, "Cycle in Reverse", ""); | |
2281 } | |
2282 | |
2283 /******************** TODO ********************/ | |
2284 | |
2285 /* XXX notifier? */ | |
2286 | |
2287 /* goes over all ImageUsers, and sets frame numbers if auto-refresh is set */ | |
2288 | |
2289 void ED_image_update_frame(const Main *mainp, int cfra) | |
2290 { | |
2291 wmWindowManager *wm; | |
2292 wmWindow *win; | |
2293 Tex *tex; | |
2294 ········ | |
2295 /* texture users */ | |
2296 for(tex= mainp->tex.first; tex; tex= tex->id.next) { | |
2297 if(tex->type==TEX_IMAGE && tex->ima) { | |
2298 if(ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENC
E)) { | |
2299 if(tex->iuser.flag & IMA_ANIM_ALWAYS) | |
2300 BKE_image_user_calc_frame(&tex->iuser, c
fra, 0); | |
2301 } | |
2302 } | |
2303 } | |
2304 ········ | |
2305 /* image window, compo node users */ | |
2306 for(wm=mainp->wm.first; wm; wm= wm->id.next) { /* only 1 wm */ | |
2307 for(win= wm->windows.first; win; win= win->next) { | |
2308 ScrArea *sa; | |
2309 for(sa= win->screen->areabase.first; sa; sa= sa->next) { | |
2310 if(sa->spacetype==SPACE_VIEW3D) { | |
2311 View3D *v3d= sa->spacedata.first; | |
2312 BGpic *bgpic; | |
2313 for(bgpic= v3d->bgpicbase.first; bgpic;
bgpic= bgpic->next) | |
2314 if(bgpic->iuser.flag & IMA_ANIM_
ALWAYS) | |
2315 BKE_image_user_calc_fram
e(&bgpic->iuser, cfra, 0); | |
2316 } | |
2317 else if(sa->spacetype==SPACE_IMAGE) { | |
2318 SpaceImage *sima= sa->spacedata.first; | |
2319 if(sima->iuser.flag & IMA_ANIM_ALWAYS) | |
2320 BKE_image_user_calc_frame(&sima-
>iuser, cfra, 0); | |
2321 } | |
2322 else if(sa->spacetype==SPACE_NODE) { | |
2323 SpaceNode *snode= sa->spacedata.first; | |
2324 if((snode->treetype==NTREE_COMPOSIT) &&
(snode->nodetree)) { | |
2325 bNode *node; | |
2326 for(node= snode->nodetree->nodes
.first; node; node= node->next) { | |
2327 if(node->id && node->typ
e==CMP_NODE_IMAGE) { | |
2328 Image *ima= (Ima
ge *)node->id; | |
2329 ImageUser *iuser
= node->storage; | |
2330 if(ELEM(ima->sou
rce, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) | |
2331 if(iuser
->flag & IMA_ANIM_ALWAYS) | |
2332
BKE_image_user_calc_frame(iuser, cfra, 0); | |
2333 } | |
2334 } | |
2335 } | |
2336 } | |
2337 } | |
2338 } | |
2339 } | |
2340 } | |
2341 | |
LEFT | RIGHT |