1
1

Compare commits

...

211 Commits

Author SHA1 Message Date
e13e8d727a Merge branch 'property-search-all-tabs-v2' into property-search-ui-v2 2020-09-14 17:36:42 -05:00
adaf9947b1 Merge branch 'property-search-all-tabs' into property-search-ui-v2 2020-09-14 17:34:23 -05:00
b037801f5e Merge branch 'property-search-highlight-tabs' into property-search-all-tabs-v2 2020-09-14 17:34:01 -05:00
fd89ef4d2f Merge branch 'property-search-start-end-operators' into property-search-highlight-tabs 2020-09-14 17:33:45 -05:00
572ce24f7e Merge branch 'property-search-single-tab' into property-search-start-end-operators 2020-09-14 17:33:32 -05:00
2c2d30df60 Property Search: Apply fixes from all tab code 2020-09-14 17:33:18 -05:00
4fbc49ff4b Property Search: Fixes for all tab search V2 2020-09-14 17:21:42 -05:00
d9b0afcf19 Merge branch 'property-search-highlight-tabs' into property-search-all-tabs-v2 2020-09-14 13:50:40 -05:00
742b8d2ca1 Merge branch 'property-search-highlight-tabs' into property-search-all-tabs 2020-09-14 13:39:00 -05:00
dcfbee5c80 Merge branch 'property-search-start-end-operators' into property-search-highlight-tabs 2020-09-14 13:38:25 -05:00
d8420767d3 Property Search: Use runtime struct properly for seach string 2020-09-14 13:38:11 -05:00
a90b701ab3 Merge branch 'property-search-highlight-tabs' into property-search-all-tabs 2020-09-14 13:36:03 -05:00
18d384ffaf Merge branch 'property-search-start-end-operators' into property-search-highlight-tabs 2020-09-14 13:33:55 -05:00
601d323d96 Merge branch 'property-search-single-tab' into property-search-start-end-operators 2020-09-14 11:23:20 -05:00
0106127364 Property Search: Fix storing search string in runtime struct 2020-09-14 11:17:01 -05:00
360549b31b Property Search: Use pointer for properties space runtime struct 2020-09-14 10:39:14 -05:00
530183b60a Property Search: Add explanatory comment 2020-09-14 10:22:56 -05:00
dabed53d12 Merge branch 'property-search-add-theme-color' into property-search-single-tab 2020-09-14 09:48:06 -05:00
97212d6258 Merge branch 'property-search-move-context-to-panel' into property-search-add-theme-color 2020-09-14 09:47:50 -05:00
ca3cc95f3d Merge branch 'property-search-button-label-pointer' into property-search-move-context-to-panel 2020-09-14 09:47:37 -05:00
3eae5f71d1 Merge branch 'master' into property-search-button-label-pointer 2020-09-14 09:47:22 -05:00
d23036e510 Property Search: New implementation for all-tab search
Use a bespoke pass for running property search in a panel region.
While this method results in more code, it doesn't reuse the panel
search, which has a few benefits:
1. It's possible to exit early when a results is found for a tab. Although
   this doesn't affect worse case performance, in general it's a benefit.
2. The code for searching all tabs in the properties editor becomes
   much simpler.
3. There should be other performance improvements, as the search
   code can skip everything not related to search.

This is accomplished by ED_region_panels_layout_ex in area.c, which
was a bit too long of a function anyway.
2020-09-13 19:52:12 -05:00
98d4da32dd Merge branch 'property-search-highlight-tabs' into property-search-all-tabs 2020-09-12 18:48:47 -05:00
a67067253b Merge branch 'property-search-start-end-operators' into property-search-highlight-tabs 2020-09-12 18:48:32 -05:00
d3dd76789c Merge branch 'property-search-single-tab' into property-search-start-end-operators 2020-09-12 18:47:54 -05:00
43533f4269 Property Search: Fix memory leak 2020-09-12 18:47:40 -05:00
cd35233ea7 Merge branch 'property-search-add-theme-color' into property-search-single-tab 2020-09-12 18:30:57 -05:00
6c1f3b40c6 Merge branch 'property-search-move-context-to-panel' into property-search-add-theme-color 2020-09-12 18:30:44 -05:00
94aa5c0dd6 Merge branch 'property-search-button-label-pointer' into property-search-move-context-to-panel 2020-09-12 18:30:30 -05:00
2dd0161860 Property Search: Replace pointer in group when button type switches 2020-09-12 18:30:13 -05:00
11f0dd4951 Merge branch 'property-search-highlight-tabs' into property-search-all-tabs 2020-09-12 17:43:46 -05:00
1496526dce Merge branch 'property-search-start-end-operators' into property-search-highlight-tabs 2020-09-12 17:43:21 -05:00
3eaca73753 Merge branch 'property-search-single-tab' into property-search-start-end-operators 2020-09-12 17:42:27 -05:00
8f6740b275 Merge branch 'property-search-add-theme-color' into property-search-single-tab 2020-09-12 17:37:49 -05:00
f9dd47475a Merge branch 'property-search-move-context-to-panel' into property-search-add-theme-color 2020-09-12 17:22:12 -05:00
7b714a9897 Merge branch 'property-search-button-label-pointer' into property-search-move-context-to-panel 2020-09-12 17:22:01 -05:00
d78a5f022d Merge branch 'master' into property-search-button-label-pointer 2020-09-12 17:20:06 -05:00
b57cd0e359 Property Search: Use LinkData instead of button for group 2020-09-12 17:17:55 -05:00
cf877d717c Merge branch 'master' into property-search-button-label-pointer 2020-09-11 14:28:58 -05:00
5c329ba2b5 Merge branch 'master' into property-search-button-label-pointer 2020-09-11 14:15:01 -05:00
245cb6e972 Property Search: Fixes for button group 2020-09-11 13:58:08 -05:00
68a5d4c56d Property Search: Code to use new button group structs 2020-09-11 12:36:22 -05:00
bc730e4ae6 Merge branch 'property-search-add-theme-color' into property-search-single-tab 2020-09-11 12:36:04 -05:00
7ce4911a71 Merge branch 'property-search-move-context-to-panel' into property-search-add-theme-color 2020-09-11 12:15:06 -05:00
3c52c75af2 Merge branch 'property-search-button-label-pointer' into property-search-move-context-to-panel 2020-09-11 12:14:51 -05:00
28f13a5697 Property Search: Use button groups instead of button pointers 2020-09-11 12:14:27 -05:00
9a2d04677a Merge branch 'property-search-add-theme-color' into property-search-single-tab 2020-09-11 10:45:20 -05:00
3c26181cd9 Merge branch 'property-search-move-context-to-panel' into property-search-add-theme-color 2020-09-11 10:44:54 -05:00
537daa5dd4 Merge branch 'property-search-button-label-pointer' into property-search-move-context-to-panel 2020-09-11 10:44:41 -05:00
5c5d022649 Merge branch 'properties-pin-operator' into property-search-button-label-pointer 2020-09-11 10:44:25 -05:00
86993444a0 Merge branch 'master' into properties-pin-operator 2020-09-11 10:44:12 -05:00
a8eb263678 Merge branch 'property-search-all-tabs' into property-search-ui-v2 2020-09-10 17:44:56 -05:00
e9c9f7d5c4 Merge branch 'property-search-highlight-tabs' into property-search-all-tabs 2020-09-10 17:44:36 -05:00
6ebc8278de Merge branch 'property-search-start-end-operators' into property-search-highlight-tabs 2020-09-10 17:44:21 -05:00
5545d83315 Merge branch 'property-search-single-tab' into property-search-start-end-operators 2020-09-10 17:44:05 -05:00
2f22d6aa7c Merge branch 'property-search-add-theme-color' into property-search-single-tab 2020-09-10 17:43:51 -05:00
bbacf94c69 Merge branch 'property-search-move-context-to-panel' into property-search-add-theme-color 2020-09-10 17:43:39 -05:00
eabba50141 Merge branch 'property-search-button-label-pointer' into property-search-move-context-to-panel 2020-09-10 17:43:08 -05:00
a444b38fa3 Merge branch 'properties-pin-operator' into property-search-button-label-pointer 2020-09-10 17:41:45 -05:00
9ba5d0e4b1 Merge branch 'master' into properties-pin-operator 2020-09-10 17:37:44 -05:00
099d603e7b Merge branch 'property-search-all-tabs' into property-search-ui-v2 2020-09-10 17:33:38 -05:00
b7b5227640 Merge branch 'property-search-highlight-tabs' into property-search-all-tabs 2020-09-10 17:33:19 -05:00
3069c4a3f7 Merge branch 'property-search-start-end-operators' into property-search-highlight-tabs 2020-09-10 17:32:28 -05:00
afe0213bca Property Search: Fix clear operator after recent change 2020-09-10 17:32:11 -05:00
2baec9e65f Merge branch 'property-search-highlight-tabs' into property-search-all-tabs 2020-09-10 17:29:34 -05:00
055d3fbe2f Merge branch 'property-search-start-end-operators' into property-search-highlight-tabs 2020-09-10 17:27:05 -05:00
83eacc0352 Merge branch 'property-search-single-tab' into property-search-start-end-operators 2020-09-10 17:26:42 -05:00
4baf63ab73 Property Search: Fix tab buttons graying out after refactor 2020-09-10 17:25:59 -05:00
46db0d65bd Property Search: Clear region search filter active flag on read 2020-09-10 15:01:23 -05:00
4e636376ca Property Search: Set expansion for subpanels based on results 2020-09-10 14:54:35 -05:00
deabcf00f2 Property Search: Use RNA_property_enum_items_gettexted 2020-09-10 13:42:23 -05:00
8679b24b91 Property Search: Remove redundant button hiding code 2020-09-10 12:39:46 -05:00
36b3364ef3 Property Search: Refactor block search into new function 2020-09-10 12:34:52 -05:00
d53e093b3e Property Search: Move search string to a runtime struct 2020-09-10 11:19:17 -05:00
01d17c525c Cleanup: Remove unecessary cast 2020-09-10 10:28:49 -05:00
01d292f151 Property Search: Clarify comment 2020-09-10 10:26:56 -05:00
9d06994229 Property Search: Refactor setting block search filter 2020-09-10 10:24:26 -05:00
049eb2f33a Property Search: Add comment to field, make const 2020-09-10 09:35:59 -05:00
79c5b90040 Merge branch 'property-search-all-tabs' into property-search-ui-v2 2020-09-10 09:09:52 -05:00
5b7a534211 Merge branch 'property-search-highlight-tabs' into property-search-all-tabs 2020-09-10 09:09:12 -05:00
b89e8b71f9 Merge branch 'property-search-start-end-operators' into property-search-highlight-tabs 2020-09-10 09:08:52 -05:00
e56e34ddd1 Merge branch 'property-search-single-tab' into property-search-start-end-operators 2020-09-10 09:07:58 -05:00
09217fc22d Merge branch 'property-search-add-theme-color' into property-search-single-tab 2020-09-10 08:56:29 -05:00
66f5008b33 Merge branch 'property-search-move-context-to-panel' into property-search-add-theme-color 2020-09-10 08:55:55 -05:00
1b5f355af8 Merge branch 'property-search-button-label-pointer' into property-search-move-context-to-panel 2020-09-10 08:54:46 -05:00
f4c8b81595 Reapply changes after failed merge 2020-09-10 08:54:17 -05:00
9a60f5cf93 Merge branch 'properties-pin-operator' into property-search-button-label-pointer 2020-09-10 08:53:57 -05:00
417fa6765e Remove changes from property-search-button-label-pointer 2020-09-10 08:48:11 -05:00
3860e8bfeb Merge branch 'master' into properties-pin-operator 2020-09-10 08:29:05 -05:00
59fcb799ca Merge branch 'properties-pin-operator' into property-search-button-label-pointer 2020-09-10 08:26:42 -05:00
3dc7c4fa83 Merge branch 'master' into properties-pin-operator 2020-09-10 08:26:25 -05:00
3551b8c83e Merge branch 'property-search-all-tabs' into property-search-ui-v2 2020-09-09 14:03:09 -05:00
4a4e36ff9b Property Search: All tabs
This patch enables property search for all tabs in the property editor.
This is definitely the most "crazy" of the changes in terms of code, but
it's also where the new functionality gets good.

There is one piece of funcionality that wasn't obvious when I began the
implementation. In order to make interaction faster, if the editor's
current tab doesn't have a result, the search moves you to the next panel
that does. That way you can just press `ctrl-F`, search, and have the
result appear.

In order to keep the searching safe, to make sure the editor isn't influenced
by anything that happens while building the layout for the other tabs,
the space is duplicated and the new search is run in the duplicated
editor. This also helps isolate this code, which could be fairly invasive
otherwise. Only the layout pass is done in the other tabs, and it works
by just running the regular single tab property search  (D8856) and
checking if any of the active panels in the tab match the search filter.

The search match status for every current tab of the property editor is
stored in a runtime field and them displayed later by dimming icons in
the tab selector panel to the left. The functionality for that dimming is
in D8858.

Note that there are currently some issues with the tool tab, where some
context variables end up being `None`. I'm curious if reviewers have any
advice if they encounter this.

**Future Improvements**
This patch does not addresss the performance aspects of searching every
tab. This shouldn't be too bad, but it would be good to make some changes
to improve this, ideally in separate patches. I have done some initial profiling,
and it looks like a significant portion of time is spent doing string comparisons,
so that may be the best place to start. Here are some ideas:
1. Use ghash instead of string lookups for panel types
2. Possibly only search in other tabs while editing search string. I would like
   to avoid this though.
3. Look into using ED_region_tag_redraw_no_rebuild for some interactions
   like panel dragging.

Differential Revision: https://developer.blender.org/D8859
2020-09-09 13:46:27 -05:00
44dcc742c6 Property Search: Add highlight arguments to tab buttons
For searching multiple tabs, we need a way to show which tabs have a search
result, but we still need to be able to show which tab is active. Also, multiple
tabs can be highlighted, so that argument needs be be a bitfield enum. This
requires giving extra arguments to `ui_item_enum_expand_tabs`.

Unforunately this adds a bit of ugly complexity to this function. It would be
better if RNA enum items could have an "active" flag, but that change would
probably have larger scope.

Differential Revision: https://developer.blender.org/D8858
2020-09-09 13:27:55 -05:00
863ea6a32c Property Search: Quick start and clear operators
This patch adds quick start and quick clear operators.

`ctrl-F` is obviously necessary, but the clear operator, `alt-F` requires
a bit of explanation. First, it maps nicely to the paradigm of "key to set,
alt-key to clear," which makes it pretty unobtrusive. Second, it can be
a quicker way to clear the search than moving the mouse to the top.
Finally, a future improvement I would like to make to property search
is adding the ability to reset the panels to their expansion before the
search started. Either escaping out of the button while text editing or
pressing `alt-F` would be the way to do that.

Differential Revision: https://developer.blender.org/D8857
2020-09-09 13:14:16 -05:00
58488c08b8 Property Search: Single tab
This adds a search bar to the properties editor. The full search for every tab
isn't includede in this patch, but the interaction with panels, searching
behavior, internal UI, region level, and DNA changes are included here.

The block-level search works by iterating over the block's buttons and
checking whether they match the search. If they do, they are tagged with
a flag, and the block's panel is tagged too.

For every update (text edit), the panel's expansion is set to whether the
panel has a result or not.

There is some complications to this that you might no initially think of:
1. Closed panel's subpanels have to be searched too. This adds some
   complexity and special cases to the area-level panel layout code.
2. //Maybe more if I think of things to add here//

There might be some methods of simplifying some of the logic, particularly
around choosing whether to highlight panel headers. Also note that automatic
subpanel expansion isn't working right now. I'll look into this, but I want to post
all the patches first.

**Future Improvements**
Here are some improvements possible in the future that won't be part of this patch:
1. Use the new fuzzy search in BLI
2. Reseting panels to their expansion before the search started if you `esc`
   out of the text box
3. Open parent panels if their subpanels have a match but they don't. This
   requires adding a reference to parent panels for subpanels.

Differential Revision: https://developer.blender.org/D8856
2020-09-09 13:01:32 -05:00
6a76eeaced Property Search: Add "Search match" theme color
We use a highlight on panel headers to convey that they have a search match.
It's also conceivable to use this color to highlight the property editor tabs
that have search results.

Normally we don't like adding new theme colors, but this is quite a special
case. For example, the color in the outliner is green. This patch has a blue
highlight so it feels more cohesive though.

Differential Revision: https://developer.blender.org/D8854
2020-09-09 12:08:43 -05:00
f3197de265 Property Search: Move properties context buttons back to a panel
The context path buttons used to be in a panel in 2.79. Although they look
a bit better in the header, there is not space for them with the property
search field in the header as well.

In the long term, maybe it will be possible to shrink the text button and
then animate it expanding when property search begins, then there
would be enough room for both.

Note that this diff is just for review, Blender won't ever actually have only
the pin button in the header like the following image.

{F8858554 size=full}

Differential Revision: https://developer.blender.org/D8853
2020-09-09 11:57:27 -05:00
a3f61ade7a Property Search: Small cleanups 2020-09-09 11:25:21 -05:00
407f8f5a4e Merge branch 'property-search-button-label-pointer' into property-search-ui-v2 2020-09-09 11:17:13 -05:00
e2f3455956 Merge branch 'properties-pin-operator' into property-search-button-label-pointer 2020-09-09 11:16:23 -05:00
27ce07a010 Merge branch 'master' into properties-pin-operator 2020-09-09 11:15:58 -05:00
e9489757ea Merge branch 'properties-pin-operator' into property-search-ui-v2 2020-09-09 11:02:03 -05:00
27f3f3d8a7 Use RNA to set the pin ID 2020-09-09 10:54:34 -05:00
69be090944 Merge branch 'master' into properties-pin-operator 2020-09-09 10:14:10 -05:00
ca0d4d90c6 Merge branch 'master' into property-search-ui-v2 2020-09-02 11:15:50 -05:00
277e03c6bd UI: Keep track of button's relationship with label buttons
This is needed for property search where we want to highlight a button's label if it matches the search
filter. Otherwise the button itself is highlighted but it has no idea what label to highlight.

This is especially important because of the use of property split layouts where the label is almost
always outside of the button in a separate column.

The additional logic in the layout code isn't ideal, but I think this is generally a good thing to keep track of.
For example, another use for this could be adding a highlight to a buttons label on mouseover.

Differential Revision: https://developer.blender.org/D8783
2020-09-02 09:39:35 -05:00
c335173a78 Merge branch 'master' into property-search-ui-v2 2020-09-01 23:32:18 -05:00
6d2069f348 Merge branch 'master' into property-search-ui-v2 2020-09-01 13:55:05 -05:00
293405b653 Merge branch 'master' into property-search-ui-v2 2020-08-30 22:36:20 -05:00
0c4a9085f8 Merge branch 'master' into property-search-ui-v2 2020-08-26 17:12:39 -05:00
fbcedf96cb Property Search: Add comment explaining menu search limitation 2020-08-26 09:24:24 -05:00
d17e2e8101 Merge branch 'master' into property-search-ui-v2 2020-08-25 22:47:36 -05:00
caa79adffb Property Search: Update panel expansion while searching 2020-08-20 16:06:11 -04:00
612b19f4e7 Property Search: Correct the last commit
Accidentally committed the wrong file...
2020-08-20 14:54:00 -04:00
171090c489 Property Search: Switch to the next tab with a result 2020-08-20 14:43:51 -04:00
31ef82b2cf Merge branch 'master' into property-search-ui-v2 2020-08-20 14:23:02 -04:00
3eea67e8c5 Property Search: Update the "search on" flag for the proper region 2020-08-20 11:55:47 -04:00
a22a8cdeeb Merge branch 'master' into property-search-ui-v2 2020-08-20 10:57:15 -04:00
abe6bd2bd2 Merge branch 'master' into property-search-ui-v2 2020-08-17 09:46:56 -04:00
ce6270d24d Property Search: Clarify comments, rename function 2020-08-14 16:12:56 -04:00
f8c386a331 Property Search: Fix ctrl-F shortcut after recent renaming change 2020-08-14 16:05:28 -04:00
7d6562d280 Property Search: Gray out panels with no search match 2020-08-14 15:53:02 -04:00
dcc3211650 Property Search: Add search filter active flag to region
This seems like a good way to quickly check whether or not to gray out
panel header text (in addition to whether they have a match).  It might
be nice to have this information quickly accessible in the future as well.
2020-08-14 15:52:30 -04:00
c8dfe0800d Merge branch 'master' into property-search-ui-v2 2020-08-14 13:36:27 -04:00
b9c4e5bd23 Property Search: Search in pulldown button RNA enums
This introduces a memory leak when accessing the enum items.
I'll solve that later.
2020-08-13 18:20:03 -04:00
904e7830e1 Property Search: Search based on label buttons 2020-08-13 17:34:33 -04:00
629c8344c4 Merge branch 'master' into property-search-ui-v2 2020-08-13 16:50:58 -04:00
1ea46cd039 Merge branch 'master' into property-search-ui-v2 2020-08-12 21:22:16 -04:00
f2c8935295 Merge branch 'master' into property-search-ui-v2 2020-08-11 22:14:01 -04:00
95fabb12cb Property Search: Highlight panel headers with a search match 2020-07-30 17:44:22 -04:00
b02e8e3504 Property Search: Add "search match" theme color 2020-07-30 17:42:42 -04:00
1836a97958 Property Search: Continued refactoring / cleanup 2020-07-30 15:23:18 -04:00
99862a72b1 Property Search: Miscellaneous cleanup
Mostly renaming UI_FILTERED to UI_SEARCH_FILTER_MATCHES
and reversing its meaning. Also reverting some unrelated changes.
2020-07-30 14:59:47 -04:00
aa3a053f31 Property Search: Gray out buttons that don't match the search 2020-07-30 14:49:59 -04:00
ba2eef2f6f Property Search: Remove code for changing to search layout
The design for this task has changed so that the layouts won't be changed
to only list the matching properties. Instead we will use highlights to
communicate matching properties.

After this commit property search doesn't do anything visible.
Functionality will be added back in future commits.
2020-07-30 12:29:14 -04:00
fff7a29861 Merge branch 'master' into property-search-ui-v2 2020-07-30 11:53:59 -04:00
68df739bb1 Merge branch 'master' into property-search-ui-v2 2020-07-29 17:21:13 -04:00
1f768bbe41 Merge branch 'master' into property-search-ui 2020-07-28 17:25:39 -04:00
ce6cf2b475 Property Search: Various cleanups and comment changes 2020-07-28 17:12:09 -04:00
f957e09398 Merge branch 'master' into property-search-ui 2020-07-28 14:25:00 -04:00
d58f361099 Property Search: Remove commented out code 2020-07-28 13:48:36 -04:00
1b391f14fc Property Search: Fixes for other-tab searching
The main change here is not running the search twice for the active tab.
We also check for the panel being active rather than just not filtered.

There are still errors when the tool tab is active, those will be solved
in a future commit.
2020-07-28 12:11:48 -04:00
b4b2185da0 Property Search: Remove debugging information 2020-07-27 16:39:43 -04:00
8f548fd856 Merge branch 'master' into property-search-ui 2020-07-27 16:32:49 -04:00
634bf8e4fc Merge branch 'master' into property-search-ui 2020-07-27 12:34:08 -04:00
6776607913 UI: Use an operator to set the property editor's pinned data-block
This is another change pulled from the `property-search-ui` branch. This is useful
because it means the pin button doesn't have to be a custom button defined in C.

Replacing the use of button callbacks with operators is always nice too.

Differential Revision: https://developer.blender.org/D8376
2020-07-23 13:21:08 -04:00
af146e7745 Use operator to toggle pin data-block 2020-07-23 12:16:49 -04:00
4b0a94661c Property Search: Clean up some unecessary changes 2020-07-23 11:36:40 -04:00
8eda823dbc Merge branch 'master' into property-search-ui 2020-07-23 11:04:11 -04:00
e40225577b Merge branch 'master' into property-search-ui 2020-07-22 22:28:48 -04:00
d219d0efa1 Property Search: Fix graying out tabs with no results 2020-07-22 15:14:06 -04:00
cc1201dce3 Property Search: Improve debug printing 2020-07-22 12:09:54 -04:00
1afdc92511 Merge branch 'master' into property-search-ui 2020-07-22 11:35:02 -04:00
20ce4a77bd Property Search: Properly filter labels for color buttons 2020-07-20 16:24:39 -04:00
7d3d6ac085 Merge branch 'master' into property-search-ui 2020-07-20 15:45:34 -04:00
304e9a0b9e Merge branch 'master' into property-search-ui 2020-07-10 13:20:49 -04:00
31657ebbbe Property Search: Initial implementation of searching all tabs
The basics should be close to working. The space and necessary context
is duplicated, then the context is switched and that tab is searched.
However, this is still pretty buggy and the enum isn't drawing correctly.
I'm probably not filling the bitfield correctly.

Mainly committing this to get it out there and focus on smaller fixes /
improvements to it.
2020-07-09 16:25:20 -04:00
169ac2805e Property Search: Add search filter active tabs property
I also generalized the tab "adding" code in RNA to make it usable for filling
both the context enum and the active search filter tabs properties. The tab
layout code might need to be extended to add the idea of a custom
highlight property.
2020-07-09 08:45:54 -04:00
c914bff16d Property Search: Fix panels occasionally overlapping 2020-07-08 13:56:55 -04:00
7758bb25e7 Property Search: Fix panels animating when added 2020-07-08 11:52:52 -04:00
94272e8347 Merge branch 'master' into property-search-ui 2020-07-08 11:06:47 -04:00
67d6d1363d Property Search: Properly filter box buttons 2020-07-07 15:27:29 -04:00
b7d47e9892 Property Search: Apply filter to operator buttons 2020-07-07 14:44:30 -04:00
6f5ca857fc Property Search: Move button tagging to separate function 2020-07-07 13:55:34 -04:00
71c6af4d59 Property Search: Solve memory leak 2020-07-07 13:21:23 -04:00
2f68b79fa8 Property Search: Cleanup, remove unrelated changes 2020-07-07 12:24:14 -04:00
98c6349bca Merge branch 'master' into property-search-ui 2020-07-07 11:10:53 -04:00
4c1095d33c Property Search: Support labels and expanded enums 2020-07-07 10:58:06 -04:00
847837c808 Property Search: Support labels and array buttons 2020-07-07 10:48:49 -04:00
16bf1807a1 Merge branch 'master' into property-search-ui 2020-07-07 10:18:44 -04:00
052baecc0d Merge branch 'master' into property-search-ui 2020-07-02 18:11:25 -04:00
34c5245c32 Property Search: Support heading labels 2020-07-01 15:16:44 -04:00
42e5314727 Property Search: Support checkboxes with no headings
Further changes will be needed to keep track of the labels added
for headings.
2020-07-01 15:10:40 -04:00
7137e99ff3 Property Search: Fix some filtered buttons not hidden 2020-07-01 12:35:57 -04:00
f3e409c1bf Property Search: Fix X margin accumulating for box panels 2020-07-01 12:11:14 -04:00
92c201b493 Property Search: Turn off search for add constraints buttons 2020-07-01 11:35:20 -04:00
7955c26f41 Merge branch 'master' into property-search-ui 2020-07-01 11:11:19 -04:00
26450636cd Property Search: Support labels with number buttons 2020-06-30 21:29:04 -04:00
f3b83271e6 Property Search: Support labels with ui_item_with_label
This includes unexpanded enums and "pointer" selection buttons, and
possibly others.

This necessitates changing uiItemL_respect_property_split to return the
label button it creates, which is reasonably anyway as it makes it
consistent with uiItemL_.
2020-06-30 21:17:27 -04:00
136475dca3 Property Search: Refactor to simpler method
This method doesn't try to change the input layouts at all. Instead it
filters out the empty buttons and removes layouts that become empty
after that.

Pointers for labels and decorators have been added to uiBut. They will
be set during the layout building process in future commits. For now
all labels will be removed though.
2020-06-30 18:54:10 -04:00
544ac33b61 Property Search: Always animate panels when filter status changes
This should finally be a proper solution to this problem. Now the last
search filter status is stored and compared to the new one to
activate animation.
2020-06-30 12:07:28 -04:00
263e42a172 Property Search: Filter panel names without case sensitivity 2020-06-30 11:42:44 -04:00
b7938c3768 Merge branch 'master' into property-search-ui 2020-06-30 09:28:26 -04:00
be7a4f4a81 Property Search: Cleaup: Remove unused variable 2020-06-29 17:09:45 -04:00
dbc9f1b0f3 Merge branch 'master' into property-search-ui 2020-06-29 17:08:57 -04:00
f3caadec90 Merge branch 'master' into property-search-ui 2020-06-29 11:29:55 -04:00
11b89dd56c Property Search: Don't remove layouts with search turned off
This mostly fixes panel headers, although they still end up with the same
problems as other layouts, with a minimum column size enforced for some
reason and misplaced labels.
2020-06-26 14:16:44 -04:00
5218fb969f Merge branch 'master' into property-search-ui 2020-06-26 10:16:50 -04:00
411f425973 Merge branch 'master' into property-search-ui 2020-06-26 09:21:29 -04:00
d4b9f41a56 Property Search: Print debug with colors 2020-06-26 09:20:06 -04:00
66ac0448ef Property Search: Improve layout debugging tool
The tool now prints button types as well. Click to drag a panel while a
search is active to print a tree of the layouts, sublayouts, and buttons.
2020-06-25 21:39:05 -04:00
170a40c338 Property Search: Sort filtered panels properly
Instead of just putting the filtered panels at the bottom, or not updating
their search order, we stop increasing the offset while the current panel
is invisible. This way the order is not completely broken if you drag to
reorder a panel while some have been filtered out.
2020-06-25 16:53:18 -04:00
d2c00d1d7f Merge branch 'master' into property-search-ui 2020-06-25 16:17:08 -04:00
cf99c25dbe Merge branch 'master' into property-search-ui 2020-06-25 12:16:26 -04:00
c95d6de3b3 Property Search: Improve interaction with panels 2020-06-19 07:41:12 -04:00
a33720329b Property Search: New method that reuses existing layouts
This method just transforms each layout into a row or a column, without
adding any new layouts at all. There are a few problems with this method
though, the columns have a fixed width for some reason, and it becomes
more difficult to add the label column.
2020-06-18 17:00:38 -04:00
9029c7be19 Merge branch 'master' into property-search-ui 2020-06-18 08:46:53 -04:00
463c4ef39e Property Search: Support aligned rows in search layout 2020-06-17 17:31:22 -04:00
c891ba0086 Property Search: Solve memory leak 2020-06-17 16:31:03 -04:00
09e555142a Merge branch 'master' into property-search-ui 2020-06-17 14:50:08 -04:00
4d5b6409ee Property Search: Expose layout flag to RNA, use for modifiers 2020-06-17 13:15:26 -04:00
712ccc2602 Property Search: Improve interaction with panels
This isn't perfect yet, but the animation is back, and it works much better.
There are still two issues though:
  1. Order doesn't update sometimes while searching / ending search.
  2. Panels are still displayed when empty in some situations.
The solution is probably just adding some more special cases. Possibly
a tag for panel aligning when the search filter is changed to force special
ordering calculations.
2020-06-17 13:14:58 -04:00
85fe4a18e8 Property Search: Various small cleanups 2020-06-17 10:21:38 -04:00
8357b7fe46 Merge branch 'master' into property-search-ui 2020-06-17 09:08:26 -04:00
13b283ca8e Property Search: Make ctrl-F work, and alt-F to clear 2020-06-16 11:54:38 -04:00
723f6e7f53 Merge branch 'master' into property-search-ui 2020-06-16 10:50:35 -04:00
040931a9b2 Merge branch 'master' into property-search-ui 2020-06-12 22:01:59 -04:00
a34c25046b Property Search: Refactor / simplify, and better layout
The single column layout works much better now, as most of the code that
dealt with trying to remove empty layouts has been rewritten. The search
filter code is not a completely separate pass for the sake of simplicity.

Also, toggle buttons have their text replaced with the rna property name.

There branch is far from stable, and there's a tricky memory leak still to
track down as well.
2020-06-12 21:59:07 -04:00
e299727fba Merge branch 'master' into property-search-ui 2020-06-12 10:26:05 -04:00
db76f34ed6 UI: Start towards property search in public branch
This is VERY WIP, but I will continue work in this branch. Implementation
starts with a few things:
  - A pass at the end of the layout system to scan buttons based on a
    search string set by the properties space. Buttons which don't fit
    the filter are removed from the layouts.
  - A pass after the filter to move buttons that are still in layouts
    to a single column "search layout." There is currently a bug with
    this that adds too much space in between items.
  - An attempt to only show panels that haven't been completely
    filtered by the previous two steps. This is quite buggy right now:
    panels don't animate properly and sometimes it fails.
  - An attempt at a keymap item "ctrl-F" to activate the search button.
    "alt-F" should probably clear the button too.
2020-06-11 18:07:24 -04:00
24 changed files with 1162 additions and 208 deletions

View File

@@ -269,6 +269,7 @@ const bTheme U_theme_default = {
.header = RGBA(0x424242ff),
.header_text = RGBA(0xeeeeeeff),
.header_text_hi = RGBA(0xffffffff),
.search_match_color = RGBA(0x5680c2ff),
.tab_active = RGBA(0x4b4b4bff),
.tab_inactive = RGBA(0x2b2b2bff),
.tab_back = RGBA(0x232323ff),

View File

@@ -736,6 +736,8 @@ def km_property_editor(_params):
{"properties": [("direction", 'PREV'), ], },),
("screen.space_context_cycle", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "ctrl": True},
{"properties": [("direction", 'NEXT'), ], },),
("buttons.start_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
("buttons.clear_filter", {"type": 'F', "value": 'PRESS', "alt": True}, None),
# Modifier panels
("object.modifier_remove", {"type": 'X', "value": 'PRESS'}, {"properties": [("report", True)]}),
("object.modifier_remove", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("report", True)]}),

View File

@@ -23,11 +23,20 @@ from bpy.types import Header, Panel
class PROPERTIES_HT_header(Header):
bl_space_type = 'PROPERTIES'
def draw(self, _context):
def draw(self, context):
layout = self.layout
view = context.space_data
layout.template_header()
layout.separator_spacer()
layout.prop(view, "search_filter", icon='VIEWZOOM', text="")
layout.separator_spacer()
row = layout.row()
row.emboss = 'NONE'
row.operator("buttons.toggle_pin", icon=('PINNED' if view.use_pin_id else 'UNPINNED'), text="")
class PROPERTIES_PT_navigation_bar(Panel):
bl_space_type = 'PROPERTIES'
@@ -42,7 +51,11 @@ class PROPERTIES_PT_navigation_bar(Panel):
layout.scale_x = 1.4
layout.scale_y = 1.4
layout.prop_tabs_enum(view, "context", icon_only=True)
if view.search_filter:
layout.prop_tabs_enum(view, "context", data_highlight=view,
property_highlight="context_search_filter_active", icon_only=True)
else:
layout.prop_tabs_enum(view, "context", icon_only=True)
classes = (

View File

@@ -4924,6 +4924,9 @@ static void direct_link_region(BlendDataReader *reader, ARegion *region, int spa
BLO_read_list(reader, &region->ui_lists);
/* The area's search filter is runtime only, so we need to clear the active flag on read. */
region->flag &= ~RGN_FLAG_SEARCH_FILTER_ACTIVE;
LISTBASE_FOREACH (uiList *, ui_list, &region->ui_lists) {
ui_list->type = NULL;
ui_list->dyn_data = NULL;
@@ -5164,6 +5167,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area)
sbuts->texuser = NULL;
sbuts->mainbo = sbuts->mainb;
sbuts->mainbuser = sbuts->mainb;
memset(&sbuts->runtime, 0x0, sizeof(sbuts->runtime));
}
else if (sl->spacetype == SPACE_CONSOLE) {
SpaceConsole *sconsole = (SpaceConsole *)sl;

View File

@@ -228,6 +228,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
*/
{
/* Keep this block, even when empty. */
FROM_DEFAULT_V4_UCHAR(space_properties.search_match_color);
/* The new defaults for the file browser theme are the same as
* the outliner's, and it's less disruptive to just copy them. */

View File

@@ -80,6 +80,9 @@ void ED_region_tag_redraw_no_rebuild(struct ARegion *region);
void ED_region_tag_refresh_ui(struct ARegion *region);
void ED_region_tag_redraw_editor_overlays(struct ARegion *region);
void ED_region_search_filter_update(const struct ScrArea *area, struct ARegion *region);
const char *ED_area_search_filter_get(const struct ScrArea *area, const struct ARegion *region);
void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *region);
void ED_region_panels_ex(const struct bContext *C, struct ARegion *region, const char *contexts[]);
void ED_region_panels(const struct bContext *C, struct ARegion *region);
@@ -88,6 +91,11 @@ void ED_region_panels_layout_ex(const struct bContext *C,
struct ListBase *paneltypes,
const char *contexts[],
const char *category_override);
bool ED_region_property_search(const struct bContext *C,
struct ARegion *region,
struct ListBase *paneltypes,
const char *contexts[],
const char *category_override);
void ED_region_panels_layout(const struct bContext *C, struct ARegion *region);
void ED_region_panels_draw(const struct bContext *C, struct ARegion *region);

View File

@@ -157,6 +157,9 @@ enum {
UI_BLOCK_POPOVER_ONCE = 1 << 22,
/** Always show keymaps, even for non-menus. */
UI_BLOCK_SHOW_SHORTCUT_ALWAYS = 1 << 23,
/** The block is only used during the search process and will not be drawn.
* Currently just for the case of a closed panel's subpanel (and its subpanels). */
UI_BLOCK_SEARCH_ONLY = 1 << 25,
};
/** #uiPopupBlockHandle.menuretval */
@@ -671,6 +674,9 @@ enum {
void UI_block_theme_style_set(uiBlock *block, char theme_style);
char UI_block_emboss_get(uiBlock *block);
void UI_block_emboss_set(uiBlock *block, char emboss);
bool UI_block_is_search_only(const uiBlock *block);
void UI_block_set_search_only(uiBlock *block, bool search_only);
void UI_block_set_search_filter(uiBlock *block, const char *search_filter);
void UI_block_free(const struct bContext *C, uiBlock *block);
void UI_blocklist_free(const struct bContext *C, struct ListBase *lb);
@@ -1684,6 +1690,9 @@ void UI_panels_scale(struct ARegion *region, float new_width);
void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y);
int UI_panel_size_y(const struct Panel *panel);
bool UI_panel_is_dragging(const struct Panel *panel);
bool UI_panel_matches_search_filter(const struct Panel *panel);
bool UI_panel_is_active(const struct Panel *panel);
void UI_panels_set_expansion_from_seach_filter(const struct bContext *C, struct ARegion *region);
bool UI_panel_category_is_visible(const struct ARegion *region);
void UI_panel_category_add(struct ARegion *region, const char *name);
@@ -1862,6 +1871,8 @@ uiLayout *UI_block_layout(uiBlock *block,
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout);
void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y);
bool UI_block_apply_search_filter(uiBlock *block);
void UI_region_message_subscribe(struct ARegion *region, struct wmMsgBus *mbus);
uiBlock *uiLayoutGetBlock(uiLayout *layout);
@@ -1914,6 +1925,7 @@ float uiLayoutGetUnitsY(uiLayout *layout);
int uiLayoutGetEmboss(uiLayout *layout);
bool uiLayoutGetPropSep(uiLayout *layout);
bool uiLayoutGetPropDecorate(uiLayout *layout);
void uiLayoutRootSetSearchOnly(uiLayout *layout, bool search_only);
/* layout specifiers */
uiLayout *uiLayoutRow(uiLayout *layout, bool align);
@@ -2414,6 +2426,8 @@ void uiItemTabsEnumR_prop(uiLayout *layout,
struct bContext *C,
struct PointerRNA *ptr,
PropertyRNA *prop,
struct PointerRNA *ptr_highlight,
PropertyRNA *prop_highlight,
bool icon_only);
/* Only for testing, inspecting layouts. */

View File

@@ -67,6 +67,7 @@ typedef enum ThemeColorID {
TH_HEADERDESEL,
TH_HEADER_TEXT,
TH_HEADER_TEXT_HI,
TH_SEARCH_MATCH,
/* panels */
TH_PANEL_HEADER,

View File

@@ -1959,8 +1959,12 @@ void UI_block_draw(const bContext *C, uiBlock *block)
}
}
}
ui_draw_aligned_panel(
&style, block, &rect, UI_panel_category_is_visible(region), show_background);
ui_draw_aligned_panel(&style,
block,
&rect,
UI_panel_category_is_visible(region),
show_background,
region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE);
}
BLF_batch_draw_begin();
@@ -3505,6 +3509,21 @@ void UI_block_theme_style_set(uiBlock *block, char theme_style)
block->theme_style = theme_style;
}
bool UI_block_is_search_only(const uiBlock *block)
{
return block->flag & UI_BLOCK_SEARCH_ONLY;
}
void UI_block_set_search_only(uiBlock *block, bool search_only)
{
SET_FLAG_FROM_TEST(block->flag, search_only, UI_BLOCK_SEARCH_ONLY);
}
void UI_block_set_search_filter(uiBlock *block, const char *search_filter)
{
block->search_filter = search_filter;
}
static void ui_but_build_drawstr_float(uiBut *but, double value)
{
size_t slen = 0;
@@ -3907,6 +3926,7 @@ uiBut *ui_but_change_type(uiBut *but, eButType new_type)
const bool found_layout = ui_layout_replace_but_ptr(but->layout, old_but_ptr, but);
BLI_assert(found_layout);
UNUSED_VARS_NDEBUG(found_layout);
ui_button_group_replace_but_ptr(but->layout, old_but_ptr, but);
}
}
}

View File

@@ -81,6 +81,11 @@ enum {
UI_HAS_ICON = (1 << 3),
UI_HIDDEN = (1 << 4),
UI_SELECT_DRAW = (1 << 5), /* Display selected, doesn't impact interaction. */
/**
* The button matches the search filter. When property search is active, this
* is used to determine which items to keep enabled and which to disable.
*/
UI_SEARCH_FILTER_MATCHES = (1 << 12),
/* warn: rest of uiBut->flag in UI_interface.h */
};
@@ -422,7 +427,7 @@ struct uiBlock {
ListBase butstore; /* UI_butstore_* runtime function */
ListBase layouts;
ListBase layouts; /* Note: Should be called layout_roots. */
struct uiLayout *curlayout;
ListBase contexts;
@@ -517,6 +522,12 @@ struct uiBlock {
*/
char display_device[64];
/**
* Pointer to the space's property search string.
* The block doesn't allocate this or change it.
*/
const char *search_filter;
struct PieMenuData pie_data;
};
@@ -805,7 +816,9 @@ extern void ui_draw_aligned_panel(const struct uiStyle *style,
const uiBlock *block,
const rcti *rect,
const bool show_pin,
const bool show_background);
const bool show_background,
const bool region_search_filter_active);
void ui_panel_set_search_filter_match(struct Panel *panel, const bool value);
/* interface_draw.c */
extern void ui_draw_dropshadow(
@@ -994,6 +1007,7 @@ void ui_resources_free(void);
/* interface_layout.c */
void ui_layout_add_but(uiLayout *layout, uiBut *but);
bool ui_layout_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but);
void ui_button_group_replace_but_ptr(uiLayout *root, const void *old_but_ptr, uiBut *new_but);
uiBut *ui_but_add_search(uiBut *but,
PointerRNA *ptr,
PropertyRNA *prop,

View File

@@ -80,12 +80,32 @@
/* uiLayoutRoot */
/**
* A group of button references, used by property search to keep track of sets of buttons that
* should be searched together. For example, in property split layouts number buttons and their
* labels (and even their decorators) are separate buttons, but they must be searched and
* highlighted together.
*/
typedef struct uiButtonGroup {
void *next, *prev;
ListBase buttons; /* #LinkData with #uiBut data field. */
} uiButtonGroup;
typedef struct uiLayoutRoot {
struct uiLayoutRoot *next, *prev;
int type;
int opcontext;
/**
* If true, the root will be removed as part of the property search process.
* Necessary for cases like searching the contents of closed panels, where the
* block-level tag isn't enough because there might be buttons in the header.
*/
bool search_only;
ListBase button_groups; /* #uiButtonGroup. */
int emw, emh;
int padding;
@@ -414,6 +434,59 @@ static void ui_item_move(uiItem *item, int delta_xmin, int delta_xmax)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Button Groups
* \{ */
/**
* Every function that adds a set of buttons must create another group,
* then #ui_def_but adds buttons to the current group (the last).
*/
static void layout_root_new_button_group(uiLayoutRoot *root)
{
uiButtonGroup *new_group = MEM_mallocN(sizeof(uiButtonGroup), __func__);
BLI_listbase_clear(&new_group->buttons);
BLI_addtail(&root->button_groups, new_group);
}
static void button_group_add_but(uiLayoutRoot *root, uiBut *but)
{
BLI_assert(root != NULL);
uiButtonGroup *current_button_group = root->button_groups.last;
BLI_assert(current_button_group != NULL);
/* We can't use the button directly because adding it to
* this list would mess with its prev and next pointers. */
LinkData *button_link = MEM_mallocN(sizeof(LinkData), __func__);
button_link->data = but;
BLI_addtail(&current_button_group->buttons, button_link);
}
static void button_group_free(uiButtonGroup *button_group)
{
BLI_freelistN(&button_group->buttons);
MEM_freeN(button_group);
}
/* This function should be removed whenever #ui_layout_replace_but_ptr is removed. */
void ui_button_group_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but)
{
LISTBASE_FOREACH (uiButtonGroup *, button_group, &layout->root->button_groups) {
LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) {
if (link->data == old_but_ptr) {
link->data = new_but;
return;
}
}
}
/* The button should be in a group. */
BLI_assert(false);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Special RNA Items
* \{ */
@@ -901,6 +974,8 @@ static void ui_item_enum_expand_tabs(uiLayout *layout,
uiBlock *block,
PointerRNA *ptr,
PropertyRNA *prop,
PointerRNA *ptr_highlight,
PropertyRNA *prop_highlight,
const char *uiname,
const int h,
const bool icon_only)
@@ -909,8 +984,26 @@ static void ui_item_enum_expand_tabs(uiLayout *layout,
ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_TAB, icon_only);
BLI_assert(last != block->buttons.last);
const bool use_custom_highlight = (prop_highlight != NULL);
int custom_highlight_flag = 0; /* Max of 32 tabs. */
if (use_custom_highlight) {
BLI_assert(prop_highlight != NULL);
BLI_assert(RNA_property_flag(prop_highlight) & PROP_ENUM_FLAG);
custom_highlight_flag = RNA_property_enum_get(ptr_highlight, prop_highlight);
}
int i = 0;
for (uiBut *tab = last ? last->next : block->buttons.first; tab; tab = tab->next) {
UI_but_drawflag_enable(tab, ui_but_align_opposite_to_area_align_get(CTX_wm_region(C)));
if (use_custom_highlight) {
if (!(custom_highlight_flag & (1 << i))) {
tab->flag |= UI_BUT_INACTIVE;
}
}
i++;
}
}
@@ -1988,6 +2081,7 @@ void uiItemFullR(uiLayout *layout,
#endif /* UI_PROP_DECORATE */
UI_block_layout_set_current(block, layout);
layout_root_new_button_group(layout->root);
/* retrieve info */
const PropertyType type = RNA_property_type(prop);
@@ -2738,6 +2832,8 @@ void uiItemPointerR_prop(uiLayout *layout,
char namestr[UI_MAX_NAME_STR];
const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
layout_root_new_button_group(layout->root);
type = RNA_property_type(prop);
if (!ELEM(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) {
RNA_warning("Property %s.%s must be a pointer, string or enum",
@@ -2843,6 +2939,7 @@ static uiBut *ui_item_menu(uiLayout *layout,
int w, h;
UI_block_layout_set_current(block, layout);
layout_root_new_button_group(layout->root);
if (!name) {
name = "";
@@ -3110,6 +3207,7 @@ static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon)
int w;
UI_block_layout_set_current(block, layout);
layout_root_new_button_group(layout->root);
if (!name) {
name = "";
@@ -3496,13 +3594,19 @@ void uiItemMenuEnumR(
uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
}
void uiItemTabsEnumR_prop(
uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool icon_only)
void uiItemTabsEnumR_prop(uiLayout *layout,
bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
PointerRNA *ptr_highlight,
PropertyRNA *prop_highlight,
bool icon_only)
{
uiBlock *block = layout->root->block;
UI_block_layout_set_current(block, layout);
ui_item_enum_expand_tabs(layout, C, block, ptr, prop, NULL, UI_UNIT_Y, icon_only);
ui_item_enum_expand_tabs(
layout, C, block, ptr, prop, ptr_highlight, prop_highlight, NULL, UI_UNIT_Y, icon_only);
}
/** \} */
@@ -5031,6 +5135,205 @@ int uiLayoutGetEmboss(uiLayout *layout)
return layout->emboss;
}
/**
* Tags the layout root as search only, meaning the search process will run, but not the rest of
* the layout process. Use in situations where part of the block's contents normally wouldn't be
* drawn, but must be searched anyway, like the contents of closed panels with headers.
*/
void uiLayoutRootSetSearchOnly(uiLayout *layout, bool search_only)
{
layout->root->search_only = search_only;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Block Layout Search Filtering
* \{ */
static void layout_root_free(uiLayoutRoot *root);
// #define PROPERTY_SEARCH_USE_TOOLTIPS
static bool block_search_panel_label_matches(const uiBlock *block)
{
if ((block->panel != NULL) && (block->panel->type != NULL)) {
if (BLI_strcasestr(block->panel->type->label, block->search_filter)) {
return true;
}
}
return false;
}
/**
* Buttons for search only layouts (closed panel subpanels) have still been added from the
* layout functions, but they need to be hidden. Theoretically they could be removed too.
*/
static void layout_free_and_hide_buttons(uiLayout *layout)
{
LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
if (item->type == ITEM_BUTTON) {
uiButtonItem *button_item = (uiButtonItem *)item;
BLI_assert(button_item->but != NULL);
button_item->but->flag |= UI_HIDDEN;
MEM_freeN(item);
}
else {
layout_free_and_hide_buttons((uiLayout *)item);
}
}
MEM_freeN(layout);
}
/**
* Remove layouts used only for search and hide their buttons.
*/
static void block_search_remove_search_only_roots(uiBlock *block)
{
LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) {
if (root->search_only) {
layout_free_and_hide_buttons(root->layout);
BLI_remlink(&block->layouts, root);
layout_root_free(root);
}
}
}
/**
* Returns true if a button or the data / operator it represents matches the search filter.
*/
static bool button_matches_search_filter(uiBut *but, const char *search_filter)
{
/* Do the shorter checks first for performance reasons. */
if (BLI_strcasestr(but->str, search_filter)) {
return true;
}
if (but->optype != NULL) {
if (BLI_strcasestr(but->optype->name, search_filter)) {
return true;
}
}
if (but->rnaprop != NULL) {
if (BLI_strcasestr(RNA_property_ui_name(but->rnaprop), search_filter)) {
return true;
}
#ifdef PROPERTY_SEARCH_USE_TOOLTIPS
if (BLI_strcasestr(RNA_property_description(but->rnaprop), search_filter)) {
return true;
}
#endif
/* Search through labels of enum property items if they are in a dropdown menu.
* Unfortunately we have no context here so we cannot search through RNA enums
* with dynamic entries (or "itemf" functions) which require context. */
if (but->type == UI_BTYPE_MENU) {
PointerRNA *ptr = &but->rnapoin;
PropertyRNA *enum_prop = but->rnaprop;
int items_len;
const EnumPropertyItem *items_array = NULL;
bool free;
RNA_property_enum_items_gettexted(NULL, ptr, enum_prop, &items_array, &items_len, &free);
if (items_array == NULL) {
return false;
}
for (int i = 0; i < items_len; i++) {
if (BLI_strcasestr(items_array[i].name, search_filter)) {
return true;
}
}
if (free) {
MEM_freeN((EnumPropertyItem *)items_array);
}
}
}
return false;
}
/**
* Test for a search result within the a specific button group.
*/
static bool button_group_has_search_match(uiButtonGroup *button_group, const char *search_filter)
{
LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) {
uiBut *but = link->data;
if (button_matches_search_filter(but, search_filter)) {
return true;
}
}
return false;
}
/**
* Apply the search filter, tagging all buttons with whether they match or not.
* Tag every button in the group as a search match if any button matches.
*
* \note It would be great to return early here if we found a match, but because
* the results could be visible we have to continue searching the entire block.
*
* \return Whether the block has any search results.
*/
static bool block_search_filter_tag_buttons(uiBlock *block)
{
bool has_result = false;
LISTBASE_FOREACH (uiLayoutRoot *, root, &block->layouts) {
LISTBASE_FOREACH (uiButtonGroup *, button_group, &root->button_groups) {
if (button_group_has_search_match(button_group, block->search_filter)) {
LISTBASE_FOREACH (LinkData *, link, &button_group->buttons) {
uiBut *but = link->data;
but->flag |= UI_SEARCH_FILTER_MATCHES;
}
has_result = true;
}
}
}
return has_result;
}
static void block_search_deactivate_buttons(uiBlock *block)
{
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
if (!(but->flag & UI_SEARCH_FILTER_MATCHES)) {
but->flag |= UI_BUT_INACTIVE;
}
}
}
/**
* Apply property search behavior, setting panel flags and deactivating buttons that don't match.
*
* \note Must be run before #UI_block_layout_resolve.
*/
bool UI_block_apply_search_filter(uiBlock *block)
{
if (!(block->search_filter && block->search_filter[0])) {
return false;
}
const bool panel_label_matches = block_search_panel_label_matches(block);
const bool has_result = panel_label_matches ? true : block_search_filter_tag_buttons(block);
block_search_remove_search_only_roots(block);
if (block->panel != NULL) {
ui_panel_set_search_filter_match(block->panel, has_result);
}
if (!panel_label_matches) {
block_search_deactivate_buttons(block);
}
return has_result;
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -5275,6 +5578,14 @@ static void ui_layout_free(uiLayout *layout)
MEM_freeN(layout);
}
static void layout_root_free(uiLayoutRoot *root)
{
LISTBASE_FOREACH_MUTABLE (uiButtonGroup *, button_group, &root->button_groups) {
button_group_free(button_group);
}
MEM_freeN(root);
}
static void ui_layout_add_padding_button(uiLayoutRoot *root)
{
if (root->padding) {
@@ -5309,6 +5620,9 @@ uiLayout *UI_block_layout(uiBlock *block,
root->padding = padding;
root->opcontext = WM_OP_INVOKE_REGION_WIN;
BLI_listbase_clear(&root->button_groups);
layout_root_new_button_group(root);
layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
layout->item.type = (type == UI_LAYOUT_VERT_BAR) ? ITEM_LAYOUT_COLUMN : ITEM_LAYOUT_ROOT;
@@ -5393,6 +5707,8 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but)
if (layout->emboss != UI_EMBOSS_UNDEFINED) {
but->emboss = layout->emboss;
}
button_group_add_but(layout->root, but);
}
bool ui_layout_replace_but_ptr(uiLayout *layout, const void *old_but_ptr, uiBut *new_but)
@@ -5458,15 +5774,19 @@ void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
block->curlayout = NULL;
LISTBASE_FOREACH (uiLayoutRoot *, root, &block->layouts) {
LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) {
/* Seach only roots should be removed by #UI_block_apply_search_filter. */
BLI_assert(!root->search_only);
ui_layout_add_padding_button(root);
/* NULL in advance so we don't interfere when adding button */
ui_layout_end(block, root->layout, r_x, r_y);
ui_layout_free(root->layout);
layout_root_free(root);
}
BLI_freelistN(&block->layouts);
BLI_listbase_clear(&block->layouts);
/* XXX silly trick, interface_templates.c doesn't get linked
* because it's not used by other files in this module? */

View File

@@ -77,6 +77,7 @@
#define PNL_ANIM_ALIGN 8
#define PNL_NEW_ADDED 16
#define PNL_FIRST 32
#define PNL_SEARCH_FILTER_MATCHES 64
/* the state of the mouse position relative to the panel */
typedef enum uiPanelMouseState {
@@ -125,16 +126,32 @@ static bool panel_type_context_poll(ARegion *region,
/** \name Local Functions
* \{ */
static void panel_title_color_get(bool show_background, uchar color[4])
static void panel_title_color_get(const Panel *panel,
const bool show_background,
const bool use_search_color,
const bool region_search_filter_active,
uchar r_color[4])
{
if (show_background) {
UI_GetThemeColor4ubv(TH_TITLE, color);
}
else {
if (!show_background) {
/* Use menu colors for floating panels. */
bTheme *btheme = UI_GetTheme();
const uiWidgetColors *wcol = &btheme->tui.wcol_menu_back;
copy_v4_v4_uchar(color, (const uchar *)wcol->text);
copy_v4_v4_uchar(r_color, (const uchar *)wcol->text);
return;
}
const bool search_match = UI_panel_matches_search_filter(panel);
if (region_search_filter_active && use_search_color && search_match) {
UI_GetThemeColor4ubv(TH_SEARCH_MATCH, r_color);
}
else {
UI_GetThemeColor4ubv(TH_TITLE, r_color);
if (region_search_filter_active && !search_match) {
r_color[0] *= 0.5;
r_color[1] *= 0.5;
r_color[2] *= 0.5;
}
}
}
@@ -230,6 +247,7 @@ static Panel *UI_panel_add_instanced_ex(ARegion *region,
BLI_strncpy(panel->panelname, panel_type->idname, sizeof(panel->panelname));
panel->runtime.custom_data_ptr = custom_data;
panel->runtime_flag |= PNL_NEW_ADDED;
/* Add the panel's children too. Although they aren't instanced panels, we can still use this
* function to create them, as UI_panel_begin does other things we don't need to do. */
@@ -786,6 +804,72 @@ static void ui_offset_panel_block(uiBlock *block)
block->rect.xmin = block->rect.ymin = 0.0;
}
void ui_panel_set_search_filter_match(struct Panel *panel, const bool value)
{
SET_FLAG_FROM_TEST(panel->runtime_flag, value, PNL_SEARCH_FILTER_MATCHES);
}
static void panel_matches_search_filter_recursive(const Panel *panel, bool *filter_matches)
{
*filter_matches |= panel->runtime_flag & PNL_SEARCH_FILTER_MATCHES;
/* If the panel is filtered (removed) we need to check that its children are too. */
if (!*filter_matches) {
LISTBASE_FOREACH (const Panel *, child_panel, &panel->children) {
panel_matches_search_filter_recursive(child_panel, filter_matches);
}
}
}
/**
* Find whether a panel or any of its subpanels contain a property that matches the search filter.
*/
bool UI_panel_matches_search_filter(const Panel *panel)
{
bool search_filter_matches = false;
panel_matches_search_filter_recursive(panel, &search_filter_matches);
return search_filter_matches;
}
/**
* Returns whether a panel is currently active (displayed).
*/
bool UI_panel_is_active(const Panel *panel)
{
return panel->runtime_flag & PNL_ACTIVE;
}
static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, Panel *panel)
{
short start_flag = panel->flag;
SET_FLAG_FROM_TEST(panel->flag, !UI_panel_matches_search_filter(panel), PNL_CLOSED);
if (start_flag != panel->flag) {
panel_activate_state(C, panel, PANEL_STATE_ANIMATION);
}
/* If the panel is filtered (removed) we need to check that its children are too. */
LISTBASE_FOREACH (Panel *, child_panel, &panel->children) {
if (panel->type == NULL || (panel->type->flag & PNL_NO_HEADER)) {
continue;
}
panel_set_expansion_from_seach_filter_recursive(C, child_panel);
}
}
/**
* Uses the panel's search filter flag to set its expansion,
* activating animation if it was closed or opened.
*/
void UI_panels_set_expansion_from_seach_filter(const bContext *C, ARegion *region)
{
LISTBASE_FOREACH (Panel *, panel, &region->panels) {
if (panel->type == NULL || (panel->type->flag & PNL_NO_HEADER)) {
continue;
}
panel_set_expansion_from_seach_filter_recursive(C, panel);
}
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -829,7 +913,8 @@ void UI_panel_label_offset(uiBlock *block, int *r_x, int *r_y)
static void ui_draw_aligned_panel_header(const uiStyle *style,
const uiBlock *block,
const rcti *rect,
const bool show_background)
const bool show_background,
const bool region_search_filter_active)
{
const Panel *panel = block->panel;
const bool is_subpanel = (panel->type && panel->type->parent);
@@ -840,7 +925,8 @@ static void ui_draw_aligned_panel_header(const uiStyle *style,
/* draw text label */
uchar col_title[4];
panel_title_color_get(show_background, col_title);
panel_title_color_get(
panel, show_background, is_subpanel, region_search_filter_active, col_title);
col_title[3] = 255;
rcti hrect = *rect;
@@ -862,7 +948,8 @@ void ui_draw_aligned_panel(const uiStyle *style,
const uiBlock *block,
const rcti *rect,
const bool show_pin,
const bool show_background)
const bool show_background,
const bool region_search_filter_active)
{
const Panel *panel = block->panel;
float color[4];
@@ -937,7 +1024,8 @@ void ui_draw_aligned_panel(const uiStyle *style,
GPU_blend(GPU_BLEND_ALPHA);
/* draw with background color */
immUniformThemeColor(TH_PANEL_HEADER);
immUniformThemeColor(UI_panel_matches_search_filter(panel) ? TH_SEARCH_MATCH :
TH_PANEL_HEADER);
immRectf(pos, minx, headrect.ymin, rect->xmax, y);
immBegin(GPU_PRIM_LINES, 4);
@@ -957,7 +1045,7 @@ void ui_draw_aligned_panel(const uiStyle *style,
/* draw optional pin icon */
if (show_pin && (block->panel->flag & PNL_PIN)) {
uchar col_title[4];
panel_title_color_get(show_background, col_title);
panel_title_color_get(panel, show_background, false, region_search_filter_active, col_title);
GPU_blend(GPU_BLEND_ALPHA);
UI_icon_draw_ex(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect),
@@ -976,7 +1064,8 @@ void ui_draw_aligned_panel(const uiStyle *style,
if (is_subpanel) {
titlerect.xmin += (0.7f * UI_UNIT_X) / block->aspect + 0.001f;
}
ui_draw_aligned_panel_header(style, block, &titlerect, show_background);
ui_draw_aligned_panel_header(
style, block, &titlerect, show_background, region_search_filter_active);
if (show_drag) {
/* Make `itemrect` smaller. */
@@ -1030,8 +1119,8 @@ void ui_draw_aligned_panel(const uiStyle *style,
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
GPU_blend(GPU_BLEND_ALPHA);
/* Draw panel backdrop if it wasn't already been drawn by the single opaque round box earlier.
* Note: Sub-panels blend with panels, so they can't be opaque. */
/* Draw panel backdrop if it wasn't already been drawn by the single opaque round box
* earlier. Note: Sub-panels blend with panels, so they can't be opaque. */
if (show_background && !(draw_box_style && !is_subpanel)) {
/* Draw the bottom sub-panels. */
if (draw_box_style) {
@@ -1071,7 +1160,7 @@ void ui_draw_aligned_panel(const uiStyle *style,
BLI_rctf_scale(&itemrect, 0.25f);
uchar col_title[4];
panel_title_color_get(show_background, col_title);
panel_title_color_get(panel, show_background, false, region_search_filter_active, col_title);
float tria_color[4];
rgb_uchar_to_float(tria_color, col_title);
tria_color[3] = 1.0f;
@@ -1859,13 +1948,15 @@ void UI_panels_draw(const bContext *C, ARegion *region)
* UI blocks are added in reverse order and we need child panels
* to draw on top. */
LISTBASE_FOREACH_BACKWARD (uiBlock *, block, &region->uiblocks) {
if (block->active && block->panel && !(block->panel->flag & PNL_SELECT)) {
if (block->active && block->panel && !(block->panel->flag & PNL_SELECT) &&
!UI_block_is_search_only(block)) {
UI_block_draw(C, block);
}
}
LISTBASE_FOREACH_BACKWARD (uiBlock *, block, &region->uiblocks) {
if (block->active && block->panel && (block->panel->flag & PNL_SELECT)) {
if (block->active && block->panel && (block->panel->flag & PNL_SELECT) &&
!UI_block_is_search_only(block)) {
UI_block_draw(C, block);
}
}

View File

@@ -261,6 +261,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_HEADER_TEXT_HI:
cp = ts->header_text_hi;
break;
case TH_SEARCH_MATCH:
cp = ts->search_match_color;
break;
case TH_PANEL_HEADER:
cp = ts->panelcolors.header;

View File

@@ -492,6 +492,9 @@ void ED_region_do_layout(bContext *C, ARegion *region)
UI_SetTheme(area ? area->spacetype : 0, at->regionid);
at->layout(C, region);
/* Clear temporary update flag. */
region->flag &= ~RGN_FLAG_SEARCH_FILTER_UPDATE;
}
/* only exported for WM */
@@ -736,6 +739,34 @@ void ED_area_tag_refresh(ScrArea *area)
/* *************************************************************** */
/**
* Returns the search string if the space type supports property search.
*/
const char *ED_area_search_filter_get(const ScrArea *area, const ARegion *region)
{
/* Only the properties editor has a search string for now. */
if (area->spacetype == SPACE_PROPERTIES) {
SpaceProperties *sbuts = area->spacedata.first;
if (region->regiontype == RGN_TYPE_WINDOW) {
return sbuts->runtime->search_string;
}
}
return NULL;
}
void ED_region_search_filter_update(const ScrArea *area, ARegion *region)
{
region->flag |= RGN_FLAG_SEARCH_FILTER_UPDATE;
const char *search_filter = ED_area_search_filter_get(area, region);
SET_FLAG_FROM_TEST(region->flag,
region->regiontype == RGN_TYPE_WINDOW && search_filter[0] != '\0',
RGN_FLAG_SEARCH_FILTER_ACTIVE);
}
/* *************************************************************** */
/* use NULL to disable it */
void ED_area_status_text(ScrArea *area, const char *str)
{
@@ -2558,7 +2589,9 @@ static void ed_panel_draw(const bContext *C,
Panel *panel,
int w,
int em,
char *unique_panel_str)
char *unique_panel_str,
const char *search_filter,
bool search_only)
{
const uiStyle *style = UI_style_get_dpi();
@@ -2571,10 +2604,14 @@ static void ed_panel_draw(const bContext *C,
strncat(block_name, unique_panel_str, INSTANCED_PANEL_UNIQUE_STR_LEN);
}
uiBlock *block = UI_block_begin(C, region, block_name, UI_EMBOSS);
UI_block_set_search_filter(block, search_filter);
UI_block_set_search_only(block, search_only);
bool open;
panel = UI_panel_begin(region, lb, block, pt, panel, &open);
const bool search_filter_active = search_filter != NULL && search_filter[0] != '\0';
/* bad fixed values */
int xco, yco, h = 0;
int headerend = w - UI_UNIT_X;
@@ -2590,9 +2627,11 @@ static void ed_panel_draw(const bContext *C,
1,
0,
style);
uiLayoutRootSetSearchOnly(panel->layout, search_only);
pt->draw_header_preset(C, panel);
UI_block_apply_search_filter(block);
UI_block_layout_resolve(block, &xco, &yco);
UI_block_translate(block, headerend - xco, 0);
panel->layout = NULL;
@@ -2620,9 +2659,11 @@ static void ed_panel_draw(const bContext *C,
panel->layout = UI_block_layout(
block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, labelx, labely, UI_UNIT_Y, 1, 0, style);
}
uiLayoutRootSetSearchOnly(panel->layout, search_only);
pt->draw_header(C, panel);
UI_block_apply_search_filter(block);
UI_block_layout_resolve(block, &xco, &yco);
panel->labelofs = xco - labelx;
panel->layout = NULL;
@@ -2631,7 +2672,7 @@ static void ed_panel_draw(const bContext *C,
panel->labelofs = 0;
}
if (open) {
if (open || search_filter_active) {
short panelContext;
/* panel context can either be toolbar region or normal panels region */
@@ -2655,9 +2696,11 @@ static void ed_panel_draw(const bContext *C,
em,
0,
style);
uiLayoutRootSetSearchOnly(panel->layout, search_only || !open);
pt->draw(C, panel);
UI_block_apply_search_filter(block);
UI_block_layout_resolve(block, &xco, &yco);
panel->layout = NULL;
@@ -2669,13 +2712,21 @@ static void ed_panel_draw(const bContext *C,
UI_block_end(C, block);
/* Draw child panels. */
if (open) {
if (open || search_filter_active) {
LISTBASE_FOREACH (LinkData *, link, &pt->children) {
PanelType *child_pt = link->data;
Panel *child_panel = UI_panel_find_by_type(&panel->children, child_pt);
if (child_pt->draw && (!child_pt->poll || child_pt->poll(C, child_pt))) {
ed_panel_draw(C, region, &panel->children, child_pt, child_panel, w, em, unique_panel_str);
ed_panel_draw(C,
region,
&panel->children,
child_pt,
child_panel,
w,
em,
unique_panel_str,
search_filter,
!open);
}
}
}
@@ -2683,6 +2734,81 @@ static void ed_panel_draw(const bContext *C,
UI_panel_end(region, block, w, h, open);
}
/**
* Check whether a panel should be added to the region's panel layout.
*/
static bool panel_add_check(const bContext *C,
const WorkSpace *workspace,
const char *contexts[],
const char *category_override,
PanelType *panel_type)
{
/* Only add top level panels. */
if (panel_type->parent) {
return false;
}
/* Check the category override first. */
if (category_override) {
if (!STREQ(panel_type->category, category_override)) {
return false;
}
}
/* Verify context. */
if (contexts != NULL && panel_type->context[0]) {
if (!streq_array_any(panel_type->context, contexts)) {
return false;
}
}
/* If we're tagged, only use compatible. */
if (panel_type->owner_id[0]) {
if (!BKE_workspace_owner_id_check(workspace, panel_type->owner_id)) {
return false;
}
}
if (LIKELY(panel_type->draw)) {
if (panel_type->poll && !panel_type->poll(C, panel_type)) {
return false;
}
}
return true;
}
static bool region_uses_category_tabs(const ScrArea *area, const ARegion *region)
{
/* XXX, should use some better check? */
/* For now also has hardcoded check for clip editor until it supports actual toolbar. */
return ((1 << region->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
(region->regiontype == RGN_TYPE_TOOLS && area->spacetype == SPACE_CLIP);
}
static const char *region_panels_collect_categories(ARegion *region,
LinkNode *panel_types_stack,
bool *use_category_tabs)
{
UI_panel_category_clear_all(region);
/* gather unique categories */
for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
PanelType *pt = pt_link->link;
if (pt->category[0]) {
if (!UI_panel_category_find(region, pt->category)) {
UI_panel_category_add(region, pt->category);
}
}
}
if (UI_panel_category_is_visible(region)) {
return UI_panel_category_active_get(region, true);
}
*use_category_tabs = false;
return NULL;
}
/**
* \param contexts: A NULL terminated array of context strings to match against.
* Matching against any of these strings will draw the panel.
@@ -2698,29 +2824,7 @@ void ED_region_panels_layout_ex(const bContext *C,
WorkSpace *workspace = CTX_wm_workspace(C);
LinkNode *panel_types_stack = NULL;
LISTBASE_FOREACH_BACKWARD (PanelType *, pt, paneltypes) {
/* Only draw top level panels. */
if (pt->parent) {
continue;
}
if (category_override) {
if (!STREQ(pt->category, category_override)) {
continue;
}
}
/* verify context */
if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) {
continue;
}
/* If we're tagged, only use compatible. */
if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) {
continue;
}
/* draw panel */
if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
if (panel_add_check(C, workspace, contexts, category_override, pt)) {
BLI_linklist_prepend_alloca(&panel_types_stack, pt);
}
}
@@ -2731,12 +2835,7 @@ void ED_region_panels_layout_ex(const bContext *C,
View2D *v2d = &region->v2d;
int x, y, w, em;
/* XXX, should use some better check? */
/* For now also has hardcoded check for clip editor until it supports actual toolbar. */
bool use_category_tabs = (category_override == NULL) &&
((((1 << region->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
(region->regiontype == RGN_TYPE_TOOLS &&
area->spacetype == SPACE_CLIP)));
bool use_category_tabs = (category_override == NULL) && region_uses_category_tabs(area, region);
/* offset panels for small vertical tab area */
const char *category = NULL;
const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH;
@@ -2752,25 +2851,10 @@ void ED_region_panels_layout_ex(const bContext *C,
/* collect categories */
if (use_category_tabs) {
UI_panel_category_clear_all(region);
/* gather unique categories */
for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
PanelType *pt = pt_link->link;
if (pt->category[0]) {
if (!UI_panel_category_find(region, pt->category)) {
UI_panel_category_add(region, pt->category);
}
}
}
if (!UI_panel_category_is_visible(region)) {
use_category_tabs = false;
}
else {
category = UI_panel_category_active_get(region, true);
margin_x = category_tabs_width;
}
category = region_panels_collect_categories(region, panel_types_stack, &use_category_tabs);
}
if (use_category_tabs) {
margin_x = category_tabs_width;
}
w = BLI_rctf_size_x(&v2d->cur);
@@ -2782,6 +2866,9 @@ void ED_region_panels_layout_ex(const bContext *C,
/* create panels */
UI_panels_begin(C, region);
/* Get search string for property search. */
const char *search_filter = ED_area_search_filter_get(area, region);
/* set view2d view matrix - UI_block_begin() stores it */
UI_view2d_view_ortho(v2d);
@@ -2813,7 +2900,9 @@ void ED_region_panels_layout_ex(const bContext *C,
panel,
(pt->flag & PNL_DRAW_BOX) ? w_box_panel : w,
em,
NULL);
NULL,
search_filter,
false);
}
/* Draw "polyinstantaited" panels that don't have a 1 to 1 correspondence with their types. */
@@ -2846,7 +2935,17 @@ void ED_region_panels_layout_ex(const bContext *C,
panel,
(panel->type->flag & PNL_DRAW_BOX) ? w_box_panel : w,
em,
unique_panel_str);
unique_panel_str,
search_filter,
false);
}
}
/* Update panel expansion based on property search results. */
if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) {
/* Don't use the last update from the deactivation, or all the panels will be left closed. */
if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) {
UI_panels_set_expansion_from_seach_filter(C, region);
}
}
@@ -2969,6 +3068,144 @@ void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
WM_event_add_keymap_handler(&region->handlers, keymap);
}
static bool panel_property_search(const bContext *C,
ARegion *region,
const uiStyle *style,
Panel *panel,
PanelType *panel_type,
const char *search_filter)
{
uiBlock *block = UI_block_begin(C, region, panel_type->idname, UI_EMBOSS);
UI_block_set_search_only(block, true);
UI_block_set_search_filter(block, search_filter);
if (panel == NULL) {
bool open;
panel = UI_panel_begin(region, &region->panels, block, panel_type, panel, &open);
}
/* Build the layouts. Because they are only used for search,
* they don't need any of the proper style or layout information. */
if (panel->type->draw_header_preset != NULL) {
panel->layout = UI_block_layout(
block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, 0, 0, 0, 0, 0, style);
uiLayoutRootSetSearchOnly(panel->layout, true);
panel_type->draw_header_preset(C, panel);
}
if (panel->type->draw_header != NULL) {
panel->layout = UI_block_layout(
block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, 0, 0, 0, 0, 0, style);
uiLayoutRootSetSearchOnly(panel->layout, true);
panel_type->draw_header(C, panel);
}
if (LIKELY(panel->type->draw != NULL)) {
panel->layout = UI_block_layout(
block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 0, 0, 0, style);
uiLayoutRootSetSearchOnly(panel->layout, true);
panel_type->draw(C, panel);
}
/* We could check after each layout to increase the likelyhood of returning early,
* but that probably wouldn't make much of a difference anyway. */
if (UI_block_apply_search_filter(block)) {
return true;
}
LISTBASE_FOREACH (LinkData *, link, &panel_type->children) {
PanelType *panel_type_child = link->data;
if (LIKELY(panel->type->draw != NULL)) {
if (!panel_type_child->poll || panel_type_child->poll(C, panel_type_child)) {
/* Search for the existing child panel here because it might be an instanced
* child panel with a custom data field that will be needed to build the layout. */
Panel *child_panel = UI_panel_find_by_type(&panel->children, panel_type_child);
if (panel_property_search(
C, region, style, child_panel, panel_type_child, search_filter)) {
return true;
}
}
}
}
return false;
}
bool ED_region_property_search(const bContext *C,
ARegion *region,
ListBase *paneltypes,
const char *contexts[],
const char *category_override)
{
ScrArea *area = CTX_wm_area(C);
WorkSpace *workspace = CTX_wm_workspace(C);
const uiStyle *style = UI_style_get_dpi();
const char *search_filter = ED_area_search_filter_get(area, region);
LinkNode *panel_types_stack = NULL;
LISTBASE_FOREACH_BACKWARD (PanelType *, pt, paneltypes) {
if (panel_add_check(C, workspace, contexts, category_override, pt)) {
BLI_linklist_prepend_alloca(&panel_types_stack, pt);
}
}
const char *category = NULL;
bool use_category_tabs = (category_override == NULL) && region_uses_category_tabs(area, region);
if (use_category_tabs) {
category = region_panels_collect_categories(region, panel_types_stack, &use_category_tabs);
}
/* Run property search for each panel, stopping if a result is found. */
bool has_result = true;
bool has_instanced_panel = false;
for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
PanelType *panel_type = pt_link->link;
/* Note that these checks are duplicated from #ED_region_panels_layout_ex. */
if (panel_type->flag & PNL_INSTANCED) {
has_instanced_panel = true;
continue;
}
if (use_category_tabs) {
if (panel_type->category[0] && !STREQ(category, panel_type->category)) {
continue;
}
}
/* We start property search with an empty panel list, so there's
* no point in trying to find an existing panel with this type. */
has_result = panel_property_search(C, region, style, NULL, panel_type, search_filter);
if (has_result) {
break;
}
}
/* Run property search for instanced panels (created in the layout calls of previous panels). */
if (!has_result && has_instanced_panel) {
LISTBASE_FOREACH (Panel *, panel, &region->panels) {
/* Note that these checks are duplicated from #ED_region_panels_layout_ex. */
if (panel->type == NULL || !(panel->type->flag & PNL_INSTANCED)) {
continue;
}
if (use_category_tabs) {
if (panel->type->category[0] && !STREQ(category, panel->type->category)) {
continue;
}
}
has_result = panel_property_search(C, region, style, panel, panel->type, search_filter);
if (has_result) {
break;
}
}
}
/* Free the panels and blocks, as they are only used for search. */
UI_blocklist_free(C, &region->uiblocks);
UI_panels_free_instanced(C, region);
BKE_area_region_panels_free(&region->panels);
return has_result;
}
void ED_region_header_layout(const bContext *C, ARegion *region)
{
const uiStyle *style = UI_style_get_dpi();

View File

@@ -1115,11 +1115,18 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
/************************* Drawing the Path ************************/
void buttons_context_draw(const bContext *C, uiLayout *layout)
static bool buttons_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceProperties *sbuts = CTX_wm_space_properties(C);
return sbuts->mainb != BCONTEXT_TOOL;
}
static void buttons_panel_context_draw(const bContext *C, Panel *panel)
{
uiLayout *layout = panel->layout;
SpaceProperties *sbuts = CTX_wm_space_properties(C);
ButsContextPath *path = sbuts->path;
uiLayout *row, *sub;
uiLayout *row;
PointerRNA *ptr;
char namebuf[128], *name;
int a, icon;
@@ -1180,52 +1187,11 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
}
}
}
uiItemSpacer(row);
sub = uiLayoutRow(row, false);
uiLayoutSetEmboss(sub, UI_EMBOSS_NONE);
uiItemO(sub,
"",
(sbuts->flag & SB_PIN_CONTEXT) ? ICON_PINNED : ICON_UNPINNED,
"BUTTONS_OT_toggle_pin");
}
#ifdef USE_HEADER_CONTEXT_PATH
static bool buttons_header_context_poll(const bContext *C, HeaderType *UNUSED(ht))
#else
static bool buttons_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
#endif
{
SpaceProperties *sbuts = CTX_wm_space_properties(C);
return (sbuts->mainb != BCONTEXT_TOOL);
}
#ifdef USE_HEADER_CONTEXT_PATH
static void buttons_header_context_draw(const bContext *C, Header *ptr)
#else
static void buttons_panel_context_draw(const bContext *C, Panel *ptr)
#endif
{
buttons_context_draw(C, ptr->layout);
}
void buttons_context_register(ARegionType *art)
{
#ifdef USE_HEADER_CONTEXT_PATH
HeaderType *ht;
ht = MEM_callocN(sizeof(HeaderType), "spacetype buttons context header");
strcpy(ht->idname, "BUTTONS_HT_context");
ht->space_type = SPACE_PROPERTIES;
ht->region_type = art->regionid;
ht->poll = buttons_header_context_poll;
ht->draw = buttons_header_context_draw;
BLI_addtail(&art->headertypes, ht);
#else
PanelType *pt;
pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
PanelType *pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
strcpy(pt->idname, "BUTTONS_PT_context");
strcpy(pt->label, N_("Context")); /* XXX C panels unavailable through RNA bpy.types! */
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
@@ -1233,7 +1199,6 @@ void buttons_context_register(ARegionType *art)
pt->draw = buttons_panel_context_draw;
pt->flag = PNL_NO_HEADER;
BLI_addtail(&art->paneltypes, pt);
#endif
}
ID *buttons_context_id_path(const bContext *C)

View File

@@ -37,9 +37,6 @@ struct bNodeTree;
struct uiLayout;
struct wmOperatorType;
/* Display the context path in the header instead of the main window */
#define USE_HEADER_CONTEXT_PATH
/* context data */
typedef struct ButsContextPath {
@@ -83,7 +80,6 @@ void buttons_context_compute(const struct bContext *C, struct SpaceProperties *s
int buttons_context(const struct bContext *C,
const char *member,
struct bContextDataResult *result);
void buttons_context_draw(const struct bContext *C, struct uiLayout *layout);
void buttons_context_register(struct ARegionType *art);
struct ID *buttons_context_id_path(const struct bContext *C);
@@ -93,6 +89,8 @@ extern const char *buttons_context_dir[]; /* doc access */
void buttons_texture_context_compute(const struct bContext *C, struct SpaceProperties *sbuts);
/* buttons_ops.c */
void BUTTONS_OT_start_filter(struct wmOperatorType *ot);
void BUTTONS_OT_clear_filter(struct wmOperatorType *ot);
void BUTTONS_OT_toggle_pin(struct wmOperatorType *ot);
void BUTTONS_OT_file_browse(struct wmOperatorType *ot);
void BUTTONS_OT_directory_browse(struct wmOperatorType *ot);

View File

@@ -38,6 +38,7 @@
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -52,6 +53,65 @@
#include "buttons_intern.h" /* own include */
/* -------------------------------------------------------------------- */
/** \name Start / Clear Seach Filter Operators
*
* \note Almost a duplicate of the file browser operator #FILE_OT_start_filter.
* \{ */
static int buttons_start_filter_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceProperties *space = CTX_wm_space_properties(C);
ScrArea *area = CTX_wm_area(C);
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
ARegion *region_ctx = CTX_wm_region(C);
CTX_wm_region_set(C, region);
UI_textbutton_activate_rna(C, region, space, "search_filter");
CTX_wm_region_set(C, region_ctx);
return OPERATOR_FINISHED;
}
void BUTTONS_OT_start_filter(struct wmOperatorType *ot)
{
/* Identifiers. */
ot->name = "Filter";
ot->description = "Start entering filter text";
ot->idname = "BUTTONS_OT_start_filter";
/* Callbacks. */
ot->exec = buttons_start_filter_exec;
ot->poll = ED_operator_buttons_active;
}
static int buttons_clear_filter_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceProperties *space = CTX_wm_space_properties(C);
space->runtime->search_string[0] = '\0';
ScrArea *area = CTX_wm_area(C);
ED_region_search_filter_update(area, CTX_wm_region(C));
ED_area_tag_redraw(area);
return OPERATOR_FINISHED;
}
void BUTTONS_OT_clear_filter(struct wmOperatorType *ot)
{
/* Identifiers. */
ot->name = "Clear Filter";
ot->description = "Clear the search filter";
ot->idname = "BUTTONS_OT_clear_filter";
/* Callbacks. */
ot->exec = buttons_clear_filter_exec;
ot->poll = ED_operator_buttons_active;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Pin ID Operator
* \{ */

View File

@@ -48,6 +48,7 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "buttons_intern.h" /* own include */
@@ -109,20 +110,29 @@ static void buttons_free(SpaceLink *sl)
BLI_freelistN(&ct->users);
MEM_freeN(ct);
}
MEM_SAFE_FREE(sbuts->runtime);
}
/* spacetype; init callback */
static void buttons_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
static void buttons_init(struct wmWindowManager *UNUSED(wm), ScrArea *area)
{
SpaceProperties *sbuts = (SpaceProperties *)area->spacedata.first;
sbuts->runtime = MEM_mallocN(sizeof(SpaceProperties_Runtime), __func__);
sbuts->runtime->search_string[0] = '\0';
}
static SpaceLink *buttons_duplicate(SpaceLink *sl)
{
SpaceProperties *sfile_old = (SpaceProperties *)sl;
SpaceProperties *sbutsn = MEM_dupallocN(sl);
/* clear or remove stuff from old */
sbutsn->path = NULL;
sbutsn->texuser = NULL;
sbutsn->runtime = MEM_dupallocN(sfile_old->runtime);
sbutsn->runtime->search_string[0] = '\0';
return (SpaceLink *)sbutsn;
}
@@ -143,6 +153,7 @@ static void buttons_main_region_init(wmWindowManager *wm, ARegion *region)
*
* \return The total number of items in the array returned.
*/
/* HANS-TODO: Use short for this. */
int ED_buttons_tabs_list(SpaceProperties *sbuts, int *context_tabs_array)
{
int length = 0;
@@ -230,71 +241,146 @@ int ED_buttons_tabs_list(SpaceProperties *sbuts, int *context_tabs_array)
return length;
}
static const char *buttons_main_region_context_string(const short mainb)
{
switch (mainb) {
case BCONTEXT_SCENE:
return "scene";
case BCONTEXT_RENDER:
return "render";
case BCONTEXT_OUTPUT:
return "output";
case BCONTEXT_VIEW_LAYER:
return "view_layer";
case BCONTEXT_WORLD:
return "world";
case BCONTEXT_OBJECT:
return "object";
case BCONTEXT_DATA:
return "data";
case BCONTEXT_MATERIAL:
return "material";
case BCONTEXT_TEXTURE:
return "texture";
case BCONTEXT_PARTICLE:
return "particle";
case BCONTEXT_PHYSICS:
return "physics";
case BCONTEXT_BONE:
return "bone";
case BCONTEXT_MODIFIER:
return "modifier";
case BCONTEXT_SHADERFX:
return "shaderfx";
case BCONTEXT_CONSTRAINT:
return "constraint";
case BCONTEXT_BONE_CONSTRAINT:
return "bone_constraint";
case BCONTEXT_TOOL:
return "tool";
}
/* All the cases should be handled. */
BLI_assert(false);
return "";
}
static void buttons_main_region_layout_properties(const bContext *C,
SpaceProperties *sbuts,
ARegion *region)
{
buttons_context_compute(C, sbuts);
const char *contexts[2] = {NULL, NULL};
switch (sbuts->mainb) {
case BCONTEXT_SCENE:
contexts[0] = "scene";
break;
case BCONTEXT_RENDER:
contexts[0] = "render";
break;
case BCONTEXT_OUTPUT:
contexts[0] = "output";
break;
case BCONTEXT_VIEW_LAYER:
contexts[0] = "view_layer";
break;
case BCONTEXT_WORLD:
contexts[0] = "world";
break;
case BCONTEXT_OBJECT:
contexts[0] = "object";
break;
case BCONTEXT_DATA:
contexts[0] = "data";
break;
case BCONTEXT_MATERIAL:
contexts[0] = "material";
break;
case BCONTEXT_TEXTURE:
contexts[0] = "texture";
break;
case BCONTEXT_PARTICLE:
contexts[0] = "particle";
break;
case BCONTEXT_PHYSICS:
contexts[0] = "physics";
break;
case BCONTEXT_BONE:
contexts[0] = "bone";
break;
case BCONTEXT_MODIFIER:
contexts[0] = "modifier";
break;
case BCONTEXT_SHADERFX:
contexts[0] = "shaderfx";
break;
case BCONTEXT_CONSTRAINT:
contexts[0] = "constraint";
break;
case BCONTEXT_BONE_CONSTRAINT:
contexts[0] = "bone_constraint";
break;
case BCONTEXT_TOOL:
contexts[0] = "tool";
break;
}
const char *contexts[2] = {buttons_main_region_context_string(sbuts->mainb), NULL};
ED_region_panels_layout_ex(C, region, &region->type->paneltypes, contexts, NULL);
}
static bool property_search_for_context(const bContext *C, ARegion *region, SpaceProperties *sbuts)
{
const char *contexts[2] = {buttons_main_region_context_string(sbuts->mainb), NULL};
if (sbuts->mainb == BCONTEXT_TOOL) {
return false;
}
else {
buttons_context_compute(C, sbuts);
return ED_region_property_search(C, region, &region->type->paneltypes, contexts, NULL);
}
}
static void property_search_move_to_next_tab_with_results(SpaceProperties *sbuts,
const int *context_tabs_array,
const int tabs_len)
{
int current_tab_index = 0;
for (int i = 0; i < tabs_len; i++) {
if (sbuts->mainb == context_tabs_array[i]) {
current_tab_index = i;
break;
}
}
/* Try the tabs after the current tab. */
for (int i = current_tab_index; i < tabs_len; i++) {
if (sbuts->runtime->context_search_filter_active & (1 << i)) {
sbuts->mainbuser = context_tabs_array[i];
return;
}
}
/* Try the tabs before the current tab. */
for (int i = 0; i < current_tab_index; i++) {
if (sbuts->runtime->context_search_filter_active & (1 << i)) {
sbuts->mainbuser = context_tabs_array[i];
return;
}
}
}
static void property_search_all_tabs(const bContext *C,
SpaceProperties *sbuts,
ARegion *main_region,
const int *context_tabs_array,
const int tabs_len)
{
sbuts->runtime->context_search_filter_active = 0;
/* Duplicate space and region so we don't change any data for this space. */
ScrArea *area_copy = MEM_dupallocN(CTX_wm_area(C));
ARegion *region_copy = BKE_area_region_copy(area_copy->type, main_region);
BKE_area_region_panels_free(&region_copy->panels);
bContext *C_copy = CTX_copy(C);
CTX_wm_area_set(C_copy, area_copy);
CTX_wm_region_set(C_copy, region_copy);
SpaceProperties *sbuts_copy = MEM_dupallocN(sbuts);
/* Loop through the tabs added to the properties editor. */
for (int i = 0; i < tabs_len; i++) {
/* -1 corresponds to a spacer. */
if (context_tabs_array[i] == -1) {
continue;
}
/* Handle search for the current tab later in the normal layout pass. */
if (context_tabs_array[i] == sbuts->mainb) {
continue;
}
sbuts_copy->mainb = sbuts_copy->mainbo = sbuts_copy->mainbuser = context_tabs_array[i];
SET_FLAG_FROM_TEST(sbuts->runtime->context_search_filter_active,
property_search_for_context(C_copy, region_copy, sbuts_copy),
(1 << i));
}
BKE_area_region_free(area_copy->type, region_copy);
MEM_freeN(region_copy);
MEM_freeN(sbuts_copy);
MEM_freeN(area_copy);
MEM_freeN(C_copy);
}
static void buttons_main_region_layout(const bContext *C, ARegion *region)
{
/* draw entirely, view changes should be handled here */
@@ -307,6 +393,42 @@ static void buttons_main_region_layout(const bContext *C, ARegion *region)
buttons_main_region_layout_properties(C, sbuts, region);
}
if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) {
int context_tabs_array[32];
int tabs_len = ED_buttons_tabs_list(sbuts, context_tabs_array);
property_search_all_tabs(C, sbuts, region, context_tabs_array, tabs_len);
/* Check whether the current tab has a search match. */
bool current_tab_has_search_match = false;
LISTBASE_FOREACH (Panel *, panel, &region->panels) {
if (UI_panel_is_active(panel) && UI_panel_matches_search_filter(panel)) {
current_tab_has_search_match = true;
}
}
/* Find which index in the list the current tab corresponds to. */
int current_tab_index = -1;
for (int i = 0; i < tabs_len; i++) {
if (context_tabs_array[i] == sbuts->mainb) {
current_tab_index = i;
}
}
BLI_assert(current_tab_index != -1);
/* Update the tab search match flag for the current tab. */
SET_FLAG_FROM_TEST(sbuts->runtime->context_search_filter_active,
current_tab_has_search_match,
(1 << current_tab_index));
/* Move to the next tab with a result */
if (!current_tab_has_search_match) {
if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) {
property_search_move_to_next_tab_with_results(sbuts, context_tabs_array, tabs_len);
}
}
}
sbuts->mainbo = sbuts->mainb;
}
@@ -328,6 +450,8 @@ static void buttons_main_region_listener(wmWindow *UNUSED(win),
static void buttons_operatortypes(void)
{
WM_operatortype_append(BUTTONS_OT_start_filter);
WM_operatortype_append(BUTTONS_OT_clear_filter);
WM_operatortype_append(BUTTONS_OT_toggle_pin);
WM_operatortype_append(BUTTONS_OT_context_menu);
WM_operatortype_append(BUTTONS_OT_file_browse);
@@ -342,14 +466,6 @@ static void buttons_keymap(struct wmKeyConfig *keyconf)
/* add handlers, stuff you only do once or on area/region changes */
static void buttons_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
{
#ifdef USE_HEADER_CONTEXT_PATH
/* Reinsert context buttons header-type at the end of the list so it's drawn last. */
HeaderType *context_ht = BLI_findstring(
&region->type->headertypes, "BUTTONS_HT_context", offsetof(HeaderType, idname));
BLI_remlink(&region->type->headertypes, context_ht);
BLI_addtail(&region->type->headertypes, context_ht);
#endif
ED_region_header_init(region);
}
@@ -389,10 +505,6 @@ static void buttons_header_region_message_subscribe(const bContext *UNUSED(C),
if (sbuts->mainb == BCONTEXT_TOOL) {
WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
}
#ifdef USE_HEADER_CONTEXT_PATH
WM_msg_subscribe_rna_anon_prop(mbus, SpaceProperties, context, &msg_sub_value_region_tag_redraw);
#endif
}
static void buttons_navigation_bar_region_init(wmWindowManager *wm, ARegion *region)
@@ -726,9 +838,7 @@ void ED_spacetype_buttons(void)
art->draw = ED_region_panels_draw;
art->listener = buttons_main_region_listener;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
#ifndef USE_HEADER_CONTEXT_PATH
buttons_context_register(art);
#endif
BLI_addhead(&st->regiontypes, art);
/* Register the panel types from modifiers. The actual panels are built per modifier rather than
@@ -764,9 +874,6 @@ void ED_spacetype_buttons(void)
art->init = buttons_header_region_init;
art->draw = buttons_header_region_draw;
art->message_subscribe = buttons_header_region_message_subscribe;
#ifdef USE_HEADER_CONTEXT_PATH
buttons_context_register(art);
#endif
BLI_addhead(&st->regiontypes, art);
/* regions: navigation bar */

View File

@@ -687,6 +687,14 @@ enum {
/** When the user sets the region is hidden,
* needed for floating regions that may be hidden for other reasons. */
RGN_FLAG_HIDDEN_BY_USER = (1 << 7),
/** Property search filter is active. */
RGN_FLAG_SEARCH_FILTER_ACTIVE = (1 << 8),
/**
* Update the expansion of the region's panels and switch contexts. Only Set
* temporarily when the search filter is updated so that interactions are still
* interactive, cleared at the end of the region's layout pass.
*/
RGN_FLAG_SEARCH_FILTER_UPDATE = (1 << 9),
};
/** #ARegion.do_draw */

View File

@@ -129,6 +129,18 @@ typedef enum eSpaceInfo_RptMask {
/** \name Properties Editor
* \{ */
typedef struct SpaceProperties_Runtime {
/** For filtering properties displayed in the space. Length defined as UI_MAX_NAME_STR. */
char search_string[128];
/**
* Bitfield flag (in the same order as the tabs) for whether each tab has properties
* that match the search filter. Only valid when #search_string is set.
*/
int context_search_filter_active;
char _pad[4];
} SpaceProperties_Runtime;
/* Properties Editor */
typedef struct SpaceProperties {
SpaceLink *next, *prev;
@@ -159,6 +171,9 @@ typedef struct SpaceProperties {
ID *pinid;
void *texuser;
/* Doesn't necessarily need to be a pointer, but runtime structs are still written to files. */
SpaceProperties_Runtime *runtime;
} SpaceProperties;
/* button defines (deprecated) */

View File

@@ -264,6 +264,9 @@ typedef struct ThemeSpace {
/* note, cannot use name 'panel' because of DNA mapping old files */
uiPanelColors panelcolors;
unsigned char search_match_color[4];
char _pad2[4];
unsigned char shade1[4];
unsigned char shade2[4];

View File

@@ -1817,6 +1817,17 @@ static void rna_SpaceProperties_context_update(Main *UNUSED(bmain),
}
}
static void rna_SpaceProperties_search_filter_update(struct bContext *C,
struct PointerRNA *UNUSED(ptr))
{
ScrArea *area = CTX_wm_area(C);
/* Update the search filter flag for the main region with the panels. */
ARegion *main_region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
BLI_assert(main_region != NULL);
ED_region_search_filter_update(area, main_region);
}
/* Space Console */
static void rna_ConsoleLine_body_get(PointerRNA *ptr, char *value)
{
@@ -4482,6 +4493,25 @@ static void rna_def_space_properties(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_pin_id", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SB_PIN_CONTEXT);
RNA_def_property_ui_text(prop, "Pin ID", "Use the pinned context");
/* Property search. */
prop = RNA_def_property(srna, "context_search_filter_active", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "runtime->context_search_filter_active");
RNA_def_property_enum_items(prop, buttons_context_items);
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
RNA_def_property_enum_funcs(
prop, NULL, "rna_SpaceProperties_context_set", "rna_SpaceProperties_context_itemf");
RNA_def_property_ui_text(prop, "", "");
RNA_def_property_update(
prop, NC_SPACE | ND_SPACE_PROPERTIES, "rna_SpaceProperties_context_update");
prop = RNA_def_property(srna, "search_filter", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "runtime->search_string");
RNA_def_property_ui_text(prop, "Display Filter", "Live search filtering string");
RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(
prop, NC_SPACE | ND_SPACE_PROPERTIES, "rna_SpaceProperties_search_filter_update");
}
static void rna_def_space_image(BlenderRNA *brna)

View File

@@ -216,8 +216,13 @@ static void rna_uiItemMenuEnumR(uiLayout *layout,
uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
}
static void rna_uiItemTabsEnumR(
uiLayout *layout, bContext *C, struct PointerRNA *ptr, const char *propname, bool icon_only)
static void rna_uiItemTabsEnumR(uiLayout *layout,
bContext *C,
struct PointerRNA *ptr,
const char *propname,
struct PointerRNA *ptr_highlight,
const char *propname_highlight,
bool icon_only)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
@@ -230,7 +235,31 @@ static void rna_uiItemTabsEnumR(
return;
}
uiItemTabsEnumR_prop(layout, C, ptr, prop, icon_only);
/* Get the highlight property used to gray out some of the tabs. */
PropertyRNA *prop_highlight = NULL;
if (!RNA_pointer_is_null(ptr_highlight)) {
prop_highlight = RNA_struct_find_property(ptr_highlight, propname_highlight);
if (!prop_highlight) {
RNA_warning("property not found: %s.%s",
RNA_struct_identifier(ptr_highlight->type),
propname_highlight);
return;
}
if (RNA_property_type(prop_highlight) != PROP_ENUM) {
RNA_warning("property is not an enum: %s.%s",
RNA_struct_identifier(ptr_highlight->type),
propname_highlight);
return;
}
if (!(RNA_property_flag(prop_highlight) & PROP_ENUM_FLAG)) {
RNA_warning("property must be a bitfield enum: %s.%s",
RNA_struct_identifier(ptr_highlight->type),
propname_highlight);
return;
}
}
uiItemTabsEnumR_prop(layout, C, ptr, prop, ptr_highlight, prop_highlight, icon_only);
}
static void rna_uiItemEnumR_string(uiLayout *layout,
@@ -920,6 +949,11 @@ void RNA_api_ui_layout(StructRNA *srna)
func = RNA_def_function(srna, "prop_tabs_enum", "rna_uiItemTabsEnumR");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
api_ui_item_rna_common(func);
parm = RNA_def_pointer(
func, "data_highlight", "AnyType", "", "Data from which to take highlight property");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR);
parm = RNA_def_string(
func, "property_highlight", NULL, 0, "", "Identifier of highlight property in data");
RNA_def_boolean(func, "icon_only", false, "", "Draw only icons in tabs, no text");
func = RNA_def_function(srna, "prop_enum", "rna_uiItemEnumR_string");

View File

@@ -1718,6 +1718,11 @@ static void rna_def_userdef_theme_space_common(StructRNA *srna)
RNA_def_property_ui_text(prop, "Header Text Highlight", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
prop = RNA_def_property(srna, "search_match_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Search Match Color", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
/* panel settings */
prop = RNA_def_property(srna, "panelcolors", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);