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); }