From 1ebdd2d9cf8e7abc81041fb3ae4240c54ab130ac Mon Sep 17 00:00:00 2001 From: Colin Marmond Date: Wed, 12 Jul 2023 16:14:12 +0200 Subject: [PATCH] Nodes: Move preview images to an overlay Move the node previews to the overlay region, atop each node. It allows nodes to keep the same size when the preview is toggled, which is more convenient for large nodes and large nodetrees. The preview has to be drawn from `node_draw_extra_info_panel` because there could be overlapping between info text and the preview. When the node is out of the view, it also has to make sure that the preview is also out of the view before exiting the draw function. Pull Request: https://projects.blender.org/blender/blender/pulls/108001 --- scripts/startup/bl_ui/space_node.py | 4 + .../blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/BKE_node_runtime.hh | 2 - .../blenloader/intern/versioning_400.cc | 13 ++ source/blender/editors/include/ED_node.h | 1 + .../blender/editors/space_node/node_draw.cc | 134 +++++++++--------- .../blender/editors/space_node/node_edit.cc | 5 + .../blender/editors/space_node/space_node.cc | 2 +- source/blender/makesdna/DNA_space_types.h | 1 + source/blender/makesrna/intern/rna_space.cc | 16 +++ 10 files changed, 110 insertions(+), 70 deletions(-) diff --git a/scripts/startup/bl_ui/space_node.py b/scripts/startup/bl_ui/space_node.py index d4713bcbf8f..c034e8b2b2e 100644 --- a/scripts/startup/bl_ui/space_node.py +++ b/scripts/startup/bl_ui/space_node.py @@ -817,6 +817,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") diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index f590cc3158a..dedc081597c 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -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 diff --git a/source/blender/blenkernel/BKE_node_runtime.hh b/source/blender/blenkernel/BKE_node_runtime.hh index 15477093117..ebd5c02803b 100644 --- a/source/blender/blenkernel/BKE_node_runtime.hh +++ b/source/blender/blenkernel/BKE_node_runtime.hh @@ -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; diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 92a89587ec2..0462c91e227 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -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(space); + snode->overlay.flag |= SN_OVERLAY_SHOW_PREVIEWS; + } + } + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index b2cec27b584..732d5fb8225 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -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. diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 6a3a05f59ee..e115e22b318 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -434,44 +434,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; @@ -1408,11 +1370,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. */ @@ -2121,10 +2086,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 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; } @@ -2141,10 +2107,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); @@ -2160,17 +2154,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. */ + extra_info_rect.ymin += preview_height; } for (int row : extra_info_rows.index_range()) { @@ -2188,9 +2188,15 @@ static void node_draw_basis(const bContext &C, bNodeInstanceKey key) { const float iconbutw = NODE_HEADER_ICON_SIZE; + bNodeInstanceHash *previews = + static_cast(CTX_data_pointer_get(&C, "node_previews").data); /* 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; } @@ -2211,7 +2217,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(BKE_node_instance_hash_lookup(previews, key)); + if (!preview || !(preview->xsize && preview->ysize)) { + preview = nullptr; + } + } + + node_draw_extra_info_panel(tree_draw_ctx, snode, node, preview, block); /* Header. */ { @@ -2501,18 +2515,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); } @@ -2534,7 +2536,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); @@ -3020,7 +3022,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); diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 78ff2c698e2..8363c4bd0be 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -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); diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index 5a5b44ef9f7..23f594c319c 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -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; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index da14fba18d8..8ccf1dd3d37 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1566,6 +1566,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 { diff --git a/source/blender/makesrna/intern/rna_space.cc b/source/blender/makesrna/intern/rna_space.cc index f6c0105ef1e..81a1d3365b2 100644 --- a/source/blender/makesrna/intern/rna_space.cc +++ b/source/blender/makesrna/intern/rna_space.cc @@ -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(ptr->data)); +} + static char *rna_SpaceNodeOverlay_path(const PointerRNA * /*ptr*/) { return BLI_strdup("overlay"); @@ -7404,6 +7409,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) @@ -7623,6 +7635,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); }