2018-10-31 09:19:44 +00:00
# include "ImGuiWrapper.hpp"
2018-11-27 11:10:21 +00:00
# include <cstdio>
2018-11-26 09:56:07 +00:00
# include <vector>
2019-01-24 10:30:29 +00:00
# include <cmath>
# include <stdexcept>
2018-11-26 09:56:07 +00:00
# include <boost/format.hpp>
# include <boost/log/trivial.hpp>
2018-10-31 09:19:44 +00:00
2018-11-26 09:56:07 +00:00
# include <wx/string.h>
2018-10-31 09:19:44 +00:00
# include <wx/event.h>
2019-02-15 14:35:32 +00:00
# include <wx/clipbrd.h>
2018-11-26 09:56:07 +00:00
# include <wx/debug.h>
2018-10-31 09:19:44 +00:00
# include <GL/glew.h>
2019-01-18 14:02:07 +00:00
# include <imgui/imgui_internal.h>
2018-11-26 09:56:07 +00:00
# include "libslic3r/libslic3r.h"
2018-11-26 13:41:58 +00:00
# include "libslic3r/Utils.hpp"
2019-03-27 13:42:09 +00:00
# include "3DScene.hpp"
2018-11-26 09:56:07 +00:00
# include "GUI.hpp"
2018-11-20 17:40:57 +00:00
2018-10-31 09:19:44 +00:00
namespace Slic3r {
namespace GUI {
2018-11-20 17:40:57 +00:00
2018-10-31 09:19:44 +00:00
2019-04-01 12:12:05 +00:00
ImGuiWrapper : : ImGuiWrapper ( )
2019-02-19 12:26:26 +00:00
: m_glyph_ranges ( nullptr )
2019-05-23 16:04:27 +00:00
, m_font_cjk ( false )
2019-04-01 12:12:05 +00:00
, m_font_size ( 18.0 )
2019-02-19 12:26:26 +00:00
, m_font_texture ( 0 )
2019-01-24 10:30:29 +00:00
, m_style_scaling ( 1.0 )
2018-11-26 09:56:07 +00:00
, m_mouse_buttons ( 0 )
2019-01-18 14:02:07 +00:00
, m_disabled ( false )
2019-02-19 11:39:24 +00:00
, m_new_frame_open ( false )
2018-10-31 09:19:44 +00:00
{
ImGui : : CreateContext ( ) ;
2019-02-15 14:35:32 +00:00
init_input ( ) ;
2019-02-19 13:46:29 +00:00
init_style ( ) ;
2018-10-31 09:19:44 +00:00
2019-01-24 10:30:29 +00:00
ImGui : : GetIO ( ) . IniFilename = nullptr ;
2019-03-29 13:57:53 +00:00
}
2018-10-31 09:19:44 +00:00
2019-03-29 13:57:53 +00:00
ImGuiWrapper : : ~ ImGuiWrapper ( )
{
2019-04-01 12:12:05 +00:00
destroy_font ( ) ;
2019-03-29 13:57:53 +00:00
ImGui : : DestroyContext ( ) ;
2018-10-31 09:19:44 +00:00
}
2019-02-19 12:26:26 +00:00
void ImGuiWrapper : : set_language ( const std : : string & language )
{
2019-03-26 16:57:54 +00:00
if ( m_new_frame_open ) {
// ImGUI internally locks the font between NewFrame() and EndFrame()
// NewFrame() might've been called here because of input from the 3D scene;
// call EndFrame()
ImGui : : EndFrame ( ) ;
m_new_frame_open = false ;
}
2019-02-19 12:26:26 +00:00
const ImWchar * ranges = nullptr ;
size_t idx = language . find ( ' _ ' ) ;
std : : string lang = ( idx = = std : : string : : npos ) ? language : language . substr ( 0 , idx ) ;
static const ImWchar ranges_latin2 [ ] =
{
0x0020 , 0x00FF , // Basic Latin + Latin Supplement
0x0100 , 0x017F , // Latin Extended-A
0 ,
} ;
2019-05-23 16:04:27 +00:00
static const ImWchar ranges_turkish [ ] = {
0x0020 , 0x01FF , // Basic Latin + Latin Supplement
0x0100 , 0x017F , // Latin Extended-A
0x0180 , 0x01FF , // Turkish
0 ,
} ;
static const ImWchar ranges_vietnamese [ ] =
{
0x0020 , 0x00FF , // Basic Latin
0x0102 , 0x0103 ,
0x0110 , 0x0111 ,
0x0128 , 0x0129 ,
0x0168 , 0x0169 ,
0x01A0 , 0x01A1 ,
0x01AF , 0x01B0 ,
0x1EA0 , 0x1EF9 ,
0 ,
} ;
m_font_cjk = false ;
2019-02-19 12:26:26 +00:00
if ( lang = = " cs " | | lang = = " pl " ) {
ranges = ranges_latin2 ;
} else if ( lang = = " ru " | | lang = = " uk " ) {
2019-05-23 16:04:27 +00:00
ranges = ImGui : : GetIO ( ) . Fonts - > GetGlyphRangesCyrillic ( ) ; // Default + about 400 Cyrillic characters
} else if ( lang = = " tr " ) {
ranges = ranges_turkish ;
} else if ( lang = = " vi " ) {
ranges = ranges_vietnamese ;
2019-02-19 12:26:26 +00:00
} else if ( lang = = " jp " ) {
2019-05-23 16:04:27 +00:00
ranges = ImGui : : GetIO ( ) . Fonts - > GetGlyphRangesJapanese ( ) ; // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
m_font_cjk = true ;
2019-05-19 08:52:09 +00:00
} else if ( lang = = " ko " ) {
2019-05-23 16:04:27 +00:00
ranges = ImGui : : GetIO ( ) . Fonts - > GetGlyphRangesKorean ( ) ; // Default + Korean characters
m_font_cjk = true ;
2019-02-19 12:26:26 +00:00
} else if ( lang = = " zh " ) {
2019-05-23 16:04:27 +00:00
ranges = ( language = = " zh_TW " ) ?
// Traditional Chinese
// Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs
ImGui : : GetIO ( ) . Fonts - > GetGlyphRangesChineseFull ( ) :
// Simplified Chinese
// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese
ImGui : : GetIO ( ) . Fonts - > GetGlyphRangesChineseSimplifiedCommon ( ) ;
m_font_cjk = true ;
} else if ( lang = = " th " ) {
ranges = ImGui : : GetIO ( ) . Fonts - > GetGlyphRangesThai ( ) ; // Default + Thai characters
} else {
ranges = ImGui : : GetIO ( ) . Fonts - > GetGlyphRangesDefault ( ) ; // Basic Latin, Extended Latin
2019-02-19 12:26:26 +00:00
}
if ( ranges ! = m_glyph_ranges ) {
m_glyph_ranges = ranges ;
2019-04-01 12:12:05 +00:00
destroy_font ( ) ;
2019-02-19 12:26:26 +00:00
}
}
2018-10-31 09:19:44 +00:00
void ImGuiWrapper : : set_display_size ( float w , float h )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . DisplaySize = ImVec2 ( w , h ) ;
io . DisplayFramebufferScale = ImVec2 ( 1.0f , 1.0f ) ;
}
2019-04-02 11:26:22 +00:00
void ImGuiWrapper : : set_scaling ( float font_size , float scale_style , float scale_both )
2019-01-24 10:30:29 +00:00
{
2019-04-02 11:26:22 +00:00
font_size * = scale_both ;
scale_style * = scale_both ;
if ( m_font_size = = font_size & & m_style_scaling = = scale_style ) {
2019-04-01 13:36:48 +00:00
return ;
2019-01-24 10:30:29 +00:00
}
2019-04-01 12:12:05 +00:00
2019-04-01 13:36:48 +00:00
m_font_size = font_size ;
2019-04-02 11:26:22 +00:00
ImGui : : GetStyle ( ) . ScaleAllSizes ( scale_style / m_style_scaling ) ;
m_style_scaling = scale_style ;
2019-04-01 13:36:48 +00:00
destroy_font ( ) ;
2019-01-24 10:30:29 +00:00
}
2018-11-26 09:56:07 +00:00
bool ImGuiWrapper : : update_mouse_data ( wxMouseEvent & evt )
2018-10-31 09:19:44 +00:00
{
2019-02-22 13:52:32 +00:00
if ( ! display_initialized ( ) ) {
return false ;
}
2018-10-31 09:19:44 +00:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . MousePos = ImVec2 ( ( float ) evt . GetX ( ) , ( float ) evt . GetY ( ) ) ;
2019-03-13 13:44:59 +00:00
io . MouseDown [ 0 ] = evt . LeftIsDown ( ) ;
io . MouseDown [ 1 ] = evt . RightIsDown ( ) ;
io . MouseDown [ 2 ] = evt . MiddleIsDown ( ) ;
2018-10-31 09:19:44 +00:00
2019-03-13 13:44:59 +00:00
unsigned buttons = ( evt . LeftIsDown ( ) ? 1 : 0 ) | ( evt . RightIsDown ( ) ? 2 : 0 ) | ( evt . MiddleIsDown ( ) ? 4 : 0 ) ;
2018-11-26 09:56:07 +00:00
m_mouse_buttons = buttons ;
2019-02-19 11:39:24 +00:00
new_frame ( ) ;
return want_mouse ( ) ;
2018-10-31 09:19:44 +00:00
}
2019-02-15 14:35:32 +00:00
bool ImGuiWrapper : : update_key_data ( wxKeyEvent & evt )
{
2019-02-22 13:52:32 +00:00
if ( ! display_initialized ( ) ) {
return false ;
}
2019-02-15 14:35:32 +00:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
if ( evt . GetEventType ( ) = = wxEVT_CHAR ) {
// Char event
2019-02-19 11:39:24 +00:00
const auto key = evt . GetUnicodeKey ( ) ;
if ( key ! = 0 ) {
io . AddInputCharacter ( key ) ;
}
2019-02-20 15:55:00 +00:00
new_frame ( ) ;
return want_keyboard ( ) | | want_text_input ( ) ;
2019-02-15 14:35:32 +00:00
} else {
// Key up/down event
int key = evt . GetKeyCode ( ) ;
wxCHECK_MSG ( key > = 0 & & key < IM_ARRAYSIZE ( io . KeysDown ) , false , " Received invalid key code " ) ;
io . KeysDown [ key ] = evt . GetEventType ( ) = = wxEVT_KEY_DOWN ;
io . KeyShift = evt . ShiftDown ( ) ;
io . KeyCtrl = evt . ControlDown ( ) ;
io . KeyAlt = evt . AltDown ( ) ;
io . KeySuper = evt . MetaDown ( ) ;
2019-02-21 10:54:18 +00:00
new_frame ( ) ;
return want_keyboard ( ) | | want_text_input ( ) ;
2019-02-20 15:55:00 +00:00
}
2019-02-15 14:35:32 +00:00
}
2018-10-31 09:19:44 +00:00
void ImGuiWrapper : : new_frame ( )
{
2019-02-19 11:39:24 +00:00
if ( m_new_frame_open ) {
return ;
}
2019-04-01 12:12:05 +00:00
if ( m_font_texture = = 0 ) {
init_font ( ) ;
}
2018-10-31 09:19:44 +00:00
ImGui : : NewFrame ( ) ;
2019-02-19 11:39:24 +00:00
m_new_frame_open = true ;
2018-10-31 09:19:44 +00:00
}
void ImGuiWrapper : : render ( )
{
ImGui : : Render ( ) ;
render_draw_data ( ImGui : : GetDrawData ( ) ) ;
2019-02-19 11:39:24 +00:00
m_new_frame_open = false ;
2018-10-31 09:19:44 +00:00
}
2019-04-01 13:36:48 +00:00
ImVec2 ImGuiWrapper : : calc_text_size ( const wxString & text )
{
auto text_utf8 = into_u8 ( text ) ;
2019-05-13 12:28:03 +00:00
ImVec2 size = ImGui : : CalcTextSize ( text_utf8 . c_str ( ) ) ;
2019-05-24 10:01:26 +00:00
/*#ifdef __linux__
2019-05-13 12:28:03 +00:00
size . x * = m_style_scaling ;
size . y * = m_style_scaling ;
2019-05-24 10:01:26 +00:00
# endif* /
2019-05-13 12:28:03 +00:00
return size ;
2019-04-01 13:36:48 +00:00
}
2018-10-31 09:19:44 +00:00
void ImGuiWrapper : : set_next_window_pos ( float x , float y , int flag )
{
ImGui : : SetNextWindowPos ( ImVec2 ( x , y ) , ( ImGuiCond ) flag ) ;
2019-01-24 14:44:00 +00:00
ImGui : : SetNextWindowSize ( ImVec2 ( 0.0 , 0.0 ) ) ;
2018-10-31 09:19:44 +00:00
}
void ImGuiWrapper : : set_next_window_bg_alpha ( float alpha )
{
ImGui : : SetNextWindowBgAlpha ( alpha ) ;
}
2018-11-26 09:56:07 +00:00
bool ImGuiWrapper : : begin ( const std : : string & name , int flags )
2018-10-31 09:19:44 +00:00
{
return ImGui : : Begin ( name . c_str ( ) , nullptr , ( ImGuiWindowFlags ) flags ) ;
}
2018-11-26 09:56:07 +00:00
bool ImGuiWrapper : : begin ( const wxString & name , int flags )
{
return begin ( into_u8 ( name ) , flags ) ;
}
2018-10-31 09:19:44 +00:00
void ImGuiWrapper : : end ( )
{
ImGui : : End ( ) ;
}
2018-11-26 09:56:07 +00:00
bool ImGuiWrapper : : button ( const wxString & label )
{
auto label_utf8 = into_u8 ( label ) ;
return ImGui : : Button ( label_utf8 . c_str ( ) ) ;
}
2019-01-30 07:26:23 +00:00
bool ImGuiWrapper : : radio_button ( const wxString & label , bool active )
{
auto label_utf8 = into_u8 ( label ) ;
return ImGui : : RadioButton ( label_utf8 . c_str ( ) , active ) ;
}
2018-11-26 09:56:07 +00:00
bool ImGuiWrapper : : input_double ( const std : : string & label , const double & value , const std : : string & format )
2018-10-31 09:19:44 +00:00
{
2018-11-26 09:56:07 +00:00
return ImGui : : InputDouble ( label . c_str ( ) , const_cast < double * > ( & value ) , 0.0f , 0.0f , format . c_str ( ) ) ;
2018-10-31 09:19:44 +00:00
}
2018-11-26 09:56:07 +00:00
bool ImGuiWrapper : : input_vec3 ( const std : : string & label , const Vec3d & value , float width , const std : : string & format )
2018-10-31 09:19:44 +00:00
{
bool value_changed = false ;
ImGui : : BeginGroup ( ) ;
for ( int i = 0 ; i < 3 ; + + i )
{
std : : string item_label = ( i = = 0 ) ? " X " : ( ( i = = 1 ) ? " Y " : " Z " ) ;
ImGui : : PushID ( i ) ;
ImGui : : PushItemWidth ( width ) ;
2018-11-26 09:56:07 +00:00
value_changed | = ImGui : : InputDouble ( item_label . c_str ( ) , const_cast < double * > ( & value ( i ) ) , 0.0f , 0.0f , format . c_str ( ) ) ;
2018-10-31 09:19:44 +00:00
ImGui : : PopID ( ) ;
}
ImGui : : EndGroup ( ) ;
return value_changed ;
}
2018-11-26 09:56:07 +00:00
bool ImGuiWrapper : : checkbox ( const wxString & label , bool & value )
{
auto label_utf8 = into_u8 ( label ) ;
return ImGui : : Checkbox ( label_utf8 . c_str ( ) , & value ) ;
}
2019-03-04 11:21:00 +00:00
void ImGuiWrapper : : text ( const char * label )
{
ImGui : : Text ( label , NULL ) ;
}
void ImGuiWrapper : : text ( const std : : string & label )
{
this - > text ( label . c_str ( ) ) ;
}
2018-11-26 14:54:12 +00:00
void ImGuiWrapper : : text ( const wxString & label )
{
2019-04-01 12:12:05 +00:00
auto label_utf8 = into_u8 ( label ) ;
this - > text ( label_utf8 . c_str ( ) ) ;
2018-11-26 14:54:12 +00:00
}
2019-03-04 14:40:06 +00:00
bool ImGuiWrapper : : combo ( const wxString & label , const std : : vector < std : : string > & options , int & selection )
2019-01-30 07:26:23 +00:00
{
// this is to force the label to the left of the widget:
text ( label ) ;
ImGui : : SameLine ( ) ;
2019-03-04 14:40:06 +00:00
int selection_out = - 1 ;
bool res = false ;
const char * selection_str = selection < options . size ( ) ? options [ selection ] . c_str ( ) : " " ;
if ( ImGui : : BeginCombo ( " " , selection_str ) ) {
for ( int i = 0 ; i < options . size ( ) ; i + + ) {
if ( ImGui : : Selectable ( options [ i ] . c_str ( ) , i = = selection ) ) {
selection_out = i ;
}
2019-03-04 11:21:00 +00:00
}
2019-03-04 14:40:06 +00:00
2019-03-04 11:21:00 +00:00
ImGui : : EndCombo ( ) ;
2019-03-04 14:40:06 +00:00
res = true ;
2019-03-04 11:21:00 +00:00
}
2019-03-04 14:40:06 +00:00
selection = selection_out ;
return res ;
2019-03-04 11:21:00 +00:00
}
2019-01-18 14:02:07 +00:00
void ImGuiWrapper : : disabled_begin ( bool disabled )
{
wxCHECK_RET ( ! m_disabled , " ImGUI: Unbalanced disabled_begin() call " ) ;
if ( disabled ) {
ImGui : : PushItemFlag ( ImGuiItemFlags_Disabled , true ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_Alpha , ImGui : : GetStyle ( ) . Alpha * 0.5f ) ;
m_disabled = true ;
}
}
void ImGuiWrapper : : disabled_end ( )
{
if ( m_disabled ) {
ImGui : : PopItemFlag ( ) ;
ImGui : : PopStyleVar ( ) ;
m_disabled = false ;
}
}
2018-11-26 09:56:07 +00:00
bool ImGuiWrapper : : want_mouse ( ) const
{
return ImGui : : GetIO ( ) . WantCaptureMouse ;
}
bool ImGuiWrapper : : want_keyboard ( ) const
{
return ImGui : : GetIO ( ) . WantCaptureKeyboard ;
}
bool ImGuiWrapper : : want_text_input ( ) const
{
return ImGui : : GetIO ( ) . WantTextInput ;
}
bool ImGuiWrapper : : want_any_input ( ) const
{
const auto io = ImGui : : GetIO ( ) ;
return io . WantCaptureMouse | | io . WantCaptureKeyboard | | io . WantTextInput ;
}
2019-04-01 12:12:05 +00:00
void ImGuiWrapper : : init_font ( )
2019-01-24 10:30:29 +00:00
{
2019-04-01 12:12:05 +00:00
destroy_font ( ) ;
2019-01-24 12:16:46 +00:00
2019-01-24 10:30:29 +00:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . Fonts - > Clear ( ) ;
2019-05-23 16:04:27 +00:00
//FIXME replace with io.Fonts->AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, m_font_size, nullptr, m_glyph_ranges);
//https://github.com/ocornut/imgui/issues/220
ImFont * font = io . Fonts - > AddFontFromFileTTF ( ( Slic3r : : resources_dir ( ) + " /fonts/ " + ( m_font_cjk ? " NotoSansCJK-Regular.ttc " : " NotoSans-Regular.ttf " ) ) . c_str ( ) , m_font_size , nullptr , m_glyph_ranges ) ;
2019-01-24 10:30:29 +00:00
if ( font = = nullptr ) {
font = io . Fonts - > AddFontDefault ( ) ;
if ( font = = nullptr ) {
throw std : : runtime_error ( " ImGui: Could not load deafult font " ) ;
}
}
2018-10-31 09:19:44 +00:00
// Build texture atlas
unsigned char * pixels ;
int width , height ;
io . Fonts - > GetTexDataAsRGBA32 ( & pixels , & width , & height ) ; // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
// Upload texture to graphics system
GLint last_texture ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glGetIntegerv ( GL_TEXTURE_BINDING_2D , & last_texture ) ) ;
glsafe ( : : glGenTextures ( 1 , & m_font_texture ) ) ;
glsafe ( : : glBindTexture ( GL_TEXTURE_2D , m_font_texture ) ) ;
glsafe ( : : glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ) ;
glsafe ( : : glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ) ;
glsafe ( : : glPixelStorei ( GL_UNPACK_ROW_LENGTH , 0 ) ) ;
glsafe ( : : glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , width , height , 0 , GL_RGBA , GL_UNSIGNED_BYTE , pixels ) ) ;
2018-10-31 09:19:44 +00:00
// Store our identifier
io . Fonts - > TexID = ( ImTextureID ) ( intptr_t ) m_font_texture ;
// Restore state
2019-03-27 13:42:09 +00:00
glsafe ( : : glBindTexture ( GL_TEXTURE_2D , last_texture ) ) ;
2018-10-31 09:19:44 +00:00
}
2019-02-15 14:35:32 +00:00
void ImGuiWrapper : : init_input ( )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
io . KeyMap [ ImGuiKey_Tab ] = WXK_TAB ;
io . KeyMap [ ImGuiKey_LeftArrow ] = WXK_LEFT ;
io . KeyMap [ ImGuiKey_RightArrow ] = WXK_RIGHT ;
io . KeyMap [ ImGuiKey_UpArrow ] = WXK_UP ;
io . KeyMap [ ImGuiKey_DownArrow ] = WXK_DOWN ;
io . KeyMap [ ImGuiKey_PageUp ] = WXK_PAGEUP ;
io . KeyMap [ ImGuiKey_PageDown ] = WXK_PAGEDOWN ;
io . KeyMap [ ImGuiKey_Home ] = WXK_HOME ;
io . KeyMap [ ImGuiKey_End ] = WXK_END ;
io . KeyMap [ ImGuiKey_Insert ] = WXK_INSERT ;
io . KeyMap [ ImGuiKey_Delete ] = WXK_DELETE ;
io . KeyMap [ ImGuiKey_Backspace ] = WXK_BACK ;
io . KeyMap [ ImGuiKey_Space ] = WXK_SPACE ;
io . KeyMap [ ImGuiKey_Enter ] = WXK_RETURN ;
io . KeyMap [ ImGuiKey_Escape ] = WXK_ESCAPE ;
io . KeyMap [ ImGuiKey_A ] = ' A ' ;
io . KeyMap [ ImGuiKey_C ] = ' C ' ;
io . KeyMap [ ImGuiKey_V ] = ' V ' ;
io . KeyMap [ ImGuiKey_X ] = ' X ' ;
io . KeyMap [ ImGuiKey_Y ] = ' Y ' ;
io . KeyMap [ ImGuiKey_Z ] = ' Z ' ;
2019-02-18 15:44:35 +00:00
// Don't let imgui special-case Mac, wxWidgets already do that
io . ConfigMacOSXBehaviors = false ;
2019-02-15 14:35:32 +00:00
// Setup clipboard interaction callbacks
io . SetClipboardTextFn = clipboard_set ;
io . GetClipboardTextFn = clipboard_get ;
io . ClipboardUserData = this ;
}
2019-02-19 13:46:29 +00:00
void ImGuiWrapper : : init_style ( )
{
ImGuiStyle & style = ImGui : : GetStyle ( ) ;
auto set_color = [ & ] ( ImGuiCol_ col , unsigned hex_color ) {
style . Colors [ col ] = ImVec4 (
( ( hex_color > > 24 ) & 0xff ) / 255.0f ,
( ( hex_color > > 16 ) & 0xff ) / 255.0f ,
( ( hex_color > > 8 ) & 0xff ) / 255.0f ,
( hex_color & 0xff ) / 255.0f ) ;
} ;
static const unsigned COL_GREY_DARK = 0x444444ff ;
static const unsigned COL_GREY_LIGHT = 0x666666ff ;
2019-02-25 15:47:49 +00:00
static const unsigned COL_ORANGE_DARK = 0xc16737ff ;
static const unsigned COL_ORANGE_LIGHT = 0xff7d38ff ;
2019-02-19 13:46:29 +00:00
// Generics
set_color ( ImGuiCol_TitleBgActive , COL_ORANGE_DARK ) ;
set_color ( ImGuiCol_FrameBg , COL_GREY_DARK ) ;
set_color ( ImGuiCol_FrameBgHovered , COL_GREY_LIGHT ) ;
set_color ( ImGuiCol_FrameBgActive , COL_GREY_LIGHT ) ;
// Text selection
set_color ( ImGuiCol_TextSelectedBg , COL_ORANGE_DARK ) ;
// Buttons
set_color ( ImGuiCol_Button , COL_ORANGE_DARK ) ;
set_color ( ImGuiCol_ButtonHovered , COL_ORANGE_LIGHT ) ;
set_color ( ImGuiCol_ButtonActive , COL_ORANGE_LIGHT ) ;
// Checkbox
set_color ( ImGuiCol_CheckMark , COL_ORANGE_LIGHT ) ;
// ComboBox items
set_color ( ImGuiCol_Header , COL_ORANGE_DARK ) ;
set_color ( ImGuiCol_HeaderHovered , COL_ORANGE_LIGHT ) ;
set_color ( ImGuiCol_HeaderActive , COL_ORANGE_LIGHT ) ;
2019-03-13 13:50:32 +00:00
// Slider
set_color ( ImGuiCol_SliderGrab , COL_ORANGE_DARK ) ;
set_color ( ImGuiCol_SliderGrabActive , COL_ORANGE_LIGHT ) ;
2019-02-19 13:46:29 +00:00
}
2018-11-26 09:56:07 +00:00
void ImGuiWrapper : : render_draw_data ( ImDrawData * draw_data )
2018-10-31 09:19:44 +00:00
{
2018-11-27 14:35:30 +00:00
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
2018-10-31 09:19:44 +00:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
int fb_width = ( int ) ( draw_data - > DisplaySize . x * io . DisplayFramebufferScale . x ) ;
int fb_height = ( int ) ( draw_data - > DisplaySize . y * io . DisplayFramebufferScale . y ) ;
2018-11-27 11:10:21 +00:00
if ( fb_width = = 0 | | fb_height = = 0 )
2018-10-31 09:19:44 +00:00
return ;
draw_data - > ScaleClipRects ( io . DisplayFramebufferScale ) ;
2018-11-27 11:10:21 +00:00
// We are using the OpenGL fixed pipeline to make the example code simpler to read!
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
2019-03-27 13:42:09 +00:00
GLint last_texture ; glsafe ( : : glGetIntegerv ( GL_TEXTURE_BINDING_2D , & last_texture ) ) ;
GLint last_polygon_mode [ 2 ] ; glsafe ( : : glGetIntegerv ( GL_POLYGON_MODE , last_polygon_mode ) ) ;
GLint last_viewport [ 4 ] ; glsafe ( : : glGetIntegerv ( GL_VIEWPORT , last_viewport ) ) ;
GLint last_scissor_box [ 4 ] ; glsafe ( : : glGetIntegerv ( GL_SCISSOR_BOX , last_scissor_box ) ) ;
glsafe ( : : glPushAttrib ( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT ) ) ;
glsafe ( : : glEnable ( GL_BLEND ) ) ;
glsafe ( : : glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ) ;
glsafe ( : : glDisable ( GL_CULL_FACE ) ) ;
glsafe ( : : glDisable ( GL_DEPTH_TEST ) ) ;
glsafe ( : : glDisable ( GL_LIGHTING ) ) ;
glsafe ( : : glDisable ( GL_COLOR_MATERIAL ) ) ;
glsafe ( : : glEnable ( GL_SCISSOR_TEST ) ) ;
glsafe ( : : glEnableClientState ( GL_VERTEX_ARRAY ) ) ;
glsafe ( : : glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ) ;
glsafe ( : : glEnableClientState ( GL_COLOR_ARRAY ) ) ;
glsafe ( : : glEnable ( GL_TEXTURE_2D ) ) ;
glsafe ( : : glPolygonMode ( GL_FRONT_AND_BACK , GL_FILL ) ) ;
glsafe ( : : glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ) ;
2018-11-27 14:35:30 +00:00
GLint texture_env_mode = GL_MODULATE ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glGetTexEnviv ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , & texture_env_mode ) ) ;
glsafe ( : : glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_MODULATE ) ) ;
2018-11-27 11:10:21 +00:00
//glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
2018-10-31 09:19:44 +00:00
// Setup viewport, orthographic projection matrix
2018-11-27 11:10:21 +00:00
// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
2019-03-27 13:42:09 +00:00
glsafe ( : : glViewport ( 0 , 0 , ( GLsizei ) fb_width , ( GLsizei ) fb_height ) ) ;
glsafe ( : : glMatrixMode ( GL_PROJECTION ) ) ;
glsafe ( : : glPushMatrix ( ) ) ;
glsafe ( : : glLoadIdentity ( ) ) ;
glsafe ( : : glOrtho ( draw_data - > DisplayPos . x , draw_data - > DisplayPos . x + draw_data - > DisplaySize . x , draw_data - > DisplayPos . y + draw_data - > DisplaySize . y , draw_data - > DisplayPos . y , - 1.0f , + 1.0f ) ) ;
glsafe ( : : glMatrixMode ( GL_MODELVIEW ) ) ;
glsafe ( : : glPushMatrix ( ) ) ;
glsafe ( : : glLoadIdentity ( ) ) ;
2018-11-27 11:10:21 +00:00
// Render command lists
2018-10-31 09:19:44 +00:00
ImVec2 pos = draw_data - > DisplayPos ;
for ( int n = 0 ; n < draw_data - > CmdListsCount ; n + + )
{
const ImDrawList * cmd_list = draw_data - > CmdLists [ n ] ;
2018-11-27 11:10:21 +00:00
const ImDrawVert * vtx_buffer = cmd_list - > VtxBuffer . Data ;
const ImDrawIdx * idx_buffer = cmd_list - > IdxBuffer . Data ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glVertexPointer ( 2 , GL_FLOAT , sizeof ( ImDrawVert ) , ( const GLvoid * ) ( ( const char * ) vtx_buffer + IM_OFFSETOF ( ImDrawVert , pos ) ) ) ) ;
glsafe ( : : glTexCoordPointer ( 2 , GL_FLOAT , sizeof ( ImDrawVert ) , ( const GLvoid * ) ( ( const char * ) vtx_buffer + IM_OFFSETOF ( ImDrawVert , uv ) ) ) ) ;
glsafe ( : : glColorPointer ( 4 , GL_UNSIGNED_BYTE , sizeof ( ImDrawVert ) , ( const GLvoid * ) ( ( const char * ) vtx_buffer + IM_OFFSETOF ( ImDrawVert , col ) ) ) ) ;
2018-10-31 09:19:44 +00:00
for ( int cmd_i = 0 ; cmd_i < cmd_list - > CmdBuffer . Size ; cmd_i + + )
{
const ImDrawCmd * pcmd = & cmd_list - > CmdBuffer [ cmd_i ] ;
if ( pcmd - > UserCallback )
{
// User callback (registered via ImDrawList::AddCallback)
pcmd - > UserCallback ( cmd_list , pcmd ) ;
}
else
{
ImVec4 clip_rect = ImVec4 ( pcmd - > ClipRect . x - pos . x , pcmd - > ClipRect . y - pos . y , pcmd - > ClipRect . z - pos . x , pcmd - > ClipRect . w - pos . y ) ;
if ( clip_rect . x < fb_width & & clip_rect . y < fb_height & & clip_rect . z > = 0.0f & & clip_rect . w > = 0.0f )
{
// Apply scissor/clipping rectangle
2019-03-27 13:42:09 +00:00
glsafe ( : : glScissor ( ( int ) clip_rect . x , ( int ) ( fb_height - clip_rect . w ) , ( int ) ( clip_rect . z - clip_rect . x ) , ( int ) ( clip_rect . w - clip_rect . y ) ) ) ;
2018-10-31 09:19:44 +00:00
// Bind texture, Draw
2019-03-27 13:42:09 +00:00
glsafe ( : : glBindTexture ( GL_TEXTURE_2D , ( GLuint ) ( intptr_t ) pcmd - > TextureId ) ) ;
glsafe ( : : glDrawElements ( GL_TRIANGLES , ( GLsizei ) pcmd - > ElemCount , sizeof ( ImDrawIdx ) = = 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT , idx_buffer ) ) ;
2018-10-31 09:19:44 +00:00
}
}
2018-11-27 11:10:21 +00:00
idx_buffer + = pcmd - > ElemCount ;
2018-10-31 09:19:44 +00:00
}
}
2018-11-27 11:10:21 +00:00
// Restore modified state
2019-03-27 13:42:09 +00:00
glsafe ( : : glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , texture_env_mode ) ) ;
glsafe ( : : glDisableClientState ( GL_COLOR_ARRAY ) ) ;
glsafe ( : : glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ) ;
glsafe ( : : glDisableClientState ( GL_VERTEX_ARRAY ) ) ;
glsafe ( : : glBindTexture ( GL_TEXTURE_2D , ( GLuint ) last_texture ) ) ;
glsafe ( : : glMatrixMode ( GL_MODELVIEW ) ) ;
glsafe ( : : glPopMatrix ( ) ) ;
glsafe ( : : glMatrixMode ( GL_PROJECTION ) ) ;
glsafe ( : : glPopMatrix ( ) ) ;
glsafe ( : : glPopAttrib ( ) ) ;
glsafe ( : : glPolygonMode ( GL_FRONT , ( GLenum ) last_polygon_mode [ 0 ] ) ; glPolygonMode ( GL_BACK , ( GLenum ) last_polygon_mode [ 1 ] ) ) ;
glsafe ( : : glViewport ( last_viewport [ 0 ] , last_viewport [ 1 ] , ( GLsizei ) last_viewport [ 2 ] , ( GLsizei ) last_viewport [ 3 ] ) ) ;
glsafe ( : : glScissor ( last_scissor_box [ 0 ] , last_scissor_box [ 1 ] , ( GLsizei ) last_scissor_box [ 2 ] , ( GLsizei ) last_scissor_box [ 3 ] ) ) ;
2018-10-31 09:19:44 +00:00
}
2019-02-22 13:52:32 +00:00
bool ImGuiWrapper : : display_initialized ( ) const
{
const ImGuiIO & io = ImGui : : GetIO ( ) ;
return io . DisplaySize . x > = 0.0f & & io . DisplaySize . y > = 0.0f ;
}
2019-04-01 12:12:05 +00:00
void ImGuiWrapper : : destroy_font ( )
2018-10-31 09:19:44 +00:00
{
2019-04-01 12:12:05 +00:00
if ( m_font_texture ! = 0 ) {
2018-10-31 09:19:44 +00:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
io . Fonts - > TexID = 0 ;
2019-03-27 13:42:09 +00:00
glsafe ( : : glDeleteTextures ( 1 , & m_font_texture ) ) ;
2018-10-31 09:19:44 +00:00
m_font_texture = 0 ;
}
}
2019-02-15 14:35:32 +00:00
const char * ImGuiWrapper : : clipboard_get ( void * user_data )
{
ImGuiWrapper * self = reinterpret_cast < ImGuiWrapper * > ( user_data ) ;
const char * res = " " ;
if ( wxTheClipboard - > Open ( ) ) {
if ( wxTheClipboard - > IsSupported ( wxDF_TEXT ) ) {
wxTextDataObject data ;
wxTheClipboard - > GetData ( data ) ;
if ( data . GetTextLength ( ) > 0 ) {
2019-02-19 11:39:24 +00:00
self - > m_clipboard_text = into_u8 ( data . GetText ( ) ) ;
res = self - > m_clipboard_text . c_str ( ) ;
2019-02-15 14:35:32 +00:00
}
}
wxTheClipboard - > Close ( ) ;
}
return res ;
}
void ImGuiWrapper : : clipboard_set ( void * /* user_data */ , const char * text )
{
if ( wxTheClipboard - > Open ( ) ) {
wxTheClipboard - > SetData ( new wxTextDataObject ( wxString : : FromUTF8 ( text ) ) ) ; // object owned by the clipboard
wxTheClipboard - > Close ( ) ;
}
}
2018-11-27 14:35:30 +00:00
2018-10-31 09:19:44 +00:00
} // namespace GUI
} // namespace Slic3r