WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 358 commits from brush-assets-project into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
5 changed files with 99 additions and 17 deletions
Showing only changes of commit 33f3d1912b - Show all commits

View File

@ -260,6 +260,13 @@ class IndexMask : private IndexMaskData {
*/
IndexMask slice(IndexRange range) const;
IndexMask slice(int64_t start, int64_t size) const;
IndexMask slice(RawMaskIterator first_it, RawMaskIterator last_it, int64_t size) const;
/**
* Slices the mask based on the stored indices. The resulting mask only contains the indices that
* are within the given range.
*/
IndexMask slice_content(IndexRange range) const;
IndexMask slice_content(int64_t start, int64_t size) const;
/**
* Same as above but can also add an offset to every index in the mask.
* Takes O(log n + range.size()) time but with a very small constant factor.

View File

@ -133,6 +133,46 @@ IndexMask IndexMask::slice(const int64_t start, const int64_t size) const
return sliced;
}
IndexMask IndexMask::slice(const RawMaskIterator first_it,
const RawMaskIterator last_it,
const int64_t size) const
{
BLI_assert(this->iterator_to_index(last_it) - this->iterator_to_index(first_it) + 1 == size);
IndexMask sliced = *this;
sliced.indices_num_ = size;
sliced.segments_num_ = last_it.segment_i - first_it.segment_i + 1;
sliced.indices_by_segment_ += first_it.segment_i;
sliced.segment_offsets_ += first_it.segment_i;
sliced.cumulative_segment_sizes_ += first_it.segment_i;
sliced.begin_index_in_segment_ = first_it.index_in_segment;
sliced.end_index_in_segment_ = last_it.index_in_segment + 1;
return sliced;
}
IndexMask IndexMask::slice_content(const IndexRange range) const
{
return this->slice_content(range.start(), range.size());
}
IndexMask IndexMask::slice_content(const int64_t start, const int64_t size) const
{
if (size <= 0) {
return {};
}
const std::optional<RawMaskIterator> first_it = this->find_larger_equal(start);
const std::optional<RawMaskIterator> last_it = this->find_smaller_equal(start + size - 1);
if (!first_it || !last_it) {
return {};
}
const int64_t first_index = this->iterator_to_index(*first_it);
const int64_t last_index = this->iterator_to_index(*last_it);
if (last_index < first_index) {
return {};
}
const int64_t sliced_mask_size = last_index - first_index + 1;
return this->slice(*first_it, *last_it, sliced_mask_size);
}
IndexMask IndexMask::slice_and_offset(const IndexRange range,
const int64_t offset,
IndexMaskMemory &memory) const

View File

@ -418,4 +418,39 @@ TEST(index_mask, FindSmallerEqual)
}
}
TEST(index_mask, SliceContent)
{
IndexMaskMemory memory;
{
const IndexMask mask;
EXPECT_TRUE(mask.slice_content(IndexRange(50, 10)).is_empty());
}
{
const IndexMask mask{IndexRange(10, 90)};
const IndexMask a = mask.slice_content(IndexRange(30));
EXPECT_EQ(a.size(), 20);
const IndexMask b = mask.slice_content(IndexRange(10, 90));
EXPECT_EQ(b.size(), 90);
const IndexMask c = mask.slice_content(IndexRange(80, 100));
EXPECT_EQ(c.size(), 20);
const IndexMask d = mask.slice_content(IndexRange(1000, 100));
EXPECT_EQ(d.size(), 0);
}
{
const IndexMask mask = IndexMask::from_initializers(
{4, 5, 100, 1'000, 10'000, 20'000, 25'000, 100'000}, memory);
EXPECT_EQ(mask.slice_content(IndexRange(10)).size(), 2);
EXPECT_EQ(mask.slice_content(IndexRange(200)).size(), 3);
EXPECT_EQ(mask.slice_content(IndexRange(2'000)).size(), 4);
EXPECT_EQ(mask.slice_content(IndexRange(10'000)).size(), 4);
EXPECT_EQ(mask.slice_content(IndexRange(10'001)).size(), 5);
EXPECT_EQ(mask.slice_content(IndexRange(1'000'000)).size(), 8);
EXPECT_EQ(mask.slice_content(IndexRange(10'000, 100'000)).size(), 4);
EXPECT_EQ(mask.slice_content(IndexRange(1'001, 100'000)).size(), 4);
EXPECT_EQ(mask.slice_content(IndexRange(1'000, 100'000)).size(), 5);
EXPECT_EQ(mask.slice_content(IndexRange(1'000, 99'000)).size(), 4);
EXPECT_EQ(mask.slice_content(IndexRange(1'000, 10'000)).size(), 2);
}
}
} // namespace blender::index_mask::tests

View File

@ -61,7 +61,7 @@ bool AbstractViewItem::set_state_active()
}
/* Deactivate other items in the view. */
get_view().foreach_view_item([](auto &item) { item.deactivate(); });
this->get_view().foreach_view_item([](auto &item) { item.deactivate(); });
is_active_ = true;
return true;
@ -125,7 +125,7 @@ bool AbstractViewItem::is_renaming() const
void AbstractViewItem::begin_renaming()
{
AbstractView &view = get_view();
AbstractView &view = this->get_view();
if (view.is_renaming() || !supports_renaming()) {
return;
}
@ -134,13 +134,13 @@ void AbstractViewItem::begin_renaming()
is_renaming_ = true;
}
StringRef initial_str = get_rename_string();
StringRef initial_str = this->get_rename_string();
std::copy(std::begin(initial_str), std::end(initial_str), std::begin(view.get_rename_buffer()));
}
void AbstractViewItem::rename_apply(const bContext &C)
{
const AbstractView &view = get_view();
const AbstractView &view = this->get_view();
rename(C, view.get_rename_buffer().data());
end_renaming();
}
@ -153,7 +153,7 @@ void AbstractViewItem::end_renaming()
is_renaming_ = false;
AbstractView &view = get_view();
AbstractView &view = this->get_view();
view.end_renaming();
}
@ -189,7 +189,7 @@ static void rename_button_fn(bContext *C, void *arg, char * /*origstr*/)
void AbstractViewItem::add_rename_button(uiBlock &block)
{
AbstractView &view = get_view();
AbstractView &view = this->get_view();
uiBut *rename_but = uiDefBut(&block,
UI_BTYPE_TEXT,
1,
@ -312,7 +312,7 @@ bool AbstractViewItem::is_interactive() const
bool AbstractViewItem::is_active() const
{
BLI_assert_msg(get_view().is_reconstructed(),
BLI_assert_msg(this->get_view().is_reconstructed(),
"State can't be queried until reconstruction is completed");
return is_active_;
}

View File

@ -36,7 +36,7 @@ AbstractGridViewItem &AbstractGridView::add_item(std::unique_ptr<AbstractGridVie
AbstractGridViewItem &added_item = *items_.last();
item_map_.add(added_item.identifier_, &added_item);
register_item(added_item);
this->register_item(added_item);
return added_item;
}
@ -106,9 +106,9 @@ int AbstractGridView::get_item_count_filtered() const
}
int i = 0;
foreach_filtered_item([&i](const auto &) { i++; });
this->foreach_filtered_item([&i](const auto &) { i++; });
BLI_assert(i <= get_item_count());
BLI_assert(i <= this->get_item_count());
item_count_filtered_ = i;
return i;
}
@ -142,7 +142,7 @@ void AbstractGridViewItem::grid_tile_click_fn(bContext *C, void *but_arg1, void
void AbstractGridViewItem::add_grid_tile_button(uiBlock &block)
{
const GridViewStyle &style = get_view().get_style();
const GridViewStyle &style = this->get_view().get_style();
view_item_but_ = (uiButViewItem *)uiDefBut(&block,
UI_BTYPE_VIEW_ITEM,
0,
@ -230,7 +230,7 @@ BuildOnlyVisibleButtonsHelper::BuildOnlyVisibleButtonsHelper(const View2D &v2d,
const int cols_per_row)
: v2d_(v2d), grid_view_(grid_view), style_(grid_view.get_style()), cols_per_row_(cols_per_row)
{
visible_items_range_ = get_visible_range();
visible_items_range_ = this->get_visible_range();
}
IndexRange BuildOnlyVisibleButtonsHelper::get_visible_range() const
@ -265,7 +265,7 @@ void BuildOnlyVisibleButtonsHelper::fill_layout_before_visible(uiBlock &block) c
}
const int tot_tiles_before_visible = first_idx_in_view;
const int scrolled_away_rows = tot_tiles_before_visible / cols_per_row_;
add_spacer_button(block, scrolled_away_rows);
this->add_spacer_button(block, scrolled_away_rows);
}
void BuildOnlyVisibleButtonsHelper::fill_layout_after_visible(uiBlock &block) const
@ -342,9 +342,9 @@ void GridViewLayoutBuilder::build_grid_tile(uiLayout &grid_layout,
void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view,
const View2D &v2d) const
{
uiLayout *parent_layout = current_layout();
uiLayout *parent_layout = this->current_layout();
uiLayout &layout = *uiLayoutColumn(current_layout(), true);
uiLayout &layout = *uiLayoutColumn(parent_layout, true);
const GridViewStyle &style = grid_view.get_style();
const int cols_per_row = std::max(uiLayoutGetWidth(&layout) / style.tile_width, 1);
@ -367,7 +367,7 @@ void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view,
row = uiLayoutRow(&layout, true);
}
build_grid_tile(*row, item);
this->build_grid_tile(*row, item);
item_idx++;
});
@ -411,7 +411,7 @@ PreviewGridItem::PreviewGridItem(StringRef identifier, StringRef label, int prev
void PreviewGridItem::build_grid_tile(uiLayout &layout) const
{
const GridViewStyle &style = get_view().get_style();
const GridViewStyle &style = this->get_view().get_style();
uiBlock *block = uiLayoutGetBlock(&layout);
uiBut *but = uiDefBut(block,