Blender V5.0
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_utf8.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"
32
33#define B_MATPRV 1
34
35static void do_preview_buttons(bContext *C, void *arg, int event)
36{
37 switch (event) {
38 case B_MATPRV:
40 break;
41 }
42}
43
45 bContext *C,
46 ID *id,
47 bool show_buttons,
48 ID *parent,
49 MTex *slot,
50 const char *preview_id)
51{
52 Material *ma = nullptr;
53 short *pr_texture = nullptr;
54
55 char _preview_id[sizeof(uiPreview::preview_id)];
56
57 if (id && !ELEM(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA, ID_LS)) {
58 RNA_warning("Expected ID of type material, texture, light, world or line style");
59 return;
60 }
61
62 /* decide what to render */
63 ID *pid = id;
64 ID *pparent = nullptr;
65
66 if (id && (GS(id->name) == ID_TE)) {
67 if (parent && (GS(parent->name) == ID_MA)) {
68 pr_texture = &((Material *)parent)->pr_texture;
69 }
70 else if (parent && (GS(parent->name) == ID_WO)) {
71 pr_texture = &((World *)parent)->pr_texture;
72 }
73 else if (parent && (GS(parent->name) == ID_LA)) {
74 pr_texture = &((Light *)parent)->pr_texture;
75 }
76 else if (parent && (GS(parent->name) == ID_LS)) {
77 pr_texture = &((FreestyleLineStyle *)parent)->pr_texture;
78 }
79
80 if (pr_texture) {
81 if (*pr_texture == TEX_PR_OTHER) {
82 pid = parent;
83 }
84 else if (*pr_texture == TEX_PR_BOTH) {
85 pparent = parent;
86 }
87 }
88 }
89
90 if (!preview_id || (preview_id[0] == '\0')) {
91 /* If no identifier given, generate one from ID type. */
92 SNPRINTF_UTF8(_preview_id, "uiPreview_%s", BKE_idtype_idcode_to_name(GS(id->name)));
93 preview_id = _preview_id;
94 }
95
96 /* Find or add the uiPreview to the current Region. */
97 ARegion *region = CTX_wm_region(C);
98 uiPreview *ui_preview = static_cast<uiPreview *>(
99 BLI_findstring(&region->ui_previews, preview_id, offsetof(uiPreview, preview_id)));
100
101 if (!ui_preview) {
102 ui_preview = MEM_callocN<uiPreview>(__func__);
103 STRNCPY_UTF8(ui_preview->preview_id, preview_id);
104 ui_preview->height = short(UI_UNIT_Y * 7.6f);
105 ui_preview->id_session_uid = pid->session_uid;
106 ui_preview->tag = UI_PREVIEW_TAG_DIRTY;
107 BLI_addtail(&region->ui_previews, ui_preview);
108 }
109 else if (ui_preview->id_session_uid != pid->session_uid) {
110 ui_preview->id_session_uid = pid->session_uid;
111 ui_preview->tag |= UI_PREVIEW_TAG_DIRTY;
112 }
113
114 if (ui_preview->height < UI_UNIT_Y) {
115 ui_preview->height = UI_UNIT_Y;
116 }
117 else if (ui_preview->height > UI_UNIT_Y * 50) { /* Rather high upper limit, yet not insane! */
118 ui_preview->height = UI_UNIT_Y * 50;
119 }
120
121 /* layout */
122 uiBlock *block = layout->block();
123 uiLayout *row = &layout->row(false);
124 uiLayout *col = &row->column(false);
125
126 /* add preview */
127 uiDefBut(
128 block, ButType::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);
162 col->scale_x_set(1.5);
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:164
Blender kernel freestyle line style functionality.
bool BKE_scene_uses_blender_eevee(const Scene *scene)
Definition scene.cc:2824
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_UTF8(dst, format,...)
#define STRNCPY_UTF8(dst, src)
#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
void UI_but_func_drawextra_set(uiBlock *block, std::function< void(const bContext *C, rcti *rect)> func)
void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg)
uiBut * uiDefButS(uiBlock *block, ButType 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)
uiBut * uiDefIconButS(uiBlock *block, ButType 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
uiBut * uiDefBut(uiBlock *block, uiButTypeWithPointerType but_and_ptr_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)
@ UI_ITEM_R_EXPAND
#define UI_ITEM_NONE
#define ND_SHADING_PREVIEW
Definition WM_types.hh:480
#define NC_MATERIAL
Definition WM_types.hh:380
#define offsetof(t, d)
#define GS(x)
uint col
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:414
char name[258]
Definition DNA_ID.h:432
unsigned int session_uid
Definition DNA_ID.h:462
uiBlock * block() const
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)