Parallelize eraser
This commit is contained in:
parent
4363fe9f9d
commit
4c4c767eef
5 changed files with 36 additions and 13 deletions
|
|
@ -33,3 +33,14 @@ template <typename ContainerType> void parallel_loop_container(const ContainerTy
|
||||||
std::for_each(std::execution::par_unseq, c.begin(), c.end(), func);
|
std::for_each(std::execution::par_unseq, c.begin(), c.end(), func);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ContainerType> void parallel_loop_container_mutable(ContainerType& c, std::function<void(typename ContainerType::value_type&)> func, bool forceSingleThread = false) {
|
||||||
|
#if defined(__EMSCRIPTEN__) || defined(__ANDROID__)
|
||||||
|
std::for_each(c.begin(), c.end(), func);
|
||||||
|
#else
|
||||||
|
if(forceSingleThread)
|
||||||
|
std::for_each(c.begin(), c.end(), func);
|
||||||
|
else
|
||||||
|
std::for_each(std::execution::par_unseq, c.begin(), c.end(), func);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,8 +150,8 @@ void CanvasComponentContainer::commit_transform_dont_invalidate_cache() {
|
||||||
|
|
||||||
// camCoordsScaleToCheckAgainst is different from camCoords.inverseScale if we locked the eraser's scale.
|
// camCoordsScaleToCheckAgainst is different from camCoords.inverseScale if we locked the eraser's scale.
|
||||||
CanvasComponentEraseDetailResult CanvasComponentContainer::collides_with_erase_detail(const CoordSpaceHelper& camCoords, const WorldScalar& camCoordsScaleToCheckAgainst, const SkPath& checkAgainstCam) const {
|
CanvasComponentEraseDetailResult CanvasComponentContainer::collides_with_erase_detail(const CoordSpaceHelper& camCoords, const WorldScalar& camCoordsScaleToCheckAgainst, const SkPath& checkAgainstCam) const {
|
||||||
constexpr static int COMP_MAX_SHIFT_BEFORE_STOP_ERASE = 3;
|
constexpr static int COMP_MAX_SHIFT_BEFORE_STOP_ERASE = 1;
|
||||||
constexpr static int COMP_COMPLETE_ERASE_SHIFT = 13;
|
constexpr static int COMP_COMPLETE_ERASE_SHIFT = 14;
|
||||||
if(!worldAABB.has_value())
|
if(!worldAABB.has_value())
|
||||||
return CanvasComponentEraseDetailResult::NO_CHANGE;
|
return CanvasComponentEraseDetailResult::NO_CHANGE;
|
||||||
if((camCoordsScaleToCheckAgainst << COMP_MAX_SHIFT_BEFORE_STOP_ERASE) < coords.inverseScale) // Object is too large, just dismiss the collision
|
if((camCoordsScaleToCheckAgainst << COMP_MAX_SHIFT_BEFORE_STOP_ERASE) < coords.inverseScale) // Object is too large, just dismiss the collision
|
||||||
|
|
|
||||||
|
|
@ -292,7 +292,7 @@ std::vector<CanvasComponentContainer*> MeshCanvasComponent::attempt_split(Drawin
|
||||||
if(clippingSubjects.size() <= 1)
|
if(clippingSubjects.size() <= 1)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
ClipperD clipper;
|
ClipperD clipper(4);
|
||||||
PolyTreeD solutionTree;
|
PolyTreeD solutionTree;
|
||||||
|
|
||||||
clipper.AddSubject(clippingSubjects);
|
clipper.AddSubject(clippingSubjects);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "../../GUIStuff/ElementHelpers/RadioButtonHelpers.hpp"
|
#include "../../GUIStuff/ElementHelpers/RadioButtonHelpers.hpp"
|
||||||
#include "../../GUIStuff/ElementHelpers/CheckBoxHelpers.hpp"
|
#include "../../GUIStuff/ElementHelpers/CheckBoxHelpers.hpp"
|
||||||
#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp"
|
#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp"
|
||||||
|
#include "Helpers/Parallel.hpp"
|
||||||
|
|
||||||
EraserTool::EraserTool(DrawingProgram& initDrawP):
|
EraserTool::EraserTool(DrawingProgram& initDrawP):
|
||||||
DrawingProgramToolBase(initDrawP)
|
DrawingProgramToolBase(initDrawP)
|
||||||
|
|
@ -139,7 +140,7 @@ void EraserTool::erase_on_path() {
|
||||||
if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector)) {
|
if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector)) {
|
||||||
auto it = updatedComponents.find(c);
|
auto it = updatedComponents.find(c);
|
||||||
if(it != updatedComponents.end()) {
|
if(it != updatedComponents.end()) {
|
||||||
c->obj->get_comp().set_data_from(*it->second->obj);
|
c->obj->get_comp().set_data_from(*it->second.copyData->obj);
|
||||||
updatedComponents.erase(it);
|
updatedComponents.erase(it);
|
||||||
}
|
}
|
||||||
erasedComponents.emplace(c);
|
erasedComponents.emplace(c);
|
||||||
|
|
@ -173,7 +174,7 @@ void EraserTool::erase_on_path() {
|
||||||
case CanvasComponentEraseDetailResult::REMOVED:
|
case CanvasComponentEraseDetailResult::REMOVED:
|
||||||
auto it = updatedComponents.find(c);
|
auto it = updatedComponents.find(c);
|
||||||
if(it != updatedComponents.end()) {
|
if(it != updatedComponents.end()) {
|
||||||
c->obj->get_comp().set_data_from(*it->second->obj);
|
c->obj->get_comp().set_data_from(*it->second.copyData->obj);
|
||||||
updatedComponents.erase(it);
|
updatedComponents.erase(it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -215,15 +216,19 @@ void EraserTool::erase_component(CanvasComponentContainer::ObjInfo* erasedComp)
|
||||||
void EraserTool::commit_erase() {
|
void EraserTool::commit_erase() {
|
||||||
bool placedNewObject = false;
|
bool placedNewObject = false;
|
||||||
std::unordered_map<DrawingProgramLayerListItem*, std::vector<std::pair<CanvasComponentContainer::ObjInfoIterator, CanvasComponentContainer*>>> newObjectsToPlace;
|
std::unordered_map<DrawingProgramLayerListItem*, std::vector<std::pair<CanvasComponentContainer::ObjInfoIterator, CanvasComponentContainer*>>> newObjectsToPlace;
|
||||||
|
|
||||||
|
parallel_loop_container_mutable(updatedComponents, [&](auto& compPair) {
|
||||||
|
compPair.second.splitComps = compPair.first->obj->get_comp().attempt_split(drawP);
|
||||||
|
});
|
||||||
|
|
||||||
std::erase_if(updatedComponents, [&] (auto& p) {
|
std::erase_if(updatedComponents, [&] (auto& p) {
|
||||||
auto& [comp, oldData] = p;
|
auto& [comp, oldData] = p;
|
||||||
std::vector<CanvasComponentContainer*> splitComps = comp->obj->get_comp().attempt_split(drawP);
|
if(!oldData.splitComps.empty()) {
|
||||||
if(!splitComps.empty()) {
|
for(CanvasComponentContainer* c : oldData.splitComps)
|
||||||
for(CanvasComponentContainer* c : splitComps)
|
|
||||||
newObjectsToPlace[comp->obj->parentLayer].emplace_back(std::next(comp->obj->objInfo), c);
|
newObjectsToPlace[comp->obj->parentLayer].emplace_back(std::next(comp->obj->objInfo), c);
|
||||||
placedNewObject = true;
|
placedNewObject = true;
|
||||||
erasedComponents.emplace(comp);
|
erasedComponents.emplace(comp);
|
||||||
comp->obj->get_comp().set_data_from(*oldData->obj);
|
comp->obj->get_comp().set_data_from(*oldData.copyData->obj);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -240,18 +245,21 @@ void EraserTool::commit_erase() {
|
||||||
if(objectsToErase)
|
if(objectsToErase)
|
||||||
drawP.layerMan.erase_component_container(erasedComponents, !placedNewObject);
|
drawP.layerMan.erase_component_container(erasedComponents, !placedNewObject);
|
||||||
bool first = !objectsToErase && !placedNewObject;
|
bool first = !objectsToErase && !placedNewObject;
|
||||||
for(auto& [comp, oldData] : updatedComponents) {
|
parallel_loop_container(updatedComponents, [&](auto& compPair) {
|
||||||
|
auto& [comp, oldData] = compPair;
|
||||||
comp->obj->get_comp().simplify_paths();
|
comp->obj->get_comp().simplify_paths();
|
||||||
comp->obj->normalize_object_coordinates();
|
comp->obj->normalize_object_coordinates();
|
||||||
|
});
|
||||||
|
for(auto& [comp, oldData] : updatedComponents) {
|
||||||
comp->obj->commit_update_dont_invalidate_cache(drawP);
|
comp->obj->commit_update_dont_invalidate_cache(drawP);
|
||||||
drawP.send_transforms_for({comp});
|
drawP.send_transforms_for({comp});
|
||||||
comp->obj->send_comp_update(drawP, true);
|
comp->obj->send_comp_update(drawP, true);
|
||||||
if(first) {
|
if(first) {
|
||||||
first = false;
|
first = false;
|
||||||
drawP.world.undo.push(std::make_unique<EditTransformCanvasComponentWorldUndoAction>(std::move(oldData->obj), oldData->coords, drawP.world.undo.get_undoid_from_netid(comp->obj.get_net_id())));
|
drawP.world.undo.push(std::make_unique<EditTransformCanvasComponentWorldUndoAction>(std::move(oldData.copyData->obj), oldData.copyData->coords, drawP.world.undo.get_undoid_from_netid(comp->obj.get_net_id())));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
drawP.world.undo.push_on_last(std::make_unique<EditTransformCanvasComponentWorldUndoAction>(std::move(oldData->obj), oldData->coords, drawP.world.undo.get_undoid_from_netid(comp->obj.get_net_id())));
|
drawP.world.undo.push_on_last(std::make_unique<EditTransformCanvasComponentWorldUndoAction>(std::move(oldData.copyData->obj), oldData.copyData->coords, drawP.world.undo.get_undoid_from_netid(comp->obj.get_net_id())));
|
||||||
}
|
}
|
||||||
}, NetworkingObjects::NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
|
}, NetworkingObjects::NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr);
|
||||||
erasedComponents.clear();
|
erasedComponents.clear();
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,11 @@ class EraserTool : public DrawingProgramToolBase {
|
||||||
virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override;
|
virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override;
|
||||||
virtual void input_pen_axis_callback(const InputManager::PenAxisCallbackArgs& axis) override;
|
virtual void input_pen_axis_callback(const InputManager::PenAxisCallbackArgs& axis) override;
|
||||||
|
|
||||||
std::unordered_map<CanvasComponentContainer::ObjInfo*, std::unique_ptr<CanvasComponentContainer::CopyData>> updatedComponents;
|
struct UpdatedComponentData {
|
||||||
|
std::unique_ptr<CanvasComponentContainer::CopyData> copyData;
|
||||||
|
std::vector<CanvasComponentContainer*> splitComps;
|
||||||
|
};
|
||||||
|
std::unordered_map<CanvasComponentContainer::ObjInfo*, UpdatedComponentData> updatedComponents;
|
||||||
std::unordered_set<CanvasComponentContainer::ObjInfo*> erasedComponents; // Pointers will be erased from this set if theyre erased in the main list (done by callback)
|
std::unordered_set<CanvasComponentContainer::ObjInfo*> erasedComponents; // Pointers will be erased from this set if theyre erased in the main list (done by callback)
|
||||||
private:
|
private:
|
||||||
SkPath erasePath;
|
SkPath erasePath;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue