WIP: Brush assets project #106303
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue