Fixed integer division by zero error when loading files
This commit is contained in:
parent
58fb02f449
commit
97d308268d
19 changed files with 97 additions and 30 deletions
|
|
@ -527,7 +527,7 @@ void DrawingProgram::pen_tool_switch_check() {
|
|||
|
||||
void DrawingProgram::invalidate_cache_at_component(CanvasComponentContainer::ObjInfo* objToCheck) {
|
||||
if(!selection.is_selected(objToCheck))
|
||||
drawCache.invalidate_cache_at_aabb(objToCheck->obj->get_world_bounds());
|
||||
drawCache.invalidate_cache_at_optional_aabb(objToCheck->obj->get_world_bounds());
|
||||
}
|
||||
|
||||
void DrawingProgram::preupdate_component(CanvasComponentContainer::ObjInfo* objToCheck) {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ DrawingProgramCache::DrawingProgramCache(DrawingProgram& initDrawP):
|
|||
|
||||
void DrawingProgramCache::add_component(CanvasComponentContainer::ObjInfo* c) {
|
||||
unsortedComponents.emplace_back(c);
|
||||
invalidate_cache_at_aabb(c->obj->get_world_bounds());
|
||||
invalidate_cache_at_optional_aabb(c->obj->get_world_bounds());
|
||||
}
|
||||
|
||||
void DrawingProgramCache::erase_component(CanvasComponentContainer::ObjInfo* c) {
|
||||
|
|
@ -43,7 +43,7 @@ void DrawingProgramCache::erase_component(CanvasComponentContainer::ObjInfo* c)
|
|||
}
|
||||
else
|
||||
std::erase(unsortedComponents, c);
|
||||
invalidate_cache_at_aabb(c->obj->get_world_bounds());
|
||||
invalidate_cache_at_optional_aabb(c->obj->get_world_bounds());
|
||||
}
|
||||
|
||||
void DrawingProgramCache::invalidate_cache_at_aabb(const SCollision::AABB<WorldScalar>& aabb) {
|
||||
|
|
@ -67,6 +67,11 @@ void DrawingProgramCache::invalidate_cache_at_aabb(const SCollision::AABB<WorldS
|
|||
}
|
||||
}
|
||||
|
||||
void DrawingProgramCache::invalidate_cache_at_optional_aabb(const std::optional<SCollision::AABB<WorldScalar>>& aabb) {
|
||||
if(aabb.has_value())
|
||||
invalidate_cache_at_aabb(aabb.value());
|
||||
}
|
||||
|
||||
bool DrawingProgramCache::should_rebuild() const {
|
||||
return (unsortedComponents.size() >= MINIMUM_COMPONENTS_TO_START_REBUILD);
|
||||
}
|
||||
|
|
@ -97,11 +102,17 @@ void DrawingProgramCache::build(const std::unordered_set<CanvasComponentContaine
|
|||
}
|
||||
|
||||
void DrawingProgramCache::internal_build(std::vector<CanvasComponentContainer::ObjInfo*> componentsToBuild, const std::unordered_set<CanvasComponentContainer::ObjInfo*>& objsToNotInclude) {
|
||||
std::erase_if(componentsToBuild, [&objsToNotInclude](auto& c) {
|
||||
return objsToNotInclude.contains(c);
|
||||
});
|
||||
bvhRoot = std::make_shared<DrawingProgramCacheBVHNode>();
|
||||
unsortedComponents.clear();
|
||||
std::erase_if(componentsToBuild, [&unsortedComponents = unsortedComponents, &objsToNotInclude](auto& c) {
|
||||
if(objsToNotInclude.contains(c))
|
||||
return true;
|
||||
if(!c->obj->get_world_bounds().has_value()) {
|
||||
unsortedComponents.emplace_back(c);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
clear_own_cached_surfaces();
|
||||
build_bvh_node(bvhRoot, componentsToBuild);
|
||||
}
|
||||
|
|
@ -156,16 +167,16 @@ void DrawingProgramCache::preupdate_component(CanvasComponentContainer::ObjInfo*
|
|||
std::erase(cacheParentBvhNodeLock->components, c);
|
||||
c->obj->cacheParentBvhNode.reset();
|
||||
}
|
||||
invalidate_cache_at_aabb(c->obj->get_world_bounds());
|
||||
invalidate_cache_at_optional_aabb(c->obj->get_world_bounds());
|
||||
}
|
||||
|
||||
void DrawingProgramCache::build_bvh_node(const std::shared_ptr<DrawingProgramCacheBVHNode>& bvhNode, const std::vector<CanvasComponentContainer::ObjInfo*>& components) {
|
||||
if(components.empty())
|
||||
return;
|
||||
|
||||
bvhNode->bounds = components.front()->obj->get_world_bounds();
|
||||
bvhNode->bounds = components.front()->obj->get_world_bounds().value();
|
||||
for(auto& c : components)
|
||||
bvhNode->bounds.include_aabb_in_bounds(c->obj->get_world_bounds());
|
||||
bvhNode->bounds.include_aabb_in_bounds(c->obj->get_world_bounds().value());
|
||||
|
||||
build_bvh_node_coords_and_resolution(*bvhNode);
|
||||
|
||||
|
|
@ -181,7 +192,7 @@ void DrawingProgramCache::build_bvh_node(const std::shared_ptr<DrawingProgramCac
|
|||
std::array<std::vector<CanvasComponentContainer::ObjInfo*>, 4> parts;
|
||||
|
||||
for(auto& c : components) {
|
||||
const auto& cAABB = c->obj->get_world_bounds();
|
||||
const auto& cAABB = c->obj->get_world_bounds().value();
|
||||
if(cAABB.min.x() < boundsCenter.x() && cAABB.max.x() < boundsCenter.x() && cAABB.min.y() < boundsCenter.y() && cAABB.max.y() < boundsCenter.y())
|
||||
parts[0].emplace_back(c);
|
||||
else if(cAABB.min.x() > boundsCenter.x() && cAABB.max.x() > boundsCenter.x() && cAABB.min.y() < boundsCenter.y() && cAABB.max.y() < boundsCenter.y())
|
||||
|
|
@ -425,14 +436,14 @@ void DrawingProgramCache::recursive_draw_layer_item_to_canvas(const DrawingProgr
|
|||
std::vector<CanvasComponentContainer::ObjInfo*> compsToDraw;
|
||||
parallel_loop_container(nodesToDraw, [&](auto& node) {
|
||||
std::for_each(node->components.begin(), node->components.end(), [&](auto& c) {
|
||||
if(c->obj->parentLayer == &layerListItem && (!drawBounds.has_value() || SCollision::collide(drawBounds.value(), c->obj->get_world_bounds())) && c->obj->should_draw(drawData))
|
||||
if(c->obj->parentLayer == &layerListItem && (!drawBounds.has_value() || SCollision::collide(drawBounds.value(), c->obj->get_world_bounds().value())) && c->obj->should_draw(drawData))
|
||||
c->obj->preDrawDataHolder = c->obj->calculate_predraw_data(drawData);
|
||||
else
|
||||
c->obj->preDrawDataHolder = std::nullopt;
|
||||
});
|
||||
});
|
||||
parallel_loop_container(unsortedComponents, [&](auto& c) {
|
||||
if(c->obj->parentLayer == &layerListItem && (!drawBounds.has_value() || SCollision::collide(drawBounds.value(), c->obj->get_world_bounds())) && c->obj->should_draw(drawData))
|
||||
if(c->obj->parentLayer == &layerListItem && c->obj->get_world_bounds().has_value() && (!drawBounds.has_value() || SCollision::collide(drawBounds.value(), c->obj->get_world_bounds().value())) && c->obj->should_draw(drawData))
|
||||
c->obj->preDrawDataHolder = c->obj->calculate_predraw_data(drawData);
|
||||
else
|
||||
c->obj->preDrawDataHolder = std::nullopt;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class DrawingProgramCache {
|
|||
void update_and_draw_cached_canvas(SkCanvas* canvas, const DrawData& drawData);
|
||||
void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, const std::optional<SCollision::AABB<WorldScalar>>& drawBounds);
|
||||
void invalidate_cache_at_aabb(const SCollision::AABB<WorldScalar>& aabb);
|
||||
void invalidate_cache_at_optional_aabb(const std::optional<SCollision::AABB<WorldScalar>>& aabb);
|
||||
static void delete_all_draw_cache();
|
||||
|
||||
CanvasComponentContainer::ObjInfo* get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection<float>& cC);
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ std::function<bool(const std::shared_ptr<DrawingProgramCacheBVHNode>&)> DrawingP
|
|||
drawP.drawCache.node_loop_erase_if_components(bvhNode, [&](auto c) {
|
||||
if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector) && c->obj->collides_with(drawP.world.drawData.cam.c, cCWorld, cC)) {
|
||||
selectedComponents.emplace_back(c);
|
||||
drawP.drawCache.invalidate_cache_at_aabb(c->obj->get_world_bounds());
|
||||
drawP.drawCache.invalidate_cache_at_optional_aabb(c->obj->get_world_bounds());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -232,9 +232,9 @@ void DrawingProgramSelection::sort_selection() {
|
|||
|
||||
void DrawingProgramSelection::calculate_aabb() {
|
||||
if(is_something_selected()) {
|
||||
initialSelectionAABB = (*selectedSet.begin())->obj->get_world_bounds();
|
||||
initialSelectionAABB = (*selectedSet.begin())->obj->get_world_bounds().value();
|
||||
for(auto& c : selectedSet)
|
||||
initialSelectionAABB.include_aabb_in_bounds(c->obj->get_world_bounds());
|
||||
initialSelectionAABB.include_aabb_in_bounds(c->obj->get_world_bounds().value());
|
||||
rotateData.centerPos = initialSelectionAABB.center();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
#include "DrawingProgramLayerManager.hpp"
|
||||
#include "../DrawingProgram.hpp"
|
||||
#include "../../World.hpp"
|
||||
#include <Helpers/NetworkingObjects/NetObjOrderedList.hpp>
|
||||
#include <Helpers/Parallel.hpp>
|
||||
#include <Helpers/Logger.hpp>
|
||||
|
||||
void DrawingProgramLayer::draw(SkCanvas* canvas, const DrawData& drawData) const {
|
||||
for(auto& p : *components)
|
||||
|
|
@ -32,7 +34,7 @@ void DrawingProgramLayer::set_component_list_callbacks(DrawingProgramLayerListIt
|
|||
components->set_insert_callback(insertCallback);
|
||||
components->set_erase_callback(eraseCallback);
|
||||
components->set_move_callback([&](const CanvasComponentContainer::ObjInfoIterator& c, uint32_t oldPos) {
|
||||
layerMan.drawP.drawCache.invalidate_cache_at_aabb(c->obj->get_world_bounds());
|
||||
layerMan.drawP.drawCache.invalidate_cache_at_optional_aabb(c->obj->get_world_bounds());
|
||||
if(layerMan.drawP.selection.is_selected(&(*c)))
|
||||
layerMan.drawP.selection.sort_selection(); // If item is selected, selected items will be unordered, so sort everything again
|
||||
});
|
||||
|
|
@ -67,6 +69,18 @@ void DrawingProgramLayer::load_file(cereal::PortableBinaryInputArchive& a, Versi
|
|||
}
|
||||
}
|
||||
|
||||
void DrawingProgramLayer::erase_invalid_components() {
|
||||
std::vector<NetworkingObjects::NetObjOrderedListIterator<CanvasComponentContainer>> compsToErase;
|
||||
for(auto it = components->begin(); it != components->end(); ++it) {
|
||||
if(!it->obj->get_world_bounds().has_value())
|
||||
compsToErase.emplace_back(it);
|
||||
}
|
||||
if(!compsToErase.empty()) {
|
||||
Logger::get().log("INFO", "[DrawingProgramLayer::erase_invalid_components] Erased " + std::to_string(compsToErase.size()) + " invalid component(s) from layer");
|
||||
components->erase_list(components, compsToErase);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawingProgramLayer::save_file(cereal::PortableBinaryOutputArchive& a) const {
|
||||
a(components->size());
|
||||
for(auto& comp : *components)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class DrawingProgramLayer {
|
|||
void save_file(cereal::PortableBinaryOutputArchive& a) const;
|
||||
|
||||
void get_used_resources(std::unordered_set<NetworkingObjects::NetObjID>& resourceSet) const;
|
||||
void erase_invalid_components();
|
||||
private:
|
||||
std::function<void(const CanvasComponentContainer::ObjInfoIterator& c)> eraseCallback;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -75,6 +75,11 @@ void DrawingProgramLayerFolder::save_file(cereal::PortableBinaryOutputArchive& a
|
|||
listItem.obj->save_file(a);
|
||||
}
|
||||
|
||||
void DrawingProgramLayerFolder::erase_invalid_components() {
|
||||
for(auto& listItem : *folderList)
|
||||
listItem.obj->erase_invalid_components();
|
||||
}
|
||||
|
||||
void DrawingProgramLayerFolder::get_used_resources(std::unordered_set<NetworkingObjects::NetObjID>& resourceSet) const {
|
||||
for(auto& listItem : *folderList)
|
||||
listItem.obj->get_used_resources(resourceSet);
|
||||
|
|
|
|||
|
|
@ -23,4 +23,5 @@ class DrawingProgramLayerFolder {
|
|||
void save_file(cereal::PortableBinaryOutputArchive& a) const;
|
||||
|
||||
void get_used_resources(std::unordered_set<NetworkingObjects::NetObjID>& resourceSet) const;
|
||||
void erase_invalid_components();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -271,6 +271,13 @@ DrawingProgramLayerListItemMetaInfo DrawingProgramLayerListItem::get_metainfo()
|
|||
};
|
||||
}
|
||||
|
||||
void DrawingProgramLayerListItem::erase_invalid_components() {
|
||||
if(folderData)
|
||||
folderData->erase_invalid_components();
|
||||
else
|
||||
layerData->erase_invalid_components();
|
||||
}
|
||||
|
||||
void DrawingProgramLayerListItem::register_class(World& w) {
|
||||
w.netObjMan.register_class<DrawingProgramLayerListItem, DrawingProgramLayerListItem, DrawingProgramLayerListItem, DrawingProgramLayerListItem>({
|
||||
.writeConstructorFuncClient = write_constructor_func,
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ class DrawingProgramLayerListItem {
|
|||
DrawingProgramLayerListItemMetaInfo get_metainfo() const;
|
||||
|
||||
uint32_t get_component_count() const;
|
||||
|
||||
void erase_invalid_components();
|
||||
private:
|
||||
static void write_constructor_func(const NetworkingObjects::NetObjTemporaryPtr<DrawingProgramLayerListItem>& o, cereal::PortableBinaryOutputArchive& a);
|
||||
static void read_constructor_func(const NetworkingObjects::NetObjTemporaryPtr<DrawingProgramLayerListItem>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c);
|
||||
|
|
|
|||
|
|
@ -284,6 +284,7 @@ void DrawingProgramLayerManager::load_file(cereal::PortableBinaryInputArchive& a
|
|||
parallel_loop_container(flattenedCompList, [&drawP = drawP](CanvasComponentContainer::ObjInfo* comp) {
|
||||
comp->obj->commit_update_dont_invalidate_cache(drawP);
|
||||
});
|
||||
layerTreeRoot->erase_invalid_components();
|
||||
drawP.rebuild_cache();
|
||||
editingLayer = layerTreeRoot->get_folder().get_initial_editing_layer();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,7 +162,12 @@ void BrushTool::commit_stroke() {
|
|||
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
|
||||
containerPtr->commit_update(drawP);
|
||||
containerPtr->send_comp_update(drawP, true);
|
||||
drawP.layerMan.add_undo_place_component(objInfoBeingEdited);
|
||||
if(containerPtr->get_world_bounds().has_value())
|
||||
drawP.layerMan.add_undo_place_component(objInfoBeingEdited);
|
||||
else {
|
||||
auto& components = containerPtr->parentLayer->get_layer().components;
|
||||
components->erase(components, containerPtr->objInfo);
|
||||
}
|
||||
objInfoBeingEdited = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,12 @@ void EllipseDrawTool::commit() {
|
|||
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
|
||||
containerPtr->commit_update(drawP);
|
||||
containerPtr->send_comp_update(drawP, true);
|
||||
drawP.layerMan.add_undo_place_component(objInfoBeingEdited);
|
||||
if(containerPtr->get_world_bounds().has_value())
|
||||
drawP.layerMan.add_undo_place_component(objInfoBeingEdited);
|
||||
else {
|
||||
auto& components = containerPtr->parentLayer->get_layer().components;
|
||||
components->erase(components, containerPtr->objInfo);
|
||||
}
|
||||
objInfoBeingEdited = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ void EraserTool::erase_between_points(const Vector2f& start, const Vector2f& end
|
|||
drawP.drawCache.node_loop_erase_if_components(bvhNode, [&](auto c) {
|
||||
if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector) && c->obj->collides_with(drawP.world.drawData.cam.c, cCWorld, cC)) {
|
||||
erasedComponents.emplace(c);
|
||||
drawP.drawCache.invalidate_cache_at_aabb(c->obj->get_world_bounds());
|
||||
drawP.drawCache.invalidate_cache_at_optional_aabb(c->obj->get_world_bounds());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -110,7 +110,12 @@ void LineDrawTool::commit() {
|
|||
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
|
||||
containerPtr->commit_update(drawP);
|
||||
containerPtr->send_comp_update(drawP, true);
|
||||
drawP.layerMan.add_undo_place_component(objInfoBeingEdited);
|
||||
if(containerPtr->get_world_bounds().has_value())
|
||||
drawP.layerMan.add_undo_place_component(objInfoBeingEdited);
|
||||
else {
|
||||
auto& components = containerPtr->parentLayer->get_layer().components;
|
||||
components->erase(components, containerPtr->objInfo);
|
||||
}
|
||||
objInfoBeingEdited = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,12 @@ void RectDrawTool::commit() {
|
|||
NetworkingObjects::NetObjOwnerPtr<CanvasComponentContainer>& containerPtr = objInfoBeingEdited->obj;
|
||||
containerPtr->commit_update(drawP);
|
||||
containerPtr->send_comp_update(drawP, true);
|
||||
drawP.layerMan.add_undo_place_component(objInfoBeingEdited);
|
||||
if(containerPtr->get_world_bounds().has_value())
|
||||
drawP.layerMan.add_undo_place_component(objInfoBeingEdited);
|
||||
else {
|
||||
auto& components = containerPtr->parentLayer->get_layer().components;
|
||||
components->erase(components, containerPtr->objInfo);
|
||||
}
|
||||
objInfoBeingEdited = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue