1
0
mirror of synced 2024-09-24 03:28:24 +02:00

ui: Added really fancy splash screen (updater in the future)

This commit is contained in:
WerWolv 2021-04-17 15:46:26 +02:00
parent 93e1c4c4e8
commit 24c7f1d5b7
12 changed files with 8121 additions and 11 deletions

View File

@ -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()

View File

@ -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()

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -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();

View File

@ -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
View 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 ()

View 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
View 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);
}

View 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();
}
}