diff --git a/src/DrawCamera.cpp b/src/DrawCamera.cpp index b408539..5df5882 100755 --- a/src/DrawCamera.cpp +++ b/src/DrawCamera.cpp @@ -114,7 +114,7 @@ void DrawCamera::update_main(World& w) { } else { bool middleClickDown = w.main.input.mouse.middleDown || w.main.input.pen.buttons[w.main.toolbar.tabletOptions.middleClickButton].held; - bool newIsMiddleClickZooming = middleClickDown && w.main.input.key(InputManager::KEY_ZOOM_CTRL).held; + bool newIsMiddleClickZooming = middleClickDown && w.main.input.key(InputManager::KEY_GENERIC_LCTRL).held; if(newIsMiddleClickZooming && !isMiddleClickZooming) { startZoomMousePos = w.get_mouse_world_pos(); startZoomVal = c.inverseScale; diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index c6d5593..079d5fc 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -285,6 +285,7 @@ void DrawingProgram::update() { else if(world.main.input.key(InputManager::KEY_DRAW_TOOL_EDIT).pressed) switch_to_tool(DrawingProgramToolType::EDIT); + selection.update(); drawTool->tool_update(); if(controls.leftClickReleased) @@ -293,8 +294,6 @@ void DrawingProgram::update() { check_delayed_update_timers(); check_updateable_components(); - selection.update(); - if(drawTool->get_type() == DrawingProgramToolType::ERASER) { EraserTool* eraserTool = static_cast(drawTool.get()); compCache.test_rebuild_dont_include_set_dont_include_nodes(components.client_list(), eraserTool->erasedComponents, eraserTool->erasedBVHNodes); @@ -312,7 +311,7 @@ void DrawingProgram::switch_to_tool_ptr(std::unique_ptr void DrawingProgram::switch_to_tool(DrawingProgramToolType newToolType) { if(newToolType != drawTool->get_type()) { - drawTool->switch_tool(drawTool->get_type()); + drawTool->switch_tool(newToolType); drawTool = DrawingProgramToolBase::allocate_tool_type(*this, newToolType); } } diff --git a/src/DrawingProgram/DrawingProgramSelection.cpp b/src/DrawingProgram/DrawingProgramSelection.cpp index d3faaa1..984a409 100644 --- a/src/DrawingProgram/DrawingProgramSelection.cpp +++ b/src/DrawingProgram/DrawingProgramSelection.cpp @@ -35,11 +35,7 @@ void DrawingProgramSelection::erase_component(const CollabListType::ObjectInfoPt } } -void DrawingProgramSelection::add_from_cam_coord_collider_to_selection(const SCollision::ColliderCollection& cC) { - auto cCWorld = drawP.world.drawData.cam.c.collider_to_world, SCollision::ColliderCollection>(cC); - - std::unordered_set selectedComponents; - +std::function&, std::vector&)> DrawingProgramSelection::erase_select_objects_in_bvh_func(std::unordered_set& selectedComponents, const SCollision::ColliderCollection& cC, const SCollision::ColliderCollection& cCWorld) { std::function&)> fullyCollidedFunc = [&](const std::shared_ptr& bvhNode) { if(bvhNode) { for(auto& c : bvhNode->components) @@ -48,7 +44,8 @@ void DrawingProgramSelection::add_from_cam_coord_collider_to_selection(const SCo fullyCollidedFunc(p); } }; - drawP.compCache.traverse_bvh_erase_function(cCWorld.bounds, [&](const auto& bvhNode, auto& comps) { + + auto toRet = [&](const auto& bvhNode, auto& comps) { if(bvhNode && (bvhNode->coords.inverseScale << 9) < drawP.world.drawData.cam.c.inverseScale && 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)) && @@ -67,9 +64,43 @@ void DrawingProgramSelection::add_from_cam_coord_collider_to_selection(const SCo return false; }); return false; - }); + }; - set_to_selection(selectedComponents); + return toRet; +} + +void DrawingProgramSelection::add_from_cam_coord_collider_to_selection(const SCollision::ColliderCollection& cC) { + auto cCWorld = drawP.world.drawData.cam.c.collider_to_world, SCollision::ColliderCollection>(cC); + std::unordered_set selectedComponents; + drawP.compCache.traverse_bvh_erase_function(cCWorld.bounds, erase_select_objects_in_bvh_func(selectedComponents, cC, cCWorld)); + add_to_selection(selectedComponents); +} + +void DrawingProgramSelection::remove_from_cam_coord_collider_to_selection(const SCollision::ColliderCollection& cC) { + auto cCWorld = drawP.world.drawData.cam.c.collider_to_world, SCollision::ColliderCollection>(cC); + std::unordered_set selectedComponents; + cache.traverse_bvh_erase_function(cCWorld.bounds, erase_select_objects_in_bvh_func(selectedComponents, cC, cCWorld)); + std::erase_if(selectedSet, [&](auto& c) { + return selectedComponents.contains(c); + }); + for(auto& obj : selectedComponents) + drawP.compCache.add_component(obj); + if(!is_something_selected()) { + reset_selection_data(); + reset_transform_data(); + } + else { + calculate_aabb(); + calculate_initial_rotate_center_location(); + } +} + +void DrawingProgramSelection::add_to_selection(const std::unordered_set& newSelection) { + selectedSet.insert(newSelection.begin(), newSelection.end()); + for(auto& obj : newSelection) + cache.add_component(obj); + calculate_aabb(); + calculate_initial_rotate_center_location(); } void DrawingProgramSelection::set_to_selection(const std::unordered_set& newSelection) { @@ -235,7 +266,7 @@ void DrawingProgramSelection::update() { switch(transformOpHappening) { case TransformOperation::NONE: - if(drawP.controls.leftClick) { + if(drawP.controls.leftClick && !drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held && !drawP.world.main.input.key(InputManager::KEY_GENERIC_LALT).held) { if(mouse_collided_with_scale_point()) { scaleData.currentPos = scaleData.startPos = selectionTransformCoords.from_space_world(initialSelectionAABB.max); scaleData.centerPos = selectionTransformCoords.from_space_world(initialSelectionAABB.center()); @@ -251,8 +282,6 @@ void DrawingProgramSelection::update() { translateData.startPos = drawP.world.get_mouse_world_pos(); transformOpHappening = TransformOperation::TRANSLATE; } - else - deselect_all(); } break; case TransformOperation::TRANSLATE: @@ -325,6 +354,10 @@ void DrawingProgramSelection::update() { paste_clipboard(); } +bool DrawingProgramSelection::is_being_transformed() { + return transformOpHappening != TransformOperation::NONE; +} + void DrawingProgramSelection::paste_clipboard() { auto& clipboard = drawP.world.main.clipboard; diff --git a/src/DrawingProgram/DrawingProgramSelection.hpp b/src/DrawingProgram/DrawingProgramSelection.hpp index 481b0f0..6075b8c 100644 --- a/src/DrawingProgram/DrawingProgramSelection.hpp +++ b/src/DrawingProgram/DrawingProgramSelection.hpp @@ -8,6 +8,8 @@ class DrawingProgramSelection { public: DrawingProgramSelection(DrawingProgram& initDrawP); void add_from_cam_coord_collider_to_selection(const SCollision::ColliderCollection& cC); + void remove_from_cam_coord_collider_to_selection(const SCollision::ColliderCollection& cC); + void deselect_all(); void update(); void draw_components(SkCanvas* canvas, const DrawData& drawData); @@ -18,9 +20,13 @@ class DrawingProgramSelection { bool is_selected(const CollabListType::ObjectInfoPtr& objToCheck); const std::unordered_set& get_selected_set(); + bool is_being_transformed(); + void invalidate_cache_at_optional_aabb_before_pos(const std::optional>& aabb, uint64_t placementToInvalidateAt); void preupdate_component(const CollabListType::ObjectInfoPtr& objToCheck); private: + std::function&, std::vector&)> erase_select_objects_in_bvh_func(std::unordered_set& selectedComponents, const SCollision::ColliderCollection& cC, const SCollision::ColliderCollection& cCWorld); + void delete_all(); bool mouse_collided_with_selection_aabb(); bool mouse_collided_with_scale_point(); @@ -28,7 +34,10 @@ class DrawingProgramSelection { bool mouse_collided_with_rotate_handle_point(); void selection_to_clipboard(); void paste_clipboard(); + void set_to_selection(const std::unordered_set& newSelection); + void add_to_selection(const std::unordered_set& newSelection); + void add_erased_objects_back_to_cache(const std::unordered_set& erasedObjects); void commit_transform_selection(); diff --git a/src/DrawingProgram/EllipseDrawTool.cpp b/src/DrawingProgram/EllipseDrawTool.cpp index d059827..0115555 100644 --- a/src/DrawingProgram/EllipseDrawTool.cpp +++ b/src/DrawingProgram/EllipseDrawTool.cpp @@ -62,7 +62,7 @@ void EllipseDrawTool::tool_update() { if(drawP.controls.leftClickHeld) { controls.intermediateItem->lastUpdateTime = std::chrono::steady_clock::now(); Vector2f newPos = controls.intermediateItem->coords.get_mouse_pos(drawP.world); - if(drawP.world.main.input.key(InputManager::KEY_EQUAL_DIMENSIONS).held) { + if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) { float height = std::fabs(controls.startAt.y() - newPos.y()); newPos.x() = controls.startAt.x() + (((newPos.x() - controls.startAt.x()) < 0.0f ? -1.0f : 1.0f) * height); } diff --git a/src/DrawingProgram/LassoSelectTool.cpp b/src/DrawingProgram/LassoSelectTool.cpp index 2f22daf..10e88bd 100644 --- a/src/DrawingProgram/LassoSelectTool.cpp +++ b/src/DrawingProgram/LassoSelectTool.cpp @@ -42,25 +42,18 @@ void LassoSelectTool::gui_toolbox() { } void LassoSelectTool::switch_tool(DrawingProgramToolType newTool) { - drawP.selection.deselect_all(); - controls.lassoPoints.clear(); - controls = LassoSelectControls(); + if(newTool != DrawingProgramToolType::RECTSELECT && newTool != DrawingProgramToolType::LASSOSELECT) + drawP.selection.deselect_all(); } void LassoSelectTool::tool_update() { switch(controls.selectionMode) { case 0: { - if(drawP.controls.leftClick) { - if(drawP.selection.is_something_selected()) { - if(!drawP.selection.mouse_collided_with_selection()) - switch_tool(get_type()); - } - else { - switch_tool(get_type()); - controls.coords = drawP.world.drawData.cam.c; - controls.lassoPoints.emplace_back(controls.coords.get_mouse_pos(drawP.world)); - controls.selectionMode = 1; - } + if(drawP.controls.leftClick && !drawP.selection.is_being_transformed()) { + controls = LassoSelectControls(); + controls.coords = drawP.world.drawData.cam.c; + controls.lassoPoints.emplace_back(controls.coords.get_mouse_pos(drawP.world)); + controls.selectionMode = 1; } break; } @@ -91,12 +84,16 @@ void LassoSelectTool::tool_update() { cC.recalculate_bounds(); - drawP.selection.add_from_cam_coord_collider_to_selection(cC); - - controls.selectionMode = 0; + if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) + drawP.selection.add_from_cam_coord_collider_to_selection(cC); + else if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LALT).held) + drawP.selection.remove_from_cam_coord_collider_to_selection(cC); + else { + drawP.selection.deselect_all(); + drawP.selection.add_from_cam_coord_collider_to_selection(cC); + } } - else - switch_tool(get_type()); + controls.selectionMode = 0; } break; } diff --git a/src/DrawingProgram/RectDrawTool.cpp b/src/DrawingProgram/RectDrawTool.cpp index 321cadf..855c070 100644 --- a/src/DrawingProgram/RectDrawTool.cpp +++ b/src/DrawingProgram/RectDrawTool.cpp @@ -59,7 +59,7 @@ void RectDrawTool::tool_update() { if(drawP.controls.leftClickHeld) { controls.intermediateItem->lastUpdateTime = std::chrono::steady_clock::now(); Vector2f newPos = controls.intermediateItem->coords.get_mouse_pos(drawP.world); - if(drawP.world.main.input.key(InputManager::KEY_EQUAL_DIMENSIONS).held) { + if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) { float height = std::fabs(controls.startAt.y() - newPos.y()); newPos.x() = controls.startAt.x() + (((newPos.x() - controls.startAt.x()) < 0.0f ? -1.0f : 1.0f) * height); } diff --git a/src/DrawingProgram/RectSelectTool.cpp b/src/DrawingProgram/RectSelectTool.cpp index be26497..118615f 100644 --- a/src/DrawingProgram/RectSelectTool.cpp +++ b/src/DrawingProgram/RectSelectTool.cpp @@ -21,24 +21,18 @@ void RectSelectTool::gui_toolbox() { } void RectSelectTool::switch_tool(DrawingProgramToolType newTool) { - drawP.selection.deselect_all(); - controls = RectSelectControls(); + if(newTool != DrawingProgramToolType::RECTSELECT && newTool != DrawingProgramToolType::LASSOSELECT) + drawP.selection.deselect_all(); } void RectSelectTool::tool_update() { switch(controls.selectionMode) { case 0: { - if(drawP.controls.leftClick) { - if(drawP.selection.is_something_selected()) { - if(!drawP.selection.mouse_collided_with_selection()) - switch_tool(get_type()); - } - else { - switch_tool(get_type()); - controls.coords = drawP.world.drawData.cam.c; - controls.selectStartAt = controls.coords.get_mouse_pos(drawP.world); - controls.selectionMode = 1; - } + if(drawP.controls.leftClick && !drawP.selection.is_being_transformed()) { + controls = RectSelectControls(); + controls.coords = drawP.world.drawData.cam.c; + controls.selectStartAt = controls.coords.get_mouse_pos(drawP.world); + controls.selectionMode = 1; } break; } @@ -54,7 +48,14 @@ void RectSelectTool::tool_update() { cC.triangle.emplace_back(controls.newT[2], controls.newT[3], controls.newT[0]); cC.recalculate_bounds(); - drawP.selection.add_from_cam_coord_collider_to_selection(cC); + if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) + drawP.selection.add_from_cam_coord_collider_to_selection(cC); + else if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LALT).held) + drawP.selection.remove_from_cam_coord_collider_to_selection(cC); + else { + drawP.selection.deselect_all(); + drawP.selection.add_from_cam_coord_collider_to_selection(cC); + } controls.selectionMode = 0; } diff --git a/src/DrawingProgram/RectSelectTool.hpp b/src/DrawingProgram/RectSelectTool.hpp index 654e389..20465e1 100644 --- a/src/DrawingProgram/RectSelectTool.hpp +++ b/src/DrawingProgram/RectSelectTool.hpp @@ -15,7 +15,6 @@ class RectSelectTool : public DrawingProgramToolBase { virtual void draw(SkCanvas* canvas, const DrawData& drawData) override; virtual void switch_tool(DrawingProgramToolType newTool) override; virtual bool prevent_undo_or_redo() override; - private: struct RectSelectControls { int selectionMode = 0; diff --git a/src/DrawingProgram/TextBoxTool.cpp b/src/DrawingProgram/TextBoxTool.cpp index d576db3..d9676cb 100644 --- a/src/DrawingProgram/TextBoxTool.cpp +++ b/src/DrawingProgram/TextBoxTool.cpp @@ -54,7 +54,7 @@ void TextBoxTool::tool_update() { } case 1: { Vector2f newPos = controls.intermediateItem->coords.get_mouse_pos(drawP.world); - if(drawP.world.main.input.key(InputManager::KEY_EQUAL_DIMENSIONS).held) { + if(drawP.world.main.input.key(InputManager::KEY_GENERIC_LSHIFT).held) { float height = std::fabs(controls.startAt.y() - newPos.y()); newPos.x() = controls.startAt.x() + (((newPos.x() - controls.startAt.x()) < 0.0f ? -1.0f : 1.0f) * height); } diff --git a/src/InputManager.cpp b/src/InputManager.cpp index 091822d..6783d99 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -227,13 +227,15 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { set_key_down(e, KEY_TEXT_HOME); break; case SDLK_LSHIFT: - set_key_down(e, KEY_ZOOM_SHIFT); set_key_down(e, KEY_TEXT_SHIFT); - set_key_down(e, KEY_EQUAL_DIMENSIONS); + set_key_down(e, KEY_GENERIC_LSHIFT); + break; + case SDLK_LALT: + set_key_down(e, KEY_GENERIC_LALT); break; case SDLK_LCTRL: set_key_down(e, KEY_TEXT_CTRL); - set_key_down(e, KEY_ZOOM_CTRL); + set_key_down(e, KEY_GENERIC_LCTRL); break; case SDLK_C: // Use either Ctrl or Meta (command for Mac) keys. We do either instead of checking, since checking can get complicated on Emscripten @@ -297,13 +299,15 @@ void InputManager::backend_key_up_update(const SDL_KeyboardEvent& e) { set_key_up(e, KEY_TEXT_HOME); break; case SDLK_LSHIFT: - set_key_up(e, KEY_ZOOM_SHIFT); set_key_up(e, KEY_TEXT_SHIFT); - set_key_up(e, KEY_EQUAL_DIMENSIONS); + set_key_up(e, KEY_GENERIC_LSHIFT); + break; + case SDLK_LALT: + set_key_up(e, KEY_GENERIC_LALT); break; case SDLK_LCTRL: set_key_up(e, KEY_TEXT_CTRL); - set_key_up(e, KEY_ZOOM_CTRL); + set_key_up(e, KEY_GENERIC_LCTRL); break; case SDLK_C: set_key_up(e, KEY_TEXT_COPY); diff --git a/src/InputManager.hpp b/src/InputManager.hpp index 5cf14c8..152ac34 100644 --- a/src/InputManager.hpp +++ b/src/InputManager.hpp @@ -154,9 +154,9 @@ struct InputManager { KEY_TEXT_CTRL, KEY_TEXT_SELECTALL, KEY_TEXT_ESCAPE, - KEY_ZOOM_SHIFT, - KEY_ZOOM_CTRL, - KEY_EQUAL_DIMENSIONS, + KEY_GENERIC_LSHIFT, + KEY_GENERIC_LALT, + KEY_GENERIC_LCTRL, KEY_COUNT };