diff options
Diffstat (limited to 'source/blender/editors/include')
-rw-r--r-- | source/blender/editors/include/ED_anim_api.h | 6 | ||||
-rw-r--r-- | source/blender/editors/include/ED_curves.h | 13 | ||||
-rw-r--r-- | source/blender/editors/include/ED_curves_sculpt.h | 25 | ||||
-rw-r--r-- | source/blender/editors/include/ED_gpencil.h | 7 | ||||
-rw-r--r-- | source/blender/editors/include/ED_keyframes_edit.h | 23 | ||||
-rw-r--r-- | source/blender/editors/include/ED_mesh.h | 4 | ||||
-rw-r--r-- | source/blender/editors/include/ED_paint.h | 7 | ||||
-rw-r--r-- | source/blender/editors/include/ED_transform_snap_object_context.h | 43 | ||||
-rw-r--r-- | source/blender/editors/include/UI_abstract_view.hh | 280 | ||||
-rw-r--r-- | source/blender/editors/include/UI_grid_view.hh | 55 | ||||
-rw-r--r-- | source/blender/editors/include/UI_icons.h | 2 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 84 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.hh | 6 | ||||
-rw-r--r-- | source/blender/editors/include/UI_tree_view.hh | 181 | ||||
-rw-r--r-- | source/blender/editors/include/UI_view2d.h | 6 |
15 files changed, 460 insertions, 282 deletions
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index da40eef87fd..cc3c68abc55 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -324,11 +324,15 @@ typedef enum eAnimFilter_Flags { /** duplicate entries for animation data attached to multi-user blocks must not occur */ ANIMFILTER_NODUPLIS = (1 << 11), + /** avoid channel that does not have any F-curve data */ + ANIMFILTER_FCURVESONLY = (1 << 12), + /** for checking if we should keep some collapsed channel around (internal use only!) */ ANIMFILTER_TMP_PEEK = (1 << 30), /** Ignore ONLYSEL flag from #bDopeSheet.filterflag (internal use only!) */ ANIMFILTER_TMP_IGNORE_ONLYSEL = (1u << 31), + } eAnimFilter_Flags; /** \} */ @@ -1042,6 +1046,8 @@ void ED_keymap_anim(struct wmKeyConfig *keyconf); void ED_operatormacros_graph(void); /* space_action */ void ED_operatormacros_action(void); +/* space_nla*/ +void ED_operatormacros_nla(void); /** \} */ diff --git a/source/blender/editors/include/ED_curves.h b/source/blender/editors/include/ED_curves.h index 9233b65b2ce..00831ff7cc3 100644 --- a/source/blender/editors/include/ED_curves.h +++ b/source/blender/editors/include/ED_curves.h @@ -6,6 +6,8 @@ #pragma once +struct bContext; + #ifdef __cplusplus extern "C" { #endif @@ -19,10 +21,19 @@ void ED_operatortypes_curves(void); #ifdef __cplusplus # include "BKE_curves.hh" +# include "BLI_vector_set.hh" namespace blender::ed::curves { bke::CurvesGeometry primitive_random_sphere(int curves_size, int points_per_curve); +bool has_anything_selected(const Curves &curves_id); +VectorSet<Curves *> get_unique_editable_curves(const bContext &C); +void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob); -} +bool editable_curves_with_surface_poll(bContext *C); +bool curves_with_surface_poll(bContext *C); +bool editable_curves_poll(bContext *C); +bool curves_poll(bContext *C); + +} // namespace blender::ed::curves #endif diff --git a/source/blender/editors/include/ED_curves_sculpt.h b/source/blender/editors/include/ED_curves_sculpt.h index 8aab1533e25..b1c0b649d2b 100644 --- a/source/blender/editors/include/ED_curves_sculpt.h +++ b/source/blender/editors/include/ED_curves_sculpt.h @@ -10,8 +10,33 @@ extern "C" { #endif +struct Curves; + void ED_operatortypes_sculpt_curves(void); #ifdef __cplusplus } #endif + +#ifdef __cplusplus + +# include "BLI_index_mask.hh" +# include "BLI_vector.hh" + +namespace blender::ed::sculpt_paint { + +/** + * Find curves that have any point selected (a selection factor greater than zero), + * or curves that have their own selection factor greater than zero. + */ +IndexMask retrieve_selected_curves(const Curves &curves_id, Vector<int64_t> &r_indices); + +/** + * Find points that are selected (a selection factor greater than zero), + * or points in curves with a selection factor greater than zero). + */ +IndexMask retrieve_selected_points(const Curves &curves_id, Vector<int64_t> &r_indices); + +} // namespace blender::ed::sculpt_paint + +#endif diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 0943636a452..b6488d6da56 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -239,7 +239,7 @@ void ED_annotation_draw_ex( /* ----------- Grease-Pencil AnimEdit API ------------------ */ /** - * Loops over the gp-frames for a gp-layer, and applies the given callback. + * Loops over the GP-frames for a GP-layer, and applies the given callback. */ bool ED_gpencil_layer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene, @@ -281,6 +281,11 @@ void ED_gpencil_select_frames(struct bGPDlayer *gpl, short select_mode); void ED_gpencil_select_frame(struct bGPDlayer *gpl, int selx, short select_mode); /** + * Set the layer's channel as active + */ +void ED_gpencil_set_active_channel(struct bGPdata *gpd, struct bGPDlayer *gpl); + +/** * Delete selected frames. */ bool ED_gpencil_layer_frames_delete(struct bGPDlayer *gpl); diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index 163797d395d..1d63e01c84b 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -229,6 +229,16 @@ typedef enum eKeyMergeMode { KEYFRAME_PASTE_MERGE_OVER_RANGE_ALL, } eKeyMergeMode; +/* Possible errors occurring while pasting keys. */ +typedef enum eKeyPasteError { + /* No errors occurred */ + KEYFRAME_PASTE_OK, + /* Nothing was copied */ + KEYFRAME_PASTE_NOTHING_TO_PASTE, + /* No F-curves was selected to paste into*/ + KEYFRAME_PASTE_NOWHERE_TO_PASTE +} eKeyPasteError; + /** \} */ /* -------------------------------------------------------------------- */ @@ -378,9 +388,6 @@ bool keyframe_region_circle_test(const KeyframeEdit_CircleData *data_circle, con /* ************************************************ */ /* Destructive Editing API (keyframes_general.c) */ -void delete_fcurve_key(struct FCurve *fcu, int index, bool do_recalc); -bool delete_fcurve_keys(struct FCurve *fcu); -void clear_fcurve_keys(struct FCurve *fcu); bool duplicate_fcurve_keys(struct FCurve *fcu); float get_default_rna_value(struct FCurve *fcu, struct PropertyRNA *prop, struct PointerRNA *ptr); @@ -416,11 +423,11 @@ void sample_fcurve(struct FCurve *fcu); void ANIM_fcurves_copybuf_free(void); short copy_animedit_keys(struct bAnimContext *ac, ListBase *anim_data); -short paste_animedit_keys(struct bAnimContext *ac, - ListBase *anim_data, - eKeyPasteOffset offset_mode, - eKeyMergeMode merge_mode, - bool flip); +eKeyPasteError paste_animedit_keys(struct bAnimContext *ac, + ListBase *anim_data, + eKeyPasteOffset offset_mode, + eKeyMergeMode merge_mode, + bool flip); /* ************************************************ */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 30a98129ee6..b73b62d5a9d 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -137,7 +137,6 @@ void EDBM_update_extern(struct Mesh *me, bool do_tessellation, bool is_destructi */ struct UvElementMap *BM_uv_element_map_create(struct BMesh *bm, const struct Scene *scene, - bool face_selected, bool uv_selected, bool use_winding, bool do_islands); @@ -425,6 +424,9 @@ void paintvert_select_ungrouped(struct Object *ob, bool extend, bool flush_flags void paintvert_flush_flags(struct Object *ob); void paintvert_tag_select_update(struct bContext *C, struct Object *ob); +void paintvert_hide(struct bContext *C, struct Object *ob, bool unselected); +void paintvert_reveal(struct bContext *C, struct Object *ob, bool select); + /* mirrtopo */ typedef struct MirrTopoStore_t { intptr_t *index_lookup; diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h index ba5834fd508..048424cdee1 100644 --- a/source/blender/editors/include/ED_paint.h +++ b/source/blender/editors/include/ED_paint.h @@ -22,6 +22,7 @@ struct UndoType; struct bContext; struct wmKeyConfig; struct wmOperator; +typedef struct PaintTileMap PaintTileMap; /* paint_ops.c */ @@ -76,7 +77,7 @@ void ED_image_undo_restore(struct UndoStep *us); /** Export for ED_undo_sys. */ void ED_image_undosys_type(struct UndoType *ut); -void *ED_image_paint_tile_find(struct ListBase *paint_tiles, +void *ED_image_paint_tile_find(PaintTileMap *paint_tile_map, struct Image *image, struct ImBuf *ibuf, struct ImageUser *iuser, @@ -84,7 +85,7 @@ void *ED_image_paint_tile_find(struct ListBase *paint_tiles, int y_tile, unsigned short **r_mask, bool validate); -void *ED_image_paint_tile_push(struct ListBase *paint_tiles, +void *ED_image_paint_tile_push(PaintTileMap *paint_tile_map, struct Image *image, struct ImBuf *ibuf, struct ImBuf **tmpibuf, @@ -98,7 +99,7 @@ void *ED_image_paint_tile_push(struct ListBase *paint_tiles, void ED_image_paint_tile_lock_init(void); void ED_image_paint_tile_lock_end(void); -struct ListBase *ED_image_paint_tile_list_get(void); +struct PaintTileMap *ED_image_paint_tile_map_get(void); #define ED_IMAGE_UNDO_TILE_BITS 6 #define ED_IMAGE_UNDO_TILE_SIZE (1 << ED_IMAGE_UNDO_TILE_BITS) diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index 20353c21f93..db44d9af706 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -60,6 +60,10 @@ struct SnapObjectParams { bool use_occlusion_test : true; /* exclude back facing geometry from snapping */ bool use_backface_culling : true; + /* Break nearest face snapping into steps to improve transformations across U-shaped targets. */ + short face_nearest_steps; + /* Enable to force nearest face snapping to snap to target the source was initially near. */ + bool keep_on_same_target; }; typedef struct SnapObjectContext SnapObjectContext; @@ -114,12 +118,33 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, bool sort, struct ListBase *r_hit_list); +/** + * Perform snapping. + * + * Given a 2D region value, snap to vert/edge/face/grid. + * + * \param sctx: Snap context. + * \param snap_to: Target elements to snap source to. + * \param params: Addition snapping options. + * \param init_co: Initial world-space coordinate of source (optional). + * \param mval: Current transformed screen-space coordinate or mouse position (optional). + * \param prev_co: Current transformed world-space coordinate of source (optional). + * \param dist_px: Maximum distance to snap (in pixels). + * \param r_loc: Snapped world-space coordinate. + * \param r_no: Snapped world-space normal (optional). + * \param r_index: Index of snapped-to target element (optional). + * \param r_ob: Snapped-to target object (optional). + * \param r_obmat: Matrix of snapped-to target object (optional). + * \param r_face_nor: World-space normal of snapped-to target face (optional). + * \return Snapped-to element, #eSnapMode. + */ eSnapMode ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx, struct Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, - eSnapMode snap_to, + const eSnapMode snap_to, const struct SnapObjectParams *params, + const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, @@ -135,19 +160,23 @@ eSnapMode ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *s * Given a 2D region value, snap to vert/edge/face. * * \param sctx: Snap context. - * \param mval: Screenspace coordinate. - * \param prev_co: Coordinate for perpendicular point calculation (optional). + * \param snap_to: Target elements to snap source to. + * \param params: Addition snapping options. + * \param init_co: Initial world-space coordinate of source (optional). + * \param mval: Current transformed screen-space coordinate or mouse position (optional). + * \param prev_co: Current transformed world-space coordinate of source (optional). * \param dist_px: Maximum distance to snap (in pixels). - * \param r_loc: hit location. - * \param r_no: hit normal (optional). - * \return Snap success. + * \param r_loc: Snapped world-space coordinate. + * \param r_no: Snapped world-space normal (optional). + * \return Snapped-to element, #eSnapMode. */ eSnapMode ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx, struct Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, - eSnapMode snap_to, + const eSnapMode snap_to, const struct SnapObjectParams *params, + const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, diff --git a/source/blender/editors/include/UI_abstract_view.hh b/source/blender/editors/include/UI_abstract_view.hh new file mode 100644 index 00000000000..dfddace8899 --- /dev/null +++ b/source/blender/editors/include/UI_abstract_view.hh @@ -0,0 +1,280 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup editorui + * + * Base class for all views (UIs to display data sets) and view items, supporting common features. + * https://wiki.blender.org/wiki/Source/Interface/Views + * + * One of the most important responsibilities of the base class is managing reconstruction, + * enabling state that is persistent over reconstructions/redraws. Other features: + * - Renaming + * - Custom context menus + * - Notifier listening + * - Drag controllers (dragging view items) + * - Drop controllers (dropping onto/into view items) + */ + +#pragma once + +#include <array> +#include <memory> + +#include "DNA_defs.h" + +#include "BLI_span.hh" +#include "BLI_string_ref.hh" + +struct bContext; +struct uiBlock; +struct uiBut; +struct uiLayout; +struct uiViewItemHandle; +struct wmDrag; +struct wmNotifier; + +namespace blender::ui { + +class AbstractViewItem; +class AbstractViewItemDropController; +class AbstractViewItemDragController; + +class AbstractView { + friend class AbstractViewItem; + + bool is_reconstructed_ = false; + /** + * Only one item can be renamed at a time. So rather than giving each item an own rename buffer + * (which just adds unused memory in most cases), have one here that is managed by the view. + * + * This fixed-size buffer is needed because that's what the rename button requires. In future we + * may be able to bind the button to a `std::string` or similar. + */ + std::unique_ptr<std::array<char, MAX_NAME>> rename_buffer_; + + public: + virtual ~AbstractView() = default; + + /** Listen to a notifier, returning true if a redraw is needed. */ + virtual bool listen(const wmNotifier &) const; + + /** + * Makes \a item valid for display in this view. Behavior is undefined for items not registered + * with this. + */ + void register_item(AbstractViewItem &item); + + /** Only one item can be renamed at a time. */ + bool is_renaming() const; + /** \return If renaming was started successfully. */ + bool begin_renaming(); + void end_renaming(); + Span<char> get_rename_buffer() const; + MutableSpan<char> get_rename_buffer(); + + protected: + AbstractView() = default; + + virtual void update_children_from_old(const AbstractView &old_view) = 0; + + /** + * Match the view and its items against an earlier version of itself (if any) and copy the old UI + * state (e.g. collapsed, active, selected, renaming, etc.) to the new one. See + * #AbstractViewItem.update_from_old(). + * After this, reconstruction is complete (see #is_reconstructed()). + */ + void update_from_old(uiBlock &new_block); + /** + * Check if the view is fully (re-)constructed. That means, both the build function and + * #update_from_old() have finished. + */ + bool is_reconstructed() const; +}; + +class AbstractViewItem { + friend class AbstractView; + friend class ViewItemAPIWrapper; + + protected: + /** + * The view this item is a part of, and was registered for using #AbstractView::register_item(). + * If this wasn't done, the behavior of items is undefined. + */ + AbstractView *view_ = nullptr; + bool is_active_ = false; + bool is_renaming_ = false; + + public: + virtual ~AbstractViewItem() = default; + + virtual void build_context_menu(bContext &C, uiLayout &column) const; + + /** + * Queries if the view item supports renaming in principle. Renaming may still fail, e.g. if + * another item is already being renamed. + */ + virtual bool supports_renaming() const; + /** + * Try renaming the item, or the data it represents. Can assume + * #AbstractViewItem::supports_renaming() returned true. Sub-classes that override this should + * usually call this, unless they have a custom #AbstractViewItem.matches() implementation. + * + * \return True if the renaming was successful. + */ + virtual bool rename(StringRefNull new_name); + /** + * Get the string that should be used for renaming, typically the item's label. This string will + * not be modified, but if the renaming is canceled, the value will be reset to this. + */ + virtual StringRef get_rename_string() const; + + /** + * If an item wants to support being dragged, it has to return a drag controller here. + * That is an object implementing #AbstractViewItemDragController. + */ + virtual std::unique_ptr<AbstractViewItemDragController> create_drag_controller() const; + /** + * If an item wants to support dropping data into it, it has to return a drop controller here. + * That is an object implementing #AbstractViewItemDropController. + * + * \note This drop controller may be requested for each event. The view doesn't keep a drop + * controller around currently. So it can not contain persistent state. + */ + virtual std::unique_ptr<AbstractViewItemDropController> create_drop_controller() const; + + /** Get the view this item is registered for using #AbstractView::register_item(). */ + AbstractView &get_view() const; + + /** + * Requires the view to have completed reconstruction, see #is_reconstructed(). Otherwise we + * can't be sure about the item state. + */ + bool is_active() const; + + bool is_renaming() const; + void begin_renaming(); + void end_renaming(); + void rename_apply(); + + template<typename ToType = AbstractViewItem> + static ToType *from_item_handle(uiViewItemHandle *handle); + + protected: + AbstractViewItem() = default; + + /** + * Compare this item's identity to \a other to check if they represent the same data. + * Implementations can assume that the types match already (caller must check). + * + * Used to recognize an item from a previous redraw, to be able to keep its state (e.g. active, + * renaming, etc.). + */ + virtual bool matches(const AbstractViewItem &other) const = 0; + + /** + * Copy persistent state (e.g. active, selection, etc.) from a matching item of + * the last redraw to this item. If sub-classes introduce more advanced state they should + * override this and make it update their state accordingly. + * + * \note Always call the base class implementation when overriding this! + */ + virtual void update_from_old(const AbstractViewItem &old); + + /** + * Add a text button for renaming the item to \a block. This must be used for the built-in + * renaming to work. This button is meant to appear temporarily. It is removed when renaming is + * done. + */ + void add_rename_button(uiBlock &block); +}; + +template<typename ToType> ToType *AbstractViewItem::from_item_handle(uiViewItemHandle *handle) +{ + static_assert(std::is_base_of<AbstractViewItem, ToType>::value, + "Type must derive from and implement the AbstractViewItem interface"); + + return dynamic_cast<ToType *>(reinterpret_cast<AbstractViewItem *>(handle)); +} + +/* ---------------------------------------------------------------------- */ +/** \name Drag 'n Drop + * \{ */ + +/** + * Class to enable dragging a view item. An item can return a drop controller for itself by + * implementing #AbstractViewItem::create_drag_controller(). + */ +class AbstractViewItemDragController { + protected: + AbstractView &view_; + + public: + AbstractViewItemDragController(AbstractView &view); + virtual ~AbstractViewItemDragController() = default; + + virtual int get_drag_type() const = 0; + virtual void *create_drag_data() const = 0; + virtual void on_drag_start(); + + /** Request the view the item is registered for as type #ViewType. Throws a `std::bad_cast` + * exception if the view is not of the requested type. */ + template<class ViewType> inline ViewType &get_view() const; +}; + +/** + * Class to define the behavior when dropping something onto/into a view item, plus the behavior + * when dragging over this item. An item can return a drop controller for itself via a custom + * implementation of #AbstractViewItem::create_drop_controller(). + */ +class AbstractViewItemDropController { + protected: + AbstractView &view_; + + public: + AbstractViewItemDropController(AbstractView &view); + virtual ~AbstractViewItemDropController() = default; + + /** + * Check if the data dragged with \a drag can be dropped on the item this controller is for. + * \param r_disabled_hint: Return a static string to display to the user, explaining why dropping + * isn't possible on this item. Shouldn't be done too aggressively, e.g. + * don't set this if the drag-type can't be dropped here; only if it can + * but there's another reason it can't be dropped. + * Can assume this is a non-null pointer. + */ + virtual bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const = 0; + /** + * Custom text to display when dragging over a view item. Should explain what happens when + * dropping the data onto this item. Will only be used if #AbstractViewItem::can_drop() + * returns true, so the implementing override doesn't have to check that again. + * The returned value must be a translated string. + */ + virtual std::string drop_tooltip(const wmDrag &drag) const = 0; + /** + * Execute the logic to apply a drop of the data dragged with \a drag onto/into the item this + * controller is for. + */ + virtual bool on_drop(struct bContext *C, const wmDrag &drag) = 0; + + /** Request the view the item is registered for as type #ViewType. Throws a `std::bad_cast` + * exception if the view is not of the requested type. */ + template<class ViewType> inline ViewType &get_view() const; +}; + +template<class ViewType> ViewType &AbstractViewItemDragController::get_view() const +{ + static_assert(std::is_base_of<AbstractView, ViewType>::value, + "Type must derive from and implement the ui::AbstractView interface"); + return dynamic_cast<ViewType &>(view_); +} + +template<class ViewType> ViewType &AbstractViewItemDropController::get_view() const +{ + static_assert(std::is_base_of<AbstractView, ViewType>::value, + "Type must derive from and implement the ui::AbstractView interface"); + return dynamic_cast<ViewType &>(view_); +} + +/** \} */ + +} // namespace blender::ui diff --git a/source/blender/editors/include/UI_grid_view.hh b/source/blender/editors/include/UI_grid_view.hh index 6f553f4fad1..402c0c8512f 100644 --- a/source/blender/editors/include/UI_grid_view.hh +++ b/source/blender/editors/include/UI_grid_view.hh @@ -13,12 +13,13 @@ #include "BLI_map.hh" #include "BLI_vector.hh" +#include "UI_abstract_view.hh" #include "UI_resources.h" struct bContext; struct PreviewImage; struct uiBlock; -struct uiButGridTile; +struct uiButViewItem; struct uiLayout; struct View2D; struct wmNotifier; @@ -31,43 +32,29 @@ class AbstractGridView; /** \name Grid-View Item Type * \{ */ -class AbstractGridViewItem { +class AbstractGridViewItem : public AbstractViewItem { friend class AbstractGridView; friend class GridViewLayoutBuilder; - const AbstractGridView *view_; - - bool is_active_ = false; - protected: /** Reference to a string that uniquely identifies this item in the view. */ StringRef identifier_{}; - /** Every visible item gets a button of type #UI_BTYPE_GRID_TILE during the layout building. */ - uiButGridTile *grid_tile_but_ = nullptr; + /** Every visible item gets a button of type #UI_BTYPE_VIEW_ITEM during the layout building. */ + uiButViewItem *view_item_but_ = nullptr; public: virtual ~AbstractGridViewItem() = default; virtual void build_grid_tile(uiLayout &layout) const = 0; - /** - * Compare this item's identifier to \a other to check if they represent the same data. - * Used to recognize an item from a previous redraw, to be able to keep its state (e.g. active, - * renaming, etc.). - */ - bool matches(const AbstractGridViewItem &other) const; - const AbstractGridView &get_view() const; - /** - * Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise we - * can't be sure about the item state. - */ - bool is_active() const; - protected: AbstractGridViewItem(StringRef identifier); + /** See AbstractViewItem::matches(). */ + virtual bool matches(const AbstractViewItem &other) const override; + /** Called when the item's state changes from inactive to active. */ virtual void on_activate(); /** @@ -77,13 +64,6 @@ class AbstractGridViewItem { virtual std::optional<bool> should_be_active() const; /** - * Copy persistent state (e.g. active, selection, etc.) from a matching item of - * the last redraw to this item. If sub-classes introduce more advanced state they should - * override this and make it update their state accordingly. - */ - virtual void update_from_old(const AbstractGridViewItem &old); - - /** * Activates this item, deactivates other items, and calls the * #AbstractGridViewItem::on_activate() function. * Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise the @@ -111,7 +91,7 @@ struct GridViewStyle { int tile_height = 0; }; -class AbstractGridView { +class AbstractGridView : public AbstractView { friend class AbstractGridViewItem; friend class GridViewBuilder; friend class GridViewLayoutBuilder; @@ -122,7 +102,6 @@ class AbstractGridView { * #update_from_old(). */ Map<StringRef, AbstractGridViewItem *> item_map_; GridViewStyle style_; - bool is_reconstructed_ = false; public: AbstractGridView(); @@ -131,9 +110,6 @@ class AbstractGridView { using ItemIterFn = FunctionRef<void(AbstractGridViewItem &)>; void foreach_item(ItemIterFn iter_fn) const; - /** Listen to a notifier, returning true if a redraw is needed. */ - virtual bool listen(const wmNotifier &) const; - /** * Convenience wrapper constructing the item by forwarding given arguments to the constructor of * the type (\a ItemT). @@ -154,19 +130,8 @@ class AbstractGridView { protected: virtual void build_items() = 0; - /** - * Check if the view is fully (re-)constructed. That means, both #build_items() and - * #update_from_old() have finished. - */ - bool is_reconstructed() const; - private: - /** - * Match the grid-view against an earlier version of itself (if any) and copy the old UI state - * (e.g. active, selected, renaming, etc.) to the new one. See - * #AbstractGridViewItem.update_from_old(). - */ - void update_from_old(uiBlock &new_block); + void update_children_from_old(const AbstractView &old_view) override; AbstractGridViewItem *find_matching_item(const AbstractGridViewItem &item_to_match, const AbstractGridView &view_to_search_in) const; /** diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index f1c0acf43f7..09057fd846e 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -652,7 +652,7 @@ DEF_ICON(PARTICLE_TIP) DEF_ICON(PARTICLE_PATH) /* EDITING */ -DEF_ICON_BLANK(669) +DEF_ICON(SNAP_FACE_NEAREST) DEF_ICON(SNAP_FACE_CENTER) DEF_ICON(SNAP_PERPENDICULAR) DEF_ICON(SNAP_MIDPOINT) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index b2ec2102ddd..a8d25b75036 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -72,14 +72,10 @@ typedef struct uiBut uiBut; typedef struct uiButExtraOpIcon uiButExtraOpIcon; typedef struct uiLayout uiLayout; typedef struct uiPopupBlockHandle uiPopupBlockHandle; -/* C handle for C++ #ui::AbstractTreeView type. */ -typedef struct uiTreeViewHandle uiTreeViewHandle; -/* C handle for C++ #ui::AbstractTreeViewItem type. */ -typedef struct uiTreeViewItemHandle uiTreeViewItemHandle; -/* C handle for C++ #ui::AbstractGridView type. */ -typedef struct uiGridViewHandle uiGridViewHandle; -/* C handle for C++ #ui::AbstractGridViewItem type. */ -typedef struct uiGridViewItemHandle uiGridViewItemHandle; +/* C handle for C++ #ui::AbstractView type. */ +typedef struct uiViewHandle uiViewHandle; +/* C handle for C++ #ui::AbstractViewItem type. */ +typedef struct uiViewItemHandle uiViewItemHandle; /* Defines */ @@ -393,10 +389,8 @@ typedef enum { /** Resize handle (resize uilist). */ UI_BTYPE_GRIP = 57 << 9, UI_BTYPE_DECORATOR = 58 << 9, - /* An item in a tree view. Parent items may be collapsible. */ - UI_BTYPE_TREEROW = 59 << 9, - /* An item in a grid view. */ - UI_BTYPE_GRID_TILE = 60 << 9, + /* An item a view (see #ui::AbstractViewItem). */ + UI_BTYPE_VIEW_ITEM = 59 << 9, } eButType; #define BUTTYPE (63 << 9) @@ -1687,8 +1681,6 @@ int UI_search_items_find_index(uiSearchItems *items, const char *name); */ void UI_but_hint_drawstr_set(uiBut *but, const char *string); -void UI_but_treerow_indentation_set(uiBut *but, int indentation); - void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]); void UI_but_number_step_size_set(uiBut *but, float step_size); @@ -3203,54 +3195,44 @@ void UI_interface_tag_script_reload(void); void UI_block_views_listen(const uiBlock *block, const struct wmRegionListenerParams *listener_params); -bool UI_grid_view_item_is_active(const uiGridViewItemHandle *item_handle); -bool UI_tree_view_item_is_active(const uiTreeViewItemHandle *item); -bool UI_grid_view_item_matches(const uiGridViewItemHandle *a, const uiGridViewItemHandle *b); -bool UI_tree_view_item_matches(const uiTreeViewItemHandle *a, const uiTreeViewItemHandle *b); +bool UI_view_item_is_active(const uiViewItemHandle *item_handle); +bool UI_view_item_matches(const uiViewItemHandle *a_handle, const uiViewItemHandle *b_handle); /** - * Attempt to start dragging the tree-item \a item_. This will not work if the tree item doesn't - * support dragging, i.e. it won't create a drag-controller upon request. - * \return True if dragging started successfully, otherwise false. - */ -bool UI_tree_view_item_drag_start(struct bContext *C, uiTreeViewItemHandle *item_); -bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_, - const struct wmDrag *drag, - const char **r_disabled_hint); -char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item, const struct wmDrag *drag); -/** - * Let a tree-view item handle a drop event. - * \return True if the drop was handled by the tree-view item. - */ -bool UI_tree_view_item_drop_handle(struct bContext *C, - const uiTreeViewItemHandle *item_, - const struct ListBase *drags); -/** - * Can \a item_handle be renamed right now? Not that this isn't just a mere wrapper around - * #AbstractTreeViewItem::can_rename(). This also checks if there is another item being renamed, + * Can \a item_handle be renamed right now? Note that this isn't just a mere wrapper around + * #AbstractViewItem::supports_renaming(). This also checks if there is another item being renamed, * and returns false if so. */ -bool UI_tree_view_item_can_rename(const uiTreeViewItemHandle *item_handle); -void UI_tree_view_item_begin_rename(uiTreeViewItemHandle *item_handle); +bool UI_view_item_can_rename(const uiViewItemHandle *item_handle); +void UI_view_item_begin_rename(uiViewItemHandle *item_handle); -void UI_tree_view_item_context_menu_build(struct bContext *C, - const uiTreeViewItemHandle *item, - uiLayout *column); +void UI_view_item_context_menu_build(struct bContext *C, + const uiViewItemHandle *item_handle, + uiLayout *column); /** - * \param xy: Coordinate to find a tree-row item at, in window space. + * Attempt to start dragging \a item_. This will not work if the view item doesn't + * support dragging, i.e. if it won't create a drag-controller upon request. + * \return True if dragging started successfully, otherwise false. */ -uiTreeViewItemHandle *UI_block_tree_view_find_item_at(const struct ARegion *region, - const int xy[2]) ATTR_NONNULL(1, 2); -uiTreeViewItemHandle *UI_block_tree_view_find_active_item(const struct ARegion *region); - +bool UI_view_item_drag_start(struct bContext *C, const uiViewItemHandle *item_); +bool UI_view_item_can_drop(const uiViewItemHandle *item_, + const struct wmDrag *drag, + const char **r_disabled_hint); +char *UI_view_item_drop_tooltip(const uiViewItemHandle *item, const struct wmDrag *drag); /** - * Listen to \a notifier, returning true if the region should redraw. + * Let a view item handle a drop event. + * \return True if the drop was handled by the view item. */ -bool UI_tree_view_listen_should_redraw(const uiTreeViewHandle *view, const wmNotifier *notifier); +bool UI_view_item_drop_handle(struct bContext *C, + const uiViewItemHandle *item_, + const struct ListBase *drags); + /** - * Listen to \a notifier, returning true if the region should redraw. + * \param xy: Coordinate to find a view item at, in window space. */ -bool UI_grid_view_listen_should_redraw(const uiGridViewHandle *view, const wmNotifier *notifier); +uiViewItemHandle *UI_region_views_find_item_at(const struct ARegion *region, const int xy[2]) + ATTR_NONNULL(); +uiViewItemHandle *UI_region_views_find_active_item(const struct ARegion *region); #ifdef __cplusplus } diff --git a/source/blender/editors/include/UI_interface.hh b/source/blender/editors/include/UI_interface.hh index 3dc56b01993..82bfdd7e212 100644 --- a/source/blender/editors/include/UI_interface.hh +++ b/source/blender/editors/include/UI_interface.hh @@ -46,7 +46,7 @@ void template_breadcrumbs(uiLayout &layout, Span<ContextPathItem> context_path); void attribute_search_add_items( StringRefNull str, - bool is_output, + bool can_create_attribute, Span<const nodes::geometry_nodes_eval_log::GeometryAttributeInfo *> infos, uiSearchItems *items, bool is_first); @@ -54,12 +54,12 @@ void attribute_search_add_items( } // namespace blender::ui /** - * Override this for all available tree types. + * Override this for all available view types. */ blender::ui::AbstractGridView *UI_block_add_view( uiBlock &block, blender::StringRef idname, - std::unique_ptr<blender::ui::AbstractGridView> tree_view); + std::unique_ptr<blender::ui::AbstractGridView> grid_view); blender::ui::AbstractTreeView *UI_block_add_view( uiBlock &block, blender::StringRef idname, diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh index 1aeb13ca5cc..872a6085060 100644 --- a/source/blender/editors/include/UI_tree_view.hh +++ b/source/blender/editors/include/UI_tree_view.hh @@ -9,7 +9,6 @@ #pragma once -#include <array> #include <functional> #include <memory> #include <string> @@ -19,23 +18,19 @@ #include "BLI_function_ref.hh" #include "BLI_vector.hh" +#include "UI_abstract_view.hh" #include "UI_resources.h" struct bContext; struct uiBlock; struct uiBut; -struct uiButTreeRow; +struct uiButViewItem; struct uiLayout; -struct wmDrag; -struct wmEvent; -struct wmNotifier; namespace blender::ui { class AbstractTreeView; class AbstractTreeViewItem; -class AbstractTreeViewItemDropController; -class AbstractTreeViewItemDragController; /* ---------------------------------------------------------------------- */ /** \name Tree-View Item Container @@ -112,45 +107,20 @@ using TreeViewOrItem = TreeViewItemContainer; /** \name Tree-View Base Class * \{ */ -class AbstractTreeView : public TreeViewItemContainer { +class AbstractTreeView : public AbstractView, public TreeViewItemContainer { friend class AbstractTreeViewItem; friend class TreeViewBuilder; - /** - * Only one item can be renamed at a time. So the tree is informed about the renaming state to - * enforce that. - */ - std::unique_ptr<std::array<char, MAX_NAME>> rename_buffer_; - - bool is_reconstructed_ = false; - public: virtual ~AbstractTreeView() = default; void foreach_item(ItemIterFn iter_fn, IterOptions options = IterOptions::None) const; - /** Listen to a notifier, returning true if a redraw is needed. */ - virtual bool listen(const wmNotifier &) const; - - /** Only one item can be renamed at a time. */ - bool is_renaming() const; - protected: virtual void build_tree() = 0; - /** - * Check if the tree is fully (re-)constructed. That means, both #build_tree() and - * #update_from_old() have finished. - */ - bool is_reconstructed() const; - private: - /** - * Match the tree-view against an earlier version of itself (if any) and copy the old UI state - * (e.g. collapsed, active, selected, renaming, etc.) to the new one. See - * #AbstractTreeViewItem.update_from_old(). - */ - void update_from_old(uiBlock &new_block); + void update_children_from_old(const AbstractView &old_view) override; static void update_children_from_old_recursive(const TreeViewOrItem &new_items, const TreeViewOrItem &old_items); static AbstractTreeViewItem *find_matching_child(const AbstractTreeViewItem &lookup_item, @@ -177,7 +147,7 @@ class AbstractTreeView : public TreeViewItemContainer { * It also stores state information that needs to be persistent over redraws, like the collapsed * state. */ -class AbstractTreeViewItem : public TreeViewItemContainer { +class AbstractTreeViewItem : public AbstractViewItem, public TreeViewItemContainer { friend class AbstractTreeView; friend class TreeViewLayoutBuilder; /* Higher-level API. */ @@ -185,20 +155,17 @@ class AbstractTreeViewItem : public TreeViewItemContainer { private: bool is_open_ = false; - bool is_active_ = false; - bool is_renaming_ = false; protected: /** This label is used as the default way to identifying an item within its parent. */ std::string label_{}; - /** Every visible item gets a button of type #UI_BTYPE_TREEROW during the layout building. */ - uiButTreeRow *tree_row_but_ = nullptr; + /** Every visible item gets a button of type #UI_BTYPE_VIEW_ITEM during the layout building. */ + uiButViewItem *view_item_but_ = nullptr; public: virtual ~AbstractTreeViewItem() = default; virtual void build_row(uiLayout &row) = 0; - virtual void build_context_menu(bContext &C, uiLayout &column) const; AbstractTreeView &get_tree_view() const; @@ -210,11 +177,6 @@ class AbstractTreeViewItem : public TreeViewItemContainer { * can't be sure about the item state. */ bool is_collapsed() const; - /** - * Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise we - * can't be sure about the item state. - */ - bool is_active() const; protected: /** @@ -227,31 +189,21 @@ class AbstractTreeViewItem : public TreeViewItemContainer { */ virtual std::optional<bool> should_be_active() const; - /** - * Queries if the tree-view item supports renaming in principle. Renaming may still fail, e.g. if - * another item is already being renamed. - */ - virtual bool supports_renaming() const; - /** - * Try renaming the item, or the data it represents. Can assume - * #AbstractTreeViewItem::supports_renaming() returned true. Sub-classes that override this - * should usually call this, unless they have a custom #AbstractTreeViewItem.matches(). - * - * \return True if the renaming was successful. - */ - virtual bool rename(StringRefNull new_name); + /** See AbstractViewItem::get_rename_string(). */ + virtual StringRef get_rename_string() const override; + /** See AbstractViewItem::rename(). */ + virtual bool rename(StringRefNull new_name) override; /** * Return whether the item can be collapsed. Used to disable collapsing for items with children. */ virtual bool supports_collapsing() const; - /** - * Copy persistent state (e.g. is-collapsed flag, selection, etc.) from a matching item of - * the last redraw to this item. If sub-classes introduce more advanced state they should - * override this and make it update their state accordingly. - */ - virtual void update_from_old(const AbstractTreeViewItem &old); + /** See #AbstractViewItem::matches(). */ + virtual bool matches(const AbstractViewItem &other) const override; + + /** See #AbstractViewItem::update_from_old(). */ + virtual void update_from_old(const AbstractViewItem &old) override; /** * Compare this item to \a other to check if they represent the same data. @@ -259,22 +211,11 @@ class AbstractTreeViewItem : public TreeViewItemContainer { * open/closed, active, etc.). Items are only matched if their parents also match. * By default this just matches the item's label (if the parents match!). If that isn't * good enough for a sub-class, that can override it. - */ - virtual bool matches(const AbstractTreeViewItem &other) const; - - /** - * If an item wants to support being dragged, it has to return a drag controller here. - * That is an object implementing #AbstractTreeViewItemDragController. - */ - virtual std::unique_ptr<AbstractTreeViewItemDragController> create_drag_controller() const; - /** - * If an item wants to support dropping data into it, it has to return a drop controller here. - * That is an object implementing #AbstractTreeViewItemDropController. * - * \note This drop controller may be requested for each event. The tree-view doesn't keep a drop - * controller around currently. So it can not contain persistent state. + * TODO #matches_single() is a rather temporary name, used to indicate that this only compares + * the item itself, not the parents. Item matching is expected to change quite a bit anyway. */ - virtual std::unique_ptr<AbstractTreeViewItemDropController> create_drop_controller() const; + virtual bool matches_single(const AbstractTreeViewItem &other) const; /** * Activates this item, deactivates other items, calls the #AbstractTreeViewItem::on_activate() @@ -292,29 +233,24 @@ class AbstractTreeViewItem : public TreeViewItemContainer { */ bool is_hovered() const; bool is_collapsible() const; - bool is_renaming() const; void ensure_parents_uncollapsed(); - uiButTreeRow *tree_row_button(); + uiButViewItem *view_item_button(); private: - static void rename_button_fn(bContext *, void *, char *); - static AbstractTreeViewItem *find_tree_item_from_rename_button(const uiBut &but); static void tree_row_click_fn(struct bContext *, void *, void *); static void collapse_chevron_click_fn(bContext *, void *but_arg1, void *); static bool is_collapse_chevron_but(const uiBut *but); /** See #AbstractTreeView::change_state_delayed() */ void change_state_delayed(); - void end_renaming(); void add_treerow_button(uiBlock &block); void add_indent(uiLayout &row) const; void add_collapse_chevron(uiBlock &block) const; void add_rename_button(uiLayout &row); - bool matches_including_parents(const AbstractTreeViewItem &other) const; bool has_active_child() const; int count_parents() const; }; @@ -322,69 +258,6 @@ class AbstractTreeViewItem : public TreeViewItemContainer { /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Drag 'n Drop - * \{ */ - -/** - * Class to enable dragging a tree-item. An item can return a drop controller for itself via a - * custom implementation of #AbstractTreeViewItem::create_drag_controller(). - */ -class AbstractTreeViewItemDragController { - protected: - AbstractTreeView &tree_view_; - - public: - AbstractTreeViewItemDragController(AbstractTreeView &tree_view); - virtual ~AbstractTreeViewItemDragController() = default; - - virtual int get_drag_type() const = 0; - virtual void *create_drag_data() const = 0; - virtual void on_drag_start(); - - template<class TreeViewType> inline TreeViewType &tree_view() const; -}; - -/** - * Class to customize the drop behavior of a tree-item, plus the behavior when dragging over this - * item. An item can return a drop controller for itself via a custom implementation of - * #AbstractTreeViewItem::create_drop_controller(). - */ -class AbstractTreeViewItemDropController { - protected: - AbstractTreeView &tree_view_; - - public: - AbstractTreeViewItemDropController(AbstractTreeView &tree_view); - virtual ~AbstractTreeViewItemDropController() = default; - - /** - * Check if the data dragged with \a drag can be dropped on the item this controller is for. - * \param r_disabled_hint: Return a static string to display to the user, explaining why dropping - * isn't possible on this item. Shouldn't be done too aggressively, e.g. - * don't set this if the drag-type can't be dropped here; only if it can - * but there's another reason it can't be dropped. - * Can assume this is a non-null pointer. - */ - virtual bool can_drop(const wmDrag &drag, const char **r_disabled_hint) const = 0; - /** - * Custom text to display when dragging over a tree item. Should explain what happens when - * dropping the data onto this item. Will only be used if #AbstractTreeViewItem::can_drop() - * returns true, so the implementing override doesn't have to check that again. - * The returned value must be a translated string. - */ - virtual std::string drop_tooltip(const wmDrag &drag) const = 0; - /** - * Execute the logic to apply a drop of the data dragged with \a drag onto/into the item this - * controller is for. - */ - virtual bool on_drop(struct bContext *C, const wmDrag &drag) = 0; - - template<class TreeViewType> inline TreeViewType &tree_view() const; -}; - -/** \} */ - -/* ---------------------------------------------------------------------- */ /** \name Predefined Tree-View Item Types * * Common, Basic Tree-View Item Types. @@ -455,18 +328,4 @@ inline ItemT &TreeViewItemContainer::add_tree_item(Args &&...args) add_tree_item(std::make_unique<ItemT>(std::forward<Args>(args)...))); } -template<class TreeViewType> TreeViewType &AbstractTreeViewItemDragController::tree_view() const -{ - static_assert(std::is_base_of<AbstractTreeView, TreeViewType>::value, - "Type must derive from and implement the AbstractTreeView interface"); - return static_cast<TreeViewType &>(tree_view_); -} - -template<class TreeViewType> TreeViewType &AbstractTreeViewItemDropController::tree_view() const -{ - static_assert(std::is_base_of<AbstractTreeView, TreeViewType>::value, - "Type must derive from and implement the AbstractTreeView interface"); - return static_cast<TreeViewType &>(tree_view_); -} - } // namespace blender::ui diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 5c4eb254462..e508c96b4f1 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -309,6 +309,12 @@ float UI_view2d_view_to_region_y(const struct View2D *v2d, float y); bool UI_view2d_view_to_region_clip( const struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL(); +bool UI_view2d_view_to_region_segment_clip(const View2D *v2d, + const float xy_a[2], + const float xy_b[2], + int r_region_a[2], + int r_region_b[2]) ATTR_NONNULL(); + /** * Convert from 2d-view space to screen/region space * |