Optimized eraser, now uses BVH
This commit is contained in:
parent
7fa82d3fa4
commit
0a8add3df1
7 changed files with 212 additions and 48 deletions
|
|
@ -23,6 +23,8 @@ template <typename T, typename IDType> class CollabList {
|
|||
std::function<void()> updateCallback;
|
||||
std::function<void(const ObjectInfoPtr& c)> clientInsertCallback;
|
||||
std::function<void(const ObjectInfoPtr& c)> clientEraseCallback;
|
||||
std::function<void(const std::unordered_set<ObjectInfoPtr>& c)> clientEraseSetCallback;
|
||||
std::function<void(const std::vector<ObjectInfoPtr>& c)> clientInsertOrderedVectorCallback;
|
||||
std::function<void(uint64_t oldPos)> clientServerLastPosShiftCallback;
|
||||
|
||||
void set_server_from_client_list() {
|
||||
|
|
@ -60,6 +62,7 @@ template <typename T, typename IDType> class CollabList {
|
|||
if(func((uint64_t)i, clientSideList[i])) {
|
||||
if(clientEraseCallback)
|
||||
clientEraseCallback(clientSideList[i]);
|
||||
clientSideList[i]->obj->collabListInfo.reset();
|
||||
clientSideList.erase(clientSideList.begin() + i);
|
||||
i--;
|
||||
if(updateCallback)
|
||||
|
|
@ -98,15 +101,69 @@ template <typename T, typename IDType> class CollabList {
|
|||
clientEraseCallback(obj);
|
||||
erasedID = obj->id;
|
||||
obj->syncIgnore = true;
|
||||
if(updateCallback)
|
||||
updateCallback();
|
||||
obj->obj->collabListInfo.reset();
|
||||
erasedSomething = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if(erasedSomething)
|
||||
if(erasedSomething) {
|
||||
if(updateCallback)
|
||||
updateCallback();
|
||||
complete_client_pos_refresh(false);
|
||||
}
|
||||
}
|
||||
|
||||
void client_erase_set(const std::unordered_set<ObjectInfoPtr>& objSet) {
|
||||
bool erasedSomething = false;
|
||||
std::erase_if(clientSideList, [&](const auto& obj) {
|
||||
if(objSet.contains(obj)) {
|
||||
obj->syncIgnore = true;
|
||||
obj->obj->collabListInfo.reset();
|
||||
erasedSomething = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if(erasedSomething) {
|
||||
complete_client_pos_refresh(false);
|
||||
if(updateCallback)
|
||||
updateCallback();
|
||||
if(clientEraseSetCallback)
|
||||
clientEraseSetCallback(objSet);
|
||||
for(auto& o : objSet)
|
||||
o->obj->collabListInfo.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Dont use this function unless you're certain every object in the vector isn't already in the client list
|
||||
void client_insert_ordered_vector(const std::vector<ObjectInfoPtr>& objOrderedVector) {
|
||||
if(objOrderedVector.empty())
|
||||
return;
|
||||
|
||||
uint64_t startPoint = 0;
|
||||
objOrderedVector.front()->syncIgnore = true;
|
||||
objOrderedVector.front()->id = getNewIDFunc();
|
||||
objOrderedVector.front()->obj->collabListInfo = objOrderedVector.front();
|
||||
|
||||
for(uint64_t i = 1; i < static_cast<uint64_t>(objOrderedVector.size()); i++) {
|
||||
auto& obj = objOrderedVector[i];
|
||||
obj->syncIgnore = true;
|
||||
obj->id = getNewIDFunc();
|
||||
obj->obj->collabListInfo = obj;
|
||||
if(obj->pos - objOrderedVector[startPoint]->pos != (i - startPoint)) {
|
||||
uint64_t insertPosition = std::max(clientSideList.size(), objOrderedVector[startPoint]->pos);
|
||||
clientSideList.insert(clientSideList.begin() + insertPosition, objOrderedVector.begin() + startPoint, objOrderedVector.begin() + i);
|
||||
startPoint = i;
|
||||
}
|
||||
}
|
||||
clientSideList.insert(clientSideList.begin() + objOrderedVector[startPoint]->pos, objOrderedVector.begin() + startPoint, objOrderedVector.end());
|
||||
|
||||
complete_client_pos_refresh(false);
|
||||
if(updateCallback)
|
||||
updateCallback();
|
||||
if(clientInsertOrderedVectorCallback)
|
||||
clientInsertOrderedVectorCallback(objOrderedVector);
|
||||
}
|
||||
|
||||
bool server_insert(uint64_t pos, IDType id, const T& item) {
|
||||
|
|
@ -152,6 +209,7 @@ template <typename T, typename IDType> class CollabList {
|
|||
obj->syncIgnore = false;
|
||||
if(clientEraseCallback)
|
||||
clientEraseCallback(obj);
|
||||
obj->obj->collabListInfo.reset();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,16 @@ DrawingProgram::DrawingProgram(World& initWorld):
|
|||
delayedUpdateTransformComponents.erase(c->obj);
|
||||
updateableComponents.erase(c->obj);
|
||||
};
|
||||
components.clientEraseSetCallback = [&](const std::unordered_set<CollabListType::ObjectInfoPtr>& comps) {
|
||||
for(auto& c : comps) {
|
||||
delayedUpdateTransformComponents.erase(c->obj);
|
||||
updateableComponents.erase(c->obj);
|
||||
}
|
||||
};
|
||||
components.clientInsertOrderedVectorCallback = [&](const std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
for(auto& c : comps)
|
||||
components.clientInsertCallback(c);
|
||||
};
|
||||
components.clientServerLastPosShiftCallback = [&](uint64_t lastShiftPos) {
|
||||
compCache.invalidate_cache_before_pos(lastShiftPos);
|
||||
};
|
||||
|
|
@ -445,6 +455,7 @@ void DrawingProgram::reset_tools() {
|
|||
rectDrawTool.reset_tool();
|
||||
ellipseDrawTool.reset_tool();
|
||||
editTool.reset_tool();
|
||||
eraserTool.reset_tool();
|
||||
reset_selection();
|
||||
}
|
||||
|
||||
|
|
@ -611,7 +622,7 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) {
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t DrawingProgram::draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, bool dontUseCache) {
|
||||
void DrawingProgram::draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, bool dontUseCache, uint64_t* lastDrawnComponentPlacement) {
|
||||
uint64_t lastComponentDrawn = 0;
|
||||
|
||||
std::vector<std::shared_ptr<DrawingProgramCache::BVHNode>> cachedNodesToDraw;
|
||||
|
|
@ -681,7 +692,8 @@ uint64_t DrawingProgram::draw_components_to_canvas(SkCanvas* canvas, const DrawD
|
|||
canvas->restore();
|
||||
}
|
||||
|
||||
return lastComponentDrawn;
|
||||
if(lastDrawnComponentPlacement)
|
||||
*lastDrawnComponentPlacement = lastComponentDrawn;
|
||||
}
|
||||
|
||||
Vector4f* DrawingProgram::get_foreground_color_ptr() {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ class DrawingProgram {
|
|||
void add_undo_place_component(uint64_t placement, const std::shared_ptr<DrawComponent>& comp);
|
||||
void add_undo_place_components(uint64_t placement, const std::vector<std::shared_ptr<DrawComponent>>& comps);
|
||||
|
||||
uint64_t draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, bool dontUseCache);
|
||||
void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, bool dontUseCache, uint64_t* lastDrawnComponentPlacement = nullptr);
|
||||
|
||||
BrushTool brushTool;
|
||||
EraserTool eraserTool;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#include <include/gpu/ganesh/SkSurfaceGanesh.h>
|
||||
#endif
|
||||
|
||||
#define MAXIMUM_DRAW_CACHE_SURFACES 64
|
||||
#define MAXIMUM_DRAW_CACHE_SURFACES 40
|
||||
|
||||
std::unordered_set<std::shared_ptr<DrawingProgramCache::BVHNode>> DrawingProgramCache::nodesWithCachedSurfaces;
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ void DrawingProgramCache::clear_own_cached_surfaces() {
|
|||
}
|
||||
|
||||
void DrawingProgramCache::update() {
|
||||
if(unsortedComponents.size() >= 1000 && (std::chrono::steady_clock::now() - lastBvhBuildTime) >= std::chrono::seconds(5))
|
||||
if(!disableRefresh && unsortedComponents.size() >= 1000 && (std::chrono::steady_clock::now() - lastBvhBuildTime) >= std::chrono::seconds(5))
|
||||
force_rebuild();
|
||||
}
|
||||
|
||||
|
|
@ -54,7 +54,10 @@ void DrawingProgramCache::force_rebuild() {
|
|||
|
||||
void DrawingProgramCache::add_component(const CollabListType::ObjectInfoPtr& c) {
|
||||
unsortedComponents.emplace_back(c);
|
||||
invalidate_cache_before_pos(c->pos);
|
||||
if(c->obj->worldAABB)
|
||||
invalidate_cache_at_aabb_before_pos(c->obj->worldAABB.value(), c->pos);
|
||||
else
|
||||
invalidate_cache_before_pos(c->pos);
|
||||
}
|
||||
|
||||
void DrawingProgramCache::erase_component(const CollabListType::ObjectInfoPtr& c) {
|
||||
|
|
@ -85,6 +88,23 @@ std::pair<std::shared_ptr<DrawingProgramCache::BVHNode>, std::vector<DrawingProg
|
|||
return {nullptr, bvhNode->components.end()};
|
||||
}
|
||||
|
||||
void DrawingProgramCache::traverse_bvh_erase_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(const std::shared_ptr<BVHNode>& node, std::vector<CollabListType::ObjectInfoPtr>& components)> f) {
|
||||
f(nullptr, unsortedComponents);
|
||||
if(traverse_bvh_erase_function_recursive(bvhRoot, aabb, f))
|
||||
bvhRoot = nullptr;
|
||||
}
|
||||
|
||||
bool DrawingProgramCache::traverse_bvh_erase_function_recursive(const std::shared_ptr<BVHNode>& bvhNode, const SCollision::AABB<WorldScalar>& aabb, std::function<bool(const std::shared_ptr<BVHNode>& node, std::vector<CollabListType::ObjectInfoPtr>& components)> f) {
|
||||
if(bvhNode && SCollision::collide(aabb, bvhNode->bounds)) {
|
||||
if(f(bvhNode, bvhNode->components))
|
||||
return true;
|
||||
std::erase_if(bvhNode->children, [&](auto& p) {
|
||||
return traverse_bvh_erase_function_recursive(p, aabb, f);
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DrawingProgramCache::traverse_bvh_collision_check(const SCollision::ColliderCollection<WorldScalar>& checkAgainstWorld, const SCollision::ColliderCollection<float>& checkAgainstCam) {
|
||||
for(auto& c : drawP.components.client_list())
|
||||
c->obj->globalCollisionCheck = false;
|
||||
|
|
@ -120,7 +140,7 @@ void DrawingProgramCache::traverse_bvh_collision_check_recursive(const std::shar
|
|||
}
|
||||
}
|
||||
|
||||
void DrawingProgramCache::traverse_bvh_run_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(const std::shared_ptr<BVHNode> node, const std::vector<CollabListType::ObjectInfoPtr>& components)> f) {
|
||||
void DrawingProgramCache::traverse_bvh_run_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(const std::shared_ptr<BVHNode>& node, const std::vector<CollabListType::ObjectInfoPtr>& components)> f) {
|
||||
f(nullptr, unsortedComponents);
|
||||
traverse_bvh_run_function_recursive(bvhRoot, aabb, f);
|
||||
}
|
||||
|
|
@ -225,6 +245,16 @@ void DrawingProgramCache::invalidate_cache_before_pos(uint64_t placementToInvali
|
|||
});
|
||||
}
|
||||
|
||||
void DrawingProgramCache::invalidate_cache_at_aabb_before_pos(const SCollision::AABB<WorldScalar>& aabb, uint64_t placementToInvalidateAt) {
|
||||
std::erase_if(nodesWithCachedSurfaces, [&](auto& n) {
|
||||
if(placementToInvalidateAt <= n->drawCache.value().lastDrawnComponentPlacement && SCollision::collide(aabb, n->bounds)) {
|
||||
n->drawCache = std::nullopt;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void DrawingProgramCache::refresh_all_draw_cache(SkCanvas* canvas, const DrawData& drawData) {
|
||||
std::deque<std::shared_ptr<BVHNode>> nodeFlatList; // We want to render children before parents, so that parents can make use of the cached children
|
||||
traverse_bvh_run_function(drawData.cam.viewingAreaGenerousCollider, [&](std::shared_ptr<DrawingProgramCache::BVHNode> node, const std::vector<CollabListType::ObjectInfoPtr>& comps) {
|
||||
|
|
@ -266,7 +296,7 @@ void DrawingProgramCache::refresh_draw_cache(const std::shared_ptr<BVHNode>& bvh
|
|||
cacheDrawData.cam.set_viewing_area(bvhNode->resolution.cast<float>());
|
||||
cacheDrawData.refresh_draw_optimizing_values();
|
||||
|
||||
drawCache.lastDrawnComponentPlacement = drawP.draw_components_to_canvas(cacheCanvas, cacheDrawData, false);
|
||||
drawP.draw_components_to_canvas(cacheCanvas, cacheDrawData, false, &drawCache.lastDrawnComponentPlacement);
|
||||
drawCache.lastRenderTime = std::chrono::steady_clock::now();
|
||||
drawCache.attachedDrawP = &drawP;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ class DrawingProgramCache {
|
|||
Vector2i resolution;
|
||||
struct DrawCacheData {
|
||||
uint64_t lastDrawnComponentPlacement;
|
||||
uint64_t firstDrawnComponentPlacement;
|
||||
sk_sp<SkSurface> surface;
|
||||
std::chrono::steady_clock::time_point lastRenderTime;
|
||||
DrawingProgram* attachedDrawP;
|
||||
|
|
@ -38,16 +39,24 @@ class DrawingProgramCache {
|
|||
|
||||
static std::unordered_set<std::shared_ptr<BVHNode>> nodesWithCachedSurfaces;
|
||||
|
||||
bool disableRefresh = false;
|
||||
|
||||
void traverse_bvh_run_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(const std::shared_ptr<BVHNode>& node, const std::vector<CollabListType::ObjectInfoPtr>& components)> f);
|
||||
void traverse_bvh_collision_check(const SCollision::ColliderCollection<WorldScalar>& checkAgainstWorld, const SCollision::ColliderCollection<float>& checkAgainstCam);
|
||||
void traverse_bvh_run_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(const std::shared_ptr<BVHNode> node, const std::vector<CollabListType::ObjectInfoPtr>& components)> f);
|
||||
|
||||
void traverse_bvh_erase_function(const SCollision::AABB<WorldScalar>& aabb, std::function<bool(const std::shared_ptr<BVHNode>& node, std::vector<CollabListType::ObjectInfoPtr>& components)> f);
|
||||
|
||||
void force_rebuild();
|
||||
|
||||
// Run before actually updating the component
|
||||
void preupdate_component(const CollabListType::ObjectInfoPtr& c);
|
||||
|
||||
void invalidate_cache_before_pos(uint64_t placementToInvalidateAt);
|
||||
void invalidate_cache_at_aabb_before_pos(const SCollision::AABB<WorldScalar>& aabb, uint64_t placementToInvalidateAt);
|
||||
private:
|
||||
void clear_own_cached_surfaces();
|
||||
bool traverse_bvh_erase_function_recursive(const std::shared_ptr<BVHNode>& bvhNode, const SCollision::AABB<WorldScalar>& aabb, std::function<bool(const std::shared_ptr<BVHNode>& node, std::vector<CollabListType::ObjectInfoPtr>& components)> f);
|
||||
|
||||
void traverse_bvh_collision_check_recursive(const std::shared_ptr<BVHNode>& bvhNode, const SCollision::ColliderCollection<WorldScalar>& checkAgainstWorld, const SCollision::ColliderCollection<float>& checkAgainstCam);
|
||||
void traverse_bvh_collision_check_recursive_tiny(const std::shared_ptr<BVHNode>& bvhNode);
|
||||
|
||||
|
|
@ -62,7 +71,11 @@ class DrawingProgramCache {
|
|||
std::pair<std::shared_ptr<DrawingProgramCache::BVHNode>, std::vector<DrawingProgramCache::CollabListType::ObjectInfoPtr>::iterator> get_bvh_node_fully_containing_recursive(const std::shared_ptr<BVHNode>& bvhNode, DrawComponent* c);
|
||||
|
||||
void build_bvh_node(const std::shared_ptr<BVHNode>& bvhNode, std::vector<CollabListType::ObjectInfoPtr> components);
|
||||
|
||||
std::shared_ptr<BVHNode> bvhRoot;
|
||||
std::vector<CollabListType::ObjectInfoPtr> unsortedComponents;
|
||||
|
||||
std::unordered_set<CollabListType::ObjectInfoPtr> componentsSetToErase;
|
||||
|
||||
DrawingProgram& drawP;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,58 @@ void EraserTool::gui_toolbox() {
|
|||
t.gui.pop_id();
|
||||
}
|
||||
|
||||
void EraserTool::reset_tool() {
|
||||
if(!erasedComponents.empty()) {
|
||||
for(auto& bvhNode : erasedBVHNodes)
|
||||
move_erased_components_from_bvh_nodes_recursive(bvhNode);
|
||||
|
||||
for(auto& c : erasedComponents)
|
||||
c->obj->client_send_erase(drawP);
|
||||
drawP.components.client_erase_set(erasedComponents);
|
||||
|
||||
drawP.world.undo.push(UndoManager::UndoRedoPair{
|
||||
[&, erasedCompVal = erasedComponents]() {
|
||||
std::vector<DrawingProgram::CollabListType::ObjectInfoPtr> sortedObjects(erasedCompVal.begin(), erasedCompVal.end());
|
||||
std::sort(sortedObjects.begin(), sortedObjects.end(), [](auto& a, auto& b) {
|
||||
return a->pos < b->pos;
|
||||
});
|
||||
|
||||
for(auto& comp : sortedObjects)
|
||||
if(comp->obj->collabListInfo.lock())
|
||||
return false;
|
||||
|
||||
drawP.components.client_insert_ordered_vector(sortedObjects);
|
||||
|
||||
for(auto& comp : sortedObjects)
|
||||
comp->obj->client_send_place(drawP);
|
||||
|
||||
drawP.reset_tools();
|
||||
|
||||
return true;
|
||||
},
|
||||
[&, erasedCompVal = erasedComponents]() {
|
||||
for(auto& comp : erasedCompVal)
|
||||
if(!comp->obj->collabListInfo.lock())
|
||||
return false;
|
||||
|
||||
for(auto& comp : erasedCompVal)
|
||||
comp->obj->client_send_erase(drawP);
|
||||
|
||||
drawP.components.client_erase_set(erasedCompVal);
|
||||
|
||||
drawP.reset_tools();
|
||||
|
||||
drawP.compCache.force_rebuild();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
erasedComponents.clear();
|
||||
erasedBVHNodes.clear();
|
||||
drawP.compCache.disableRefresh = false;
|
||||
}
|
||||
|
||||
void EraserTool::tool_update() {
|
||||
if(drawP.controls.cursorHoveringOverCanvas)
|
||||
drawP.world.main.input.hideCursor = true;
|
||||
|
|
@ -28,47 +80,43 @@ void EraserTool::tool_update() {
|
|||
const Vector2f& prevMousePos = drawP.controls.leftClick ? drawP.world.main.input.mouse.pos : drawP.world.main.input.mouse.lastPos;
|
||||
SCollision::ColliderCollection<float> cC;
|
||||
SCollision::generate_wide_line(cC, prevMousePos, drawP.world.main.input.mouse.pos, drawP.controls.relativeWidth * 2.0f, true);
|
||||
drawP.check_all_collisions_transform(cC);
|
||||
drawP.components.client_erase_if([&](uint64_t oldPlacement, const auto& c) {
|
||||
if(c->obj->globalCollisionCheck) {
|
||||
erasedComponents.emplace_back(oldPlacement, c->obj);
|
||||
c->obj->client_send_erase(drawP);
|
||||
auto cCWorld = drawP.world.drawData.cam.c.collider_to_world<SCollision::ColliderCollection<WorldScalar>, SCollision::ColliderCollection<float>>(cC);
|
||||
|
||||
drawP.compCache.disableRefresh = true;
|
||||
|
||||
drawP.compCache.traverse_bvh_erase_function(cCWorld.bounds, [&](const auto& bvhNode, auto& comps) {
|
||||
if(bvhNode &&
|
||||
SCollision::collide(cC, drawP.world.drawData.cam.c.to_space(bvhNode->bounds.min)) &&
|
||||
SCollision::collide(cC, drawP.world.drawData.cam.c.to_space(bvhNode->bounds.max)) &&
|
||||
SCollision::collide(cC, drawP.world.drawData.cam.c.to_space(bvhNode->bounds.top_right())) &&
|
||||
SCollision::collide(cC, drawP.world.drawData.cam.c.to_space(bvhNode->bounds.bottom_left()))) {
|
||||
erasedBVHNodes.emplace(bvhNode);
|
||||
drawP.compCache.invalidate_cache_at_aabb_before_pos(bvhNode->bounds, 0);
|
||||
return true;
|
||||
}
|
||||
std::erase_if(comps, [&](auto& c) {
|
||||
if(c->obj->collides_with(drawP.world.drawData.cam.c, cCWorld, cC, drawP.colliderAllocated)) {
|
||||
erasedComponents.emplace(c);
|
||||
if(c->obj->worldAABB)
|
||||
drawP.compCache.invalidate_cache_at_aabb_before_pos(c->obj->worldAABB.value(), c->obj->collabListInfo.lock()->pos);
|
||||
else
|
||||
drawP.compCache.invalidate_cache_before_pos(c->obj->collabListInfo.lock()->pos);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
else if(!erasedComponents.empty()) {
|
||||
auto erasedCompVal = erasedComponents;
|
||||
drawP.world.undo.push(UndoManager::UndoRedoPair{
|
||||
[&, erasedCompVal]() {
|
||||
for(auto& comp : erasedCompVal)
|
||||
if(drawP.components.get_id(comp.second) != ServerClientID{0, 0})
|
||||
return false;
|
||||
else
|
||||
reset_tool();
|
||||
}
|
||||
|
||||
for(auto& comp : erasedCompVal | std::views::reverse) {
|
||||
drawP.components.client_insert(comp.first, comp.second);
|
||||
comp.second->client_send_place(drawP);
|
||||
}
|
||||
drawP.reset_tools();
|
||||
return true;
|
||||
},
|
||||
[&, erasedCompVal]() {
|
||||
for(auto& comp : erasedCompVal)
|
||||
if(drawP.components.get_id(comp.second) == ServerClientID{0, 0})
|
||||
return false;
|
||||
|
||||
for(auto& comp : erasedCompVal) {
|
||||
ServerClientID compID;
|
||||
comp.second->client_send_erase(drawP);
|
||||
drawP.components.client_erase(comp.second, compID);
|
||||
}
|
||||
drawP.reset_tools();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
erasedComponents.clear();
|
||||
}
|
||||
void EraserTool::move_erased_components_from_bvh_nodes_recursive(const std::shared_ptr<DrawingProgramCache::BVHNode>& bvhNode) {
|
||||
for(auto& c : bvhNode->components)
|
||||
erasedComponents.emplace(c);
|
||||
for(auto& p : bvhNode->children)
|
||||
move_erased_components_from_bvh_nodes_recursive(p);
|
||||
}
|
||||
|
||||
void EraserTool::draw(SkCanvas* canvas, const DrawData& drawData) {
|
||||
|
|
|
|||
|
|
@ -10,10 +10,13 @@ class EraserTool {
|
|||
EraserTool(DrawingProgram& initDrawP);
|
||||
void gui_toolbox();
|
||||
void tool_update();
|
||||
void reset_tool();
|
||||
void draw(SkCanvas* canvas, const DrawData& drawData);
|
||||
private:
|
||||
std::unordered_set<CollabList<std::shared_ptr<DrawComponent>, ServerClientID>::ObjectInfoPtr> erasedComponents;
|
||||
std::unordered_set<std::shared_ptr<DrawingProgramCache::BVHNode>> erasedBVHNodes;
|
||||
|
||||
std::vector<std::pair<uint64_t, std::shared_ptr<DrawComponent>>> erasedComponents; // <placement order, object>
|
||||
void move_erased_components_from_bvh_nodes_recursive(const std::shared_ptr<DrawingProgramCache::BVHNode>& bvhNode);
|
||||
|
||||
DrawingProgram& drawP;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue