Merge branch 'blender-v4.3-release'
This commit is contained in:
@@ -2918,16 +2918,16 @@ void GreasePencil::remove_drawings_with_no_users()
|
||||
Array<int> drawing_index_map(drawings.size(), unchanged_index);
|
||||
|
||||
int first_unused_drawing = -1;
|
||||
int last_used_drawing = drawings.size();
|
||||
int last_used_drawing = drawings.size() - 1;
|
||||
/* Advance head and tail iterators to the next unused/used drawing respectively.
|
||||
* Returns true if an index pair was found that needs to be swapped. */
|
||||
auto find_next_swap_index = [&]() -> bool {
|
||||
do {
|
||||
++first_unused_drawing;
|
||||
} while (first_unused_drawing < last_used_drawing && is_drawing_used(first_unused_drawing));
|
||||
do {
|
||||
} while (first_unused_drawing <= last_used_drawing && is_drawing_used(first_unused_drawing));
|
||||
while (last_used_drawing >= 0 && !is_drawing_used(last_used_drawing)) {
|
||||
--last_used_drawing;
|
||||
} while (first_unused_drawing < last_used_drawing && !is_drawing_used(last_used_drawing));
|
||||
}
|
||||
|
||||
return first_unused_drawing < last_used_drawing;
|
||||
};
|
||||
@@ -2938,10 +2938,25 @@ void GreasePencil::remove_drawings_with_no_users()
|
||||
drawing_index_map[last_used_drawing] = first_unused_drawing;
|
||||
}
|
||||
|
||||
/* `last_used_drawing` is expected to be exactly the item before the first unused drawing, once
|
||||
* the loop above is fully done and all unused drawings are supposed to be at the end of the
|
||||
* array. */
|
||||
BLI_assert(last_used_drawing == first_unused_drawing - 1);
|
||||
#ifndef NDEBUG
|
||||
for (const int i : drawings.index_range()) {
|
||||
if (i < first_unused_drawing) {
|
||||
BLI_assert(is_drawing_used(i));
|
||||
}
|
||||
else {
|
||||
BLI_assert(!is_drawing_used(i));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Tail range of unused drawings that can be removed. */
|
||||
const IndexRange drawings_to_remove = (first_unused_drawing > 0) ?
|
||||
drawings.index_range().drop_front(last_used_drawing +
|
||||
1) :
|
||||
drawings.index_range().drop_front(
|
||||
first_unused_drawing) :
|
||||
drawings.index_range();
|
||||
if (drawings_to_remove.is_empty()) {
|
||||
return;
|
||||
|
||||
@@ -91,6 +91,36 @@ TEST(greasepencil, remove_drawings)
|
||||
expected_frames_pairs_layer0[1][1]);
|
||||
}
|
||||
|
||||
TEST(greasepencil, remove_drawings_last_unused)
|
||||
{
|
||||
GreasePencil *grease_pencil = reinterpret_cast<GreasePencil *>(
|
||||
BKE_id_new_nomain(ID_GP, "Grease Pencil test"));
|
||||
|
||||
/* Regression test for #129900: unused drawing at the end causes crash. */
|
||||
|
||||
grease_pencil->add_empty_drawings(2);
|
||||
reinterpret_cast<const GreasePencilDrawing *>(grease_pencil->drawing(0))->wrap().remove_user();
|
||||
reinterpret_cast<const GreasePencilDrawing *>(grease_pencil->drawing(1))->wrap().remove_user();
|
||||
|
||||
Layer &layer_a = grease_pencil->add_layer("LayerA");
|
||||
layer_a.add_frame(10)->drawing_index = 0;
|
||||
const GreasePencilDrawingBase *used_drawing = grease_pencil->drawings()[0];
|
||||
grease_pencil->update_drawing_users_for_layer(layer_a);
|
||||
|
||||
EXPECT_EQ(layer_a.frames().size(), 1);
|
||||
EXPECT_EQ(layer_a.frames().lookup(10).drawing_index, 0);
|
||||
/* Test DNA storage data too. */
|
||||
layer_a.prepare_for_dna_write();
|
||||
EXPECT_EQ(layer_a.frames_storage.num, 1);
|
||||
EXPECT_EQ(layer_a.frames_storage.values[0].drawing_index, 0);
|
||||
|
||||
grease_pencil->remove_drawings_with_no_users();
|
||||
EXPECT_EQ(grease_pencil->drawings().size(), 1);
|
||||
EXPECT_EQ(grease_pencil->drawings()[0], used_drawing);
|
||||
|
||||
BKE_id_free(nullptr, grease_pencil);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/* Layer Tree Tests. */
|
||||
|
||||
|
||||
@@ -299,6 +299,10 @@ class JsonFormatter : public Formatter {
|
||||
|
||||
public:
|
||||
void serialize(std::ostream &os, const Value &value) override;
|
||||
/**
|
||||
* \return The deserialized value or null on failure to parse the JSON contents. Typically this
|
||||
* indicates a malformed file.
|
||||
*/
|
||||
std::unique_ptr<Value> deserialize(std::istream &is) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -363,8 +363,13 @@ void JsonFormatter::serialize(std::ostream &os, const Value &value)
|
||||
std::unique_ptr<Value> JsonFormatter::deserialize(std::istream &is)
|
||||
{
|
||||
nlohmann::ordered_json j;
|
||||
is >> j;
|
||||
return convert_from_json(j);
|
||||
try {
|
||||
is >> j;
|
||||
return convert_from_json(j);
|
||||
}
|
||||
catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void write_json_file(const StringRef path, const Value &value)
|
||||
|
||||
@@ -566,8 +566,12 @@ class AssetIndexFile : public AbstractFile {
|
||||
JsonFormatter formatter;
|
||||
std::ifstream is;
|
||||
is.open(this->filename);
|
||||
BLI_SCOPED_DEFER([&]() { is.close(); });
|
||||
|
||||
std::unique_ptr<Value> read_data = formatter.deserialize(is);
|
||||
is.close();
|
||||
if (!read_data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<AssetIndex>(read_data);
|
||||
}
|
||||
@@ -680,6 +684,11 @@ static eFileIndexerResult read_index(const char *filename,
|
||||
}
|
||||
|
||||
std::unique_ptr<AssetIndex> contents = asset_index_file.read_contents();
|
||||
if (!contents) {
|
||||
CLOG_INFO(&LOG, 3, "Asset file index is ignored; failed to read contents.");
|
||||
return FILE_INDEXER_NEEDS_UPDATE;
|
||||
}
|
||||
|
||||
if (!contents->is_latest_version()) {
|
||||
CLOG_INFO(&LOG,
|
||||
3,
|
||||
|
||||
@@ -274,6 +274,7 @@ class StepObject {
|
||||
if (grease_pencil.root_group_ptr) {
|
||||
MEM_delete(&grease_pencil.root_group());
|
||||
}
|
||||
grease_pencil.set_active_node(nullptr);
|
||||
|
||||
grease_pencil.root_group_ptr = MEM_new<bke::greasepencil::LayerGroup>(__func__, root_group_);
|
||||
BLI_assert(layers_num_ == grease_pencil.layers().size());
|
||||
|
||||
Reference in New Issue
Block a user