binds... * clipper::enter, shift+enter, doubleclick: merge brushes and components with clipper points, if no cut occured

This commit is contained in:
Garux 2018-10-22 13:58:36 +03:00
parent 07bc303c2d
commit 053df17a35
5 changed files with 82 additions and 44 deletions

View File

@ -33,10 +33,9 @@
GdkCursor* g_clipper_cursor; GdkCursor* g_clipper_cursor;
ClipperPoints g_clipper_points( g_vector3_identity, g_vector3_identity, g_vector3_identity ); ClipperPoints g_clipper_points;
bool g_clipper_flipped = false; bool g_clipper_flipped = false;
bool g_clipper_quick = false; bool g_clipper_quick = false;
bool g_clipper_doubleclicked = false;
/* preferences */ /* preferences */
bool g_clipper_caulk = true; bool g_clipper_caulk = true;
@ -55,28 +54,27 @@ void ClipperModeQuick(){
} }
bool Clipper_ok(){ bool Clipper_ok_plane(){
return GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip && plane3_valid( plane3_for_points( g_clipper_points._points ) ); return GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip && g_clipper_points._count > 1 && plane3_valid( plane3_for_points( g_clipper_points._points ) );
} }
ClipperPoints Clipper_getPlanePoints(){ bool Clipper_ok(){
return g_clipper_flipped? ClipperPoints( g_clipper_points[0], g_clipper_points[2], g_clipper_points[1] ) : g_clipper_points; return GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip && g_clipper_points._count > 0;
} }
void Clipper_update(){ void Clipper_update(){
Scene_BrushSetClipPlane( GlobalSceneGraph(), Clipper_getPlanePoints() ); Scene_BrushSetClipPlane( GlobalSceneGraph(), g_clipper_points, g_clipper_flipped );
SceneChangeNotify(); SceneChangeNotify();
} }
void Clipper_setPlanePoints( const ClipperPoints& points ){ void Clipper_setPlanePoints( const ClipperPoints& points ){
g_clipper_points = points; g_clipper_points = points;
// g_clipper_doubleclicked = false; //assuming, that new point was set... dragging in fact calls this too >_<
Clipper_update(); Clipper_update();
} }
#include "gtkutil/idledraw.h" #include "gtkutil/idledraw.h"
void Clipper_BoundsChanged(){ void Clipper_BoundsChanged(){
if ( Clipper_ok() ) if ( Clipper_ok_plane() )
Clipper_update(); Clipper_update();
} }
@ -118,7 +116,7 @@ void Clipper_modeChanged( bool isClipper ){
void Clipper_do( bool split ){ void Clipper_do( bool split ){
Scene_BrushSplitByPlane( GlobalSceneGraph(), Clipper_getPlanePoints(), g_clipper_caulk, split ); Scene_BrushSplitByPlane( GlobalSceneGraph(), g_clipper_points, g_clipper_flipped, g_clipper_caulk, split );
if( g_clipper_resetPoints ){ if( g_clipper_resetPoints ){
GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eClip ); /* reset points this way */ GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eClip ); /* reset points this way */
if( g_clipper_resetFlip ) if( g_clipper_resetFlip )
@ -144,7 +142,7 @@ void Clipper_doSplit(){
} }
void Clipper_doFlip(){ void Clipper_doFlip(){
if( Clipper_ok() ){ if( Clipper_ok_plane() ){
g_clipper_flipped = !g_clipper_flipped; g_clipper_flipped = !g_clipper_flipped;
Clipper_update(); Clipper_update();
} }
@ -152,13 +150,17 @@ void Clipper_doFlip(){
#include "timer.h" #include "timer.h"
Timer g_clipper_timer; Timer g_clipper_timer;
void Clipper_tryDoubleclick(){ bool g_clipper_doubleclicked = false;
g_clipper_doubleclicked = g_clipper_timer.elapsed_msec() < 200 && Clipper_ok(); std::size_t g_clipper_doubleclicked_point = 0; //monitor clicking the same point twice
void Clipper_tryDoubleclick(){ //onMouseDown
g_clipper_doubleclicked = g_clipper_timer.elapsed_msec() < 200;
g_clipper_timer.start(); g_clipper_timer.start();
g_clipper_doubleclicked_point = g_clipper_points._count;
} }
void Clipper_tryDoubleclickedCut(){ void Clipper_tryDoubleclickedCut(){ //onMouseUp
if( g_clipper_doubleclicked ){ if( g_clipper_doubleclicked && g_clipper_doubleclicked_point == g_clipper_points._count ){
g_clipper_doubleclicked = false; g_clipper_doubleclicked = false;
return g_clipper_doubleclicked_split? Clipper_doSplit() : Clipper_doClip(); return g_clipper_doubleclicked_split? Clipper_doSplit() : Clipper_doClip();
} }

View File

@ -28,10 +28,15 @@ class ClipperPoints
{ {
public: public:
Vector3 _points[3]; Vector3 _points[3];
ClipperPoints( const Vector3& p0, const Vector3& p1, const Vector3& p2 ){ std::size_t _count;
ClipperPoints( const Vector3& p0, const Vector3& p1, const Vector3& p2, std::size_t count ){
_points[0] = p0; _points[0] = p0;
_points[1] = p1; _points[1] = p1;
_points[2] = p2; _points[2] = p2;
_count = count;
}
ClipperPoints() : _count( 0 ){
_points[0] = _points[1] = _points[2] = Vector3( 0, 0, 0 );
} }
const Vector3& operator[]( std::size_t i ) const { const Vector3& operator[]( std::size_t i ) const {
return _points[i]; return _points[i];

View File

@ -744,14 +744,17 @@ void CSG_Subtract(){
#include "clippertool.h" #include "clippertool.h"
class BrushSplitByPlaneSelected : public scene::Graph::Walker class BrushSplitByPlaneSelected : public scene::Graph::Walker
{ {
const Plane3 m_plane;
const ClipperPoints m_points; const ClipperPoints m_points;
const Plane3 m_plane;
const char* m_shader; const char* m_shader;
const TextureProjection& m_projection; const TextureProjection& m_projection;
const bool m_split; /* split or clip */ const bool m_split; /* split or clip */
public: public:
BrushSplitByPlaneSelected( const ClipperPoints& points, const char* shader, const TextureProjection& projection, bool split ) mutable bool m_gj;
: m_plane( plane3_for_points( points._points ) ), m_points( points ), m_shader( shader ), m_projection( projection ), m_split( split ){ BrushSplitByPlaneSelected( const ClipperPoints& points, bool flip, const char* shader, const TextureProjection& projection, bool split )
: m_points( flip? ClipperPoints( points[0], points[2], points[1], points._count ) : points ),
m_plane( plane3_for_points( m_points[0], m_points[1], m_points[2] ) ),
m_shader( shader ), m_projection( projection ), m_split( split ), m_gj( false ){
} }
bool pre( const scene::Path& path, scene::Instance& instance ) const { bool pre( const scene::Path& path, scene::Instance& instance ) const {
return true; return true;
@ -764,11 +767,12 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
const brushsplit_t split = Brush_classifyPlane( *brush, m_plane ); const brushsplit_t split = Brush_classifyPlane( *brush, m_plane );
if ( split.counts[ePlaneBack] && split.counts[ePlaneFront] ) { if ( split.counts[ePlaneBack] && split.counts[ePlaneFront] ) {
// the plane intersects this brush // the plane intersects this brush
m_gj = true;
if ( m_split ) { if ( m_split ) {
NodeSmartReference node( ( new BrushNode() )->node() ); NodeSmartReference node( ( new BrushNode() )->node() );
Brush* fragment = Node_getBrush( node ); Brush* fragment = Node_getBrush( node );
fragment->copy( *brush ); fragment->copy( *brush );
fragment->addPlane( m_points[0], m_points[2], m_points[1], m_shader, m_projection ); /* flip plane points */ fragment->addPlane( m_points[0], m_points[1], m_points[2], m_shader, m_projection );
fragment->removeEmptyFaces(); fragment->removeEmptyFaces();
ASSERT_MESSAGE( !fragment->empty(), "brush left with no faces after split" ); ASSERT_MESSAGE( !fragment->empty(), "brush left with no faces after split" );
@ -780,7 +784,7 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
} }
} }
brush->addPlane( m_points[0], m_points[1], m_points[2], m_shader, m_projection ); brush->addPlane( m_points[0], m_points[2], m_points[1], m_shader, m_projection );
brush->removeEmptyFaces(); brush->removeEmptyFaces();
ASSERT_MESSAGE( !brush->empty(), "brush left with no faces after split" ); ASSERT_MESSAGE( !brush->empty(), "brush left with no faces after split" );
} }
@ -788,6 +792,7 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
// the plane does not intersect this brush // the plane does not intersect this brush
if ( !m_split && split.counts[ePlaneFront] != 0 ) { if ( !m_split && split.counts[ePlaneFront] != 0 ) {
// the brush is "behind" the plane // the brush is "behind" the plane
m_gj = true;
Path_deleteTop( path ); Path_deleteTop( path );
} }
} }
@ -795,12 +800,18 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
} }
}; };
void Scene_BrushSplitByPlane( scene::Graph& graph, const ClipperPoints& points, bool caulk, bool split ){ void CSG_WrapMerge( const ClipperPoints& clipperPoints );
void Scene_BrushSplitByPlane( scene::Graph& graph, const ClipperPoints& points, bool flip, bool caulk, bool split ){
const char* shader = caulk? GetCaulkShader() : TextureBrowser_GetSelectedShader(); const char* shader = caulk? GetCaulkShader() : TextureBrowser_GetSelectedShader();
TextureProjection projection; TextureProjection projection;
TexDef_Construct_Default( projection ); TexDef_Construct_Default( projection );
graph.traverse( BrushSplitByPlaneSelected( points, shader, projection, split ) ); BrushSplitByPlaneSelected dosplit( points, flip, shader, projection, split );
SceneChangeNotify(); if( points._count > 1 && plane3_valid( plane3_for_points( points._points ) ) )
graph.traverse( dosplit );
if( !dosplit.m_gj ){
CSG_WrapMerge( points );
}
} }
@ -808,8 +819,8 @@ class BrushInstanceSetClipPlane : public scene::Graph::Walker
{ {
const Plane3 m_plane; const Plane3 m_plane;
public: public:
BrushInstanceSetClipPlane( const ClipperPoints& points ) BrushInstanceSetClipPlane( const ClipperPoints& points, bool flip )
: m_plane( plane3_for_points( points._points ) ){ : m_plane( points._count < 2? Plane3( 0, 0, 0, 0 ) : flip? plane3_for_points( points[0], points[2], points[1] ) : plane3_for_points( points[0], points[1], points[2] ) ){
} }
bool pre( const scene::Path& path, scene::Instance& instance ) const { bool pre( const scene::Path& path, scene::Instance& instance ) const {
BrushInstance* brush = Instance_getBrush( instance ); BrushInstance* brush = Instance_getBrush( instance );
@ -823,8 +834,8 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
} }
}; };
void Scene_BrushSetClipPlane( scene::Graph& graph, const ClipperPoints& points ){ void Scene_BrushSetClipPlane( scene::Graph& graph, const ClipperPoints& points, bool flip ){
graph.traverse( BrushInstanceSetClipPlane( points ) ); graph.traverse( BrushInstanceSetClipPlane( points, flip ) );
} }
/* /*
@ -970,7 +981,6 @@ void CSG_Merge( void ){
selectPath( path, true ); selectPath( path, true );
globalOutputStream() << "CSG Merge: Succeeded.\n"; globalOutputStream() << "CSG Merge: Succeeded.\n";
SceneChangeNotify();
} }
} }
@ -1073,7 +1083,7 @@ public:
} }
}; };
void CSG_WrapMerge(){ void CSG_WrapMerge( const ClipperPoints& clipperPoints ){
const bool primit = ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ); const bool primit = ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive );
brush_vector_t selected_brushes; brush_vector_t selected_brushes;
if( primit ) if( primit )
@ -1096,6 +1106,9 @@ void CSG_WrapMerge(){
GlobalSceneGraph().traverse( Scene_gatherSelectedComponents( mergeVertices ) ); GlobalSceneGraph().traverse( Scene_gatherSelectedComponents( mergeVertices ) );
for( std::size_t i = 0; i < clipperPoints._count; ++i )
mergeVertices.insert( clipperPoints[i] );
//globalOutputStream() << mergeVertices.size() << " mergeVertices.size()\n"; //globalOutputStream() << mergeVertices.size() << " mergeVertices.size()\n";
if( mergeVertices.size() < 4 ){ if( mergeVertices.size() < 4 ){
globalWarningStream() << "CSG Wrap Merge: Too few vertices: " << mergeVertices.size() << ".\n"; globalWarningStream() << "CSG Wrap Merge: Too few vertices: " << mergeVertices.size() << ".\n";
@ -1135,8 +1148,6 @@ void CSG_WrapMerge(){
return; return;
} }
UndoableCommand undo( "brushWrapMerge" );
NodeSmartReference node( ( new BrushNode() )->node() ); NodeSmartReference node( ( new BrushNode() )->node() );
Brush* brush = Node_getBrush( node ); Brush* brush = Node_getBrush( node );
@ -1173,6 +1184,11 @@ void CSG_WrapMerge(){
} }
} }
void CSG_WrapMerge(){
UndoableCommand undo( "brushWrapMerge" );
CSG_WrapMerge( ClipperPoints() );
}
class find_instance_to_DeleteComponents : public SelectionSystem::Visitor class find_instance_to_DeleteComponents : public SelectionSystem::Visitor

View File

@ -36,7 +36,7 @@ class Graph;
class ClipperPoints; class ClipperPoints;
void Scene_BrushSetClipPlane( scene::Graph& graph, const ClipperPoints& points ); void Scene_BrushSetClipPlane( scene::Graph& graph, const ClipperPoints& points, bool flip );
void Scene_BrushSplitByPlane( scene::Graph& graph, const ClipperPoints& points, bool caulk, bool split ); void Scene_BrushSplitByPlane( scene::Graph& graph, const ClipperPoints& points, bool flip, bool caulk, bool split );
#endif #endif

View File

@ -4047,19 +4047,34 @@ public:
} }
} }
void updatePlane(){ void updatePlane(){
if( m_points[0].m_set && m_points[1].m_set ){ std::size_t npoints = 0;
if( !m_points[2].m_set ){ for(; npoints < 3; )
if( m_points[npoints].m_set )
++npoints;
else
break;
switch ( npoints )
{
case 1:
Clipper_setPlanePoints( ClipperPoints( m_points[0].m_point, m_points[0].m_point, m_points[0].m_point, npoints ) );
break;
case 2:
{
if( m_view->fill() ){ //3d if( m_view->fill() ){ //3d
viewdir_fixup(); viewdir_fixup();
m_points[2].m_point = m_points[0].m_point + m_viewdir * vector3_length( m_points[0].m_point - m_points[1].m_point ); m_points[2].m_point = m_points[0].m_point + m_viewdir * vector3_length( m_points[0].m_point - m_points[1].m_point );
viewdir_make_cut_worthy( plane3_for_points( m_points[0].m_point, m_points[2].m_point, m_points[1].m_point ) ); viewdir_make_cut_worthy( plane3_for_points( m_points[0].m_point, m_points[1].m_point, m_points[2].m_point ) );
} }
m_points[2].m_point = m_points[0].m_point + m_viewdir * vector3_length( m_points[0].m_point - m_points[1].m_point ); m_points[2].m_point = m_points[0].m_point + m_viewdir * vector3_length( m_points[0].m_point - m_points[1].m_point );
} }
Clipper_setPlanePoints( ClipperPoints( m_points[0].m_point, m_points[2].m_point, m_points[1].m_point ) ); /* points order corresponds the plane, we want to insert */ case 3:
} Clipper_setPlanePoints( ClipperPoints( m_points[0].m_point, m_points[1].m_point, m_points[2].m_point, npoints ) );
else{ break;
Clipper_setPlanePoints( ClipperPoints( g_vector3_identity, g_vector3_identity, g_vector3_identity ) );
default:
Clipper_setPlanePoints( ClipperPoints() );
break;
} }
} }
std::size_t newPointIndex( bool viewfill ) const { std::size_t newPointIndex( bool viewfill ) const {