Blender V4.3
ed_util_ops.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cstring>
12
13#include "DNA_space_types.h"
15
16#include "BLI_fileops.h"
17#include "BLI_utildefines.h"
18
19#include "BKE_context.hh"
20#include "BKE_lib_id.hh"
21#include "BKE_lib_override.hh"
22#include "BKE_preview_image.hh"
23#include "BKE_report.hh"
24
25#include "ED_asset.hh"
26#include "ED_render.hh"
27#include "ED_undo.hh"
28#include "ED_util.hh"
29
30#include "RNA_access.hh"
31#include "RNA_prototypes.hh"
32
33#include "UI_interface.hh"
34
35#include "WM_api.hh"
36#include "WM_types.hh"
37
38/* -------------------------------------------------------------------- */
43{
44 const PointerRNA idptr = CTX_data_pointer_get(C, "id");
45 BLI_assert(!idptr.data || RNA_struct_is_ID(idptr.type));
46
47 const ID *id = (ID *)idptr.data;
48 if (!id) {
49 return false;
50 }
51 if (!ID_IS_EDITABLE(id)) {
52 CTX_wm_operator_poll_msg_set(C, "Can't edit external library data");
53 return false;
54 }
55 if (ID_IS_OVERRIDE_LIBRARY(id)) {
56 CTX_wm_operator_poll_msg_set(C, "Can't edit previews of overridden library data");
57 return false;
58 }
59 if (!BKE_previewimg_id_get_p(id)) {
60 CTX_wm_operator_poll_msg_set(C, "Data-block does not support previews");
61 return false;
62 }
63
64 return true;
65}
66
68{
69 /* #invoke() gets the ID from context and saves it in the custom data. */
70 if (op->customdata) {
71 return static_cast<ID *>(op->customdata);
72 }
73
74 PointerRNA idptr = CTX_data_pointer_get(C, "id");
75 return static_cast<ID *>(idptr.data);
76}
77
79{
80 char filepath[FILE_MAX];
81
82 RNA_string_get(op->ptr, "filepath", filepath);
83
84 if (!BLI_is_file(filepath)) {
85 BKE_reportf(op->reports, RPT_ERROR, "File not found '%s'", filepath);
86 return OPERATOR_CANCELLED;
87 }
88
90 if (!id) {
92 op->reports, RPT_ERROR, "Failed to set preview: no ID in context (incorrect context?)");
93 return OPERATOR_CANCELLED;
94 }
95
96 BKE_previewimg_id_custom_set(id, filepath);
97
99
100 return OPERATOR_FINISHED;
101}
102
110{
112 return WM_operator_filesel(C, op, event);
113}
114
116{
117 ot->name = "Load Custom Preview";
118 ot->description = "Choose an image to help identify the data-block visually";
119 ot->idname = "ED_OT_lib_id_load_custom_preview";
120
121 /* api callbacks */
125
126 /* flags */
128
136}
137
139{
141 return false;
142 }
143
144 const PointerRNA idptr = CTX_data_pointer_get(C, "id");
145 const ID *id = (ID *)idptr.data;
146 const char *disabled_hint = nullptr;
147 if (!ED_preview_id_is_supported(id, &disabled_hint)) {
148 CTX_wm_operator_poll_msg_set(C, disabled_hint);
149 return false;
150 }
151
152 return true;
153}
154
156{
157 using namespace blender::ed;
158 PointerRNA idptr = CTX_data_pointer_get(C, "id");
159 ID *id = (ID *)idptr.data;
160
162
163 PreviewImage *preview = BKE_previewimg_id_get(id);
164 if (preview) {
165 BKE_previewimg_clear(preview);
166 }
167
168 UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true);
169
171 asset::list::storage_tag_main_data_dirty();
172
173 return OPERATOR_FINISHED;
174}
175
177{
178 ot->name = "Generate Preview";
179 ot->description = "Create an automatic preview for the selected data-block";
180 ot->idname = "ED_OT_lib_id_generate_preview";
181
182 /* api callbacks */
185
186 /* flags */
188}
189
191{
193 return false;
194 }
195 if (CTX_data_active_object(C) == nullptr) {
196 return false;
197 }
198 return true;
199}
200
202{
203 using namespace blender::ed;
204 PointerRNA idptr = CTX_data_pointer_get(C, "id");
205 ID *id = (ID *)idptr.data;
206
208
209 Object *object_to_render = CTX_data_active_object(C);
210
212 PreviewImage *preview_image = BKE_previewimg_id_ensure(id);
213 UI_icon_render_id_ex(C, nullptr, &object_to_render->id, ICON_SIZE_PREVIEW, true, preview_image);
214
216 asset::list::storage_tag_main_data_dirty();
217
218 return OPERATOR_FINISHED;
219}
220
222{
223 ot->name = "Generate Preview from Object";
224 ot->description = "Create a preview for this asset by rendering the active object";
225 ot->idname = "ED_OT_lib_id_generate_preview_from_object";
226
227 /* api callbacks */
230
231 /* flags */
233}
234
237/* -------------------------------------------------------------------- */
242{
243 PropertyPointerRNA pprop;
245
247
248 if (pprop.prop) {
249 idptr = RNA_property_pointer_get(&pprop.ptr, pprop.prop);
250 }
251
252 if ((pprop.prop == nullptr) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) {
254 op->reports, RPT_ERROR, "Incorrect context for running data-block fake user toggling");
255 return OPERATOR_CANCELLED;
256 }
257
258 ID *id = (ID *)idptr.data;
259
260 if (!BKE_id_is_editable(CTX_data_main(C), id) ||
261 ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))
262 {
263 BKE_report(op->reports, RPT_ERROR, "Data-block type does not support fake user");
264 return OPERATOR_CANCELLED;
265 }
266
267 if (ID_FAKE_USERS(id)) {
269 }
270 else {
272 }
273
274 return OPERATOR_FINISHED;
275}
276
278{
279 /* identifiers */
280 ot->name = "Toggle Fake User";
281 ot->description = "Save this data-block even if it has no users";
282 ot->idname = "ED_OT_lib_id_fake_user_toggle";
283
284 /* api callbacks */
286
287 /* flags */
289}
290
292{
293 PropertyPointerRNA pprop;
294 PointerRNA idptr;
295
297
298 if (pprop.prop) {
299 idptr = RNA_property_pointer_get(&pprop.ptr, pprop.prop);
300 }
301
302 if ((pprop.prop == nullptr) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) {
304 op->reports, RPT_ERROR, "Incorrect context for running data-block fake user toggling");
305 return OPERATOR_CANCELLED;
306 }
307
308 idptr = {};
309 RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, nullptr);
310 RNA_property_update(C, &pprop.ptr, pprop.prop);
311
312 return OPERATOR_FINISHED;
313}
314
316{
317 /* identifiers */
318 ot->name = "Unlink Data-Block";
319 ot->description = "Remove a usage of a data-block, clearing the assignment";
320 ot->idname = "ED_OT_lib_id_unlink";
321
322 /* api callbacks */
324
325 /* flags */
327}
328
330{
331 const PointerRNA id_ptr = CTX_data_pointer_get_type(C, "id", &RNA_ID);
332 const ID *id = static_cast<ID *>(id_ptr.data);
333
334 return id && ID_IS_OVERRIDE_LIBRARY_REAL(id) && !ID_IS_LINKED(id);
335}
336
338{
339 Main *bmain = CTX_data_main(C);
340 const PointerRNA id_ptr = CTX_data_pointer_get_type(C, "id", &RNA_ID);
341 ID *id = static_cast<ID *>(id_ptr.data);
342
343 const bool is_system_override = BKE_lib_override_library_is_system_defined(bmain, id);
344 if (is_system_override) {
345 /* A system override is not editable. Make it an editable (non-system-defined) one. */
346 id->override_library->flag &= ~LIBOVERRIDE_FLAG_SYSTEM_DEFINED;
347 }
348 else {
349 /* Reset override, which makes it non-editable (i.e. a system define override). */
350 BKE_lib_override_library_id_reset(bmain, id, true);
351
353 WM_event_add_notifier(C, NC_WINDOW, nullptr);
354 }
355
357
358 return OPERATOR_FINISHED;
359}
360
362{
363 /* identifiers */
364 ot->name = "Toggle Library Override Editable";
365 ot->description = "Set if this library override data-block can be edited";
366 ot->idname = "ED_OT_lib_id_override_editable_toggle";
367
368 /* api callbacks */
371
372 /* flags */
374}
375
378/* -------------------------------------------------------------------- */
383{
384 Main *bmain = CTX_data_main(C);
386 return OPERATOR_FINISHED;
387}
388
390{
391 /* identifiers */
392 ot->name = "Flush Edits";
393 ot->description = "Flush edit data from active editing modes";
394 ot->idname = "ED_OT_flush_edits";
395
396 /* api callbacks */
398
399 /* flags */
401}
402
PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
Object * CTX_data_active_object(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2456
void id_fake_user_set(ID *id)
Definition lib_id.cc:389
void id_fake_user_clear(ID *id)
Definition lib_id.cc:397
bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id)
void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root, bool do_reset_system_override)
PreviewImage * BKE_previewimg_id_get(const ID *id)
PreviewImage * BKE_previewimg_id_ensure(ID *id)
PreviewImage ** BKE_previewimg_id_get_p(const ID *id)
void BKE_previewimg_id_custom_set(ID *id, const char *filepath)
void BKE_previewimg_clear(PreviewImage *prv)
void BKE_previewimg_id_free(ID *id)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
#define BLI_assert(a)
Definition BLI_assert.h:50
File and directory operations.
bool BLI_is_file(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:438
#define FILE_MAX
#define ELEM(...)
#define ID_FAKE_USERS(id)
Definition DNA_ID.h:616
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition DNA_ID.h:676
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:658
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:683
@ ICON_SIZE_PREVIEW
@ ID_WS
@ ID_TXT
@ ID_SCE
@ ID_SCR
@ ID_GR
@ ID_OB
@ FILE_SORT_DEFAULT
@ FILE_SPECIAL
@ FILE_TYPE_FOLDER
@ FILE_TYPE_IMAGE
@ FILE_DEFAULTDISPLAY
bool ED_preview_id_is_supported(const ID *id, const char **r_disabled_hint=nullptr)
void ED_preview_kill_jobs(wmWindowManager *wm, Main *bmain)
void ED_OT_redo(wmOperatorType *ot)
Definition ed_undo.cc:614
void ED_OT_undo_redo(wmOperatorType *ot)
Definition ed_undo.cc:626
void ED_OT_undo_push(wmOperatorType *ot)
Definition ed_undo.cc:583
void ED_OT_undo(wmOperatorType *ot)
Definition ed_undo.cc:571
void ED_OT_undo_history(wmOperatorType *ot)
Definition ed_undo.cc:769
bool ED_editors_flush_edits(Main *bmain)
Definition ed_util.cc:331
constexpr PointerRNA PointerRNA_NULL
Definition RNA_types.hh:45
void UI_context_active_but_prop_get_templateID(const bContext *C, PointerRNA *r_ptr, PropertyRNA **r_prop)
void UI_icon_render_id(const bContext *C, Scene *scene, ID *id, enum eIconSizes size, bool use_job)
void UI_icon_render_id_ex(const bContext *C, Scene *scene, ID *id_to_render, const enum eIconSizes size, const bool use_job, PreviewImage *r_preview_image)
@ WM_FILESEL_FILEPATH
Definition WM_api.hh:936
@ FILE_OPENFILE
Definition WM_api.hh:945
@ OPTYPE_INTERNAL
Definition WM_types.hh:182
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_WINDOW
Definition WM_types.hh:342
#define NC_WM
Definition WM_types.hh:341
#define ND_LIB_OVERRIDE_CHANGED
Definition WM_types.hh:386
#define NA_EDITED
Definition WM_types.hh:550
#define NC_ASSET
Definition WM_types.hh:371
#define ND_SPACE_VIEW3D
Definition WM_types.hh:494
#define NC_SPACE
Definition WM_types.hh:359
static bool lib_id_generate_preview_poll(bContext *C)
static int lib_id_fake_user_toggle_exec(bContext *C, wmOperator *op)
void ED_operatortypes_edutils()
static void ED_OT_lib_id_generate_preview(wmOperatorType *ot)
static int lib_id_load_custom_preview_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int lib_id_generate_preview_from_object_exec(bContext *C, wmOperator *)
static void ED_OT_lib_id_unlink(wmOperatorType *ot)
static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op)
static void ED_OT_lib_id_generate_preview_from_object(wmOperatorType *ot)
static int ed_flush_edits_exec(bContext *C, wmOperator *)
static void ED_OT_flush_edits(wmOperatorType *ot)
static ID * lib_id_load_custom_preview_id_get(bContext *C, const wmOperator *op)
static bool lib_id_generate_preview_from_object_poll(bContext *C)
static void ED_OT_lib_id_override_editable_toggle(wmOperatorType *ot)
static bool lib_id_override_editable_toggle_poll(bContext *C)
static bool lib_id_preview_editing_poll(bContext *C)
static void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot)
static void ED_OT_lib_id_fake_user_toggle(wmOperatorType *ot)
static int lib_id_generate_preview_exec(bContext *C, wmOperator *)
static int lib_id_override_editable_toggle_exec(bContext *C, wmOperator *)
static int lib_id_unlink_exec(bContext *C, wmOperator *op)
#define GS(x)
Definition iris.cc:202
bool RNA_struct_is_ID(const StructRNA *type)
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value, ReportList *reports)
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
bool RNA_pointer_is_null(const PointerRNA *ptr)
Definition DNA_ID.h:413
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
PropertyRNA * prop
Definition RNA_types.hh:49
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
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
struct ReportList * reports
struct PointerRNA * ptr
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
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)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *)