2020-11-10 15:26:38 +01:00
# include "window.hpp"
2020-12-22 18:10:01 +01:00
# include <hex.hpp>
2021-01-13 17:28:27 +01:00
# include <hex/api/content_registry.hpp>
2020-12-22 18:10:01 +01:00
2020-11-10 15:26:38 +01:00
# include <iostream>
2020-12-11 14:24:42 +01:00
# include <numeric>
2020-11-10 15:26:38 +01:00
2021-01-13 17:28:27 +01:00
# include <imgui.h>
# include <imgui_internal.h>
# include <imgui_impl_glfw.h>
# include <imgui_impl_opengl3.h>
# include <imgui_freetype.h>
2021-01-27 12:04:42 +01:00
# include <imgui_imhex_extensions.h>
2020-11-10 15:26:38 +01:00
2020-12-22 18:10:01 +01:00
# include "helpers/plugin_handler.hpp"
2020-11-10 15:26:38 +01:00
# include <glad/glad.h>
# include <GLFW/glfw3.h>
2021-01-25 13:36:01 +01:00
# if defined(OS_WINDOWS)
# include <windows.h>
# endif
2020-11-10 15:26:38 +01:00
namespace hex {
2020-11-23 23:57:19 +01:00
constexpr auto MenuBarItems = { " File " , " Edit " , " View " , " Help " } ;
2020-11-15 15:49:21 +01:00
2020-11-23 23:57:19 +01:00
void * ImHexSettingsHandler_ReadOpenFn ( ImGuiContext * ctx , ImGuiSettingsHandler * , const char * ) {
return ctx ; // Unused, but the return value has to be non-null
}
2020-11-15 15:49:21 +01:00
2020-11-23 23:57:19 +01:00
void ImHexSettingsHandler_ReadLine ( ImGuiContext * , ImGuiSettingsHandler * handler , void * , const char * line ) {
2021-01-12 16:50:15 +01:00
for ( auto & view : ContentRegistry : : Views : : getEntries ( ) ) {
2021-01-21 10:53:12 +01:00
std : : string format = std : : string ( view - > getName ( ) ) + " =%d " ;
2020-12-11 14:24:42 +01:00
sscanf ( line , format . c_str ( ) , & view - > getWindowOpenState ( ) ) ;
2020-11-15 15:49:21 +01:00
}
2020-11-23 23:57:19 +01:00
}
2020-11-15 15:49:21 +01:00
2020-11-23 23:57:19 +01:00
void ImHexSettingsHandler_WriteAll ( ImGuiContext * ctx , ImGuiSettingsHandler * handler , ImGuiTextBuffer * buf ) {
buf - > reserve ( buf - > size ( ) + 0x20 ) ; // Ballpark reserve
2020-11-15 15:49:21 +01:00
2020-11-23 23:57:19 +01:00
buf - > appendf ( " [%s][General] \n " , handler - > TypeName ) ;
2020-11-15 15:49:21 +01:00
2021-01-12 16:50:15 +01:00
for ( auto & view : ContentRegistry : : Views : : getEntries ( ) ) {
2021-01-21 10:53:12 +01:00
buf - > appendf ( " %s=%d \n " , view - > getName ( ) . data ( ) , view - > getWindowOpenState ( ) ) ;
2020-11-15 15:49:21 +01:00
}
2020-11-23 23:57:19 +01:00
buf - > append ( " \n " ) ;
2020-11-15 15:49:21 +01:00
}
2021-01-12 16:50:15 +01:00
Window : : Window ( int & argc , char * * & argv ) {
2021-01-12 23:28:41 +01:00
hex : : SharedData : : mainArgc = argc ;
hex : : SharedData : : mainArgv = argv ;
2021-01-12 16:50:15 +01:00
2021-01-25 13:36:01 +01:00
// Try to attach to a currently open console on Windows if available
# if defined(OS_WINDOWS)
if ( AttachConsole ( ATTACH_PARENT_PROCESS ) ) {
HANDLE hStdOut = GetStdHandle ( STD_OUTPUT_HANDLE ) ;
if ( hStdOut ! = INVALID_HANDLE_VALUE ) {
freopen ( " CONOUT$ " , " w " , stdout ) ;
freopen ( " CONERR$ " , " w " , stderr ) ;
setvbuf ( stdout , nullptr , _IONBF , 0 ) ;
setvbuf ( stderr , nullptr , _IONBF , 0 ) ;
}
}
# endif
2021-01-11 20:31:40 +01:00
ContentRegistry : : Settings : : load ( ) ;
2021-01-21 10:53:12 +01:00
View : : postEvent ( Events : : SettingsChanged ) ;
2021-01-04 00:19:56 +01:00
2020-11-10 15:26:38 +01:00
this - > initGLFW ( ) ;
this - > initImGui ( ) ;
}
Window : : ~ Window ( ) {
this - > deinitImGui ( ) ;
this - > deinitGLFW ( ) ;
2021-01-11 20:31:40 +01:00
ContentRegistry : : Settings : : store ( ) ;
2020-11-10 15:26:38 +01:00
2021-01-12 16:50:15 +01:00
for ( auto & view : ContentRegistry : : Views : : getEntries ( ) )
2020-11-10 15:26:38 +01:00
delete view ;
2021-01-12 16:50:15 +01:00
ContentRegistry : : Views : : getEntries ( ) . clear ( ) ;
2021-01-12 16:56:14 +01:00
this - > deinitPlugins ( ) ;
2020-11-10 15:26:38 +01:00
}
void Window : : loop ( ) {
while ( ! glfwWindowShouldClose ( this - > m_window ) ) {
this - > frameBegin ( ) ;
2020-11-16 00:07:42 +01:00
for ( const auto & call : View : : getDeferedCalls ( ) )
call ( ) ;
View : : getDeferedCalls ( ) . clear ( ) ;
2021-01-27 14:26:24 +01:00
for ( auto & view : ContentRegistry : : Views : : getEntries ( ) ) {
if ( ! view - > isAvailable ( ) | | ! view - > getWindowOpenState ( ) )
continue ;
2020-12-22 18:10:01 +01:00
2021-01-27 14:26:24 +01:00
auto minSize = view - > getMinSize ( ) ;
minSize . x * = this - > m_globalScale ;
minSize . y * = this - > m_globalScale ;
2021-01-21 23:09:43 +01:00
2021-01-27 14:26:24 +01:00
ImGui : : SetNextWindowSizeConstraints ( minSize , view - > getMaxSize ( ) ) ;
view - > drawContent ( ) ;
2020-11-11 00:12:49 +01:00
}
2020-11-10 15:26:38 +01:00
2020-11-27 13:45:27 +01:00
View : : drawCommonInterfaces ( ) ;
2020-11-23 22:23:06 +01:00
# ifdef DEBUG
if ( this - > m_demoWindowOpen )
ImGui : : ShowDemoWindow ( & this - > m_demoWindowOpen ) ;
# endif
2020-11-10 15:26:38 +01:00
this - > frameEnd ( ) ;
}
}
2020-12-11 14:24:42 +01:00
bool Window : : setFont ( const std : : filesystem : : path & path ) {
if ( ! std : : filesystem : : exists ( path ) )
return false ;
auto & io = ImGui : : GetIO ( ) ;
// If we have a custom font, then rescaling is unnecessary and will make it blurry
io . FontGlobalScale = 1.0f ;
// Load font data & build atlas
std : : uint8_t * px ;
int w , h ;
io . Fonts - > AddFontFromFileTTF ( path . string ( ) . c_str ( ) , std : : floor ( 14.0f * this - > m_fontScale ) ) ; // Needs conversion to char for Windows
ImGuiFreeType : : BuildFontAtlas ( io . Fonts , ImGuiFreeType : : Monochrome ) ;
io . Fonts - > GetTexDataAsRGBA32 ( & px , & w , & h ) ;
// Create new font atlas
GLuint tex ;
glGenTextures ( 1 , & tex ) ;
glBindTexture ( GL_TEXTURE_2D , tex ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA8 , w , h , 0 , GL_RGBA8 , GL_UNSIGNED_INT , px ) ;
io . Fonts - > SetTexID ( reinterpret_cast < ImTextureID > ( tex ) ) ;
return true ;
}
2020-11-10 15:26:38 +01:00
void Window : : frameBegin ( ) {
glfwPollEvents ( ) ;
ImGui_ImplOpenGL3_NewFrame ( ) ;
ImGui_ImplGlfw_NewFrame ( ) ;
ImGui : : NewFrame ( ) ;
ImGuiViewport * viewport = ImGui : : GetMainViewport ( ) ;
ImGui : : SetNextWindowPos ( viewport - > GetWorkPos ( ) ) ;
ImGui : : SetNextWindowSize ( viewport - > GetWorkSize ( ) ) ;
ImGui : : SetNextWindowViewport ( viewport - > ID ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowRounding , 0.0f ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowBorderSize , 0.0f ) ;
2020-11-30 00:03:12 +01:00
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking
| ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse
| ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize
| ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoBringToFrontOnFocus ;
2020-11-10 15:26:38 +01:00
2021-01-21 17:48:24 +01:00
ImGui : : GetIO ( ) . ConfigFlags | = ImGuiConfigFlags_NavEnableKeyboard ;
2020-11-23 23:57:19 +01:00
if ( ImGui : : Begin ( " DockSpace " , nullptr , windowFlags ) ) {
ImGui : : PopStyleVar ( 2 ) ;
2021-01-21 23:09:43 +01:00
ImGui : : DockSpace ( ImGui : : GetID ( " MainDock " ) , ImVec2 ( 0.0f , 0.0f ) ) ;
2020-11-10 15:26:38 +01:00
2020-11-23 23:57:19 +01:00
if ( ImGui : : BeginMenuBar ( ) ) {
2020-11-10 15:26:38 +01:00
2020-11-23 23:57:19 +01:00
for ( auto menu : MenuBarItems )
if ( ImGui : : BeginMenu ( menu ) ) ImGui : : EndMenu ( ) ;
2020-11-10 15:26:38 +01:00
2020-11-23 23:57:19 +01:00
if ( ImGui : : BeginMenu ( " View " ) ) {
2021-01-12 16:50:15 +01:00
for ( auto & view : ContentRegistry : : Views : : getEntries ( ) ) {
2021-01-27 14:26:24 +01:00
if ( view - > isAvailable ( ) & & view - > hasViewMenuItemEntry ( ) )
2021-01-21 10:53:12 +01:00
ImGui : : MenuItem ( ( std : : string ( view - > getName ( ) ) + " View " ) . c_str ( ) , " " , & view - > getWindowOpenState ( ) ) ;
2020-11-28 22:01:50 +01:00
}
2020-11-23 23:57:19 +01:00
ImGui : : EndMenu ( ) ;
}
2020-11-11 09:22:55 +01:00
2021-01-12 16:50:15 +01:00
for ( auto & view : ContentRegistry : : Views : : getEntries ( ) ) {
2020-12-22 18:10:01 +01:00
view - > drawMenu ( ) ;
2020-11-23 23:57:19 +01:00
}
2020-11-11 11:56:37 +01:00
2020-11-23 23:57:19 +01:00
if ( ImGui : : BeginMenu ( " View " ) ) {
ImGui : : Separator ( ) ;
ImGui : : MenuItem ( " Display FPS " , " " , & this - > m_fpsVisible ) ;
# ifdef DEBUG
ImGui : : MenuItem ( " Demo View " , " " , & this - > m_demoWindowOpen ) ;
# endif
ImGui : : EndMenu ( ) ;
}
2020-11-11 09:22:55 +01:00
2020-11-23 23:57:19 +01:00
if ( this - > m_fpsVisible ) {
char buffer [ 0x20 ] ;
snprintf ( buffer , 0x20 , " %.1f FPS " , ImGui : : GetIO ( ) . Framerate ) ;
2020-11-11 09:22:55 +01:00
2020-11-23 23:57:19 +01:00
ImGui : : SameLine ( ImGui : : GetWindowWidth ( ) - ImGui : : GetFontSize ( ) * strlen ( buffer ) + 20 ) ;
ImGui : : TextUnformatted ( buffer ) ;
}
2020-11-10 15:26:38 +01:00
2020-11-23 23:57:19 +01:00
ImGui : : EndMenuBar ( ) ;
}
2020-11-11 14:41:44 +01:00
2020-11-23 23:57:19 +01:00
if ( auto & [ key , mods ] = Window : : s_currShortcut ; key ! = - 1 ) {
2021-01-12 16:50:15 +01:00
for ( auto & view : ContentRegistry : : Views : : getEntries ( ) ) {
2020-11-29 01:18:12 +01:00
if ( view - > getWindowOpenState ( ) ) {
2021-01-12 16:50:15 +01:00
if ( view - > handleShortcut ( key , mods ) )
2020-11-29 01:18:12 +01:00
break ;
}
2020-11-23 23:57:19 +01:00
}
Window : : s_currShortcut = { - 1 , - 1 } ;
2020-11-11 14:41:44 +01:00
}
2021-01-27 14:26:24 +01:00
bool anyViewOpen = false ;
for ( auto & view : ContentRegistry : : Views : : getEntries ( ) )
anyViewOpen = anyViewOpen | | ( view - > getWindowOpenState ( ) & & view - > isAvailable ( ) ) ;
if ( ! anyViewOpen ) {
2021-01-27 01:10:13 +01:00
char title [ 256 ] ;
ImFormatString ( title , IM_ARRAYSIZE ( title ) , " %s/DockSpace_%08X " , ImGui : : GetCurrentWindow ( ) - > Name , ImGui : : GetID ( " MainDock " ) ) ;
if ( ImGui : : Begin ( title ) ) {
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowPadding , ImVec2 ( 10 * this - > m_globalScale , 10 * this - > m_globalScale ) ) ;
2021-01-27 14:26:24 +01:00
if ( ImGui : : BeginChild ( " Welcome Screen " , ImVec2 ( 0 , 0 ) , false , ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_NoDecoration ) ) {
2021-01-27 01:10:13 +01:00
this - > drawWelcomeScreen ( ) ;
}
ImGui : : EndChild ( ) ;
ImGui : : PopStyleVar ( ) ;
}
ImGui : : End ( ) ;
}
2020-11-11 14:41:44 +01:00
}
2020-11-23 23:57:19 +01:00
ImGui : : End ( ) ;
2020-11-10 15:26:38 +01:00
}
void Window : : frameEnd ( ) {
ImGui : : Render ( ) ;
2020-11-17 13:58:50 +01:00
2020-11-23 23:57:19 +01:00
int displayWidth , displayHeight ;
glfwGetFramebufferSize ( this - > m_window , & displayWidth , & displayHeight ) ;
glViewport ( 0 , 0 , displayWidth , displayHeight ) ;
2020-11-10 15:26:38 +01:00
glClearColor ( 0.45f , 0.55f , 0.60f , 1.00f ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
ImGui_ImplOpenGL3_RenderDrawData ( ImGui : : GetDrawData ( ) ) ;
2020-11-23 15:51:40 +01:00
GLFWwindow * backup_current_context = glfwGetCurrentContext ( ) ;
ImGui : : UpdatePlatformWindows ( ) ;
ImGui : : RenderPlatformWindowsDefault ( ) ;
glfwMakeContextCurrent ( backup_current_context ) ;
2020-11-10 15:26:38 +01:00
glfwSwapBuffers ( this - > m_window ) ;
}
2021-01-27 01:10:13 +01:00
void Window : : drawWelcomeScreen ( ) {
2021-01-27 12:04:42 +01:00
ImGui : : UnderlinedText ( " Welcome to ImHex! " , ImGui : : GetStyleColorVec4 ( ImGuiCol_HeaderActive ) ) ;
ImGui : : NewLine ( ) ;
auto availableSpace = ImGui : : GetContentRegionAvail ( ) ;
ImGui : : Indent ( ) ;
if ( ImGui : : BeginTable ( " Welcome Left " , 1 , ImGuiTableFlags_NoBordersInBody , ImVec2 ( availableSpace . x / 2 , availableSpace . y ) ) ) {
ImGui : : TableNextRow ( ImGuiTableRowFlags_None , 100 ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Start " ) ;
{
2021-01-27 14:26:24 +01:00
if ( ImGui : : BulletHyperlink ( " Open File " ) )
EventManager : : post ( Events : : OpenWindow , " Open File " ) ;
2021-01-27 12:04:42 +01:00
}
ImGui : : TableNextRow ( ImGuiTableRowFlags_None , 100 ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Recent " ) ;
{
}
ImGui : : TableNextRow ( ImGuiTableRowFlags_None , 100 ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Help " ) ;
{
if ( ImGui : : BulletHyperlink ( " GitHub Repository " ) ) hex : : openWebpage ( " https://github.com/WerWolv/ImHex " ) ;
if ( ImGui : : BulletHyperlink ( " Get help " ) ) hex : : openWebpage ( " https://github.com/WerWolv/ImHex/discussions/categories/get-help " ) ;
}
ImGui : : EndTable ( ) ;
}
ImGui : : SameLine ( ) ;
if ( ImGui : : BeginTable ( " Welcome Right " , 1 , ImGuiTableFlags_NoBordersInBody , ImVec2 ( availableSpace . x / 2 , availableSpace . y ) ) ) {
ImGui : : TableNextRow ( ImGuiTableRowFlags_None , 100 ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Customize " ) ;
{
2021-01-27 14:26:24 +01:00
if ( ImGui : : DescriptionButton ( " Settings " , " Change preferences of ImHex " , ImVec2 ( ImGui : : GetContentRegionAvail ( ) . x * 0.8f , 0 ) ) )
EventManager : : post ( Events : : OpenWindow , " Preferences " ) ;
2021-01-27 12:04:42 +01:00
}
ImGui : : TableNextRow ( ImGuiTableRowFlags_None , 100 ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : Text ( " Learn " ) ;
{
if ( ImGui : : DescriptionButton ( " Pattern Language Documentation " , " Learn how to write ImHex patterns with our extensive documentation " , ImVec2 ( ImGui : : GetContentRegionAvail ( ) . x * 0.8 , 0 ) ) )
hex : : openWebpage ( " https://github.com/WerWolv/ImHex/wiki/Pattern-Language-Guide " ) ;
if ( ImGui : : DescriptionButton ( " Plugins API " , " Extend ImHex with additional features using plugins " , ImVec2 ( ImGui : : GetContentRegionAvail ( ) . x * 0.8 , 0 ) ) )
hex : : openWebpage ( " https://github.com/WerWolv/ImHex/wiki/Plugins-Development-Guide " ) ;
}
ImGui : : EndTable ( ) ;
}
2021-01-27 01:10:13 +01:00
}
2020-11-10 15:26:38 +01:00
void Window : : initGLFW ( ) {
2020-11-11 14:41:44 +01:00
glfwSetErrorCallback ( [ ] ( int error , const char * desc ) {
fprintf ( stderr , " Glfw Error %d: %s \n " , error , desc ) ;
} ) ;
2020-11-10 15:26:38 +01:00
if ( ! glfwInit ( ) )
throw std : : runtime_error ( " Failed to initialize GLFW! " ) ;
2020-11-23 22:23:06 +01:00
# ifdef __APPLE__
glfwWindowHint ( GLFW_OPENGL_FORWARD_COMPAT , GL_TRUE ) ;
# endif
2020-11-10 15:26:38 +01:00
2020-12-11 14:24:42 +01:00
if ( auto * monitor = glfwGetPrimaryMonitor ( ) ; monitor ) {
float xscale , yscale ;
glfwGetMonitorContentScale ( monitor , & xscale , & yscale ) ;
// In case the horizontal and vertical scale are different, fall back on the average
this - > m_globalScale = this - > m_fontScale = std : : midpoint ( xscale , yscale ) ;
}
2020-11-10 15:26:38 +01:00
glfwWindowHint ( GLFW_CONTEXT_VERSION_MAJOR , 3 ) ;
glfwWindowHint ( GLFW_CONTEXT_VERSION_MINOR , 2 ) ;
2020-11-11 14:41:44 +01:00
glfwWindowHint ( GLFW_OPENGL_PROFILE , GLFW_OPENGL_CORE_PROFILE ) ;
2020-11-10 15:26:38 +01:00
2020-11-30 00:03:12 +01:00
2020-12-11 14:24:42 +01:00
this - > m_window = glfwCreateWindow ( 1280 * this - > m_globalScale , 720 * this - > m_globalScale , " ImHex " , nullptr , nullptr ) ;
2020-11-10 15:26:38 +01:00
2020-11-23 23:57:19 +01:00
2020-11-10 15:26:38 +01:00
if ( this - > m_window = = nullptr )
throw std : : runtime_error ( " Failed to create window! " ) ;
glfwMakeContextCurrent ( this - > m_window ) ;
glfwSwapInterval ( 1 ) ;
2020-12-16 22:43:07 +01:00
{
int x = 0 , y = 0 ;
glfwGetWindowPos ( this - > m_window , & x , & y ) ;
2021-01-12 23:28:41 +01:00
SharedData : : windowPos = ImVec2 ( x , y ) ;
2020-12-16 22:43:07 +01:00
}
{
int width = 0 , height = 0 ;
glfwGetWindowSize ( this - > m_window , & width , & height ) ;
2021-01-12 23:28:41 +01:00
SharedData : : windowSize = ImVec2 ( width , height ) ;
2020-12-16 22:43:07 +01:00
}
glfwSetWindowPosCallback ( this - > m_window , [ ] ( GLFWwindow * window , int x , int y ) {
2021-01-12 23:28:41 +01:00
SharedData : : windowPos = ImVec2 ( x , y ) ;
2020-12-16 22:43:07 +01:00
} ) ;
glfwSetWindowSizeCallback ( this - > m_window , [ ] ( GLFWwindow * window , int width , int height ) {
2021-01-12 23:28:41 +01:00
SharedData : : windowSize = ImVec2 ( width , height ) ;
2020-12-16 22:43:07 +01:00
} ) ;
2020-11-11 14:41:44 +01:00
glfwSetKeyCallback ( this - > m_window , [ ] ( GLFWwindow * window , int key , int scancode , int action , int mods ) {
2021-01-21 15:02:49 +01:00
if ( action = = GLFW_PRESS ) {
2020-11-11 14:41:44 +01:00
Window : : s_currShortcut = { key , mods } ;
2021-01-21 15:02:49 +01:00
auto & io = ImGui : : GetIO ( ) ;
io . KeysDown [ key ] = true ;
io . KeyCtrl = ( mods & GLFW_MOD_CONTROL ) ! = 0 ;
io . KeyShift = ( mods & GLFW_MOD_SHIFT ) ! = 0 ;
io . KeyAlt = ( mods & GLFW_MOD_ALT ) ! = 0 ;
}
else if ( action = = GLFW_RELEASE ) {
auto & io = ImGui : : GetIO ( ) ;
io . KeysDown [ key ] = false ;
io . KeyCtrl = ( mods & GLFW_MOD_CONTROL ) ! = 0 ;
io . KeyShift = ( mods & GLFW_MOD_SHIFT ) ! = 0 ;
io . KeyAlt = ( mods & GLFW_MOD_ALT ) ! = 0 ;
}
2020-11-11 14:41:44 +01:00
} ) ;
2020-11-17 13:58:50 +01:00
glfwSetDropCallback ( this - > m_window , [ ] ( GLFWwindow * window , int count , const char * * paths ) {
if ( count ! = 1 )
return ;
View : : postEvent ( Events : : FileDropped , paths [ 0 ] ) ;
} ) ;
2020-11-30 00:03:12 +01:00
glfwSetWindowCloseCallback ( this - > m_window , [ ] ( GLFWwindow * window ) {
View : : postEvent ( Events : : WindowClosing , window ) ;
} ) ;
glfwSetWindowSizeLimits ( this - > m_window , 720 , 480 , GLFW_DONT_CARE , GLFW_DONT_CARE ) ;
2020-11-12 23:58:31 +01:00
2020-11-10 15:26:38 +01:00
if ( gladLoadGL ( ) = = 0 )
throw std : : runtime_error ( " Failed to initialize OpenGL loader! " ) ;
}
void Window : : initImGui ( ) {
IMGUI_CHECKVERSION ( ) ;
2020-11-15 15:49:21 +01:00
auto * ctx = ImGui : : CreateContext ( ) ;
2021-01-12 23:28:41 +01:00
GImGui = ctx ;
2020-11-15 15:49:21 +01:00
ImGuiIO & io = ImGui : : GetIO ( ) ;
2020-11-23 15:51:40 +01:00
ImGuiStyle & style = ImGui : : GetStyle ( ) ;
2021-01-21 15:02:49 +01:00
io . ConfigFlags | = ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_ViewportsEnable | ImGuiConfigFlags_NavEnableKeyboard ;
2020-11-23 15:51:40 +01:00
io . ConfigViewportsNoTaskBarIcon = true ;
2021-01-21 15:02:49 +01:00
io . KeyMap [ ImGuiKey_Tab ] = GLFW_KEY_TAB ;
io . KeyMap [ ImGuiKey_LeftArrow ] = GLFW_KEY_LEFT ;
io . KeyMap [ ImGuiKey_RightArrow ] = GLFW_KEY_RIGHT ;
io . KeyMap [ ImGuiKey_UpArrow ] = GLFW_KEY_UP ;
io . KeyMap [ ImGuiKey_DownArrow ] = GLFW_KEY_DOWN ;
io . KeyMap [ ImGuiKey_PageUp ] = GLFW_KEY_PAGE_UP ;
io . KeyMap [ ImGuiKey_PageDown ] = GLFW_KEY_PAGE_DOWN ;
io . KeyMap [ ImGuiKey_Home ] = GLFW_KEY_HOME ;
io . KeyMap [ ImGuiKey_End ] = GLFW_KEY_END ;
io . KeyMap [ ImGuiKey_Insert ] = GLFW_KEY_INSERT ;
io . KeyMap [ ImGuiKey_Delete ] = GLFW_KEY_DELETE ;
io . KeyMap [ ImGuiKey_Backspace ] = GLFW_KEY_BACKSPACE ;
io . KeyMap [ ImGuiKey_Space ] = GLFW_KEY_SPACE ;
io . KeyMap [ ImGuiKey_Enter ] = GLFW_KEY_ENTER ;
io . KeyMap [ ImGuiKey_Escape ] = GLFW_KEY_ESCAPE ;
io . KeyMap [ ImGuiKey_KeyPadEnter ] = GLFW_KEY_KP_ENTER ;
io . KeyMap [ ImGuiKey_A ] = GLFW_KEY_A ;
io . KeyMap [ ImGuiKey_C ] = GLFW_KEY_C ;
io . KeyMap [ ImGuiKey_V ] = GLFW_KEY_V ;
io . KeyMap [ ImGuiKey_X ] = GLFW_KEY_X ;
io . KeyMap [ ImGuiKey_Y ] = GLFW_KEY_Y ;
io . KeyMap [ ImGuiKey_Z ] = GLFW_KEY_Z ;
2020-11-23 15:51:40 +01:00
2020-12-11 14:24:42 +01:00
if ( this - > m_globalScale ! = 0.0f )
style . ScaleAllSizes ( this - > m_globalScale ) ;
2021-01-27 12:04:42 +01:00
# if defined(OS_WINDOWS)
std : : filesystem : : path resourcePath = std : : filesystem : : path ( ( SharedData : : mainArgv ) [ 0 ] ) . parent_path ( ) ;
# elif defined(OS_LINUX) || defined(OS_MACOS)
std : : filesystem : : path resourcePath = " /usr/share/ImHex " ;
# else
std : : filesystem : : path resourcePath = " " ;
# warning "Unsupported OS for custom font support"
# endif
2020-12-11 14:24:42 +01:00
2021-01-27 12:04:42 +01:00
if ( ! resourcePath . empty ( ) & & this - > setFont ( resourcePath / " font.ttf " ) ) {
}
2020-12-11 14:24:42 +01:00
else if ( ( this - > m_fontScale ! = 0.0f ) & & ( this - > m_fontScale ! = 1.0f ) ) {
io . Fonts - > Clear ( ) ;
ImFontConfig cfg ;
cfg . OversampleH = cfg . OversampleV = 1 , cfg . PixelSnapH = true ;
cfg . SizePixels = 13.0f * this - > m_fontScale ;
io . Fonts - > AddFontDefault ( & cfg ) ;
}
2020-11-23 15:51:40 +01:00
style . WindowMenuButtonPosition = ImGuiDir_None ;
2020-11-23 22:14:11 +01:00
style . IndentSpacing = 10.0F ;
2020-11-10 15:26:38 +01:00
2020-11-15 15:49:21 +01:00
// Install custom settings handler
ImGuiSettingsHandler handler ;
handler . TypeName = " ImHex " ;
handler . TypeHash = ImHashStr ( " ImHex " ) ;
handler . ReadOpenFn = ImHexSettingsHandler_ReadOpenFn ;
handler . ReadLineFn = ImHexSettingsHandler_ReadLine ;
handler . WriteAllFn = ImHexSettingsHandler_WriteAll ;
handler . UserData = this ;
ctx - > SettingsHandlers . push_back ( handler ) ;
2020-11-10 15:26:38 +01:00
ImGui : : StyleColorsDark ( ) ;
ImGui_ImplGlfw_InitForOpenGL ( this - > m_window , true ) ;
ImGui_ImplOpenGL3_Init ( " #version 150 " ) ;
}
2020-12-22 18:10:01 +01:00
void Window : : initPlugins ( ) {
2021-01-04 13:52:49 +01:00
try {
2021-01-12 23:28:41 +01:00
auto pluginFolderPath = std : : filesystem : : path ( ( SharedData : : mainArgv ) [ 0 ] ) . parent_path ( ) / " plugins " ;
2021-01-04 13:52:49 +01:00
PluginHandler : : load ( pluginFolderPath . string ( ) ) ;
} catch ( std : : runtime_error & e ) { return ; }
2020-12-22 18:10:01 +01:00
for ( const auto & plugin : PluginHandler : : getPlugins ( ) ) {
2021-01-12 23:28:41 +01:00
plugin . initializePlugin ( ) ;
2020-12-22 18:10:01 +01:00
}
}
2020-11-10 15:26:38 +01:00
void Window : : deinitGLFW ( ) {
glfwDestroyWindow ( this - > m_window ) ;
glfwTerminate ( ) ;
}
void Window : : deinitImGui ( ) {
ImGui_ImplOpenGL3_Shutdown ( ) ;
ImGui_ImplGlfw_Shutdown ( ) ;
ImGui : : DestroyContext ( ) ;
}
2020-12-22 18:10:01 +01:00
void Window : : deinitPlugins ( ) {
PluginHandler : : unload ( ) ;
}
2020-11-10 15:26:38 +01:00
}