From 20a7e0bc3798e58581ba08ec690ff9459cb21f6d Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Tue, 26 May 2026 11:59:55 +0300 Subject: [PATCH] Fixed eraser tool coordinate space --- .../CanvasComponentContainer.cpp | 12 +++++------ .../CanvasComponentContainer.hpp | 4 ++-- src/CanvasComponents/ImageCanvasComponent.cpp | 2 +- src/DrawingProgram/Tools/EraserTool.cpp | 21 ++++++++++++------- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/CanvasComponents/CanvasComponentContainer.cpp b/src/CanvasComponents/CanvasComponentContainer.cpp index 9873c0a..cc6fe8f 100644 --- a/src/CanvasComponents/CanvasComponentContainer.cpp +++ b/src/CanvasComponents/CanvasComponentContainer.cpp @@ -153,7 +153,7 @@ CanvasComponentEraseDetailResult CanvasComponentContainer::collides_with_erase_d return CanvasComponentEraseDetailResult::NO_CHANGE; } else if(get_comp().can_erase_detail()) { - TransformData drawTransform = calculate_draw_transform(camCoords); + TransformData drawTransform = calculate_draw_transform(camCoords, coords); SkMatrix m = SkMatrix::I(); m.postScale(1.0 / drawTransform.scale, 1.0 / drawTransform.scale).postRotate(-drawTransform.rotation).postTranslate(-drawTransform.translation.x(), -drawTransform.translation.y()); std::optional transformedPath = checkAgainstCam.tryMakeTransform(m); @@ -173,7 +173,7 @@ bool CanvasComponentContainer::collides_with(const CoordSpaceHelper& camCoords, else if(coords.inverseScale < (camCoords.inverseScale >> COMP_COLLIDE_MIN_SHIFT_TINY)) return checkAgainstCam.contains(convert_vec2(camCoords.to_space(worldAABB.value().min))); else { - TransformData drawTransform = calculate_draw_transform(camCoords); + TransformData drawTransform = calculate_draw_transform(camCoords, coords); SkMatrix m = SkMatrix::I(); m.postScale(1.0 / drawTransform.scale, 1.0 / drawTransform.scale).postRotate(-drawTransform.rotation).postTranslate(-drawTransform.translation.x(), -drawTransform.translation.y()); std::optional transformedPath = checkAgainstCam.tryMakeTransform(m); @@ -191,7 +191,7 @@ bool CanvasComponentContainer::collides_with_point(const CoordSpaceHelper& camCo else if(coords.inverseScale < (camCoords.inverseScale >> COMP_COLLIDE_MIN_SHIFT_TINY)) // Object is too tiny, just dismiss the collision return false; else { - TransformData drawTransform = calculate_draw_transform(camCoords); + TransformData drawTransform = calculate_draw_transform(camCoords, coords); SkMatrix m = SkMatrix::I(); m.postScale(1.0 / drawTransform.scale, 1.0 / drawTransform.scale).postRotate(-drawTransform.rotation).postTranslate(-drawTransform.translation.x(), -drawTransform.translation.y()); SkPoint p = m.mapPoint(convert_vec2(checkAgainstCam)); @@ -199,7 +199,7 @@ bool CanvasComponentContainer::collides_with_point(const CoordSpaceHelper& camCo } } -void CanvasComponentContainer::canvas_do_transform(SkCanvas* canvas, const TransformData& transformData) const { +void CanvasComponentContainer::canvas_do_transform(SkCanvas* canvas, const TransformData& transformData) { canvas->scale(transformData.scale, transformData.scale); canvas->rotate(transformData.rotation); canvas->translate(transformData.translation.x(), transformData.translation.y()); @@ -211,7 +211,7 @@ bool CanvasComponentContainer::should_draw(const DrawData& drawData) const { CanvasComponentContainer::PreDrawData CanvasComponentContainer::calculate_predraw_data(const DrawData& drawData) const { PreDrawData toRet; - toRet.transformData = calculate_draw_transform(drawData.cam.c); + toRet.transformData = calculate_draw_transform(drawData.cam.c, coords); if(toRet.transformData.scale < COMP_MAX_BEFORE_STOP_SCALING) toRet.extraData = get_comp().get_predraw_data(drawData); else @@ -219,7 +219,7 @@ CanvasComponentContainer::PreDrawData CanvasComponentContainer::calculate_predra return toRet; } -CanvasComponentContainer::TransformData CanvasComponentContainer::calculate_draw_transform(const CoordSpaceHelper& camCoords) const { +CanvasComponentContainer::TransformData CanvasComponentContainer::calculate_draw_transform(const CoordSpaceHelper& camCoords, const CoordSpaceHelper& coords) { TransformData toRet; toRet.translation = -coords.to_space(camCoords.pos); toRet.rotation = (coords.rotation - camCoords.rotation) * 180.0 / std::numbers::pi; diff --git a/src/CanvasComponents/CanvasComponentContainer.hpp b/src/CanvasComponents/CanvasComponentContainer.hpp index 3d355d9..5d00a18 100644 --- a/src/CanvasComponents/CanvasComponentContainer.hpp +++ b/src/CanvasComponents/CanvasComponentContainer.hpp @@ -83,7 +83,8 @@ class CanvasComponentContainer { void draw(SkCanvas* canvas, const DrawData& drawData) const; void draw_with_predraw_data(SkCanvas* canvas, const DrawData& drawData, const PreDrawData& preDrawData) const; PreDrawData calculate_predraw_data(const DrawData& drawData) const; - TransformData calculate_draw_transform(const CoordSpaceHelper& camCoords) const; + static TransformData calculate_draw_transform(const CoordSpaceHelper& camCoords, const CoordSpaceHelper& coords); + static void canvas_do_transform(SkCanvas* canvas, const TransformData& transformData); void commit_update(DrawingProgram& drawP); void commit_transform_dont_invalidate_cache(); // Must be thread safe void commit_transform(DrawingProgram& drawP); @@ -107,7 +108,6 @@ class CanvasComponentContainer { unsigned get_mipmap_level(const DrawData& drawData) const; CanvasComponent* allocate_comp(CanvasComponentType type); - void canvas_do_transform(SkCanvas* canvas, const TransformData& transformData) const; void calculate_world_bounds(); std::optional> worldAABB; diff --git a/src/CanvasComponents/ImageCanvasComponent.cpp b/src/CanvasComponents/ImageCanvasComponent.cpp index 87dc5c0..3510105 100644 --- a/src/CanvasComponents/ImageCanvasComponent.cpp +++ b/src/CanvasComponents/ImageCanvasComponent.cpp @@ -78,7 +78,7 @@ void ImageCanvasComponent::draw_download_progress_bar(SkCanvas* canvas, const Dr return; if(compContainer->should_draw(drawData)) { canvas->save(); - compContainer->canvas_do_transform(canvas, compContainer->calculate_draw_transform(drawData.cam.c)); + compContainer->canvas_do_transform(canvas, compContainer->calculate_draw_transform(drawData.cam.c, compContainer->coords)); SkPaint p; p.setStroke(true); p.setStrokeWidth(10.0f); diff --git a/src/DrawingProgram/Tools/EraserTool.cpp b/src/DrawingProgram/Tools/EraserTool.cpp index 1872ba4..30de75a 100644 --- a/src/DrawingProgram/Tools/EraserTool.cpp +++ b/src/DrawingProgram/Tools/EraserTool.cpp @@ -115,13 +115,13 @@ void EraserTool::input_pen_axis_callback(const InputManager::PenAxisCallbackArgs } void EraserTool::erase_on_path() { - auto cCWorldBounds = drawP.world.drawData.cam.c.collider_to_world, SCollision::AABB>(erasePath.getBounds()); + auto cCWorldBounds = genData.coords.collider_to_world, SCollision::AABB>(erasePath.getBounds()); drawP.drawCache.traverse_bvh_run_function(cCWorldBounds, [&](const auto& bvhNode) { if(bvhNode && - erasePath.contains(convert_vec2(drawP.world.drawData.cam.c.to_space(bvhNode->bounds.min))) && - erasePath.contains(convert_vec2(drawP.world.drawData.cam.c.to_space(bvhNode->bounds.max))) && - erasePath.contains(convert_vec2(drawP.world.drawData.cam.c.to_space(bvhNode->bounds.top_right()))) && - erasePath.contains(convert_vec2(drawP.world.drawData.cam.c.to_space(bvhNode->bounds.bottom_left())))) { + erasePath.contains(convert_vec2(genData.coords.to_space(bvhNode->bounds.min))) && + erasePath.contains(convert_vec2(genData.coords.to_space(bvhNode->bounds.max))) && + erasePath.contains(convert_vec2(genData.coords.to_space(bvhNode->bounds.top_right()))) && + erasePath.contains(convert_vec2(genData.coords.to_space(bvhNode->bounds.bottom_left())))) { drawP.drawCache.invalidate_cache_at_aabb(bvhNode->bounds); drawP.drawCache.traverse_bvh_run_function_starting_at_node_no_collision_check(bvhNode, [&](const auto& bvhNodeChild) { drawP.drawCache.node_loop_erase_if_components(bvhNodeChild, [&](auto c) { @@ -144,7 +144,7 @@ void EraserTool::erase_on_path() { if(drawP.world.main.toolConfig.eraser.eraseDetail) { if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector)) { auto dataCopy = c->obj->get_comp().get_data_copy(); - CanvasComponentEraseDetailResult result = c->obj->collides_with_erase_detail(drawP.world.drawData.cam.c, erasePath); + CanvasComponentEraseDetailResult result = c->obj->collides_with_erase_detail(genData.coords, erasePath); switch(result) { case CanvasComponentEraseDetailResult::NO_CHANGE: return false; @@ -174,7 +174,7 @@ void EraserTool::erase_on_path() { } } else { - if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector) && c->obj->collides_with(drawP.world.drawData.cam.c, erasePath)) { + if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector) && c->obj->collides_with(genData.coords, erasePath)) { erasedComponents.emplace(c); drawP.drawCache.invalidate_cache_at_optional_aabb(c->obj->get_world_bounds()); return true; @@ -256,6 +256,11 @@ bool EraserTool::prevent_undo_or_redo() { void EraserTool::draw(SkCanvas* canvas, const DrawData& drawData) { if(!drawP.world.main.input.isTouchDevice && (!drawData.main->g.gui.cursor_obstructed() || isErasing) && !erasePath.isEmpty()) { + if(isErasing) { + CanvasComponentContainer::TransformData drawTransform = CanvasComponentContainer::calculate_draw_transform(drawData.cam.c, genData.coords); + canvas->save(); + CanvasComponentContainer::canvas_do_transform(canvas, drawTransform); + } SkPaint linePaint; linePaint.setAntiAlias(drawData.skiaAA); linePaint.setColor4f({0.0f, 0.0f, 0.0f, 0.4f}); @@ -264,5 +269,7 @@ void EraserTool::draw(SkCanvas* canvas, const DrawData& drawData) { linePaint.setColor4f({1.0f, 1.0f, 1.0f, 0.4f}); canvas->drawPath(erasePath, linePaint); + if(isErasing) + canvas->restore(); } }