From 868ff8fe50fceece40145b19a504f2d84d085ac9 Mon Sep 17 00:00:00 2001 From: Garux Date: Tue, 11 Dec 2018 13:19:07 +0300 Subject: [PATCH] * insert brush vertices in vertex mode by clicking with no ones selected --- radiant/brush.h | 20 ++- radiant/selection.cpp | 324 +++++++++++++++++++++++++++--------------- 2 files changed, 227 insertions(+), 117 deletions(-) diff --git a/radiant/brush.h b/radiant/brush.h index 1d2c6b7a..f822c717 100644 --- a/radiant/brush.h +++ b/radiant/brush.h @@ -1883,7 +1883,7 @@ void freezeTransform(){ const Vector3 m_vertex; Vector3 m_vertexTransformed; const bool m_selected; - std::vector m_faces; + std::vector m_faces; VertexModeVertex( const Vector3& vertex, const bool selected ) : m_vertex( vertex ), m_vertexTransformed( vertex ), m_selected( selected ) { } }; @@ -3788,6 +3788,24 @@ void gatherSelectedComponents( const Vector3Callback& callback ) const { } } +void insert_vertices( const Brush::VertexModeVertices& vertexModeVertices ){ + if( !m_vertexInstances.empty() ){ + m_brush.vertexModeInit(); + for ( const auto& i : m_vertexInstances ){ + i.gather( m_brush.m_vertexModeVertices ); + } + for ( const auto& i : vertexModeVertices ){ + m_brush.m_vertexModeVertices.push_back( i ); + if( i.m_faces.empty() ) + m_brush.m_vertexModeVertices.back().m_faces.push_back( m_brush.m_vertexModeVertices[0].m_faces[0] ); + } + m_transform.m_transformFrozen = false; + m_transform.setType( TRANSFORM_COMPONENT ); + m_brush.transformChanged(); + m_brush.evaluateBRep(); + } +} + void snapComponents( float snap ){ for ( const auto& fi : m_faceInstances ){ if( fi.selectedComponents( SelectionSystem::eVertex ) ){ diff --git a/radiant/selection.cpp b/radiant/selection.cpp index 5b5b89e7..2fa89f73 100644 --- a/radiant/selection.cpp +++ b/radiant/selection.cpp @@ -3696,6 +3696,204 @@ const SelectionIntersection& best() const { }; + + + +class ClipperSelector : public Selector { + SelectionIntersection m_bestIntersection; + Face* m_face; +public: + ClipperSelector() : m_bestIntersection( SelectionIntersection() ), m_face( 0 ) { + } + + void pushSelectable( Selectable& selectable ) { + } + void popSelectable() { + } + void addIntersection( const SelectionIntersection& intersection ) { + if( SelectionIntersection_closer( intersection, m_bestIntersection ) ) { + m_bestIntersection = intersection; + m_face = 0; + } + } + + void addIntersection( const SelectionIntersection& intersection, Face* face ) { + if( SelectionIntersection_closer( intersection, m_bestIntersection ) ) { + m_bestIntersection = intersection; + m_face = face; + } + } + bool isSelected() { + return m_bestIntersection.valid(); + } + const SelectionIntersection& best() { + return m_bestIntersection; + } + const Face* face() { + return m_face; + } +}; + +class testselect_scene_4clipper : public scene::Graph::Walker { + ClipperSelector& m_clipperSelector; + SelectionTest& m_test; +public: + testselect_scene_4clipper( ClipperSelector& clipperSelector, SelectionTest& test ) : m_clipperSelector( clipperSelector ), m_test( test ) { + } + bool pre( const scene::Path& path, scene::Instance& instance ) const { + BrushInstance* brush = Instance_getBrush( instance ); + if( brush != 0 ) { + m_test.BeginMesh( brush->localToWorld() ); + for( Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i ) { + Face* face = *i; + if( !face->isFiltered() ) { + SelectionIntersection intersection; + face->testSelect( m_test, intersection ); + m_clipperSelector.addIntersection( intersection, face ); + } + } + } + else { + SelectionTestable* selectionTestable = Instance_getSelectionTestable( instance ); + if( selectionTestable ) { + selectionTestable->testSelect( m_clipperSelector, m_test ); + } + } + return true; + } +}; + +class testselect_scene_4clipper_selected : public scene::Graph::Walker { + ClipperSelector& m_clipperSelector; + SelectionTest& m_test; +public: + testselect_scene_4clipper_selected( ClipperSelector& clipperSelector, SelectionTest& test ) : m_clipperSelector( clipperSelector ), m_test( test ) { + } + bool pre( const scene::Path& path, scene::Instance& instance ) const { + BrushInstance* brush = Instance_getBrush( instance ); + if( brush != 0 && brush->isSelected() ) { + m_test.BeginMesh( brush->localToWorld() ); + for( Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i ) { + Face* face = *i; + if( !face->isFiltered() ) { + SelectionIntersection intersection; + face->testSelect( m_test, intersection ); + m_clipperSelector.addIntersection( intersection, face ); + } + } + } + return true; + } +}; + +Vector3 testSelected_scene_snapped_point( const SelectionVolume& test, ClipperSelector& clipperSelector ){ + Vector3 point = vector4_projected( matrix4_transformed_vector4( test.getScreen2world(), Vector4( 0, 0, clipperSelector.best().depth(), 1 ) ) ); + if( clipperSelector.face() ){ + const Face& face = *clipperSelector.face(); + float bestDist = FLT_MAX; + Vector3 wannabePoint; + for ( Winding::const_iterator prev = face.getWinding().end() - 1, curr = face.getWinding().begin(); curr != face.getWinding().end(); prev = curr, ++curr ){ + { /* try vertices */ + const float dist = vector3_length_squared( ( *curr ).vertex - point ); + if( dist < bestDist ){ + wannabePoint = ( *curr ).vertex; + bestDist = dist; + } + } + { /* try edges */ + Vector3 edgePoint = segment_closest_point_to_point( Segment3D( ( *prev ).vertex, ( *curr ).vertex ), point ); + if( edgePoint != ( *prev ).vertex && edgePoint != ( *curr ).vertex ){ + const Vector3 edgedir = vector3_normalised( ( *curr ).vertex - ( *prev ).vertex ); + const std::size_t maxi = vector3_max_abs_component_index( edgedir ); + // ( *prev ).vertex[maxi] + edgedir[maxi] * coef = float_snapped( point[maxi], GetSnapGridSize() ) + const float coef = ( float_snapped( point[maxi], GetSnapGridSize() ) - ( *prev ).vertex[maxi] ) / edgedir[maxi]; + edgePoint = ( *prev ).vertex + edgedir * coef; + const float dist = vector3_length_squared( edgePoint - point ); + if( dist < bestDist ){ + wannabePoint = edgePoint; + bestDist = dist; + } + } + } + } + if( clipperSelector.best().distance() == 0.f ){ /* try plane, if pointing inside of polygon */ + const std::size_t maxi = vector3_max_abs_component_index( face.plane3().normal() ); + Vector3 planePoint( vector3_snapped( point, GetSnapGridSize() ) ); + // face.plane3().normal().dot( point snapped ) = face.plane3().dist() + planePoint[maxi] = ( face.plane3().dist() + - face.plane3().normal()[( maxi + 1 ) % 3] * planePoint[( maxi + 1 ) % 3] + - face.plane3().normal()[( maxi + 2 ) % 3] * planePoint[( maxi + 2 ) % 3] ) / face.plane3().normal()[maxi]; + const float dist = vector3_length_squared( planePoint - point ); + if( dist < bestDist ){ + wannabePoint = planePoint; + bestDist = dist; + } + } + point = wannabePoint; + } + else{ + vector3_snap( point, GetSnapGridSize() ); + } + return point; +} + +class Scene_insert_brush_vertices +{ + const Brush::VertexModeVertices& m_vertexModeVertices; +public: + Scene_insert_brush_vertices( const Brush::VertexModeVertices& vertexModeVertices ) : m_vertexModeVertices( vertexModeVertices ) { + } + void operator()( BrushInstance& brush ) const { + brush.insert_vertices( m_vertexModeVertices ); + } +}; + +bool scene_insert_brush_vertices( const View& view, TranslateFreeXY_Z& freeDragXY_Z ){ + SelectionVolume test( view ); + ClipperSelector clipperSelector; + if( view.fill() ) + Scene_forEachVisible( GlobalSceneGraph(), view, testselect_scene_4clipper( clipperSelector, test ) ); + else + Scene_forEachVisible( GlobalSceneGraph(), view, testselect_scene_4clipper_selected( clipperSelector, test ) ); + test.BeginMesh( g_matrix4_identity, true ); + if( clipperSelector.isSelected() ){ + freeDragXY_Z.set0( vector4_projected( matrix4_transformed_vector4( test.getScreen2world(), Vector4( 0, 0, clipperSelector.best().depth(), 1 ) ) ) ); + Vector3 point = testSelected_scene_snapped_point( test, clipperSelector ); + if( !view.fill() ){ + point -= view.getViewDir() * GetGridSize(); + } + Brush::VertexModeVertices vertexModeVertices; + vertexModeVertices.push_back( Brush::VertexModeVertex( point, true ) ); + if( clipperSelector.face() ) + vertexModeVertices.back().m_faces.push_back( clipperSelector.face() ); + + UndoableCommand undo( "InsertBrushVertices" ); + Scene_forEachSelectedBrush( Scene_insert_brush_vertices( vertexModeVertices ) ); + return true; + } + else if( !view.fill() ){ //+two points + freeDragXY_Z.set0( g_vector3_identity ); + const AABB bounds = GlobalSelectionSystem().getBoundsSelected(); + if( aabb_valid( bounds ) ){ + Vector3 xy = vector4_projected( matrix4_transformed_vector4( test.getScreen2world(), Vector4( 0, 0, 0, 1 ) ) ); + vector3_snap( xy, GetSnapGridSize() ); + Vector3 a( xy ), b( xy ); + const std::size_t max = vector3_max_abs_component_index( view.getViewDir() ); + a[max] = bounds.origin[max] + bounds.extents[max]; + b[max] = bounds.origin[max] - bounds.extents[max]; + Brush::VertexModeVertices vertexModeVertices; + vertexModeVertices.push_back( Brush::VertexModeVertex( a, true ) ); + vertexModeVertices.push_back( Brush::VertexModeVertex( b, true ) ); + + UndoableCommand undo( "InsertBrushVertices" ); + Scene_forEachSelectedBrush( Scene_insert_brush_vertices( vertexModeVertices ) ); + return true; + } + } + return false; +} + + bool g_bAltResize_AltSelect = false; //AltDragManipulatorResize + select primitives in component modes bool g_bTmpComponentMode = false; @@ -3777,14 +3975,19 @@ void testSelect( const View& view, const Matrix4& pivot2world ){ selector.addSelectable( SelectionIntersection( 0, 0 ), ( *i ) ); m_dragSelected = true; } - if( GlobalSelectionSystem().countSelectedComponents() != 0 ){ /* even if hit nothing, but got selected */ - m_dragSelected = true; - m_freeDragXY_Z.set0( g_vector3_identity ); - } if( bestSelector.bestIntersection().valid() ){ test.BeginMesh( g_matrix4_identity, true ); m_freeDragXY_Z.set0( vector4_projected( matrix4_transformed_vector4( test.getScreen2world(), Vector4( 0, 0, bestSelector.bestIntersection().depth(), 1 ) ) ) ); } + else{ + if( GlobalSelectionSystem().countSelectedComponents() != 0 ){ /* even if hit nothing, but got selected */ + m_dragSelected = true; + m_freeDragXY_Z.set0( g_vector3_identity ); + } + else if( GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex ){ + m_dragSelected = scene_insert_brush_vertices( view, m_freeDragXY_Z ); + } + } } for ( SelectionPool::iterator i = selector.begin(); i != selector.end(); ++i ) @@ -3823,71 +4026,6 @@ bool isSelected() const { - -class ClipperSelector : public Selector { - SelectionIntersection m_bestIntersection; - Face* m_face; -public: - ClipperSelector() : m_bestIntersection( SelectionIntersection() ), m_face( 0 ) { - } - - void pushSelectable( Selectable& selectable ) { - } - void popSelectable() { - } - void addIntersection( const SelectionIntersection& intersection ) { - if( SelectionIntersection_closer( intersection, m_bestIntersection ) ) { - m_bestIntersection = intersection; - m_face = 0; - } - } - - void addIntersection( const SelectionIntersection& intersection, Face* face ) { - if( SelectionIntersection_closer( intersection, m_bestIntersection ) ) { - m_bestIntersection = intersection; - m_face = face; - } - } - bool isSelected() { - return m_bestIntersection.valid(); - } - const SelectionIntersection& best() { - return m_bestIntersection; - } - const Face* face() { - return m_face; - } -}; - -class testselect_scene_4clipper : public scene::Graph::Walker { - ClipperSelector& m_clipperSelector; - SelectionTest& m_test; -public: - testselect_scene_4clipper( ClipperSelector& clipperSelector, SelectionTest& test ) : m_clipperSelector( clipperSelector ), m_test( test ) { - } - bool pre( const scene::Path& path, scene::Instance& instance ) const { - BrushInstance* brush = Instance_getBrush( instance ); - if( brush != 0 ) { - m_test.BeginMesh( brush->localToWorld() ); - for( Brush::const_iterator i = brush->getBrush().begin(); i != brush->getBrush().end(); ++i ) { - Face* face = *i; - if( !face->isFiltered() ) { - SelectionIntersection intersection; - face->testSelect( m_test, intersection ); - m_clipperSelector.addIntersection( intersection, face ); - } - } - } - else { - SelectionTestable* selectionTestable = Instance_getSelectionTestable( instance ); - if( selectionTestable ) { - selectionTestable->testSelect( m_clipperSelector, m_test ); - } - } - return true; - } -}; - #include "clippertool.h" class ClipManipulator : public Manipulator, public ManipulatorSelectionChangeable, public Translatable, public Manipulatable @@ -4053,53 +4191,7 @@ public: Scene_forEachVisible( GlobalSceneGraph(), view, testselect_scene_4clipper( clipperSelector, test ) ); test.BeginMesh( g_matrix4_identity, true ); if( clipperSelector.isSelected() ){ - point = vector4_projected( matrix4_transformed_vector4( test.getScreen2world(), Vector4( 0, 0, clipperSelector.best().depth(), 1 ) ) ); - if( clipperSelector.face() ){ - const Face& face = *clipperSelector.face(); - float bestDist = FLT_MAX; - Vector3 wannabePoint; - for ( Winding::const_iterator prev = face.getWinding().end() - 1, curr = face.getWinding().begin(); curr != face.getWinding().end(); prev = curr, ++curr ){ - { /* try vertices */ - const float dist = vector3_length_squared( ( *curr ).vertex - point ); - if( dist < bestDist ){ - wannabePoint = ( *curr ).vertex; - bestDist = dist; - } - } - { /* try edges */ - Vector3 edgePoint = segment_closest_point_to_point( Segment3D( ( *prev ).vertex, ( *curr ).vertex ), point ); - if( edgePoint != ( *prev ).vertex && edgePoint != ( *curr ).vertex ){ - const Vector3 edgedir = vector3_normalised( ( *curr ).vertex - ( *prev ).vertex ); - const std::size_t maxi = vector3_max_abs_component_index( edgedir ); - // ( *prev ).vertex[maxi] + edgedir[maxi] * coef = float_snapped( point[maxi], GetSnapGridSize() ) - const float coef = ( float_snapped( point[maxi], GetSnapGridSize() ) - ( *prev ).vertex[maxi] ) / edgedir[maxi]; - edgePoint = ( *prev ).vertex + edgedir * coef; - const float dist = vector3_length_squared( edgePoint - point ); - if( dist < bestDist ){ - wannabePoint = edgePoint; - bestDist = dist; - } - } - } - } - if( clipperSelector.best().distance() == 0.f ){ /* try plane, if pointing inside of polygon */ - const std::size_t maxi = vector3_max_abs_component_index( face.plane3().normal() ); - Vector3 planePoint( vector3_snapped( point, GetSnapGridSize() ) ); - // face.plane3().normal().dot( point snapped ) = face.plane3().dist() - planePoint[maxi] = ( face.plane3().dist() - - face.plane3().normal()[( maxi + 1 ) % 3] * planePoint[( maxi + 1 ) % 3] - - face.plane3().normal()[( maxi + 2 ) % 3] * planePoint[( maxi + 2 ) % 3] ) / face.plane3().normal()[maxi]; - const float dist = vector3_length_squared( planePoint - point ); - if( dist < bestDist ){ - wannabePoint = planePoint; - bestDist = dist; - } - } - point = wannabePoint; - } - else{ - vector3_snap( point, GetSnapGridSize() ); - } + point = testSelected_scene_snapped_point( test, clipperSelector ); return true; } return false;