Blender V5.0
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
9
10#include <cerrno>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_path_utils.hh"
16#include "BLI_string_utf8.h"
17#include "BLI_utildefines.h"
18
19#include "IMB_imbuf.hh"
20#include "IMB_imbuf_types.hh"
21
22#include "DNA_scene_types.h"
23#include "DNA_screen_types.h"
24#include "DNA_space_types.h"
25
26#include "BKE_context.hh"
27#include "BKE_global.hh"
28#include "BKE_image.hh"
29#include "BKE_image_format.hh"
30#include "BKE_main.hh"
31#include "BKE_report.hh"
32#include "BKE_screen.hh"
33
34#include "BLT_translation.hh"
35
36#include "RNA_access.hh"
37#include "RNA_prototypes.hh"
38
39#include "UI_interface.hh"
41
42#include "WM_api.hh"
43#include "WM_types.hh"
44
45#include "screen_intern.hh"
46
55
56/* call from both exec and invoke */
58{
59 int dumprect_size[2];
60
61 wmWindow *win = CTX_wm_window(C);
62
63 /* do redraw so we don't show popups/menus */
65
66 uint8_t *dumprect = WM_window_pixels_read(C, win, dumprect_size);
67
68 if (dumprect) {
70
71 scd->dumpsx = dumprect_size[0];
72 scd->dumpsy = dumprect_size[1];
73 scd->dumprect = dumprect;
74 if (area) {
75 scd->crop = area->totrct;
76 }
77
79
80 op->customdata = scd;
81
82 return true;
83 }
84 op->customdata = nullptr;
85 return false;
86}
87
89{
90 ScreenshotData *scd = static_cast<ScreenshotData *>(op->customdata);
91
92 if (scd) {
93 if (scd->dumprect) {
94 MEM_freeN(scd->dumprect);
95 }
96 MEM_freeN(scd);
97 op->customdata = nullptr;
98 }
99}
100
102{
103 const bool use_crop = STREQ(op->idname, "SCREEN_OT_screenshot_area");
104 ScreenshotData *scd = static_cast<ScreenshotData *>(op->customdata);
105 bool ok = false;
106
107 if (scd == nullptr) {
108 /* when running exec directly */
109 screenshot_data_create(C, op, use_crop ? CTX_wm_area(C) : nullptr);
110 scd = static_cast<ScreenshotData *>(op->customdata);
111 }
112
113 if (scd) {
114 if (scd->dumprect) {
115 ImBuf *ibuf;
116 char filepath[FILE_MAX];
117
118 RNA_string_get(op->ptr, "filepath", filepath);
120
121 /* operator ensures the extension */
122 ibuf = IMB_allocImBuf(scd->dumpsx, scd->dumpsy, 24, 0);
124
125 /* crop to show only single editor */
126 if (use_crop) {
127 IMB_rect_crop(ibuf, &scd->crop);
128 scd->dumprect = ibuf->byte_buffer.data;
129 }
130
131 if ((scd->im_format.planes == R_IMF_PLANES_BW) &&
133 {
134 /* bw screenshot? - users will notice if it fails! */
135 IMB_color_to_bw(ibuf);
136 }
137 if (BKE_imbuf_write(ibuf, filepath, &scd->im_format)) {
138 ok = true;
139 }
140 else {
141 BKE_reportf(op->reports, RPT_ERROR, "Could not write image: %s", strerror(errno));
142 }
143
144 IMB_freeImBuf(ibuf);
145 }
146 }
147
149
151}
152
154{
155 const bool use_crop = STREQ(op->idname, "SCREEN_OT_screenshot_area");
156 ScrArea *area = nullptr;
157 if (use_crop) {
158 area = CTX_wm_area(C);
159 bScreen *screen = CTX_wm_screen(C);
160 ScrArea *area_test = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->xy);
161 if (area_test != nullptr) {
162 area = area_test;
163 }
164 }
165
166 if (screenshot_data_create(C, op, area)) {
167 if (RNA_struct_property_is_set(op->ptr, "filepath")) {
168 return screenshot_exec(C, op);
169 }
170
171 /* extension is added by 'screenshot_check' after */
172 char filepath[FILE_MAX];
173 const char *blendfile_path = BKE_main_blendfile_path_from_global();
174 if (blendfile_path[0] != '\0') {
175 STRNCPY(filepath, blendfile_path);
176 BLI_path_extension_strip(filepath); /* Strip `.blend`. */
177 }
178 else {
179 /* As the file isn't saved, only set the name and let the file selector pick a directory. */
180 STRNCPY_UTF8(filepath, DATA_("screen"));
181 }
182 RNA_string_set(op->ptr, "filepath", filepath);
183
185
187 }
188 return OPERATOR_CANCELLED;
189}
190
191static bool screenshot_check(bContext * /*C*/, wmOperator *op)
192{
193 ScreenshotData *scd = static_cast<ScreenshotData *>(op->customdata);
195}
196
197static void screenshot_cancel(bContext * /*C*/, wmOperator *op)
198{
200}
201
203 PropertyRNA *prop,
204 void * /*user_data*/)
205{
206 const char *prop_id = RNA_property_identifier(prop);
207
208 return !STREQ(prop_id, "filepath");
209}
210
212{
213 uiLayout *layout = op->layout;
214 ScreenshotData *scd = static_cast<ScreenshotData *>(op->customdata);
215
216 layout->use_property_split_set(true);
217 layout->use_property_decorate_set(false);
218
219 /* image template */
220 PointerRNA ptr = RNA_pointer_create_discrete(nullptr, &RNA_ImageFormatSettings, &scd->im_format);
221 uiTemplateImageSettings(layout, C, &ptr, false);
222
223 /* main draw call */
224 uiDefAutoButsRNA(layout,
225 op->ptr,
227 nullptr,
228 nullptr,
230 false);
231}
232
234{
235 if (G.background) {
236 return false;
237 }
238
239 return WM_operator_winactive(C);
240}
241
259
261{
262 ot->name = "Save Screenshot";
263 ot->idname = "SCREEN_OT_screenshot";
264 ot->description = "Capture a picture of the whole Blender window";
265
267
268 ot->flag = 0;
269}
270
272{
273 /* NOTE: the term "area" is a Blender internal name, "Editor" makes more sense for the UI. */
274 ot->name = "Save Screenshot (Editor)";
275 ot->idname = "SCREEN_OT_screenshot_area";
276 ot->description = "Capture a picture of an editor";
277
279
281}
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 char * BKE_main_blendfile_path_from_global()
Definition main.cc:892
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_ERROR
Definition BKE_report.hh:39
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
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
#define STRNCPY_UTF8(dst, src)
#define STREQ(a, b)
#define DATA_(msgid)
@ R_IMF_PLANES_BW
@ R_IMF_IMTYPE_MULTILAYER
@ FILE_SORT_DEFAULT
@ FILE_SPECIAL
@ FILE_TYPE_FOLDER
@ FILE_TYPE_IMAGE
@ FILE_DEFAULTDISPLAY
#define SPACE_TYPE_ANY
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
void IMB_color_to_bw(ImBuf *ibuf)
void IMB_rect_crop(ImBuf *ibuf, const rcti *crop)
Definition rectop.cc:241
void IMB_freeImBuf(ImBuf *ibuf)
ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
void IMB_assign_byte_buffer(ImBuf *ibuf, uint8_t *buffer_data, ImBufOwnership ownership)
@ IB_DO_NOT_TAKE_OWNERSHIP
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
void uiTemplateImageSettings(uiLayout *layout, bContext *C, PointerRNA *imfptr, bool color_management, const char *panel_idname=nullptr)
@ 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)
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:1124
@ FILE_SAVE
Definition WM_api.hh:1134
@ OPTYPE_DEPENDS_ON_CURSOR
Definition WM_types.hh:218
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
PointerRNA RNA_pointer_create_discrete(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 void screenshot_draw(bContext *C, wmOperator *op)
static int screenshot_data_create(bContext *C, wmOperator *op, ScrArea *area)
Definition screendump.cc:57
static bool screenshot_draw_check_prop(PointerRNA *, PropertyRNA *prop, void *)
static wmOperatorStatus screenshot_exec(bContext *C, wmOperator *op)
static wmOperatorStatus screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void screen_screenshot_impl(wmOperatorType *ot)
static void screenshot_cancel(bContext *, wmOperator *op)
void SCREEN_OT_screenshot_area(wmOperatorType *ot)
static void screenshot_data_free(wmOperator *op)
Definition screendump.cc:88
ImBufByteBuffer byte_buffer
ImageFormatData im_format
Definition screendump.cc:53
uint8_t * dumprect
Definition screendump.cc:48
void use_property_decorate_set(bool is_sep)
void use_property_split_set(bool value)
int xy[2]
Definition WM_types.hh:761
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:1484
void WM_redraw_windows(bContext *C)
Definition wm_draw.cc:1695
void WM_event_add_fileselect(bContext *C, wmOperator *op)
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
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)