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

View File

@ -28,10 +28,15 @@ class ClipperPoints
{
public:
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[1] = p1;
_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 {
return _points[i];

View File

@ -744,14 +744,17 @@ void CSG_Subtract(){
#include "clippertool.h"
class BrushSplitByPlaneSelected : public scene::Graph::Walker
{
const Plane3 m_plane;
const ClipperPoints m_points;
const Plane3 m_plane;
const char* m_shader;
const TextureProjection& m_projection;
const bool m_split; /* split or clip */
public:
BrushSplitByPlaneSelected( const ClipperPoints& points, const char* shader, const TextureProjection& projection, bool split )
: m_plane( plane3_for_points( points._points ) ), m_points( points ), m_shader( shader ), m_projection( projection ), m_split( split ){
mutable bool m_gj;
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 {
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 );
if ( split.counts[ePlaneBack] && split.counts[ePlaneFront] ) {
// the plane intersects this brush
m_gj = true;
if ( m_split ) {
NodeSmartReference node( ( new BrushNode() )->node() );
Brush* fragment = Node_getBrush( node );
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();
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();
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
if ( !m_split && split.counts[ePlaneFront] != 0 ) {
// the brush is "behind" the plane
m_gj = true;
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();
TextureProjection projection;
TexDef_Construct_Default( projection );
graph.traverse( BrushSplitByPlaneSelected( points, shader, projection, split ) );
SceneChangeNotify();
BrushSplitByPlaneSelected dosplit( points, flip, shader, projection, split );
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;
public:
BrushInstanceSetClipPlane( const ClipperPoints& points )
: m_plane( plane3_for_points( points._points ) ){
BrushInstanceSetClipPlane( const ClipperPoints& points, bool flip )
: 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 {
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 ){
graph.traverse( BrushInstanceSetClipPlane( points ) );
void Scene_BrushSetClipPlane( scene::Graph& graph, const ClipperPoints& points, bool flip ){
graph.traverse( BrushInstanceSetClipPlane( points, flip ) );
}
/*
@ -970,7 +981,6 @@ void CSG_Merge( void ){
selectPath( path, true );
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 );
brush_vector_t selected_brushes;
if( primit )
@ -1096,6 +1106,9 @@ void CSG_WrapMerge(){
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";
if( mergeVertices.size() < 4 ){
globalWarningStream() << "CSG Wrap Merge: Too few vertices: " << mergeVertices.size() << ".\n";
@ -1135,8 +1148,6 @@ void CSG_WrapMerge(){
return;
}
UndoableCommand undo( "brushWrapMerge" );
NodeSmartReference node( ( new BrushNode() )->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

View File

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

View File

@ -4047,19 +4047,34 @@ public:
}
}
void updatePlane(){
if( m_points[0].m_set && m_points[1].m_set ){
if( !m_points[2].m_set ){
std::size_t npoints = 0;
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
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 );
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 );
}
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 */
}
else{
Clipper_setPlanePoints( ClipperPoints( g_vector3_identity, g_vector3_identity, g_vector3_identity ) );
case 3:
Clipper_setPlanePoints( ClipperPoints( m_points[0].m_point, m_points[1].m_point, m_points[2].m_point, npoints ) );
break;
default:
Clipper_setPlanePoints( ClipperPoints() );
break;
}
}
std::size_t newPointIndex( bool viewfill ) const {