Nodes: Move preview images to an overlay #108001

Merged
Brecht Van Lommel merged 44 commits from Kdaf/blender:main into main 2023-07-12 16:14:21 +02:00
10 changed files with 110 additions and 70 deletions

View File

@ -816,6 +816,10 @@ class NODE_PT_overlay(Panel):
col.prop(overlay, "show_context_path", text="Context Path")
col.prop(snode, "show_annotation", text="Annotations")
if snode.supports_preview:
col.separator()
col.prop(overlay, "show_previews", text="Previews")
if snode.tree_type == 'GeometryNodeTree':
col.separator()
col.prop(overlay, "show_timing", text="Timings")

View File

@ -27,7 +27,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 9
#define BLENDER_FILE_SUBVERSION 10
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@ -259,8 +259,6 @@ class bNodeRuntime : NonCopyable, NonMovable {
short preview_xsize, preview_ysize = 0;
/** Entire bound-box (world-space). */
rctf totr{};
/** Optional preview area. */
rctf prvr{};
/** Used at runtime when going through the tree. Initialize before use. */
short tmp_flag = 0;

View File

@ -324,6 +324,19 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 400, 10)) {
LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
if (space->spacetype == SPACE_NODE) {
SpaceNode *snode = reinterpret_cast<SpaceNode *>(space);
snode->overlay.flag |= SN_OVERLAY_SHOW_PREVIEWS;
}
}
}
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -93,6 +93,7 @@ bool ED_node_is_compositor(struct SpaceNode *snode);
bool ED_node_is_shader(struct SpaceNode *snode);
bool ED_node_is_texture(struct SpaceNode *snode);
bool ED_node_is_geometry(struct SpaceNode *snode);
bool ED_node_supports_preview(struct SpaceNode *snode);
/**
* Assumes nothing being done in ntree yet, sets the default in/out node.

View File

@ -433,44 +433,6 @@ static void node_update_basis(const bContext &C,
dy -= NODE_DY / 4;
}
node.runtime->prvr.xmin = loc.x + NODE_DYS;
node.runtime->prvr.xmax = loc.x + NODE_WIDTH(node) - NODE_DYS;
/* preview rect? */
if (node.flag & NODE_PREVIEW) {
float aspect = 1.0f;
if (node.runtime->preview_xsize && node.runtime->preview_ysize) {
aspect = float(node.runtime->preview_ysize) / float(node.runtime->preview_xsize);
}
dy -= NODE_DYS / 2;
node.runtime->prvr.ymax = dy;
if (aspect <= 1.0f) {
node.runtime->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
}
else {
/* Width correction of image. XXX huh? (ton) */
float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
node.runtime->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
node.runtime->prvr.xmin += 0.5f * dx;
node.runtime->prvr.xmax -= 0.5f * dx;
}
dy = node.runtime->prvr.ymin - NODE_DYS / 2;
/* Make sure that maximums are bigger or equal to minimums. */
if (node.runtime->prvr.xmax < node.runtime->prvr.xmin) {
std::swap(node.runtime->prvr.xmax, node.runtime->prvr.xmin);
}
if (node.runtime->prvr.ymax < node.runtime->prvr.ymin) {
std::swap(node.runtime->prvr.ymax, node.runtime->prvr.ymin);
}
}
/* Buttons rect? */
if (node_options) {
dy -= NODE_DYS / 2;
@ -1407,11 +1369,14 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
GPU_blend(GPU_BLEND_NONE);
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformThemeColorShadeAlpha(TH_BACK, -15, +100);
imm_draw_box_wire_2d(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
immUnbindProgram();
float black[4] = {0.f, 0.f, 0.f, 1.f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
const float outline_width = 1.0f;
draw_rect.xmin -= outline_width;
draw_rect.xmax += outline_width;
draw_rect.ymin -= outline_width;
draw_rect.ymax += outline_width;
UI_draw_roundbox_4fv(&draw_rect, false, BASIS_RAD / 2, black);
}
/* Common handle function for operator buttons that need to select the node first. */
@ -2120,10 +2085,11 @@ static void node_draw_extra_info_row(const bNode &node,
static void node_draw_extra_info_panel(TreeDrawContext &tree_draw_ctx,
const SpaceNode &snode,
const bNode &node,
bNodePreview *preview,
uiBlock &block)
{
Vector<NodeExtraInfoRow> extra_info_rows = node_get_extra_info(tree_draw_ctx, snode, node);
if (extra_info_rows.size() == 0) {
if (extra_info_rows.size() == 0 && !preview) {
return;
}
@ -2140,10 +2106,38 @@ static void node_draw_extra_info_panel(TreeDrawContext &tree_draw_ctx,
extra_info_rect.ymax = rct.ymin + 2.0f * UI_SCALE_FAC;
}
else {
float preview_height = 0;
rctf preview_rect;
extra_info_rect.xmin = rct.xmin + 3.0f * UI_SCALE_FAC;
extra_info_rect.xmax = rct.xmin + width;
extra_info_rect.xmax = extra_info_rect.xmin + width;
extra_info_rect.ymin = rct.ymax;
extra_info_rect.ymax = rct.ymax + extra_info_rows.size() * (20.0f * UI_SCALE_FAC);
if (preview) {
if (preview->xsize > preview->ysize) {
const float preview_padding = 3.0f * UI_SCALE_FAC;
preview_height = (width - 2.0 * preview_padding) * float(preview->ysize) /
float(preview->xsize) +
2.0 * preview_padding;
preview_rect.ymin = extra_info_rect.ymin + preview_padding;
preview_rect.ymax = extra_info_rect.ymin + preview_height - preview_padding;
preview_rect.xmin = extra_info_rect.xmin + preview_padding;
preview_rect.xmax = extra_info_rect.xmax - preview_padding;
extra_info_rect.ymax += preview_height;
}
else {
const float preview_padding = 3.0f * UI_SCALE_FAC;
preview_height = width;
const float preview_width = (width - 2.0 * preview_padding) * float(preview->xsize) /
float(preview->ysize) +
2.0 * preview_padding;
preview_rect.ymin = extra_info_rect.ymin + preview_padding;
preview_rect.ymax = extra_info_rect.ymin + preview_height - preview_padding;
preview_rect.xmin = extra_info_rect.xmin + preview_padding + (width - preview_width) / 2;
preview_rect.xmax = extra_info_rect.xmax - preview_padding - (width - preview_width) / 2;
extra_info_rect.ymax += preview_height;
}
}
if (node.flag & NODE_MUTED) {
UI_GetThemeColorBlend4f(TH_BACK, TH_NODE, 0.2f, color);
@ -2159,17 +2153,23 @@ static void node_draw_extra_info_panel(TreeDrawContext &tree_draw_ctx,
/* Draw outline. */
const float outline_width = 1.0f;
extra_info_rect.xmin = rct.xmin + 3.0f * UI_SCALE_FAC - outline_width;
extra_info_rect.xmax = rct.xmin + width + outline_width;
extra_info_rect.ymin = rct.ymax - outline_width;
extra_info_rect.ymax = rct.ymax + outline_width +
extra_info_rows.size() * (20.0f * UI_SCALE_FAC);
extra_info_rect.xmin -= outline_width;
extra_info_rect.xmax += outline_width;
extra_info_rect.ymin -= outline_width;
extra_info_rect.ymax += outline_width;
UI_GetThemeColorBlendShade4fv(TH_BACK, TH_NODE, 0.4f, -20, color);
UI_draw_roundbox_corner_set(
UI_CNR_ALL & ~UI_CNR_BOTTOM_LEFT &
((rct.xmax) > extra_info_rect.xmax ? ~UI_CNR_BOTTOM_RIGHT : UI_CNR_ALL));
UI_draw_roundbox_4fv(&extra_info_rect, false, BASIS_RAD, color);
if (preview) {
node_draw_preview(preview, &preview_rect);
}
/* Resize the rect to draw the textual infos on top of the preview. */
Kdaf marked this conversation as resolved Outdated
Comment style https://wiki.blender.org/wiki/Style_Guide/C_Cpp#Comments
extra_info_rect.ymin += preview_height;
}
for (int row : extra_info_rows.index_range()) {
@ -2187,9 +2187,15 @@ static void node_draw_basis(const bContext &C,
bNodeInstanceKey key)
{
const float iconbutw = NODE_HEADER_ICON_SIZE;
bNodeInstanceHash *previews =
static_cast<bNodeInstanceHash *>(CTX_data_pointer_get(&C, "node_previews").data);
Kdaf marked this conversation as resolved Outdated

static_cast

`static_cast`
/* Skip if out of view. */
if (BLI_rctf_isect(&node.runtime->totr, &v2d.cur, nullptr) == false) {
rctf rect_with_preview = node.runtime->totr;
if (node.flag & NODE_PREVIEW && previews && snode.overlay.flag & SN_OVERLAY_SHOW_PREVIEWS) {
rect_with_preview.ymax += NODE_WIDTH(node);
}
if (BLI_rctf_isect(&rect_with_preview, &v2d.cur, nullptr) == false) {
UI_block_end(&C, &block);
return;
}
@ -2205,7 +2211,15 @@ static void node_draw_basis(const bContext &C,
GPU_line_width(1.0f);
node_draw_extra_info_panel(tree_draw_ctx, snode, node, block);
bNodePreview *preview = nullptr;
if (node.flag & NODE_PREVIEW && previews && snode.overlay.flag & SN_OVERLAY_SHOW_PREVIEWS) {
preview = static_cast<bNodePreview *>(BKE_node_instance_hash_lookup(previews, key));
Kdaf marked this conversation as resolved Outdated

static_cast

`static_cast`
if (!preview || !(preview->xsize && preview->ysize)) {
preview = nullptr;
}
}
node_draw_extra_info_panel(tree_draw_ctx, snode, node, preview, block);
/* Header. */
{
@ -2491,18 +2505,6 @@ static void node_draw_basis(const bContext &C,
node_draw_sockets(v2d, C, ntree, node, block, true, false);
}
/* Preview. */
bNodeInstanceHash *previews =
(bNodeInstanceHash *)CTX_data_pointer_get(&C, "node_previews").data;
if (node.flag & NODE_PREVIEW && previews) {
bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_lookup(previews, key);
if (preview && (preview->xsize && preview->ysize)) {
if (preview->rect && !BLI_rctf_is_empty(&node.runtime->prvr)) {
node_draw_preview(preview, &node.runtime->prvr);
}
}
}
UI_block_end(&C, &block);
UI_block_draw(&C, &block);
}
@ -2524,7 +2526,7 @@ static void node_draw_hidden(const bContext &C,
const int color_id = node_get_colorid(tree_draw_ctx, node);
node_draw_extra_info_panel(tree_draw_ctx, snode, node, block);
node_draw_extra_info_panel(tree_draw_ctx, snode, node, nullptr, block);
/* Shadow. */
node_draw_shadow(snode, node, hiddenrad, 1.0f);
@ -3010,7 +3012,7 @@ static void frame_node_draw(const bContext &C,
/* Label and text. */
frame_node_draw_label(tree_draw_ctx, ntree, node, snode);
node_draw_extra_info_panel(tree_draw_ctx, snode, node, block);
node_draw_extra_info_panel(tree_draw_ctx, snode, node, nullptr, block);
UI_block_end(&C, &block);
UI_block_draw(&C, &block);

View File

@ -503,6 +503,11 @@ bool ED_node_is_geometry(SpaceNode *snode)
return STREQ(snode->tree_idname, ntreeType_Geometry->idname);
}
bool ED_node_supports_preview(SpaceNode *snode)
{
return ED_node_is_compositor(snode);
}
void ED_node_shader_default(const bContext *C, ID *id)
{
Main *bmain = CTX_data_main(C);

View File

@ -242,7 +242,7 @@ static SpaceLink *node_create(const ScrArea * /*area*/, const Scene * /*scene*/)
snode->flag = SNODE_SHOW_GPENCIL | SNODE_USE_ALPHA;
snode->overlay.flag = (SN_OVERLAY_SHOW_OVERLAYS | SN_OVERLAY_SHOW_WIRE_COLORS |
SN_OVERLAY_SHOW_PATH);
SN_OVERLAY_SHOW_PATH | SN_OVERLAY_SHOW_PREVIEWS);
/* backdrop */
snode->zoom = 1.0f;

View File

@ -1564,6 +1564,7 @@ typedef enum eSpaceNodeOverlay_Flag {
SN_OVERLAY_SHOW_TIMINGS = (1 << 3),
SN_OVERLAY_SHOW_PATH = (1 << 4),
SN_OVERLAY_SHOW_NAMED_ATTRIBUTES = (1 << 5),
SN_OVERLAY_SHOW_PREVIEWS = (1 << 6),
} eSpaceNodeOverlay_Flag;
typedef struct SpaceNode {

View File

@ -2502,6 +2502,11 @@ static PointerRNA rna_SpaceNode_overlay_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_SpaceNodeOverlay, ptr->data);
}
static bool rna_SpaceNode_supports_previews(PointerRNA *ptr)
{
return ED_node_supports_preview(static_cast<SpaceNode *>(ptr->data));
Kdaf marked this conversation as resolved Outdated

static_cast

`static_cast`
}
static char *rna_SpaceNodeOverlay_path(const PointerRNA * /*ptr*/)
{
return BLI_strdup("overlay");
@ -7402,6 +7407,13 @@ static void rna_def_space_node_overlay(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Show Named Attributes", "Show when nodes are using named attributes");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, nullptr);
prop = RNA_def_property(srna, "show_previews", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "overlay.flag", SN_OVERLAY_SHOW_PREVIEWS);
RNA_def_property_boolean_default(prop, false);
RNA_def_property_ui_text(
prop, "Show Node Previews", "Display each node's preview if node is toggled");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, nullptr);
}
static void rna_def_space_node(BlenderRNA *brna)
@ -7621,6 +7633,10 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Overlay Settings", "Settings for display of overlays in the Node Editor");
prop = RNA_def_property(srna, "supports_preview", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_SpaceNode_supports_previews", nullptr);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
rna_def_space_node_overlay(brna);
RNA_api_space_node(srna);
}