ui: Added really fancy splash screen (updater in the future)
This commit is contained in:
parent
93e1c4c4e8
commit
24c7f1d5b7
@ -1,7 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# Updating the version here will update it throughout ImHex as well
|
||||
project(imhex VERSION 1.7.0)
|
||||
set(IMHEX_VERSION "1.7.0")
|
||||
project(imhex VERSION ${IMHEX_VERSION})
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")
|
||||
@ -67,17 +68,18 @@ add_executable(imhex ${application_type}
|
||||
${imhex_icon}
|
||||
)
|
||||
|
||||
set_target_properties(imhex PROPERTIES OUTPUT_NAME "imhexg")
|
||||
set_target_properties(imhex PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
target_link_directories(imhex PRIVATE ${CAPSTONE_LIBRARY_DIRS} ${MAGIC_LIBRARY_DIRS})
|
||||
|
||||
if (WIN32)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
target_link_libraries(imhex magic gnurx tre intl iconv libshlwapi.a ${CMAKE_DL_LIBS} capstone LLVMDemangle libimhex ${Python_LIBRARIES} dl pthread wsock32 ws2_32 libyara)
|
||||
else ()
|
||||
target_link_libraries(imhex libdl.a libmagic.a libgnurx.a libtre.a libintl.a libiconv.a libshlwapi.a libcapstone.a LLVMDemangle libimhex ${Python_LIBRARIES} wsock32 ws2_32 libyara)
|
||||
endif()
|
||||
target_link_libraries(imhex libdl.a libmagic.a libgnurx.a libtre.a libintl.a libiconv.a libshlwapi.a libcapstone.a LLVMDemangle libimhex ${Python_LIBRARIES} wsock32 ws2_32 libyara)
|
||||
else ()
|
||||
target_link_libraries(imhex magic ${CMAKE_DL_LIBS} capstone LLVMDemangle libimhex ${Python_LIBRARIES} dl pthread libyara)
|
||||
endif ()
|
||||
|
||||
set_target_properties(imhex PROPERTIES VERSION ${IMHEX_VERSION})
|
||||
add_subdirectory(splash)
|
||||
set_target_properties(splash PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
createPackage()
|
||||
|
@ -76,18 +76,21 @@ macro(detectOS)
|
||||
set(CMAKE_INSTALL_LIBDIR ".")
|
||||
set(PLUGINS_INSTALL_LOCATION "plugins")
|
||||
set(MAGIC_INSTALL_LOCATION "magic")
|
||||
set(RESOURCES_INSTALL_LOCATION "resources")
|
||||
elseif(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOS_MACOS")
|
||||
set(CMAKE_INSTALL_BINDIR ".")
|
||||
set(CMAKE_INSTALL_LIBDIR ".")
|
||||
set(PLUGINS_INSTALL_LOCATION "plugins")
|
||||
set(MAGIC_INSTALL_LOCATION "magic")
|
||||
set(RESOURCES_INSTALL_LOCATION "resources")
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOS_LINUX")
|
||||
set(CMAKE_INSTALL_BINDIR "bin")
|
||||
set(CMAKE_INSTALL_LIBDIR "lib")
|
||||
set(PLUGINS_INSTALL_LOCATION "share/imhex/plugins")
|
||||
set(MAGIC_INSTALL_LOCATION "share/imhex/magic")
|
||||
set(RESOURCES_INSTALL_LOCATION "share/imhex/resources")
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown / unsupported system!")
|
||||
endif()
|
||||
@ -116,7 +119,7 @@ macro(configurePackageCreation)
|
||||
else ()
|
||||
set(application_type)
|
||||
endif ()
|
||||
set(imhex_icon "${PROJECT_SOURCE_DIR}/res/resource.rc")
|
||||
set(imhex_icon "${CMAKE_SOURCE_DIR}/res/resource.rc")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc -Wl,--allow-multiple-definition -static")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wl,-subsystem,windows")
|
||||
|
||||
@ -132,7 +135,7 @@ macro(configurePackageCreation)
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/res/LICENSE.rtf")
|
||||
endif()
|
||||
elseif (APPLE)
|
||||
set (imhex_icon "${PROJECT_SOURCE_DIR}/res/mac/AppIcon.icns")
|
||||
set (imhex_icon "${CMAKE_SOURCE_DIR}/res/mac/AppIcon.icns")
|
||||
|
||||
if (CREATE_BUNDLE)
|
||||
set(application_type MACOSX_BUNDLE)
|
||||
@ -226,9 +229,13 @@ macro(createPackage)
|
||||
COMMAND file -C -m ${CMAKE_SOURCE_DIR}/magic_dbs
|
||||
)
|
||||
|
||||
|
||||
# Install the magicdb files.
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/magic_dbs.mgc DESTINATION ${MAGIC_INSTALL_LOCATION} RENAME imhex.mgc)
|
||||
|
||||
# Install splash screen
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/res/splash.png DESTINATION ${RESOURCES_INSTALL_LOCATION})
|
||||
|
||||
if (CREATE_BUNDLE)
|
||||
include(PostprocessBundle)
|
||||
|
||||
@ -244,9 +251,9 @@ macro(createPackage)
|
||||
# Enforce DragNDrop packaging.
|
||||
set(CPACK_GENERATOR "DragNDrop")
|
||||
|
||||
install(TARGETS imhex BUNDLE DESTINATION .)
|
||||
install(TARGETS splash imhex BUNDLE DESTINATION .)
|
||||
else()
|
||||
install(TARGETS imhex RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(TARGETS splash imhex RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
|
||||
|
@ -17,6 +17,9 @@ namespace ImGui {
|
||||
|
||||
void Header(const char *label, bool firstEntry = false);
|
||||
|
||||
std::tuple<ImTextureID, int, int> LoadImageFromPath(const char *path);
|
||||
void UnloadImage(ImTextureID texture);
|
||||
|
||||
enum ImGuiCustomCol {
|
||||
ImGuiCustomCol_DescButton,
|
||||
ImGuiCustomCol_DescButtonHovered,
|
||||
|
7762
external/ImGui/include/stb_image.h
vendored
Normal file
7762
external/ImGui/include/stb_image.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
36
external/ImGui/source/imgui_imhex_extensions.cpp
vendored
36
external/ImGui/source/imgui_imhex_extensions.cpp
vendored
@ -6,8 +6,13 @@
|
||||
#include <imgui_internal.h>
|
||||
#undef IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <glad/glad.h>
|
||||
|
||||
namespace ImGui {
|
||||
|
||||
bool Hyperlink(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags) {
|
||||
@ -195,4 +200,35 @@ namespace ImGui {
|
||||
colors[ImGuiCustomCol_DescButtonActive] = ImColor(80, 80, 120);
|
||||
}
|
||||
|
||||
std::tuple<ImTextureID, int, int> LoadImageFromPath(const char *path) {
|
||||
int imageWidth = 0;
|
||||
int imageHeight = 0;
|
||||
|
||||
unsigned char* imageData = stbi_load(path, &imageWidth, &imageHeight, nullptr, 4);
|
||||
if (imageData == nullptr)
|
||||
return { nullptr, -1, -1 };
|
||||
|
||||
GLuint texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
#if defined(GL_UNPACK_ROW_LENGTH)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
#endif
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
|
||||
stbi_image_free(imageData);
|
||||
|
||||
return { reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture)), imageWidth, imageHeight };
|
||||
}
|
||||
|
||||
void UnloadImage(ImTextureID texture) {
|
||||
auto glTextureId = static_cast<GLuint>(reinterpret_cast<intptr_t>(texture));
|
||||
glDeleteTextures(1, &glTextureId);
|
||||
}
|
||||
|
||||
}
|
BIN
res/splash.png
Normal file
BIN
res/splash.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
@ -52,7 +52,7 @@ int main(int argc, char **argv) {
|
||||
ContentRegistry::Views::add<ViewDataProcessor>();
|
||||
ContentRegistry::Views::add<ViewYara>();
|
||||
|
||||
if (argc > 1)
|
||||
if (argc > 2)
|
||||
EventManager::post<EventFileDropped>(argv[1]);
|
||||
|
||||
window.loop();
|
||||
|
@ -58,6 +58,13 @@ namespace hex {
|
||||
SharedData::mainArgv = argv;
|
||||
SharedData::currentProvider = nullptr;
|
||||
|
||||
#if defined(RELEASE)
|
||||
if (argv[argc - 1] != std::string(GIT_COMMIT_HASH)) {
|
||||
printf("Version mismatch! Make sure you updated all of ImHex\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
this->createDirectories();
|
||||
this->initGLFW();
|
||||
this->initImGui();
|
||||
|
33
splash/CMakeLists.txt
Normal file
33
splash/CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
include("${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake")
|
||||
include("${CMAKE_SOURCE_DIR}/cmake/modules/PostprocessBundle.cmake")
|
||||
|
||||
get_target_property(IMHEX_VERSION imhex VERSION)
|
||||
project(splash VERSION ${IMHEX_VERSION})
|
||||
|
||||
addVersionDefines()
|
||||
configurePackageCreation()
|
||||
|
||||
if (WIN32)
|
||||
set(application_type "WIN32")
|
||||
else ()
|
||||
set(application_type)
|
||||
endif ()
|
||||
|
||||
add_executable(splash ${application_type}
|
||||
source/main.cpp
|
||||
source/splash_window.cpp
|
||||
${imhex_icon}
|
||||
)
|
||||
|
||||
target_include_directories(splash PUBLIC include)
|
||||
|
||||
add_compile_definitions(IMHEX_FILE_NAME=\"$<TARGET_FILE_NAME:imhex>\")
|
||||
set_target_properties(splash PROPERTIES OUTPUT_NAME "imhex")
|
||||
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(splash libstdc++.a libgcc.a libimhex)
|
||||
else ()
|
||||
target_link_libraries(splash libimhex pthread)
|
||||
endif ()
|
40
splash/include/splash_window.hpp
Normal file
40
splash/include/splash_window.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <vector>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
struct GLFWwindow;
|
||||
|
||||
namespace hex::pre {
|
||||
|
||||
class WindowSplash {
|
||||
public:
|
||||
WindowSplash();
|
||||
~WindowSplash();
|
||||
|
||||
void loop();
|
||||
|
||||
void addStartupTask(const std::function<bool()> &task) {
|
||||
this->m_tasks.push_back(task);
|
||||
}
|
||||
|
||||
private:
|
||||
GLFWwindow *m_window;
|
||||
std::mutex m_progressMutex;
|
||||
float m_progress;
|
||||
|
||||
void initGLFW();
|
||||
void initImGui();
|
||||
|
||||
void deinitGLFW();
|
||||
void deinitImGui();
|
||||
|
||||
std::future<bool> processTasksAsync();
|
||||
|
||||
std::vector<std::function<bool()>> m_tasks;
|
||||
};
|
||||
|
||||
}
|
53
splash/source/main.cpp
Normal file
53
splash/source/main.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include <hex.hpp>
|
||||
|
||||
#include "splash_window.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
constexpr auto ImHexPath = IMHEX_FILE_NAME;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const char *filePath = nullptr;
|
||||
bool skipSplash = false;
|
||||
|
||||
// Handle command line arguments
|
||||
{
|
||||
if (argc == 1) {
|
||||
// No optional arguments used, use default
|
||||
} else if (argc == 2) {
|
||||
if (argv[1] == std::string("--no-splash")) skipSplash = true;
|
||||
else filePath = argv[1];
|
||||
} else if (argc == 3) {
|
||||
filePath = argv[1];
|
||||
|
||||
if (argv[2] == std::string("--no-splash")) skipSplash = true;
|
||||
else {
|
||||
printf("Invalid argument '%s'\n", argv[2]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else {
|
||||
printf("Usage: imhex [file_path] [--no-splash] ");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!skipSplash) {
|
||||
hex::pre::WindowSplash window;
|
||||
|
||||
/* Dummy task */
|
||||
window.addStartupTask([]{ std::this_thread::sleep_for(1s); return true; });
|
||||
|
||||
window.loop();
|
||||
}
|
||||
|
||||
// Launch ImHex
|
||||
if (filePath == nullptr)
|
||||
return execl(ImHexPath, ImHexPath, GIT_COMMIT_HASH, nullptr);
|
||||
else
|
||||
return execl(ImHexPath, ImHexPath, filePath, GIT_COMMIT_HASH, nullptr);
|
||||
}
|
167
splash/source/splash_window.cpp
Normal file
167
splash/source/splash_window.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
#include "splash_window.hpp"
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <imgui_imhex_extensions.h>
|
||||
#include <imgui_impl_glfw.h>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <future>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::literals::chrono_literals;
|
||||
|
||||
namespace hex::pre {
|
||||
|
||||
static void centerWindow(GLFWwindow *window) {
|
||||
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||
if (!monitor)
|
||||
return;
|
||||
|
||||
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||||
if (!mode)
|
||||
return;
|
||||
|
||||
int monitorX, monitorY;
|
||||
glfwGetMonitorPos(monitor, &monitorX, &monitorY);
|
||||
|
||||
int windowWidth, windowHeight;
|
||||
glfwGetWindowSize(window, &windowWidth, &windowHeight);
|
||||
|
||||
glfwSetWindowPos(window, monitorX + (mode->width - windowWidth) / 2, monitorY + (mode->height - windowHeight) / 2);
|
||||
}
|
||||
|
||||
|
||||
WindowSplash::WindowSplash() {
|
||||
this->initGLFW();
|
||||
this->initImGui();
|
||||
}
|
||||
|
||||
WindowSplash::~WindowSplash() {
|
||||
this->deinitImGui();
|
||||
this->deinitGLFW();
|
||||
}
|
||||
|
||||
static void drawSplashScreen(ImTextureID splashTexture, u32 width, u32 height, float progress) {
|
||||
auto drawList = ImGui::GetOverlayDrawList();
|
||||
|
||||
drawList->AddImage(splashTexture, ImVec2(0, 0), ImVec2(width, height));
|
||||
drawList->AddText(ImVec2(20, 120), 0xFFFFFFFF, hex::format("WerWolv 2020 - {0}\n{1} : {2}@{3}", __DATE__ + 7, IMHEX_VERSION, GIT_COMMIT_HASH, GIT_BRANCH).c_str());
|
||||
drawList->AddRectFilled(ImVec2(0, height - 5), ImVec2(width * progress, height), 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
std::future<bool> WindowSplash::processTasksAsync() {
|
||||
return std::async(std::launch::async, [this] {
|
||||
bool status = true;
|
||||
|
||||
for (const auto &task : this->m_tasks) {
|
||||
status = status && task();
|
||||
|
||||
{
|
||||
std::lock_guard guard(this->m_progressMutex);
|
||||
this->m_progress += 1.0F / m_tasks.size();
|
||||
}
|
||||
}
|
||||
|
||||
// Small extra delay so the last progress step is visible
|
||||
std::this_thread::sleep_for(200ms);
|
||||
|
||||
return status;
|
||||
});
|
||||
}
|
||||
|
||||
void WindowSplash::loop() {
|
||||
auto [splashTexture, splashWidth, splashHeight] = ImGui::LoadImageFromPath((hex::getPath(hex::ImHexPath::Resources)[0] + "/splash.png").c_str());
|
||||
|
||||
if (splashTexture == nullptr)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
auto done = processTasksAsync();
|
||||
|
||||
while (!glfwWindowShouldClose(this->m_window)) {
|
||||
glfwPollEvents();
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
{
|
||||
std::lock_guard guard(this->m_progressMutex);
|
||||
drawSplashScreen(splashTexture, splashWidth, splashHeight, this->m_progress);
|
||||
}
|
||||
|
||||
ImGui::Render();
|
||||
int display_w, display_h;
|
||||
glfwGetFramebufferSize(this->m_window, &display_w, &display_h);
|
||||
glViewport(0, 0, display_w, display_h);
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
glfwSwapBuffers(this->m_window);
|
||||
|
||||
if (done.wait_for(0s) == std::future_status::ready) {
|
||||
if (!done.get()) printf("One or more tasks failed to execute!");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::UnloadImage(splashTexture);
|
||||
}
|
||||
|
||||
void WindowSplash::initGLFW() {
|
||||
glfwSetErrorCallback([](int error, const char *description) {
|
||||
printf("GLFW Error: %d - %s\n", error, description);
|
||||
exit(EXIT_FAILURE);
|
||||
});
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
|
||||
glfwWindowHint(GLFW_FLOATING, GLFW_TRUE);
|
||||
|
||||
this->m_window = glfwCreateWindow(640, 400, "ImHex", nullptr, nullptr);
|
||||
if (this->m_window == nullptr)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
centerWindow(this->m_window);
|
||||
|
||||
glfwMakeContextCurrent(this->m_window);
|
||||
glfwSwapInterval(1);
|
||||
|
||||
if (gladLoadGL() == 0)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void WindowSplash::initImGui() {
|
||||
IMGUI_CHECKVERSION();
|
||||
GImGui = ImGui::CreateContext();
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGui_ImplGlfw_InitForOpenGL(this->m_window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 130");
|
||||
}
|
||||
|
||||
void WindowSplash::deinitGLFW() {
|
||||
glfwDestroyWindow(this->m_window);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
void WindowSplash::deinitImGui() {
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user