From 982d2b613b12c8395fe92f5c62d0a14b6b059e10 Mon Sep 17 00:00:00 2001 From: ohyzha Date: Thu, 19 Dec 2024 13:27:47 +0200 Subject: [PATCH] implement first version of embedded resource loader for Windows --- .../Windows/EmbeddedResourceLoaderWindows.cpp | 80 ++++++++++++++++++ .../Windows/EmbeddedResourceLoaderWindows.hpp | 23 +++++ resources/icon.rc | 62 ++++++++++++++ resources/madvoxel_icon.ico | Bin 0 -> 194366 bytes resources/resource.h | 1 + tests/CMakeLists.txt | 8 +- tests/Host/Windows/ResourceLoaderTests.cpp | 35 ++++++++ 7 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 openVulkanoCpp/Host/Windows/EmbeddedResourceLoaderWindows.cpp create mode 100644 openVulkanoCpp/Host/Windows/EmbeddedResourceLoaderWindows.hpp create mode 100644 resources/icon.rc create mode 100644 resources/madvoxel_icon.ico create mode 100644 resources/resource.h create mode 100644 tests/Host/Windows/ResourceLoaderTests.cpp diff --git a/openVulkanoCpp/Host/Windows/EmbeddedResourceLoaderWindows.cpp b/openVulkanoCpp/Host/Windows/EmbeddedResourceLoaderWindows.cpp new file mode 100644 index 0000000..9ea8756 --- /dev/null +++ b/openVulkanoCpp/Host/Windows/EmbeddedResourceLoaderWindows.cpp @@ -0,0 +1,80 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "EmbeddedResourceLoaderWindows.hpp" +#include "Base/Utils.hpp" +#include "Base/Logger.hpp" +#include "../resources/resource.h" +#include +#include +#include + + +namespace OpenVulkano +{ + namespace + { + void* HANDLE = ResourceLoader::RegisterResourceLoader(std::make_unique()); + } + + std::string EmbeddedResourceLoaderWindows::GetResourcePath(const std::string& resourceName) + { + return ""; + } + + Array EmbeddedResourceLoaderWindows::GetResource(const std::string& resourceName) + { + return {}; + //return GetResource(resourceName, GetResourceType(resourceName)); + } + + //LPSTR EmbeddedResourceLoaderWindows::GetResourceType(const std::string& resourceName) const + //{ + // std::filesystem::path path(resourceName); + // std::string ext = path.extension().string(); + // if (ext.empty() || ext == ".") + // { + // Logger::APP->warn("Could not load embedded resource {}. Unsupported extension", resourceName, ext); + // return {}; + // } + // if (ext == ".ico" || ext == ".icon") + // { + // return RT_ICON; + // } + // else if (ext == ".ttf" || ext == ".fnt" || ext == ".font") + // { + // return RT_FONT; + // } + // // custom raw data + // return RT_RCDATA; + //} + + Array EmbeddedResourceLoaderWindows::GetResource(LPSTR resId, LPSTR resourceType) const + { + HMODULE exe = GetModuleHandleA(NULL); + LPCSTR resourceName = resId; + HRSRC hRes = FindResourceA(exe, resourceName, resourceType); + if (!hRes) + { + Logger::APP->warn("Could not find embedded resource"); + return {}; + } + + HGLOBAL hResData = LoadResource(exe, hRes); + if (!hResData) + { + Logger::APP->warn("Embedded resource found, but could not load."); + return {}; + } + + void* data = LockResource(hResData); + DWORD size = SizeofResource(exe, hRes); + Array dst(size); + std::memcpy(dst.Data(), data, size); + return dst; + } + +} \ No newline at end of file diff --git a/openVulkanoCpp/Host/Windows/EmbeddedResourceLoaderWindows.hpp b/openVulkanoCpp/Host/Windows/EmbeddedResourceLoaderWindows.hpp new file mode 100644 index 0000000..c2a300f --- /dev/null +++ b/openVulkanoCpp/Host/Windows/EmbeddedResourceLoaderWindows.hpp @@ -0,0 +1,23 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Host/ResourceLoader.hpp" +#include + +namespace OpenVulkano +{ + class EmbeddedResourceLoaderWindows final : public ResourceLoader + { + public: + std::string GetResourcePath(const std::string& resourceName) override; + Array GetResource(const std::string& resourceName) override; + Array GetResource(char* resId, char* resourceType) const; + private: + char* GetResourceType(const std::string& resourceName) const; + }; +} \ No newline at end of file diff --git a/resources/icon.rc b/resources/icon.rc new file mode 100644 index 0000000..d0aa0e0 --- /dev/null +++ b/resources/icon.rc @@ -0,0 +1,62 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + +IDI_MADVOXEL_ICON ICON "madvoxel_icon.ico" +MADVOXEL_ICON ICON "madvoxel_icon.ico" diff --git a/resources/madvoxel_icon.ico b/resources/madvoxel_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c178264f0b6f6535cb5428503b41cd65fc680653 GIT binary patch literal 194366 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 literal 0 HcmV?d00001 diff --git a/resources/resource.h b/resources/resource.h new file mode 100644 index 0000000..2c4237e --- /dev/null +++ b/resources/resource.h @@ -0,0 +1 @@ +#define IDI_MADVOXEL_ICON 101 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 297f739..e38cd8f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,12 +2,16 @@ cmake_minimum_required(VERSION 3.28 FATAL_ERROR) include(SetupVulkan) include(Utils) +include(Filter) -file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp") +cmake_path(GET CMAKE_CURRENT_SOURCE_DIR PARENT_PATH ROOT_FOLDER) +file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp" + "${ROOT_FOLDER}/resources/*.rc" "${ROOT_FOLDER}/resources/*.h") + +FilterPlatformPaths(SOURCES) if (NOT ENABLE_CURL) list(FILTER SOURCES EXCLUDE REGEX "WebResourceLoader") endif() -source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${SOURCES}) add_executable(OpenVulkano_Tests ${SOURCES}) target_include_directories(OpenVulkano_Tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/Host/Windows/ResourceLoaderTests.cpp b/tests/Host/Windows/ResourceLoaderTests.cpp new file mode 100644 index 0000000..4e92ae1 --- /dev/null +++ b/tests/Host/Windows/ResourceLoaderTests.cpp @@ -0,0 +1,35 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include + +#include "Host/Windows/EmbeddedResourceLoaderWindows.hpp" +#include "Base/Logger.hpp" +#include "../resources/resource.h" +#include +#include +#include + +using namespace OpenVulkano; + +TEST_CASE("Load icon") +{ + Logger::SetupLogger("", "tests.log"); + EmbeddedResourceLoaderWindows loader; + + // the icon is split into RT_GROUP_ICON and RT_ICON. resource.h defines RT_GROUP_ICON entry + // RT_GROUP_ICON data + Array groupData = loader.GetResource(MAKEINTRESOURCE(IDI_MADVOXEL_ICON), RT_GROUP_ICON); + + // load resource that has no numeric ID + Array groupData2 = loader.GetResource("MADVOXEL_ICON", RT_GROUP_ICON); + REQUIRE((!groupData.Empty() && groupData.Size() == groupData2.Size())); + + // ICON data + Array iconData = loader.GetResource(MAKEINTRESOURCE(1), RT_ICON); + REQUIRE((!iconData.Empty() && iconData.Size() == 194344)); + +}