2019-03-15 11:53:15 +00:00
# include "GLGizmoBase.hpp"
2019-03-20 12:51:25 +00:00
# include "slic3r/GUI/GLCanvas3D.hpp"
2019-03-15 11:53:15 +00:00
# include <GL/glew.h>
# include "slic3r/GUI/GUI_App.hpp"
// TODO: Display tooltips quicker on Linux
namespace Slic3r {
namespace GUI {
2019-05-10 09:13:55 +00:00
const float GLGizmoBase : : Grabber : : SizeFactor = 0.05f ;
2019-03-15 11:53:15 +00:00
const float GLGizmoBase : : Grabber : : MinHalfSize = 1.5f ;
const float GLGizmoBase : : Grabber : : DraggingScaleFactor = 1.25f ;
GLGizmoBase : : Grabber : : Grabber ( )
: center ( Vec3d : : Zero ( ) )
, angles ( Vec3d : : Zero ( ) )
, dragging ( false )
, enabled ( true )
{
color [ 0 ] = 1.0f ;
color [ 1 ] = 1.0f ;
color [ 2 ] = 1.0f ;
2019-08-07 12:15:38 +00:00
color [ 3 ] = 1.0f ;
2019-03-15 11:53:15 +00:00
}
void GLGizmoBase : : Grabber : : render ( bool hover , float size ) const
{
2019-08-07 12:15:38 +00:00
float render_color [ 4 ] ;
2019-03-15 11:53:15 +00:00
if ( hover )
{
render_color [ 0 ] = 1.0f - color [ 0 ] ;
render_color [ 1 ] = 1.0f - color [ 1 ] ;
render_color [ 2 ] = 1.0f - color [ 2 ] ;
2019-08-07 12:15:38 +00:00
render_color [ 3 ] = color [ 3 ] ;
2019-03-15 11:53:15 +00:00
}
else
2019-08-07 12:15:38 +00:00
: : memcpy ( ( void * ) render_color , ( const void * ) color , 4 * sizeof ( float ) ) ;
2019-03-15 11:53:15 +00:00
render ( size , render_color , true ) ;
}
float GLGizmoBase : : Grabber : : get_half_size ( float size ) const
{
return std : : max ( size * SizeFactor , MinHalfSize ) ;
}
float GLGizmoBase : : Grabber : : get_dragging_half_size ( float size ) const
{
2019-04-15 13:05:26 +00:00
return get_half_size ( size ) * DraggingScaleFactor ;
2019-03-15 11:53:15 +00:00
}
void GLGizmoBase : : Grabber : : render ( float size , const float * render_color , bool use_lighting ) const
{
float half_size = dragging ? get_dragging_half_size ( size ) : get_half_size ( size ) ;
if ( use_lighting )
2019-03-27 13:42:09 +00:00
glsafe ( : : glEnable ( GL_LIGHTING ) ) ;
2019-03-15 11:53:15 +00:00
2019-08-07 12:15:38 +00:00
glsafe ( : : glColor4fv ( render_color ) ) ;
2019-03-15 11:53:15 +00:00
2019-03-27 13:42:09 +00:00
glsafe ( : : glPushMatrix ( ) ) ;
glsafe ( : : glTranslated ( center ( 0 ) , center ( 1 ) , center ( 2 ) ) ) ;
2019-03-15 11:53:15 +00:00
2019-03-27 13:42:09 +00:00
glsafe ( : : glRotated ( Geometry : : rad2deg ( angles ( 2 ) ) , 0.0 , 0.0 , 1.0 ) ) ;
glsafe ( : : glRotated ( Geometry : : rad2deg ( angles ( 1 ) ) , 0.0 , 1.0 , 0.0 ) ) ;
glsafe ( : : glRotated ( Geometry : : rad2deg ( angles ( 0 ) ) , 1.0 , 0.0 , 0.0 ) ) ;
2019-03-15 11:53:15 +00:00
// face min x
2019-03-27 13:42:09 +00:00
glsafe ( : : glPushMatrix ( ) ) ;
glsafe ( : : glTranslatef ( - ( GLfloat ) half_size , 0.0f , 0.0f ) ) ;
glsafe ( : : glRotatef ( - 90.0f , 0.0f , 1.0f , 0.0f ) ) ;
2019-03-15 11:53:15 +00:00
render_face ( half_size ) ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glPopMatrix ( ) ) ;
2019-03-15 11:53:15 +00:00
// face max x
2019-03-27 13:42:09 +00:00
glsafe ( : : glPushMatrix ( ) ) ;
glsafe ( : : glTranslatef ( ( GLfloat ) half_size , 0.0f , 0.0f ) ) ;
glsafe ( : : glRotatef ( 90.0f , 0.0f , 1.0f , 0.0f ) ) ;
2019-03-15 11:53:15 +00:00
render_face ( half_size ) ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glPopMatrix ( ) ) ;
2019-03-15 11:53:15 +00:00
// face min y
2019-03-27 13:42:09 +00:00
glsafe ( : : glPushMatrix ( ) ) ;
glsafe ( : : glTranslatef ( 0.0f , - ( GLfloat ) half_size , 0.0f ) ) ;
glsafe ( : : glRotatef ( 90.0f , 1.0f , 0.0f , 0.0f ) ) ;
2019-03-15 11:53:15 +00:00
render_face ( half_size ) ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glPopMatrix ( ) ) ;
2019-03-15 11:53:15 +00:00
// face max y
2019-03-27 13:42:09 +00:00
glsafe ( : : glPushMatrix ( ) ) ;
glsafe ( : : glTranslatef ( 0.0f , ( GLfloat ) half_size , 0.0f ) ) ;
glsafe ( : : glRotatef ( - 90.0f , 1.0f , 0.0f , 0.0f ) ) ;
2019-03-15 11:53:15 +00:00
render_face ( half_size ) ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glPopMatrix ( ) ) ;
2019-03-15 11:53:15 +00:00
// face min z
2019-03-27 13:42:09 +00:00
glsafe ( : : glPushMatrix ( ) ) ;
glsafe ( : : glTranslatef ( 0.0f , 0.0f , - ( GLfloat ) half_size ) ) ;
glsafe ( : : glRotatef ( 180.0f , 1.0f , 0.0f , 0.0f ) ) ;
2019-03-15 11:53:15 +00:00
render_face ( half_size ) ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glPopMatrix ( ) ) ;
2019-03-15 11:53:15 +00:00
// face max z
2019-03-27 13:42:09 +00:00
glsafe ( : : glPushMatrix ( ) ) ;
glsafe ( : : glTranslatef ( 0.0f , 0.0f , ( GLfloat ) half_size ) ) ;
2019-03-15 11:53:15 +00:00
render_face ( half_size ) ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glPopMatrix ( ) ) ;
2019-03-15 11:53:15 +00:00
2019-03-27 13:42:09 +00:00
glsafe ( : : glPopMatrix ( ) ) ;
2019-03-15 11:53:15 +00:00
if ( use_lighting )
2019-03-27 13:42:09 +00:00
glsafe ( : : glDisable ( GL_LIGHTING ) ) ;
2019-03-15 11:53:15 +00:00
}
void GLGizmoBase : : Grabber : : render_face ( float half_size ) const
{
: : glBegin ( GL_TRIANGLES ) ;
: : glNormal3f ( 0.0f , 0.0f , 1.0f ) ;
: : glVertex3f ( - ( GLfloat ) half_size , - ( GLfloat ) half_size , 0.0f ) ;
: : glVertex3f ( ( GLfloat ) half_size , - ( GLfloat ) half_size , 0.0f ) ;
: : glVertex3f ( ( GLfloat ) half_size , ( GLfloat ) half_size , 0.0f ) ;
: : glVertex3f ( ( GLfloat ) half_size , ( GLfloat ) half_size , 0.0f ) ;
: : glVertex3f ( - ( GLfloat ) half_size , ( GLfloat ) half_size , 0.0f ) ;
: : glVertex3f ( - ( GLfloat ) half_size , - ( GLfloat ) half_size , 0.0f ) ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glEnd ( ) ) ;
2019-03-15 11:53:15 +00:00
}
2019-07-17 06:38:48 +00:00
2019-03-15 11:53:15 +00:00
GLGizmoBase : : GLGizmoBase ( GLCanvas3D & parent , const std : : string & icon_filename , unsigned int sprite_id )
: m_parent ( parent )
, m_group_id ( - 1 )
, m_state ( Off )
, m_shortcut_key ( 0 )
, m_icon_filename ( icon_filename )
, m_sprite_id ( sprite_id )
, m_hover_id ( - 1 )
, m_dragging ( false )
, m_imgui ( wxGetApp ( ) . imgui ( ) )
2019-08-26 07:06:21 +00:00
, m_first_input_window_render ( true )
2019-03-15 11:53:15 +00:00
{
2019-08-07 12:15:38 +00:00
: : memcpy ( ( void * ) m_base_color , ( const void * ) DEFAULT_BASE_COLOR , 4 * sizeof ( float ) ) ;
: : memcpy ( ( void * ) m_drag_color , ( const void * ) DEFAULT_DRAG_COLOR , 4 * sizeof ( float ) ) ;
: : memcpy ( ( void * ) m_highlight_color , ( const void * ) DEFAULT_HIGHLIGHT_COLOR , 4 * sizeof ( float ) ) ;
2019-03-15 11:53:15 +00:00
}
void GLGizmoBase : : set_hover_id ( int id )
{
if ( m_grabbers . empty ( ) | | ( id < ( int ) m_grabbers . size ( ) ) )
{
m_hover_id = id ;
on_set_hover_id ( ) ;
}
}
void GLGizmoBase : : set_highlight_color ( const float * color )
{
if ( color ! = nullptr )
2019-08-07 12:15:38 +00:00
: : memcpy ( ( void * ) m_highlight_color , ( const void * ) color , 4 * sizeof ( float ) ) ;
2019-03-15 11:53:15 +00:00
}
void GLGizmoBase : : enable_grabber ( unsigned int id )
{
2019-07-23 09:22:54 +00:00
if ( id < m_grabbers . size ( ) )
2019-03-15 11:53:15 +00:00
m_grabbers [ id ] . enabled = true ;
on_enable_grabber ( id ) ;
}
void GLGizmoBase : : disable_grabber ( unsigned int id )
{
2019-07-23 09:22:54 +00:00
if ( id < m_grabbers . size ( ) )
2019-03-15 11:53:15 +00:00
m_grabbers [ id ] . enabled = false ;
on_disable_grabber ( id ) ;
}
2019-07-17 10:06:23 +00:00
void GLGizmoBase : : start_dragging ( )
2019-03-15 11:53:15 +00:00
{
m_dragging = true ;
for ( int i = 0 ; i < ( int ) m_grabbers . size ( ) ; + + i )
{
m_grabbers [ i ] . dragging = ( m_hover_id = = i ) ;
}
2019-07-17 10:06:23 +00:00
on_start_dragging ( ) ;
2019-03-15 11:53:15 +00:00
}
void GLGizmoBase : : stop_dragging ( )
{
m_dragging = false ;
for ( int i = 0 ; i < ( int ) m_grabbers . size ( ) ; + + i )
{
m_grabbers [ i ] . dragging = false ;
}
on_stop_dragging ( ) ;
}
2019-07-17 10:06:23 +00:00
void GLGizmoBase : : update ( const UpdateData & data )
2019-03-15 11:53:15 +00:00
{
if ( m_hover_id ! = - 1 )
2019-07-17 10:06:23 +00:00
on_update ( data ) ;
2019-03-15 11:53:15 +00:00
}
2019-08-07 12:15:38 +00:00
std : : array < float , 4 > GLGizmoBase : : picking_color_component ( unsigned int id ) const
2019-03-15 11:53:15 +00:00
{
static const float INV_255 = 1.0f / 255.0f ;
id = BASE_ID - id ;
if ( m_group_id > - 1 )
id - = m_group_id ;
// color components are encoded to match the calculation of volume_id made into GLCanvas3D::_picking_pass()
2019-08-07 12:15:38 +00:00
return std : : array < float , 4 > {
float ( ( id > > 0 ) & 0xff ) * INV_255 , // red
float ( ( id > > 8 ) & 0xff ) * INV_255 , // green
float ( ( id > > 16 ) & 0xff ) * INV_255 , // blue
float ( picking_checksum_alpha_channel ( id & 0xff , ( id > > 8 ) & 0xff , ( id > > 16 ) & 0xff ) ) * INV_255 // checksum for validating against unwanted alpha blending and multi sampling
} ;
2019-03-15 11:53:15 +00:00
}
void GLGizmoBase : : render_grabbers ( const BoundingBoxf3 & box ) const
{
2019-03-25 14:03:35 +00:00
render_grabbers ( ( float ) ( ( box . size ( ) ( 0 ) + box . size ( ) ( 1 ) + box . size ( ) ( 2 ) ) / 3.0 ) ) ;
2019-03-15 11:53:15 +00:00
}
void GLGizmoBase : : render_grabbers ( float size ) const
{
for ( int i = 0 ; i < ( int ) m_grabbers . size ( ) ; + + i )
{
if ( m_grabbers [ i ] . enabled )
m_grabbers [ i ] . render ( ( m_hover_id = = i ) , size ) ;
}
}
void GLGizmoBase : : render_grabbers_for_picking ( const BoundingBoxf3 & box ) const
{
2019-03-25 14:03:35 +00:00
float mean_size = ( float ) ( ( box . size ( ) ( 0 ) + box . size ( ) ( 1 ) + box . size ( ) ( 2 ) ) / 3.0 ) ;
2019-03-15 11:53:15 +00:00
for ( unsigned int i = 0 ; i < ( unsigned int ) m_grabbers . size ( ) ; + + i )
{
if ( m_grabbers [ i ] . enabled )
{
2019-08-07 12:15:38 +00:00
std : : array < float , 4 > color = picking_color_component ( i ) ;
2019-03-15 11:53:15 +00:00
m_grabbers [ i ] . color [ 0 ] = color [ 0 ] ;
m_grabbers [ i ] . color [ 1 ] = color [ 1 ] ;
m_grabbers [ i ] . color [ 2 ] = color [ 2 ] ;
2019-08-07 12:15:38 +00:00
m_grabbers [ i ] . color [ 3 ] = color [ 3 ] ;
2019-03-25 14:03:35 +00:00
m_grabbers [ i ] . render_for_picking ( mean_size ) ;
2019-03-15 11:53:15 +00:00
}
}
}
void GLGizmoBase : : set_tooltip ( const std : : string & tooltip ) const
{
m_parent . set_tooltip ( tooltip ) ;
}
std : : string GLGizmoBase : : format ( float value , unsigned int decimals ) const
{
return Slic3r : : string_printf ( " %.*f " , decimals , value ) ;
}
2019-08-26 07:06:21 +00:00
void GLGizmoBase : : render_input_window ( float x , float y , float bottom_limit )
{
on_render_input_window ( x , y , bottom_limit ) ;
if ( m_first_input_window_render )
{
// for some reason, the imgui dialogs are not shown on screen in the 1st frame where they are rendered, but show up only with the 2nd rendered frame
// so, we forces another frame rendering the first time the imgui window is shown
m_parent . set_as_dirty ( ) ;
m_first_input_window_render = false ;
}
}
2019-08-07 12:15:38 +00:00
// Produce an alpha channel checksum for the red green blue components. The alpha channel may then be used to verify, whether the rgb components
// were not interpolated by alpha blending or multi sampling.
unsigned char picking_checksum_alpha_channel ( unsigned char red , unsigned char green , unsigned char blue )
{
// 8 bit hash for the color
unsigned char b = ( ( ( ( 37 * red ) + green ) & 0x0ff ) * 37 + blue ) & 0x0ff ;
// Increase enthropy by a bit reversal
b = ( b & 0xF0 ) > > 4 | ( b & 0x0F ) < < 4 ;
b = ( b & 0xCC ) > > 2 | ( b & 0x33 ) < < 2 ;
b = ( b & 0xAA ) > > 1 | ( b & 0x55 ) < < 1 ;
// Flip every second bit to increase the enthropy even more.
b ^ = 0x55 ;
return b ;
}
2019-03-15 11:53:15 +00:00
} // namespace GUI
} // namespace Slic3r