Blender V4.5
interface_template_preview.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BKE_context.hh"
10#include "BKE_idtype.hh"
11#include "BKE_linestyle.h"
12#include "BKE_scene.hh"
13
14#include "BLI_listbase.h"
15#include "BLI_string.h"
16
17#include "BLT_translation.hh"
18
19#include "DNA_light_types.h"
20#include "DNA_material_types.h"
21#include "DNA_texture_types.h"
22#include "DNA_world_types.h"
23
24#include "ED_render.hh"
25
26#include "RNA_access.hh"
27
28#include "WM_api.hh"
29
30#include "UI_interface.hh"
31
32#define B_MATPRV 1
33
34static void do_preview_buttons(bContext *C, void *arg, int event)
35{
36 switch (event) {
37 case B_MATPRV:
39 break;
40 }
41}
42
44 bContext *C,
45 ID *id,
46 bool show_buttons,
47 ID *parent,
48 MTex *slot,
49 const char *preview_id)
50{
51 Material *ma = nullptr;
52 short *pr_texture = nullptr;
53
54 char _preview_id[sizeof(uiPreview::preview_id)];
55
56 if (id && !ELEM(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA, ID_LS)) {
57 RNA_warning("Expected ID of type material, texture, light, world or line style");
58 return;
59 }
60
61 /* decide what to render */
62 ID *pid = id;
63 ID *pparent = nullptr;
64
65 if (id && (GS(id->name) == ID_TE)) {
66 if (parent && (GS(parent->name) == ID_MA)) {
67 pr_texture = &((Material *)parent)->pr_texture;
68 }
69 else if (parent && (GS(parent->name) == ID_WO)) {
70 pr_texture = &((World *)parent)->pr_texture;
71 }
72 else if (parent && (GS(parent->name) == ID_LA)) {
73 pr_texture = &((Light *)parent)->pr_texture;
74 }
75 else if (parent && (GS(parent->name) == ID_LS)) {
76 pr_texture = &((FreestyleLineStyle *)parent)->pr_texture;
77 }
78
79 if (pr_texture) {
80 if (*pr_texture == TEX_PR_OTHER) {
81 pid = parent;
82 }
83 else if (*pr_texture == TEX_PR_BOTH) {
84 pparent = parent;
85 }
86 }
87 }
88
89 if (!preview_id || (preview_id[0] == '\0')) {
90 /* If no identifier given, generate one from ID type. */
91 SNPRINTF(_preview_id, "uiPreview_%s", BKE_idtype_idcode_to_name(GS(id->name)));
92 preview_id = _preview_id;
93 }
94
95 /* Find or add the uiPreview to the current Region. */
96 ARegion *region = CTX_wm_region(C);
97 uiPreview *ui_preview = static_cast<uiPreview *>(
98 BLI_findstring(&region->ui_previews, preview_id, offsetof(uiPreview, preview_id)));
99
100 if (!ui_preview) {
101 ui_preview = MEM_callocN<uiPreview>(__func__);
102 STRNCPY(ui_preview->preview_id, preview_id);
103 ui_preview->height = short(UI_UNIT_Y * 7.6f);
104 ui_preview->id_session_uid = pid->session_uid;
105 ui_preview->tag = UI_PREVIEW_TAG_DIRTY;
106 BLI_addtail(&region->ui_previews, ui_preview);
107 }
108 else if (ui_preview->id_session_uid != pid->session_uid) {
109 ui_preview->id_session_uid = pid->session_uid;
110 ui_preview->tag |= UI_PREVIEW_TAG_DIRTY;
111 }
112
113 if (ui_preview->height < UI_UNIT_Y) {
114 ui_preview->height = UI_UNIT_Y;
115 }
116 else if (ui_preview->height > UI_UNIT_Y * 50) { /* Rather high upper limit, yet not insane! */
117 ui_preview->height = UI_UNIT_Y * 50;
118 }
119
120 /* layout */
121 uiBlock *block = uiLayoutGetBlock(layout);
122 uiLayout *row = &layout->row(false);
123 uiLayout *col = &row->column(false);
125
126 /* add preview */
127 uiDefBut(
128 block, UI_BTYPE_EXTRA, 0, "", 0, 0, UI_UNIT_X * 10, ui_preview->height, pid, 0.0, 0.0, "");
130 [pid, pparent, slot, ui_preview](const bContext *C, rcti *rect) {
131 ED_preview_draw(C, pid, pparent, slot, ui_preview, rect);
132 });
134
135 uiDefIconButS(block,
137 0,
138 ICON_GRIP,
139 0,
140 0,
141 UI_UNIT_X * 10,
142 short(UI_UNIT_Y * 0.3f),
143 &ui_preview->height,
144 UI_UNIT_Y,
145 UI_UNIT_Y * 50.0f,
146 "");
147
148 /* add buttons */
149 if (pid && show_buttons) {
150 if (GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
151 if (GS(pid->name) == ID_MA) {
152 ma = (Material *)pid;
153 }
154 else {
155 ma = (Material *)pparent;
156 }
157
158 /* Create RNA Pointer */
159 PointerRNA material_ptr = RNA_id_pointer_create(&ma->id);
160
161 col = &row->column(true);
163 col->prop(&material_ptr, "preview_render_type", UI_ITEM_R_EXPAND, "", ICON_NONE);
164
165 /* EEVEE preview file has baked lighting so use_preview_world has no effect,
166 * just hide the option until this feature is supported. */
168 col->separator();
169 col->prop(&material_ptr, "use_preview_world", UI_ITEM_NONE, "", ICON_WORLD);
170 }
171 }
172
173 if (pr_texture) {
174 /* Create RNA Pointer */
175 PointerRNA texture_ptr = RNA_id_pointer_create(id);
176
177 layout->row(true);
178 uiDefButS(block,
180 B_MATPRV,
181 IFACE_("Texture"),
182 0,
183 0,
184 UI_UNIT_X * 10,
185 UI_UNIT_Y,
186 pr_texture,
187 10,
189 "");
190 if (GS(parent->name) == ID_MA) {
191 uiDefButS(block,
193 B_MATPRV,
194 IFACE_("Material"),
195 0,
196 0,
197 UI_UNIT_X * 10,
198 UI_UNIT_Y,
199 pr_texture,
200 10,
202 "");
203 }
204 else if (GS(parent->name) == ID_LA) {
205 uiDefButS(block,
207 B_MATPRV,
209 0,
210 0,
211 UI_UNIT_X * 10,
212 UI_UNIT_Y,
213 pr_texture,
214 10,
216 "");
217 }
218 else if (GS(parent->name) == ID_WO) {
219 uiDefButS(block,
221 B_MATPRV,
223 0,
224 0,
225 UI_UNIT_X * 10,
226 UI_UNIT_Y,
227 pr_texture,
228 10,
230 "");
231 }
232 else if (GS(parent->name) == ID_LS) {
233 uiDefButS(block,
235 B_MATPRV,
236 IFACE_("Line Style"),
237 0,
238 0,
239 UI_UNIT_X * 10,
240 UI_UNIT_Y,
241 pr_texture,
242 10,
244 "");
245 }
246 uiDefButS(block,
248 B_MATPRV,
249 IFACE_("Both"),
250 0,
251 0,
252 UI_UNIT_X * 10,
253 UI_UNIT_Y,
254 pr_texture,
255 10,
257 "");
258
259 /* Alpha button for texture preview */
260 if (*pr_texture != TEX_PR_OTHER) {
261 row = &layout->row(false);
262 row->prop(&texture_ptr, "use_preview_alpha", UI_ITEM_NONE, std::nullopt, ICON_NONE);
263 }
264 }
265 }
266}
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
const char * BKE_idtype_idcode_to_name(short idcode)
Definition idtype.cc:165
Blender kernel freestyle line style functionality.
bool BKE_scene_uses_blender_eevee(const Scene *scene)
Definition scene.cc:2821
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#define ELEM(...)
#define BLT_I18NCONTEXT_ID_WORLD
#define BLT_I18NCONTEXT_ID_LIGHT
#define CTX_IFACE_(context, msgid)
#define IFACE_(msgid)
@ ID_TE
@ ID_LA
@ ID_LS
@ ID_WO
@ ID_MA
@ UI_PREVIEW_TAG_DIRTY
@ TEX_PR_OTHER
@ TEX_PR_BOTH
@ TEX_PR_TEXTURE
void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, uiPreview *ui_preview, rcti *rect)
#define RNA_warning(format,...)
#define C
Definition RandGen.cpp:29
#define UI_UNIT_Y
uiBut * uiDefButS(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, short *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_but_func_drawextra_set(uiBlock *block, std::function< void(const bContext *C, rcti *rect)> func)
uiBut * uiDefBut(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg)
uiBut * uiDefIconButS(uiBlock *block, int type, int retval, int icon, int x, int y, short width, short height, short *poin, float min, float max, std::optional< blender::StringRef > tip)
#define UI_UNIT_X
@ UI_BTYPE_EXTRA
@ UI_BTYPE_ROW
@ UI_BTYPE_GRIP
@ UI_ITEM_R_EXPAND
uiBlock * uiLayoutGetBlock(uiLayout *layout)
void uiLayoutSetScaleX(uiLayout *layout, float scale)
#define UI_ITEM_NONE
void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect)
#define ND_SHADING_PREVIEW
Definition WM_types.hh:477
#define NC_MATERIAL
Definition WM_types.hh:377
#define offsetof(t, d)
uint col
#define GS(a)
void uiTemplatePreview(uiLayout *layout, bContext *C, ID *id, bool show_buttons, ID *parent, MTex *slot, const char *preview_id)
#define B_MATPRV
static void do_preview_buttons(bContext *C, void *arg, int event)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
PointerRNA RNA_id_pointer_create(ID *id)
ListBase ui_previews
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
unsigned int session_uid
Definition DNA_ID.h:444
uiLayout & column(bool align)
uiLayout & row(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
char preview_id[64]
unsigned int id_session_uid
void WM_event_add_notifier(const bContext *C, uint type, void *reference)