2025-08-02 12:31:16 +03:00
# include "LassoSelectTool.hpp"
2025-12-26 10:40:58 +03:00
# include "../DrawingProgram.hpp"
# include "../../MainProgram.hpp"
# include "../../DrawData.hpp"
2025-08-02 20:10:33 +03:00
# include "DrawingProgramToolBase.hpp"
2025-08-02 12:31:16 +03:00
# include "Helpers/MathExtras.hpp"
# include "Helpers/SCollision.hpp"
2025-12-26 10:40:58 +03:00
# include "../../CoordSpaceHelper.hpp"
2025-08-02 12:31:16 +03:00
# include <ranges>
2025-12-26 10:40:58 +03:00
# include "../../DrawCollision.hpp"
2025-08-02 14:42:53 +03:00
# include <earcut.hpp>
2025-11-18 18:15:50 +03:00
# include <include/core/SkPathBuilder.h>
2025-08-02 14:42:53 +03:00
namespace mapbox {
namespace util {
template < >
struct nth < 0 , Vector2f > {
inline static auto get ( const Vector2f & t ) {
return t . x ( ) ;
} ;
} ;
template < >
struct nth < 1 , Vector2f > {
inline static auto get ( const Vector2f & t ) {
return t . y ( ) ;
} ;
} ;
} // namespace util
} // namespace mapbox
2025-08-02 12:31:16 +03:00
LassoSelectTool : : LassoSelectTool ( DrawingProgram & initDrawP ) :
2025-08-02 20:10:33 +03:00
DrawingProgramToolBase ( initDrawP )
{ }
DrawingProgramToolType LassoSelectTool : : get_type ( ) {
return DrawingProgramToolType : : LASSOSELECT ;
2025-08-02 12:31:16 +03:00
}
void LassoSelectTool : : gui_toolbox ( ) {
2025-12-29 15:04:32 +03:00
auto & t = drawP . world . main . toolbar ;
t . gui . push_id ( " lasso select tool " ) ;
t . gui . text_label_centered ( " Lasso Select " ) ;
t . gui . text_label ( " Select from: " ) ;
if ( t . gui . radio_button_field ( " layer edited " , " Layer being edited " , drawP . controls . layerSelector = = DrawingProgramLayerManager : : LayerSelector : : LAYER_BEING_EDITED ) )
drawP . controls . layerSelector = DrawingProgramLayerManager : : LayerSelector : : LAYER_BEING_EDITED ;
if ( t . gui . radio_button_field ( " all visible " , " All visible layers " , drawP . controls . layerSelector = = DrawingProgramLayerManager : : LayerSelector : : ALL_VISIBLE_LAYERS ) )
drawP . controls . layerSelector = DrawingProgramLayerManager : : LayerSelector : : ALL_VISIBLE_LAYERS ;
t . gui . pop_id ( ) ;
2025-08-02 12:31:16 +03:00
}
2025-12-01 17:33:14 +03:00
bool LassoSelectTool : : right_click_popup_gui ( Vector2f popupPos ) {
return drawP . selection_action_menu ( popupPos ) ;
}
2025-12-15 15:36:42 +03:00
void LassoSelectTool : : erase_component ( const CanvasComponentContainer : : ObjInfoSharedPtr & erasedComp ) {
}
2025-08-02 20:39:21 +03:00
void LassoSelectTool : : switch_tool ( DrawingProgramToolType newTool ) {
2025-12-29 15:04:32 +03:00
if ( ! drawP . is_selection_allowing_tool ( newTool ) )
drawP . selection . deselect_all ( ) ;
2025-08-02 12:31:16 +03:00
}
void LassoSelectTool : : tool_update ( ) {
switch ( controls . selectionMode ) {
case 0 : {
2025-12-29 15:04:32 +03:00
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 ;
}
2025-08-02 12:31:16 +03:00
break ;
}
case 1 : {
using namespace SCollision ;
Vector2f newLassoPoint = controls . coords . get_mouse_pos ( drawP . world ) ;
2025-08-02 14:42:53 +03:00
float lassoPointDist = vec_distance ( controls . lassoPoints . back ( ) , newLassoPoint ) ;
if ( lassoPointDist > 4.0f )
2025-08-02 12:31:16 +03:00
controls . lassoPoints . emplace_back ( newLassoPoint ) ;
2025-08-02 14:42:53 +03:00
2025-08-02 12:31:16 +03:00
if ( ! drawP . controls . leftClickHeld ) {
2025-08-02 14:42:53 +03:00
if ( controls . lassoPoints . size ( ) > 3 ) {
SCollision : : ColliderCollection < float > cC ;
std : : vector < std : : vector < Vector2f > > polygon ;
polygon . emplace_back ( controls . lassoPoints ) ;
auto & poly = polygon [ 0 ] ;
std : : vector < unsigned > indices = mapbox : : earcut ( polygon ) ;
for ( size_t i = 0 ; i < indices . size ( ) ; i + = 3 ) {
cC . triangle . emplace_back (
poly [ indices [ i ] ] ,
poly [ indices [ i + 1 ] ] ,
poly [ indices [ i + 2 ] ]
) ;
}
cC . recalculate_bounds ( ) ;
2025-12-29 15:04:32 +03:00
if ( drawP . world . main . input . key ( InputManager : : KEY_GENERIC_LSHIFT ) . held )
drawP . selection . add_from_cam_coord_collider_to_selection ( cC , drawP . controls . layerSelector , false ) ;
else if ( drawP . world . main . input . key ( InputManager : : KEY_GENERIC_LALT ) . held )
drawP . selection . remove_from_cam_coord_collider_to_selection ( cC , drawP . controls . layerSelector , false ) ;
else {
drawP . selection . deselect_all ( ) ;
drawP . selection . add_from_cam_coord_collider_to_selection ( cC , drawP . controls . layerSelector , false ) ;
}
2025-12-28 17:34:33 +03:00
}
else if ( ! drawP . world . main . input . key ( InputManager : : KEY_GENERIC_LSHIFT ) . held & & ! drawP . world . main . input . key ( InputManager : : KEY_GENERIC_LALT ) . held ) {
2025-12-29 15:04:32 +03:00
drawP . selection . deselect_all ( ) ;
2025-08-02 12:31:16 +03:00
}
2025-08-05 19:04:47 +03:00
controls . selectionMode = 0 ;
2025-08-02 12:31:16 +03:00
}
break ;
}
}
}
bool LassoSelectTool : : prevent_undo_or_redo ( ) {
2025-12-29 15:04:32 +03:00
return drawP . selection . is_something_selected ( ) | | controls . selectionMode = = 1 ;
2025-08-02 12:31:16 +03:00
}
void LassoSelectTool : : draw ( SkCanvas * canvas , const DrawData & drawData ) {
if ( controls . selectionMode = = 1 ) {
canvas - > save ( ) ;
controls . coords . transform_sk_canvas ( canvas , drawData ) ;
2025-11-18 18:15:50 +03:00
SkPathBuilder lassoPath ;
2025-08-02 12:31:16 +03:00
lassoPath . moveTo ( convert_vec2 < SkPoint > ( controls . lassoPoints . front ( ) ) ) ;
for ( Vector2f & p : controls . lassoPoints | std : : views : : drop ( 1 ) )
lassoPath . lineTo ( convert_vec2 < SkPoint > ( p ) ) ;
2025-11-18 18:15:50 +03:00
canvas - > drawPath ( lassoPath . detach ( ) , drawP . select_tool_line_paint ( ) ) ;
2025-08-02 12:31:16 +03:00
canvas - > restore ( ) ;
}
}