2021-04-20 21:46:48 +02:00
# include "init/tasks.hpp"
2021-08-31 15:22:00 +02:00
# include <imgui.h>
# include <imgui_freetype.h>
2021-04-20 21:46:48 +02:00
# include <hex/helpers/net.hpp>
# include <hex/api/content_registry.hpp>
2021-09-08 15:18:24 +02:00
# include <hex/pattern_language/pattern_data.hpp>
2021-12-07 22:47:41 +01:00
# include <hex/helpers/paths.hpp>
2021-04-20 21:46:48 +02:00
2021-08-31 15:22:00 +02:00
# include <fontawesome_font.h>
# include <codicons_font.h>
# include <unifont_font.h>
2021-04-20 21:46:48 +02:00
# include "helpers/plugin_manager.hpp"
# include <filesystem>
2021-08-29 14:18:45 +02:00
# include <nlohmann/json.hpp>
2021-04-20 21:46:48 +02:00
namespace hex : : init {
2021-08-29 14:18:45 +02:00
using namespace std : : literals : : string_literals ;
2021-04-20 21:46:48 +02:00
static bool checkForUpdates ( ) {
hex : : Net net ;
2022-01-13 14:33:30 +01:00
auto releases = net . getJson ( GitHubApiURL + " /releases/latest " s , 2000 ) . get ( ) ;
2021-04-20 21:46:48 +02:00
if ( releases . code ! = 200 )
2021-05-24 23:34:17 +02:00
return false ;
2021-04-20 21:46:48 +02:00
2021-08-28 00:45:59 +02:00
if ( ! releases . body . contains ( " tag_name " ) | | ! releases . body [ " tag_name " ] . is_string ( ) )
2021-04-20 21:46:48 +02:00
return false ;
2021-09-22 12:57:40 +02:00
auto versionString = std : : string ( IMHEX_VERSION ) ;
auto currVersion = " v " + versionString . substr ( 0 , versionString . find_first_of ( ' - ' ) ) ;
2021-08-28 00:45:59 +02:00
auto latestVersion = releases . body [ " tag_name " ] . get < std : : string_view > ( ) ;
2021-04-20 21:46:48 +02:00
if ( latestVersion ! = currVersion )
getInitArguments ( ) . push_back ( { " update-available " , latestVersion . data ( ) } ) ;
return true ;
}
2021-08-22 21:11:01 +02:00
static bool downloadInformation ( ) {
hex : : Net net ;
2021-12-17 09:52:58 +01:00
auto tip = net . getString ( ImHexApiURL + " /tip " s , 200 ) . get ( ) ;
2021-08-22 21:11:01 +02:00
if ( tip . code ! = 200 )
return false ;
2021-08-28 00:45:59 +02:00
getInitArguments ( ) . push_back ( { " tip-of-the-day " , tip . body } ) ;
2021-08-22 21:11:01 +02:00
return true ;
}
2021-04-20 21:46:48 +02:00
bool createDirectories ( ) {
2021-05-21 23:46:36 +02:00
bool result = true ;
2022-01-17 20:06:00 +01:00
constexpr std : : array paths = {
2021-08-28 16:29:15 +02:00
ImHexPath : : Patterns ,
ImHexPath : : PatternsInclude ,
ImHexPath : : Magic ,
ImHexPath : : Plugins ,
ImHexPath : : Resources ,
ImHexPath : : Config ,
ImHexPath : : Constants ,
ImHexPath : : Yara ,
2022-01-17 20:06:00 +01:00
ImHexPath : : Python ,
ImHexPath : : Logs
2021-05-21 23:46:36 +02:00
} ;
2021-04-20 21:46:48 +02:00
2021-05-21 23:46:36 +02:00
for ( auto path : paths ) {
2022-01-12 09:02:03 +01:00
for ( auto & folder : hex : : getPath ( path , true ) ) {
2021-05-21 23:46:36 +02:00
try {
2022-01-13 14:33:30 +01:00
fs : : create_directories ( folder ) ;
2021-05-21 23:46:36 +02:00
} catch ( . . . ) {
2022-01-13 14:34:27 +01:00
log : : error ( " Failed to create folder {}! " , folder . string ( ) ) ;
2021-05-21 23:46:36 +02:00
result = false ;
}
}
}
2021-04-20 21:46:48 +02:00
2021-05-21 23:46:36 +02:00
if ( ! result )
getInitArguments ( ) . push_back ( { " folder-creation-error " , { } } ) ;
return result ;
2021-04-20 21:46:48 +02:00
}
2021-08-31 15:22:00 +02:00
bool loadFonts ( ) {
auto & fonts = SharedData : : fontAtlas ;
auto & cfg = SharedData : : fontConfig ;
fonts = IM_NEW ( ImFontAtlas ) ( ) ;
cfg = { } ;
2022-01-13 14:33:30 +01:00
fs : : path fontFile ;
2021-08-31 15:22:00 +02:00
for ( const auto & dir : hex : : getPath ( ImHexPath : : Resources ) ) {
2022-01-13 14:33:30 +01:00
auto path = dir / " font.ttf " ;
if ( fs : : exists ( path ) ) {
2022-01-13 14:34:27 +01:00
log : : info ( " Loading custom front from {} " , path . string ( ) ) ;
2021-09-22 23:42:52 +02:00
fontFile = path ;
2021-08-31 15:22:00 +02:00
break ;
2021-09-22 23:42:52 +02:00
}
2021-08-31 15:22:00 +02:00
}
ImVector < ImWchar > ranges ;
{
ImFontGlyphRangesBuilder glyphRangesBuilder ;
glyphRangesBuilder . AddRanges ( fonts - > GetGlyphRangesDefault ( ) ) ;
glyphRangesBuilder . AddRanges ( fonts - > GetGlyphRangesJapanese ( ) ) ;
glyphRangesBuilder . AddRanges ( fonts - > GetGlyphRangesChineseFull ( ) ) ;
glyphRangesBuilder . AddRanges ( fonts - > GetGlyphRangesCyrillic ( ) ) ;
glyphRangesBuilder . AddRanges ( fonts - > GetGlyphRangesKorean ( ) ) ;
glyphRangesBuilder . AddRanges ( fonts - > GetGlyphRangesThai ( ) ) ;
glyphRangesBuilder . AddRanges ( fonts - > GetGlyphRangesVietnamese ( ) ) ;
glyphRangesBuilder . BuildRanges ( & ranges ) ;
}
ImWchar fontAwesomeRange [ ] = {
ICON_MIN_FA , ICON_MAX_FA ,
0
} ;
ImWchar codiconsRange [ ] = {
ICON_MIN_VS , ICON_MAX_VS ,
0
} ;
ImWchar unifontRange [ ] = {
0x0020 , 0xFFF0 ,
0
} ;
2021-09-22 23:42:52 +02:00
if ( fontFile . empty ( ) ) {
2021-08-31 15:22:00 +02:00
// Load default font
2021-09-22 23:42:52 +02:00
2021-08-31 15:22:00 +02:00
fonts - > Clear ( ) ;
cfg . OversampleH = cfg . OversampleV = 1 , cfg . PixelSnapH = true ;
2022-01-11 23:48:18 +01:00
cfg . SizePixels = 13.0F * SharedData : : fontScale ;
2021-08-31 15:22:00 +02:00
fonts - > AddFontDefault ( & cfg ) ;
} else {
// Load custom font
2021-09-22 23:42:52 +02:00
auto fontSize = ContentRegistry : : Settings : : read ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.font_size " , 14 ) ;
2021-08-31 15:22:00 +02:00
cfg . OversampleH = cfg . OversampleV = 1 , cfg . PixelSnapH = true ;
2021-09-22 23:42:52 +02:00
cfg . SizePixels = fontSize * SharedData : : fontScale ;
2021-08-31 15:22:00 +02:00
2022-01-13 14:33:30 +01:00
fonts - > AddFontFromFileTTF ( fontFile . string ( ) . c_str ( ) , std : : floor ( fontSize * SharedData : : fontScale ) , & cfg , ranges . Data ) ; // Needs conversion to char for Windows
2021-08-31 15:22:00 +02:00
}
cfg . MergeMode = true ;
2022-01-11 23:48:18 +01:00
fonts - > AddFontFromMemoryCompressedTTF ( font_awesome_compressed_data , font_awesome_compressed_size , 13.0F * SharedData : : fontScale , & cfg , fontAwesomeRange ) ;
fonts - > AddFontFromMemoryCompressedTTF ( codicons_compressed_data , codicons_compressed_size , 13.0F * SharedData : : fontScale , & cfg , codiconsRange ) ;
fonts - > AddFontFromMemoryCompressedTTF ( unifont_compressed_data , unifont_compressed_size , 13.0F * SharedData : : fontScale , & cfg , unifontRange ) ;
2021-08-31 15:22:00 +02:00
ImGuiFreeType : : BuildFontAtlas ( fonts ) ;
return true ;
}
2021-07-31 17:11:10 +02:00
bool deleteSharedData ( ) {
SharedData : : deferredCalls . clear ( ) ;
2021-09-21 02:29:54 +02:00
while ( ImHexApi : : Provider : : isValid ( ) )
ImHexApi : : Provider : : remove ( ImHexApi : : Provider : : get ( ) ) ;
2021-07-31 17:11:10 +02:00
SharedData : : settingsEntries . clear ( ) ;
SharedData : : settingsJson . clear ( ) ;
SharedData : : commandPaletteCommands . clear ( ) ;
SharedData : : patternLanguageFunctions . clear ( ) ;
2022-01-18 00:10:10 +01:00
for ( auto & [ name , view ] : ContentRegistry : : Views : : getEntries ( ) )
2021-04-20 21:46:48 +02:00
delete view ;
SharedData : : views . clear ( ) ;
2021-07-31 17:11:10 +02:00
SharedData : : toolsEntries . clear ( ) ;
SharedData : : dataInspectorEntries . clear ( ) ;
SharedData : : bookmarkEntries . clear ( ) ;
for ( auto & pattern : SharedData : : patternData )
delete pattern ;
SharedData : : patternData . clear ( ) ;
SharedData : : languageNames . clear ( ) ;
SharedData : : languageDefinitions . clear ( ) ;
SharedData : : loadedLanguageStrings . clear ( ) ;
SharedData : : welcomeScreenEntries . clear ( ) ;
SharedData : : footerItems . clear ( ) ;
2021-12-15 16:53:32 +01:00
SharedData : : toolbarItems . clear ( ) ;
2022-01-23 02:28:38 +01:00
SharedData : : mainMenuItems . clear ( ) ;
SharedData : : menuItems . clear ( ) ;
2021-07-31 17:11:10 +02:00
2022-01-09 21:57:22 +01:00
SharedData : : globalShortcuts . clear ( ) ;
SharedData : : runningTasks . clear ( ) ;
2021-07-31 17:11:10 +02:00
SharedData : : dataProcessorNodes . clear ( ) ;
SharedData : : recentFilePaths . clear ( ) ;
2022-01-13 14:34:19 +01:00
SharedData : : dataFormatters . clear ( ) ;
SharedData : : fileHandlers . clear ( ) ;
2022-01-09 21:57:22 +01:00
2021-07-31 17:11:10 +02:00
SharedData : : clearVariables ( ) ;
2021-04-20 21:46:48 +02:00
return true ;
}
bool loadPlugins ( ) {
for ( const auto & dir : hex : : getPath ( ImHexPath : : Plugins ) ) {
PluginManager : : load ( dir ) ;
}
if ( PluginManager : : getPlugins ( ) . empty ( ) ) {
2022-01-13 14:34:27 +01:00
log : : error ( " No plugins found! " ) ;
2021-04-20 21:46:48 +02:00
getInitArguments ( ) . push_back ( { " no-plugins " , { } } ) ;
return false ;
}
for ( const auto & plugin : PluginManager : : getPlugins ( ) ) {
2022-01-17 20:06:00 +01:00
if ( ! plugin . initializePlugin ( ) )
log : : error ( " Failed to initialize plugin {} " , plugin . getPath ( ) . filename ( ) . string ( ) ) ;
2021-04-20 21:46:48 +02:00
}
return true ;
}
bool unloadPlugins ( ) {
PluginManager : : unload ( ) ;
return true ;
}
bool loadSettings ( ) {
2021-05-21 23:46:36 +02:00
try {
ContentRegistry : : Settings : : load ( ) ;
2022-01-13 14:34:27 +01:00
} catch ( std : : exception & e ) {
log : : error ( " Failed to load configuration! {} " , e . what ( ) ) ;
2021-05-21 23:46:36 +02:00
return false ;
}
2021-04-20 21:46:48 +02:00
2021-08-31 15:22:00 +02:00
switch ( ContentRegistry : : Settings : : read ( " hex.builtin.setting.interface " , " hex.builtin.setting.interface.scaling " , 0 ) ) {
default :
case 0 :
// Native scaling
break ;
case 1 :
SharedData : : globalScale = SharedData : : fontScale = 0.5F ;
break ;
case 2 :
SharedData : : globalScale = SharedData : : fontScale = 1.0F ;
break ;
case 3 :
SharedData : : globalScale = SharedData : : fontScale = 1.5F ;
break ;
case 4 :
SharedData : : globalScale = SharedData : : fontScale = 2.0F ;
break ;
}
2021-04-20 21:46:48 +02:00
return true ;
}
bool storeSettings ( ) {
2021-05-21 23:46:36 +02:00
try {
ContentRegistry : : Settings : : store ( ) ;
2022-01-13 14:34:27 +01:00
} catch ( std : : exception & e ) {
log : : error ( " Failed to store configuration! {} " , e . what ( ) ) ;
2021-05-21 23:46:36 +02:00
return false ;
}
2021-04-20 21:46:48 +02:00
return true ;
}
std : : vector < Task > getInitTasks ( ) {
return {
{ " Checking for updates... " , checkForUpdates } ,
2021-08-22 21:11:01 +02:00
{ " Downloading information... " , downloadInformation } ,
2021-04-20 21:46:48 +02:00
{ " Creating directories... " , createDirectories } ,
2021-05-29 21:51:00 +02:00
{ " Loading settings... " , loadSettings } ,
2021-09-12 13:59:23 +02:00
{ " Loading plugins... " , loadPlugins } ,
2021-08-31 15:22:00 +02:00
{ " Loading fonts... " , loadFonts } ,
2021-04-20 21:46:48 +02:00
} ;
}
std : : vector < Task > getExitTasks ( ) {
return {
{ " Saving settings... " , storeSettings } ,
2021-07-31 17:11:10 +02:00
{ " Cleaning up shared data... " , deleteSharedData } ,
2021-05-29 21:51:00 +02:00
{ " Unloading plugins... " , unloadPlugins } ,
2021-04-20 21:46:48 +02:00
} ;
}
std : : vector < Argument > & getInitArguments ( ) {
static std : : vector < Argument > initArguments ;
return initArguments ;
}
}