diff options
Diffstat (limited to 'source/blender/editors/util')
-rw-r--r-- | source/blender/editors/util/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/editors/util/ed_draw.c | 3 | ||||
-rw-r--r-- | source/blender/editors/util/ed_transverts.c | 4 | ||||
-rw-r--r-- | source/blender/editors/util/ed_util.c | 19 | ||||
-rw-r--r-- | source/blender/editors/util/ed_util_imbuf.c | 10 | ||||
-rw-r--r-- | source/blender/editors/util/ed_util_ops.cc | 10 | ||||
-rw-r--r-- | source/blender/editors/util/ed_viewer_path.cc | 365 |
7 files changed, 389 insertions, 24 deletions
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index a9e6adc6e60..128cb897ac4 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -28,6 +28,7 @@ set(SRC ed_util.c ed_util_imbuf.c ed_util_ops.cc + ed_viewer_path.cc gizmo_utils.c numinput.c select_utils.c @@ -89,6 +90,7 @@ set(SRC ../include/ED_uvedit.h ../include/ED_view3d.h ../include/ED_view3d_offscreen.h + ../include/ED_viewer_path.hh ../include/UI_abstract_view.hh ../include/UI_grid_view.hh ../include/UI_icons.h diff --git a/source/blender/editors/util/ed_draw.c b/source/blender/editors/util/ed_draw.c index 7ec3d3c1ef4..80bf732e173 100644 --- a/source/blender/editors/util/ed_draw.c +++ b/source/blender/editors/util/ed_draw.c @@ -484,6 +484,7 @@ float ED_slider_factor_get(struct tSlider *slider) void ED_slider_factor_set(struct tSlider *slider, const float factor) { + slider->raw_factor = factor; slider->factor = factor; if (!slider->overshoot) { slider->factor = clamp_f(slider->factor, 0, 1); @@ -768,7 +769,7 @@ void ED_region_image_metadata_draw( GPU_matrix_translate_2f(x, y); GPU_matrix_scale_2f(zoomx, zoomy); - BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f * U.pixelsize, U.dpi); + BLF_size(blf_mono_font, style->widgetlabel.points * U.dpi_fac); /* *** upper box*** */ diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c index ef57f9e9b33..334516bfd6c 100644 --- a/source/blender/editors/util/ed_transverts.c +++ b/source/blender/editors/util/ed_transverts.c @@ -318,8 +318,8 @@ void ED_transverts_create_from_obedit(TransVertStore *tvs, const Object *obedit, if (ebo->layer & arm->layer) { const bool tipsel = (ebo->flag & BONE_TIPSEL) != 0; const bool rootsel = (ebo->flag & BONE_ROOTSEL) != 0; - const bool rootok = (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && - (ebo->parent->flag & BONE_TIPSEL))); + const bool rootok = !(ebo->parent && (ebo->flag & BONE_CONNECTED) && + (ebo->parent->flag & BONE_TIPSEL)); if ((tipsel && rootsel) || (rootsel)) { /* Don't add the tip (unless mode & TM_ALL_JOINTS, for getting all joints), diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index e70851aedd6..92d65688bf1 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -54,22 +54,19 @@ #include "WM_api.h" #include "WM_types.h" -/* ********* general editor util funcs, not BKE stuff please! ********* */ +/* ********* general editor util functions, not BKE stuff please! ********* */ void ED_editors_init_for_undo(Main *bmain) { wmWindowManager *wm = bmain->wm.first; LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + Scene *scene = WM_window_get_active_scene(win); ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Base *base = view_layer->basact; - if (base != NULL) { - Object *ob = base->object; - if (ob->mode & OB_MODE_TEXTURE_PAINT) { - Scene *scene = WM_window_get_active_scene(win); - - BKE_texpaint_slots_refresh_object(scene, ob); - ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); - } + BKE_view_layer_synced_ensure(scene, view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); + if (ob && (ob->mode & OB_MODE_TEXTURE_PAINT)) { + BKE_texpaint_slots_refresh_object(scene, ob); + ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL); } } } @@ -377,7 +374,7 @@ void unpack_menu(bContext *C, char local_name[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; BLI_split_file_part(abs_name, fi, sizeof(fi)); - BLI_path_join(local_name, sizeof(local_name), "//", folder, fi, NULL); + BLI_path_join(local_name, sizeof(local_name), "//", folder, fi); if (!STREQ(abs_name, local_name)) { switch (BKE_packedfile_compare_to_file(blendfile_path, local_name, pf)) { case PF_CMP_NOFILE: diff --git a/source/blender/editors/util/ed_util_imbuf.c b/source/blender/editors/util/ed_util_imbuf.c index f222f93d2b6..b1c8fc42d08 100644 --- a/source/blender/editors/util/ed_util_imbuf.c +++ b/source/blender/editors/util/ed_util_imbuf.c @@ -52,13 +52,13 @@ typedef struct ImageSampleInfo { int width, height; int sample_size; - unsigned char col[4]; + uchar col[4]; float colf[4]; float linearcol[4]; int z; float zf; - unsigned char *colp; + uchar *colp; const float *colfp; int *zp; float *zfp; @@ -79,7 +79,7 @@ static void image_sample_pixel_color_ubyte(const ImBuf *ibuf, uchar r_col[4], float r_col_linear[4]) { - const uchar *cp = (unsigned char *)(ibuf->rect + coord[1] * ibuf->x + coord[0]); + const uchar *cp = (uchar *)(ibuf->rect + coord[1] * ibuf->x + coord[0]); copy_v4_v4_uchar(r_col, cp); rgba_uchar_to_float(r_col_linear, r_col); IMB_colormanagement_colorspace_to_scene_linear_v4(r_col_linear, false, ibuf->rect_colorspace); @@ -311,7 +311,7 @@ static void sequencer_sample_apply(bContext *C, wmOperator *op, const wmEvent *e if (fx >= 0.0f && fy >= 0.0f && fx < ibuf->x && fy < ibuf->y) { const float *fp; - unsigned char *cp; + uchar *cp; int x = (int)fx, y = (int)fy; info->x = x; @@ -323,7 +323,7 @@ static void sequencer_sample_apply(bContext *C, wmOperator *op, const wmEvent *e info->colfp = NULL; if (ibuf->rect) { - cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); + cp = (uchar *)(ibuf->rect + y * ibuf->x + x); info->col[0] = cp[0]; info->col[1] = cp[1]; diff --git a/source/blender/editors/util/ed_util_ops.cc b/source/blender/editors/util/ed_util_ops.cc index af3589e50f0..18d47af7854 100644 --- a/source/blender/editors/util/ed_util_ops.cc +++ b/source/blender/editors/util/ed_util_ops.cc @@ -125,7 +125,7 @@ static bool lib_id_generate_preview_poll(bContext *C) return true; } -static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op)) +static int lib_id_generate_preview_exec(bContext *C, wmOperator * /*op*/) { PointerRNA idptr = CTX_data_pointer_get(C, "id"); ID *id = (ID *)idptr.data; @@ -170,7 +170,7 @@ static bool lib_id_generate_preview_from_object_poll(bContext *C) return true; } -static int lib_id_generate_preview_from_object_exec(bContext *C, wmOperator *UNUSED(op)) +static int lib_id_generate_preview_from_object_exec(bContext *C, wmOperator * /*op*/) { PointerRNA idptr = CTX_data_pointer_get(C, "id"); ID *id = (ID *)idptr.data; @@ -229,7 +229,7 @@ static int lib_id_fake_user_toggle_exec(bContext *C, wmOperator *op) ID *id = (ID *)idptr.data; if (!BKE_id_is_editable(CTX_data_main(C), id) || - (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { + ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS)) { BKE_report(op->reports, RPT_ERROR, "Data-block type does not support fake user"); return OPERATOR_CANCELLED; } @@ -304,7 +304,7 @@ static bool lib_id_override_editable_toggle_poll(bContext *C) return id && ID_IS_OVERRIDE_LIBRARY_REAL(id) && !ID_IS_LINKED(id); } -static int lib_id_override_editable_toggle_exec(bContext *C, wmOperator *UNUSED(op)) +static int lib_id_override_editable_toggle_exec(bContext *C, wmOperator * /*op*/) { Main *bmain = CTX_data_main(C); const PointerRNA id_ptr = CTX_data_pointer_get_type(C, "id", &RNA_ID); @@ -346,7 +346,7 @@ static void ED_OT_lib_id_override_editable_toggle(wmOperatorType *ot) /** \name General editor utils. * \{ */ -static int ed_flush_edits_exec(bContext *C, wmOperator *UNUSED(op)) +static int ed_flush_edits_exec(bContext *C, wmOperator * /*op*/) { Main *bmain = CTX_data_main(C); ED_editors_flush_edits(bmain); diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc new file mode 100644 index 00000000000..4da1559b726 --- /dev/null +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -0,0 +1,365 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "ED_viewer_path.hh" +#include "ED_screen.h" + +#include "BKE_context.h" +#include "BKE_main.h" +#include "BKE_node_runtime.hh" +#include "BKE_workspace.h" + +#include "BLI_listbase.h" +#include "BLI_vector.hh" + +#include "DNA_modifier_types.h" +#include "DNA_windowmanager_types.h" + +#include "DEG_depsgraph.h" + +#include "WM_api.h" + +namespace blender::ed::viewer_path { + +static void viewer_path_for_geometry_node(const SpaceNode &snode, + const bNode &node, + ViewerPath &r_dst) +{ + BKE_viewer_path_init(&r_dst); + + Object *ob = reinterpret_cast<Object *>(snode.id); + IDViewerPathElem *id_elem = BKE_viewer_path_elem_new_id(); + id_elem->id = &ob->id; + BLI_addtail(&r_dst.path, id_elem); + + NodesModifierData *modifier = nullptr; + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type != eModifierType_Nodes) { + continue; + } + NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md); + if (nmd->node_group != snode.nodetree) { + continue; + } + if (snode.flag & SNODE_PIN) { + /* If the node group is pinned, use the first matching modifier. This can be improved by + * storing the modifier name in the node editor when the context is pinned. */ + modifier = nmd; + break; + } + if (md->flag & eModifierFlag_Active) { + modifier = nmd; + } + } + + ModifierViewerPathElem *modifier_elem = BKE_viewer_path_elem_new_modifier(); + modifier_elem->modifier_name = BLI_strdup(modifier->modifier.name); + BLI_addtail(&r_dst.path, modifier_elem); + + Vector<const bNodeTreePath *, 16> tree_path = snode.treepath; + for (const bNodeTreePath *tree_path_elem : tree_path.as_span().drop_front(1)) { + NodeViewerPathElem *node_elem = BKE_viewer_path_elem_new_node(); + node_elem->node_name = BLI_strdup(tree_path_elem->node_name); + BLI_addtail(&r_dst.path, node_elem); + } + + NodeViewerPathElem *viewer_node_elem = BKE_viewer_path_elem_new_node(); + viewer_node_elem->node_name = BLI_strdup(node.name); + BLI_addtail(&r_dst.path, viewer_node_elem); +} + +void activate_geometry_node(Main &bmain, SpaceNode &snode, bNode &node) +{ + wmWindowManager *wm = (wmWindowManager *)bmain.wm.first; + if (wm == nullptr) { + return; + } + LISTBASE_FOREACH (bNode *, iter_node, &snode.edittree->nodes) { + if (iter_node->type == GEO_NODE_VIEWER) { + SET_FLAG_FROM_TEST(iter_node->flag, iter_node == &node, NODE_DO_OUTPUT); + } + } + ViewerPath new_viewer_path{}; + BLI_SCOPED_DEFER([&]() { BKE_viewer_path_clear(&new_viewer_path); }); + viewer_path_for_geometry_node(snode, node, new_viewer_path); + + bool found_view3d_with_enabled_viewer = false; + View3D *any_view3d_without_viewer = nullptr; + LISTBASE_FOREACH (wmWindow *, window, &wm->windows) { + WorkSpace *workspace = BKE_workspace_active_get(window->workspace_hook); + bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first); + if (sl->spacetype == SPACE_SPREADSHEET) { + SpaceSpreadsheet &sspreadsheet = *reinterpret_cast<SpaceSpreadsheet *>(sl); + if (!(sspreadsheet.flag & SPREADSHEET_FLAG_PINNED)) { + sspreadsheet.object_eval_state = SPREADSHEET_OBJECT_EVAL_STATE_VIEWER_NODE; + } + } + else if (sl->spacetype == SPACE_VIEW3D) { + View3D &v3d = *reinterpret_cast<View3D *>(sl); + if (v3d.flag2 & V3D_SHOW_VIEWER) { + found_view3d_with_enabled_viewer = true; + } + else { + any_view3d_without_viewer = &v3d; + } + } + } + + /* Enable viewer in one viewport if it is disable in all of them. */ + if (!found_view3d_with_enabled_viewer && any_view3d_without_viewer != nullptr) { + any_view3d_without_viewer->flag2 |= V3D_SHOW_VIEWER; + } + + BKE_viewer_path_clear(&workspace->viewer_path); + BKE_viewer_path_copy(&workspace->viewer_path, &new_viewer_path); + + /* Make sure the viewed data becomes available. */ + DEG_id_tag_update(snode.id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_VIEWER_PATH, nullptr); + } +} + +Object *parse_object_only(const ViewerPath &viewer_path) +{ + if (BLI_listbase_count(&viewer_path.path) != 1) { + return nullptr; + } + const ViewerPathElem *elem = static_cast<ViewerPathElem *>(viewer_path.path.first); + if (elem->type != VIEWER_PATH_ELEM_TYPE_ID) { + return nullptr; + } + ID *id = reinterpret_cast<const IDViewerPathElem *>(elem)->id; + if (id == nullptr) { + return nullptr; + } + if (GS(id->name) != ID_OB) { + return nullptr; + } + return reinterpret_cast<Object *>(id); +} + +std::optional<ViewerPathForGeometryNodesViewer> parse_geometry_nodes_viewer( + const ViewerPath &viewer_path) +{ + const Vector<const ViewerPathElem *, 16> elems_vec = viewer_path.path; + if (elems_vec.size() < 3) { + /* Need at least the object, modifier and viewer node name. */ + return std::nullopt; + } + Span<const ViewerPathElem *> remaining_elems = elems_vec; + const ViewerPathElem &id_elem = *remaining_elems[0]; + if (id_elem.type != VIEWER_PATH_ELEM_TYPE_ID) { + return std::nullopt; + } + ID *root_id = reinterpret_cast<const IDViewerPathElem &>(id_elem).id; + if (root_id == nullptr) { + return std::nullopt; + } + if (GS(root_id->name) != ID_OB) { + return std::nullopt; + } + Object *root_ob = reinterpret_cast<Object *>(root_id); + remaining_elems = remaining_elems.drop_front(1); + const ViewerPathElem &modifier_elem = *remaining_elems[0]; + if (modifier_elem.type != VIEWER_PATH_ELEM_TYPE_MODIFIER) { + return std::nullopt; + } + const char *modifier_name = + reinterpret_cast<const ModifierViewerPathElem &>(modifier_elem).modifier_name; + if (modifier_name == nullptr) { + return std::nullopt; + } + remaining_elems = remaining_elems.drop_front(1); + Vector<StringRefNull> node_names; + for (const ViewerPathElem *elem : remaining_elems) { + if (elem->type != VIEWER_PATH_ELEM_TYPE_NODE) { + return std::nullopt; + } + const char *node_name = reinterpret_cast<const NodeViewerPathElem *>(elem)->node_name; + if (node_name == nullptr) { + return std::nullopt; + } + node_names.append(node_name); + } + const StringRefNull viewer_node_name = node_names.pop_last(); + return ViewerPathForGeometryNodesViewer{root_ob, modifier_name, node_names, viewer_node_name}; +} + +bool exists_geometry_nodes_viewer(const ViewerPathForGeometryNodesViewer &parsed_viewer_path) +{ + const NodesModifierData *modifier = nullptr; + LISTBASE_FOREACH (const ModifierData *, md, &parsed_viewer_path.object->modifiers) { + if (md->type != eModifierType_Nodes) { + continue; + } + if (md->name != parsed_viewer_path.modifier_name) { + continue; + } + modifier = reinterpret_cast<const NodesModifierData *>(md); + break; + } + if (modifier == nullptr) { + return false; + } + if (modifier->node_group == nullptr) { + return false; + } + const bNodeTree *ngroup = modifier->node_group; + ngroup->ensure_topology_cache(); + for (const StringRefNull group_node_name : parsed_viewer_path.group_node_names) { + const bNode *group_node = nullptr; + for (const bNode *node : ngroup->group_nodes()) { + if (node->name != group_node_name) { + continue; + } + group_node = node; + break; + } + if (group_node == nullptr) { + return false; + } + if (group_node->id == nullptr) { + return false; + } + ngroup = reinterpret_cast<const bNodeTree *>(group_node->id); + } + const bNode *viewer_node = nullptr; + for (const bNode *node : ngroup->nodes_by_type("GeometryNodeViewer")) { + if (node->name != parsed_viewer_path.viewer_node_name) { + continue; + } + viewer_node = node; + break; + } + if (viewer_node == nullptr) { + return false; + } + return true; +} + +bool is_active_geometry_nodes_viewer(const bContext &C, + const ViewerPathForGeometryNodesViewer &parsed_viewer_path) +{ + const NodesModifierData *modifier = nullptr; + LISTBASE_FOREACH (const ModifierData *, md, &parsed_viewer_path.object->modifiers) { + if (md->name != parsed_viewer_path.modifier_name) { + continue; + } + if (md->type != eModifierType_Nodes) { + return false; + } + if ((md->mode & eModifierMode_Realtime) == 0) { + return false; + } + modifier = reinterpret_cast<const NodesModifierData *>(md); + break; + } + if (modifier == nullptr) { + return false; + } + if (modifier->node_group == nullptr) { + return false; + } + const bool modifier_is_active = modifier->modifier.flag & eModifierFlag_Active; + + const Main *bmain = CTX_data_main(&C); + const wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first); + if (wm == nullptr) { + return false; + } + LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) { + const bScreen *active_screen = BKE_workspace_active_screen_get(window->workspace_hook); + Vector<const bScreen *> screens = {active_screen}; + if (ELEM(active_screen->state, SCREENMAXIMIZED, SCREENFULL)) { + const ScrArea *area = static_cast<ScrArea *>(active_screen->areabase.first); + screens.append(area->full); + } + for (const bScreen *screen : screens) { + LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) { + const SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first); + if (sl == nullptr) { + continue; + } + if (sl->spacetype != SPACE_NODE) { + continue; + } + const SpaceNode &snode = *reinterpret_cast<const SpaceNode *>(sl); + if (!modifier_is_active) { + if (!(snode.flag & SNODE_PIN)) { + /* Node tree has to be pinned when the modifier is not active. */ + continue; + } + } + if (snode.id != &parsed_viewer_path.object->id) { + continue; + } + if (snode.nodetree != modifier->node_group) { + continue; + } + Vector<const bNodeTreePath *, 16> tree_path = snode.treepath; + if (tree_path.size() != parsed_viewer_path.group_node_names.size() + 1) { + continue; + } + bool valid_path = true; + for (const int i : parsed_viewer_path.group_node_names.index_range()) { + if (parsed_viewer_path.group_node_names[i] != tree_path[i + 1]->node_name) { + valid_path = false; + break; + } + } + if (!valid_path) { + continue; + } + const bNodeTree *ngroup = snode.edittree; + ngroup->ensure_topology_cache(); + const bNode *viewer_node = nullptr; + for (const bNode *node : ngroup->nodes_by_type("GeometryNodeViewer")) { + if (node->name != parsed_viewer_path.viewer_node_name) { + continue; + } + viewer_node = node; + } + if (viewer_node == nullptr) { + continue; + } + if (!(viewer_node->flag & NODE_DO_OUTPUT)) { + continue; + } + return true; + } + } + } + return false; +} + +bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snode) +{ + const std::optional<ViewerPathForGeometryNodesViewer> parsed_viewer_path = + parse_geometry_nodes_viewer(viewer_path); + if (!parsed_viewer_path.has_value()) { + return nullptr; + } + + snode.edittree->ensure_topology_cache(); + bNode *possible_viewer = nullptr; + for (bNode *node : snode.edittree->nodes_by_type("GeometryNodeViewer")) { + if (node->name == parsed_viewer_path->viewer_node_name) { + possible_viewer = node; + break; + } + } + if (possible_viewer == nullptr) { + return nullptr; + } + ViewerPath tmp_viewer_path; + BLI_SCOPED_DEFER([&]() { BKE_viewer_path_clear(&tmp_viewer_path); }); + viewer_path_for_geometry_node(snode, *possible_viewer, tmp_viewer_path); + + if (BKE_viewer_path_equal(&viewer_path, &tmp_viewer_path)) { + return possible_viewer; + } + return nullptr; +} + +} // namespace blender::ed::viewer_path |