Blender V4.3
screendump.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10#include <cerrno>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_blenlib.h"
16#include "BLI_utildefines.h"
17
18#include "IMB_imbuf.hh"
19#include "IMB_imbuf_types.hh"
20
21#include "DNA_scene_types.h"
22#include "DNA_screen_types.h"
23#include "DNA_space_types.h"
24
25#include "BKE_context.hh"
26#include "BKE_global.hh"
27#include "BKE_image.hh"
28#include "BKE_image_format.hh"
29#include "BKE_main.hh"
30#include "BKE_report.hh"
31#include "BKE_screen.hh"
32
33#include "BLT_translation.hh"
34
35#include "RNA_access.hh"
36#include "RNA_prototypes.hh"
37
38#include "UI_interface.hh"
39
40#include "WM_api.hh"
41#include "WM_types.hh"
42
43#include "screen_intern.hh"
44
53
54/* call from both exec and invoke */
56{
57 int dumprect_size[2];
58
59 wmWindow *win = CTX_wm_window(C);
60
61 /* do redraw so we don't show popups/menus */
63
64 uint8_t *dumprect = WM_window_pixels_read(C, win, dumprect_size);
65
66 if (dumprect) {
67 ScreenshotData *scd = static_cast<ScreenshotData *>(
68 MEM_callocN(sizeof(ScreenshotData), "screenshot"));
69
70 scd->dumpsx = dumprect_size[0];
71 scd->dumpsy = dumprect_size[1];
72 scd->dumprect = dumprect;
73 if (area) {
74 scd->crop = area->totrct;
75 }
76
77 BKE_image_format_init(&scd->im_format, false);
78
79 op->customdata = scd;
80
81 return true;
82 }
83 op->customdata = nullptr;
84 return false;
85}
86
88{
89 ScreenshotData *scd = static_cast<ScreenshotData *>(op->customdata);
90
91 if (scd) {
92 if (scd->dumprect) {
93 MEM_freeN(scd->dumprect);
94 }
95 MEM_freeN(scd);
96 op->customdata = nullptr;
97 }
98}
99
101{
102 const bool use_crop = STREQ(op->idname, "SCREEN_OT_screenshot_area");
103 ScreenshotData *scd = static_cast<ScreenshotData *>(op->customdata);
104 bool ok = false;
105
106 if (scd == nullptr) {
107 /* when running exec directly */
108 screenshot_data_create(C, op, use_crop ? CTX_wm_area(C) : nullptr);
109 scd = static_cast<ScreenshotData *>(op->customdata);
110 }
111
112 if (scd) {
113 if (scd->dumprect) {
114 ImBuf *ibuf;
115 char filepath[FILE_MAX];
116
117 RNA_string_get(op->ptr, "filepath", filepath);
119
120 /* operator ensures the extension */
121 ibuf = IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0);
123
124 /* crop to show only single editor */
125 if (use_crop) {
126 IMB_rect_crop(ibuf, &scd->crop);
127 scd->dumprect = ibuf->byte_buffer.data;
128 }
129
130 if ((scd->im_format.planes == R_IMF_PLANES_BW) &&
132 {
133 /* bw screenshot? - users will notice if it fails! */
134 IMB_color_to_bw(ibuf);
135 }
136 if (BKE_imbuf_write(ibuf, filepath, &scd->im_format)) {
137 ok = true;
138 }
139 else {
140 BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno));
141 }
142
143 IMB_freeImBuf(ibuf);
144 }
145 }
146
148
150}
151
152static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *event)
153{
154 const bool use_crop = STREQ(op->idname, "SCREEN_OT_screenshot_area");
155 ScrArea *area = nullptr;
156 if (use_crop) {
157 area = CTX_wm_area(C);
158 bScreen *screen = CTX_wm_screen(C);
159 ScrArea *area_test = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->xy);
160 if (area_test != nullptr) {
161 area = area_test;
162 }
163 }
164
165 if (screenshot_data_create(C, op, area)) {
166 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
167 return screenshot_exec(C, op);
168 }
169
170 /* extension is added by 'screenshot_check' after */
171 char filepath[FILE_MAX];
172 const char *blendfile_path = BKE_main_blendfile_path_from_global();
173 if (blendfile_path[0] != '\0') {
174 STRNCPY(filepath, blendfile_path);
175 BLI_path_extension_strip(filepath); /* Strip `.blend`. */
176 }
177 else {
178 /* As the file isn't saved, only set the name and let the file selector pick a directory. */
179 STRNCPY(filepath, DATA_("screen"));
180 }
181 RNA_string_set(op->ptr, "filepath", filepath);
182
184
186 }
187 return OPERATOR_CANCELLED;
188}
189
190static bool screenshot_check(bContext * /*C*/, wmOperator *op)
191{
192 ScreenshotData *scd = static_cast<ScreenshotData *>(op->customdata);
194}
195
196static void screenshot_cancel(bContext * /*C*/, wmOperator *op)
197{
199}
200
202 PropertyRNA *prop,
203 void * /*user_data*/)
204{
205 const char *prop_id = RNA_property_identifier(prop);
206
207 return !STREQ(prop_id, "filepath");
208}
209
210static void screenshot_draw(bContext * /*C*/, wmOperator *op)
211{
212 uiLayout *layout = op->layout;
213 ScreenshotData *scd = static_cast<ScreenshotData *>(op->customdata);
214
215 uiLayoutSetPropSep(layout, true);
216 uiLayoutSetPropDecorate(layout, false);
217
218 /* image template */
219 PointerRNA ptr = RNA_pointer_create(nullptr, &RNA_ImageFormatSettings, &scd->im_format);
220 uiTemplateImageSettings(layout, &ptr, false);
221
222 /* main draw call */
223 uiDefAutoButsRNA(layout,
224 op->ptr,
226 nullptr,
227 nullptr,
229 false);
230}
231
233{
234 if (G.background) {
235 return false;
236 }
237
238 return WM_operator_winactive(C);
239}
240
258
260{
261 ot->name = "Save Screenshot";
262 ot->idname = "SCREEN_OT_screenshot";
263 ot->description = "Capture a picture of the whole Blender window";
264
266
267 ot->flag = 0;
268}
269
271{
272 /* NOTE: the term "area" is a Blender internal name, "Editor" makes more sense for the UI. */
273 ot->name = "Save Screenshot (Editor)";
274 ot->idname = "SCREEN_OT_screenshot_area";
275 ot->description = "Capture a picture of an editor";
276
278
280}
bScreen * CTX_wm_screen(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
bool BKE_imbuf_write(ImBuf *ibuf, const char *filepath, const ImageFormatData *imf)
void BKE_image_format_init(ImageFormatData *imf, const bool render)
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:837
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
ScrArea ScrArea * BKE_screen_find_area_xy(const bScreen *screen, int spacetype, const int xy[2]) ATTR_NONNULL(1
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
bool bool BLI_path_extension_strip(char *path) ATTR_NONNULL(1)
#define FILE_MAX
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define STREQ(a, b)
#define DATA_(msgid)
@ R_IMF_IMTYPE_MULTILAYER
@ R_IMF_PLANES_BW
@ FILE_SORT_DEFAULT
@ FILE_SPECIAL
@ FILE_TYPE_FOLDER
@ FILE_TYPE_IMAGE
@ FILE_DEFAULTDISPLAY
#define SPACE_TYPE_ANY
@ OPERATOR_RUNNING_MODAL
void IMB_color_to_bw(ImBuf *ibuf)
Definition divers.cc:838
void IMB_rect_crop(ImBuf *ibuf, const rcti *crop)
Definition rectop.cc:240
void IMB_assign_byte_buffer(ImBuf *ibuf, uint8_t *buffer_data, ImBufOwnership ownership)
Contains defines and structs used throughout the imbuf module.
@ IB_DO_NOT_TAKE_OWNERSHIP
Read Guarded memory(de)allocation.
void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
@ UI_BUT_LABEL_ALIGN_NONE
eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, PointerRNA *ptr, bool(*check_prop)(PointerRNA *ptr, PropertyRNA *prop, void *user_data), void *user_data, PropertyRNA *prop_activate_init, eButLabelAlign label_align, bool compact)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:936
@ FILE_SAVE
Definition WM_api.hh:946
@ OPTYPE_DEPENDS_ON_CURSOR
Definition WM_types.hh:198
struct ImBuf * IMB_allocImBuf(unsigned int, unsigned int, unsigned char, unsigned int)
void IMB_freeImBuf(ImBuf *)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
#define G(x, y, z)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
const char * RNA_property_identifier(const PropertyRNA *prop)
static bool screenshot_poll(bContext *C)
static bool screenshot_check(bContext *, wmOperator *op)
void SCREEN_OT_screenshot(wmOperatorType *ot)
static int screenshot_data_create(bContext *C, wmOperator *op, ScrArea *area)
Definition screendump.cc:55
static bool screenshot_draw_check_prop(PointerRNA *, PropertyRNA *prop, void *)
static void screen_screenshot_impl(wmOperatorType *ot)
static void screenshot_cancel(bContext *, wmOperator *op)
void SCREEN_OT_screenshot_area(wmOperatorType *ot)
static int screenshot_exec(bContext *C, wmOperator *op)
static void screenshot_data_free(wmOperator *op)
Definition screendump.cc:87
static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void screenshot_draw(bContext *, wmOperator *op)
unsigned char uint8_t
Definition stdint.h:78
ImBufByteBuffer byte_buffer
ImageFormatData im_format
Definition screendump.cc:51
uint8_t * dumprect
Definition screendump.cc:46
int xy[2]
Definition WM_types.hh:726
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
bool(* check)(bContext *C, wmOperator *op)
Definition WM_types.hh:1014
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
struct ReportList * reports
struct uiLayout * layout
struct PointerRNA * ptr
uint8_t * WM_window_pixels_read(bContext *C, wmWindow *win, int r_size[2])
Definition wm_draw.cc:1411
void WM_redraw_windows(bContext *C)
Definition wm_draw.cc:1621
void WM_event_add_fileselect(bContext *C, wmOperator *op)
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
void WM_operator_properties_filesel(wmOperatorType *ot, const int filter, const short type, const eFileSel_Action action, const eFileSel_Flag flag, const short display, const short sort)
bool WM_operator_winactive(bContext *C)
bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const ImageFormatData *im_format)