diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 97fd9b389..fd6d60113 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -57,3 +57,6 @@ jobs: - name: Test working-directory: ${{github.workspace}}/build run: ctest -C ${{env.BUILD_TYPE}} --extra-verbose + + - name: Install + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target install -j ${{env.MAKE_THREAD_NUM}} diff --git a/CMake/Common.cmake b/CMake/Common.cmake index 3ac00459f..8f15a5ef4 100644 --- a/CMake/Common.cmake +++ b/CMake/Common.cmake @@ -16,10 +16,18 @@ else () set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Lib) endif () +if (${CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT}) + if (${GENERATOR_IS_MULTI_CONFIG}) + set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/Install/$ CACHE PATH "" FORCE) + else () + set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/Install CACHE PATH "" FORCE) + endif () +endif() + add_definitions(-DENGINE_CMAKE_SOURCE_DIRECTORY="${CMAKE_SOURCE_DIR}") add_definitions(-DENGINE_CMAKE_BINARY_DIRECTORY="${CMAKE_BINARY_DIR}") -add_definitions(-DBUILD_CONFIG_DEBUG=$,1,0>) +add_definitions(-DBUILD_CONFIG_DEBUG=$,$>,1,0>) add_definitions(-DPLATFORM_WINDOWS=$,1,0>) add_definitions(-DPLATFORM_LINUX=$,1,0>) diff --git a/CMake/Target.cmake b/CMake/Target.cmake index 41cbdd852..076b9d4b4 100644 --- a/CMake/Target.cmake +++ b/CMake/Target.cmake @@ -32,13 +32,13 @@ function(LinkLibraries) foreach(L ${PARAMS_LIB}) if (NOT (TARGET ${L})) - target_link_libraries(${PARAMS_NAME} ${L}) + target_link_libraries(${PARAMS_NAME} PUBLIC ${L}) continue() endif() get_target_property(3RD_TYPE ${L} 3RD_TYPE) if (${3RD_TYPE} STREQUAL "3RD_TYPE-NOTFOUND") - target_link_libraries(${PARAMS_NAME} ${L}) + target_link_libraries(${PARAMS_NAME} PUBLIC ${L}) else() get_target_property(INCLUDE ${L} 3RD_INCLUDE) get_target_property(LINK ${L} 3RD_LINK) @@ -51,7 +51,7 @@ function(LinkLibraries) target_link_directories(${PARAMS_NAME} PUBLIC ${LINK}) endif() if (NOT ("${LIB}" STREQUAL "LIB-NOTFOUND")) - target_link_libraries(${PARAMS_NAME} ${LIB}) + target_link_libraries(${PARAMS_NAME} PUBLIC ${LIB}) endif() if (${3RD_TYPE} STREQUAL "CMakeProject") @@ -114,7 +114,7 @@ function(GetTargetRuntimeDependenciesRecurse) endfunction() function(AddRuntimeDependenciesCopyCommand) - cmake_parse_arguments(PARAMS "" "NAME" "" ${ARGN}) + cmake_parse_arguments(PARAMS "NOT_INSTALL" "NAME" "" ${ARGN}) GetTargetRuntimeDependenciesRecurse( NAME ${PARAMS_NAME} @@ -127,9 +127,11 @@ function(AddRuntimeDependenciesCopyCommand) list(GET TEMP 0 SRC) list(GET TEMP 1 DST) set(COPY_COMMAND ${SRC} $/${DST}) + set(INSTALL_DST ${CMAKE_INSTALL_PREFIX}/Engine/Binaries/${DST}) else () set(SRC ${R}) set(COPY_COMMAND ${SRC} $) + set(INSTALL_DST ${CMAKE_INSTALL_PREFIX}/Engine/Binaries) endif () if (IS_DIRECTORY ${SRC}) @@ -137,11 +139,21 @@ function(AddRuntimeDependenciesCopyCommand) TARGET ${PARAMS_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${COPY_COMMAND} ) + if (NOT ${PARAMS_NOT_INSTALL}) + install( + DIRECTORY ${SRC} DESTINATION ${INSTALL_DST} + ) + endif () else () add_custom_command( TARGET ${PARAMS_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${COPY_COMMAND} ) + if (NOT ${PARAMS_NOT_INSTALL}) + install( + FILES ${SRC} DESTINATION ${INSTALL_DST} + ) + endif () endif () endforeach() endfunction() @@ -158,7 +170,7 @@ function(ExpandResourcePathExpression) endfunction() function(AddResourcesCopyCommand) - cmake_parse_arguments(PARAMS "" "NAME" "RES" ${ARGN}) + cmake_parse_arguments(PARAMS "NOT_INSTALL" "NAME" "RES" ${ARGN}) foreach(R ${PARAMS_RES}) ExpandResourcePathExpression( @@ -167,13 +179,19 @@ function(AddResourcesCopyCommand) OUTPUT_DST DST ) - list(APPEND COMMANDS COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SRC} $/${DST}) + list(APPEND COPY_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SRC} $/${DST}) + + get_filename_component(ABSOLUTE_DST ${CMAKE_INSTALL_PREFIX}/Engine/Binaries/${DST} ABSOLUTE) + get_filename_component(DST_DIR ${ABSOLUTE_DST} DIRECTORY) + if (NOT ${PARAMS_NOT_INSTALL}) + install(FILES ${SRC} DESTINATION ${DST_DIR}) + endif () endforeach() set(COPY_RES_TARGET_NAME ${PARAMS_NAME}.CopyRes) add_custom_target( ${COPY_RES_TARGET_NAME} - ${COMMANDS} + ${COPY_COMMANDS} ) add_dependencies(${PARAMS_NAME} ${COPY_RES_TARGET_NAME}) endfunction() @@ -284,12 +302,18 @@ function(AddMirrorInfoSourceGenerationTarget) endfunction() function(AddExecutable) - cmake_parse_arguments(PARAMS "SAMPLE" "NAME" "SRC;INC;LINK;LIB;DEP_TARGET;RES;REFLECT" ${ARGN}) + cmake_parse_arguments(PARAMS "SAMPLE;NOT_INSTALL" "NAME" "SRC;INC;LINK;LIB;DEP_TARGET;RES;REFLECT" ${ARGN}) if (${PARAMS_SAMPLE} AND (NOT ${BUILD_SAMPLE})) return() endif() + if (${PARAMS_NOT_INSTALL}) + set(NOT_INSTALL_FLAG NOT_INSTALL) + else () + set(NOT_INSTALL_FLAG "") + endif () + if (DEFINED PARAMS_REFLECT) AddMirrorInfoSourceGenerationTarget( NAME ${PARAMS_NAME} @@ -324,10 +348,12 @@ function(AddExecutable) ) AddRuntimeDependenciesCopyCommand( NAME ${PARAMS_NAME} + ${NOT_INSTALL_FLAG} ) AddResourcesCopyCommand( NAME ${PARAMS_NAME} RES ${PARAMS_RES} + ${NOT_INSTALL_FLAG} ) if (DEFINED PARAMS_DEP_TARGET) add_dependencies(${PARAMS_NAME} ${PARAMS_DEP_TARGET}) @@ -339,10 +365,21 @@ function(AddExecutable) if (${MSVC}) set_target_properties(${PARAMS_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) endif() + + if (NOT ${PARAMS_NOT_INSTALL}) + install( + TARGETS ${PARAMS_NAME} + RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/Engine/Binaries + ) + + if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") + install(CODE "execute_process(COMMAND install_name_tool -add_rpath @executable_path ${CMAKE_INSTALL_PREFIX}/Engine/Binaries/$)") + endif () + endif () endfunction() function(AddLibrary) - cmake_parse_arguments(PARAMS "" "NAME;TYPE" "SRC;PRIVATE_INC;PUBLIC_INC;PRIVATE_LINK;LIB;REFLECT" ${ARGN}) + cmake_parse_arguments(PARAMS "NOT_INSTALL" "NAME;TYPE" "SRC;PRIVATE_INC;PUBLIC_INC;PRIVATE_LINK;LIB;REFLECT" ${ARGN}) if ("${PARAMS_TYPE}" STREQUAL "SHARED") list(APPEND PARAMS_PUBLIC_INC ${API_HEADER_DIR}/${PARAMS_NAME}) @@ -413,6 +450,35 @@ function(AddLibrary) if (DEFINED PARAMS_REFLECT) add_dependencies(${PARAMS_NAME} ${GENERATED_TARGET}) endif() + + if (NOT ${PARAMS_NOT_INSTALL}) + foreach (INC ${PARAMS_PUBLIC_INC}) + get_filename_component(ABSOLUTE_INC ${INC} ABSOLUTE) + file(GLOB_RECURSE PUBLIC_HEADERS ${ABSOLUTE_INC}/*.h) + target_sources( + ${PARAMS_NAME} + PUBLIC FILE_SET HEADERS + BASE_DIRS ${ABSOLUTE_INC} FILES ${PUBLIC_HEADERS} + ) + endforeach () + + if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR "${PARAMS_TYPE}" STREQUAL "STATIC") + install( + TARGETS ${PARAMS_NAME} + FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_PREFIX}/Engine/Include + ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/Engine/Lib + LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/Engine/Lib + RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/Engine/Binaries + ) + endif () + + if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" AND "${PARAMS_TYPE}" STREQUAL "SHARED") + install( + FILES $ + DESTINATION ${CMAKE_INSTALL_PREFIX}/Engine/Binaries + ) + endif () + endif () endfunction() function(AddTest) @@ -456,10 +522,12 @@ function(AddTest) ) AddRuntimeDependenciesCopyCommand( NAME ${PARAMS_NAME} + NOT_INSTALL ) AddResourcesCopyCommand( NAME ${PARAMS_NAME} RES ${PARAMS_RES} + NOT_INSTALL ) if (DEFINED PARAMS_DEP_TARGET) add_dependencies(${PARAMS_NAME} ${PARAMS_DEP_TARGET}) diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt index 16ba4612e..b5163e274 100644 --- a/Editor/CMakeLists.txt +++ b/Editor/CMakeLists.txt @@ -9,20 +9,33 @@ qt_standard_project_setup(REQUIRES ${QT_VERSION}) if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") set(PLATFORM_EXECUTABLE_HINT MACOSX_BUNDLE) + set(BUNDLE_INSTALL_DESTINATION BUNDLE DESTINATION ${CMAKE_INSTALL_PREFIX}/Engine/Binaries) endif () file(GLOB_RECURSE SOURCES Src/*.cpp) qt_add_executable(Editor ${PLATFORM_EXECUTABLE_HINT} ${SOURCES}) target_include_directories(Editor PRIVATE Include) target_include_directories(Editor PRIVATE ${CPP_HTTP_LIB_SOURCE_DIR}) -target_link_libraries(Editor PRIVATE Core RHI Runtime Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Quick Qt6::WebEngineWidgets) +LinkLibraries( + NAME Editor + LIB Core RHI Runtime Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Quick Qt6::WebEngineWidgets +) if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") - set(PLATFORM_DEP_TARGET RHI-DirectX12 RHI-Vulkan) + set(RHI_DEP_TARGETS RHI-DirectX12 RHI-Vulkan) else() - set(PLATFORM_DEP_TARGET RHI-Vulkan) + set(RHI_DEP_TARGETS RHI-Vulkan) endif() -add_dependencies(Editor ${PLATFORM_DEP_TARGET}) +add_dependencies(Editor ${RHI_DEP_TARGETS}) + +AddRuntimeDependenciesCopyCommand( + NAME Editor +) +install( + TARGETS Editor + RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/Engine/Binaries + ${BUNDLE_INSTALL_DESTINATION} +) if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") set(QT_WIN_DEPLOY_EXECUTABLE ${QT_LIB_PREFIX}/bin/windeployqt.exe) @@ -42,11 +55,28 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") # -- QT 6.9.1 Temporal Fix End COMMAND ${QT_WIN_DEPLOY_EXECUTABLE} $ ) + install( + CODE "execute_process(COMMAND ${QT_WIN_DEPLOY_EXECUTABLE} ${CMAKE_INSTALL_PREFIX}/Engine/Binaries/$)" + ) elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") set(QT_MAC_DEPLOY_EXECUTABLE ${QT_LIB_PREFIX}/bin/macdeployqt) add_custom_command( TARGET Editor POST_BUILD - COMMAND ${QT_MAC_DEPLOY_EXECUTABLE} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Editor.app $,-no-strip,> + COMMAND ${QT_MAC_DEPLOY_EXECUTABLE} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Editor.app -no-strip + ) + install( + CODE "execute_process(COMMAND ${QT_MAC_DEPLOY_EXECUTABLE} ${CMAKE_INSTALL_PREFIX}/Engine/Binaries/Editor.app -no-strip)" + ) +endif () + +if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") + foreach (RHI_DEP_TARGET ${RHI_DEP_TARGETS}) + list(APPEND RHI_DEP_TARGET_COPY_COMMANDS COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $/../Frameworks/$) + endforeach () + + add_custom_command( + TARGET Editor POST_BUILD + ${RHI_DEP_TARGET_COPY_COMMANDS} ) endif () @@ -130,4 +160,7 @@ add_custom_command( TARGET Editor.Web POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/Web/dist $/Web ) +if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") + install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/Web/dist ${CMAKE_INSTALL_PREFIX}/Engine/Binaries/Web)") +endif () # ---- end web project ------------------------------------------------------------------------------- diff --git a/Editor/Include/Editor/WebUIServer.h b/Editor/Include/Editor/WebUIServer.h index 3cc795531..6b16f66da 100644 --- a/Editor/Include/Editor/WebUIServer.h +++ b/Editor/Include/Editor/WebUIServer.h @@ -16,9 +16,13 @@ namespace Editor { void Start(); void Stop(); + const std::string& BaseUrl() const; private: - Common::UniquePtr serverThread; - Common::UniquePtr server; + WebUIServer(); + + std::string baseUrl; + Common::UniquePtr productServerThread; + Common::UniquePtr productServer; }; } diff --git a/Editor/Include/Editor/Widget/ProjectHub.h b/Editor/Include/Editor/Widget/ProjectHub.h index 855320d73..431460c66 100644 --- a/Editor/Include/Editor/Widget/ProjectHub.h +++ b/Editor/Include/Editor/Widget/ProjectHub.h @@ -11,12 +11,16 @@ namespace Editor { class ProjectHubBridge final : public QObject { Q_OBJECT + Q_PROPERTY(QString engineVersion MEMBER engineVersion CONSTANT) public: explicit ProjectHubBridge(ProjectHub* parent = nullptr); public Q_SLOTS: void CreateProject() const; + + private: + QString engineVersion; }; class ProjectHub final : public WebWidget { diff --git a/Editor/Src/Main.cpp b/Editor/Src/Main.cpp index 4067fa41e..ce5eb0c5c 100644 --- a/Editor/Src/Main.cpp +++ b/Editor/Src/Main.cpp @@ -3,6 +3,7 @@ // #include +#include #include #include @@ -73,7 +74,10 @@ static void InitializePreQtApp(EditorApplicationModel inModel) Runtime::EngineHolder::Load("Editor", params); } -static void InitializePostQtApp() {} +static void InitializePostQtApp() +{ + QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy); +} static void Cleanup(EditorApplicationModel inModel) { diff --git a/Editor/Src/WebUIServer.cpp b/Editor/Src/WebUIServer.cpp index e9c3e33b1..2aa491a25 100644 --- a/Editor/Src/WebUIServer.cpp +++ b/Editor/Src/WebUIServer.cpp @@ -2,13 +2,23 @@ // Created by johnk on 2025/8/8. // -#include #include +#include +#include +#include static Core::CmdlineArgValue caWebUIPort( "webUIPort", "-webUIPort", 10907, "WebUI port"); +static Core::CmdlineArgValue caWebUIDev( + "webUIDev", "-webUIDev", false, + "Whether to enable hot reload for web UI"); + +static Core::CmdlineArgValue caWebUIDevServerPort( + "webUIDevServerPort", "-webUIDevServerPort", 5173, + "Port of web ui dev server, which works only when dev mode enabled"); + namespace Editor { WebUIServer& WebUIServer::Get() { @@ -16,23 +26,56 @@ namespace Editor { return webUIServer; } + WebUIServer::WebUIServer() = default; + void WebUIServer::Start() { - serverThread = std::make_unique("WebUIServerThread", [this]() -> void { - server = Common::MakeUnique(); - server->set_mount_point("/", "./Web"); - server->Get("/(.+)", [](const httplib::Request&, httplib::Response& res) { - res.set_file_content("./Web/index.html"); + uint32_t serverPort; + std::string serverMode; + + if (caWebUIDev.GetValue()) { + serverPort = caWebUIDevServerPort.GetValue(); + serverMode = "development"; + + httplib::Client client(std::format("http://localhost:{}", serverPort)); + auto res = client.Get("/"); + AssertWithReason( + res->status == 200, + "did you forget to start dev server, just call Script/start_editor_web_dev_server.py manually"); + } else { + serverPort = caWebUIPort.GetValue(); + serverMode = "product"; + productServerThread = std::make_unique("WebUIServerThread", [this, serverPort]() -> void { + const auto webRoot = Core::Paths::ExecutablePath().Parent() / "Web"; + const auto indexHtmlFile = webRoot / "index.html"; + + productServer = Common::MakeUnique(); + productServer->set_mount_point("/", webRoot.Absolute().String()); + productServer->Get("/(.+)", [indexHtmlFile](const httplib::Request&, httplib::Response& res) { + res.set_file_content(indexHtmlFile.Absolute().String()); + }); + productServer->listen("localhost", static_cast(serverPort)); }); - server->listen("localhost", caWebUIPort.GetValue()); - }); + } + + baseUrl = std::format("http://localhost:{}", serverPort); + LogInfo(WebUI, "{} web ui server listening on {}", serverMode, baseUrl); } void WebUIServer::Stop() { - server->stop(); - serverThread->Join(); - server.Reset(); - serverThread.Reset(); + if (productServer.Valid()) { + productServer->stop(); + } + if (productServerThread.Valid()) { + productServerThread->Join(); + } + productServer.Reset(); + productServerThread.Reset(); + } + + const std::string& WebUIServer::BaseUrl() const + { + return baseUrl; } } // namespace Editor diff --git a/Editor/Src/Widget/ProjectHub.cpp b/Editor/Src/Widget/ProjectHub.cpp index 3ce48ca95..6637f8457 100644 --- a/Editor/Src/Widget/ProjectHub.cpp +++ b/Editor/Src/Widget/ProjectHub.cpp @@ -7,10 +7,12 @@ #include #include #include +#include namespace Editor { ProjectHubBridge::ProjectHubBridge(ProjectHub* parent) : QObject(parent) + , engineVersion(QString::fromStdString(std::format("v{}.{}.{}", ENGINE_VERSION_MAJOR, ENGINE_VERSION_MINOR, ENGINE_VERSION_PATCH))) { } diff --git a/Editor/Src/Widget/WebWidget.cpp b/Editor/Src/Widget/WebWidget.cpp index a3de910cc..569325e97 100644 --- a/Editor/Src/Widget/WebWidget.cpp +++ b/Editor/Src/Widget/WebWidget.cpp @@ -3,16 +3,9 @@ // #include -#include #include - -static Core::CmdlineArgValue caWebUIDev( - "webUIDev", "-webUIDev", false, - "Whether to enable hot reload for web UI"); - -static Core::CmdlineArgValue caWebUIDevServerPort( - "webUIDevServerPort", "-webUIDevServerPort", 5173, - "Port of web ui dev server, which works only when dev mode enabled"); +#include +#include namespace Editor { WebWidget::WebWidget(QWidget* inParent) @@ -29,8 +22,8 @@ namespace Editor { static Core::CmdlineArg& caWebUIPort = Core::Cli::Get().GetArg("webUIPort"); Assert(inUrl.starts_with("/")); - const std::string baseUrl = std::format("http://localhost:{}", caWebUIDev.GetValue() ? caWebUIDevServerPort.GetValue() : caWebUIPort.GetValue()); - const std::string fullUrl = baseUrl + inUrl; + const auto& baseUrl = WebUIServer::Get().BaseUrl(); + const auto fullUrl = baseUrl + inUrl; load(QUrl(fullUrl.c_str())); } diff --git a/Editor/Web/src/pages/project-hub.tsx b/Editor/Web/src/pages/project-hub.tsx index 6e802ccc7..b1997051c 100644 --- a/Editor/Web/src/pages/project-hub.tsx +++ b/Editor/Web/src/pages/project-hub.tsx @@ -1,15 +1,89 @@ -import { useEffect } from "react"; +import { useEffect, useState } from 'react'; import { QWebChannel } from '@/qwebchannel' import { Tabs, Tab } from '@heroui/tabs'; import { User } from '@heroui/user'; import { Form } from '@heroui/form'; import { Button } from '@heroui/button'; import { Input } from '@heroui/input'; +import { Chip } from '@heroui/chip'; +import { Listbox, ListboxItem } from '@heroui/listbox'; +import { Avatar } from '@heroui/avatar'; +import { ScrollShadow } from "@heroui/scroll-shadow"; export default function ProjectHubPage() { + const [engineVersion, setEngineVersion] = useState(''); + // TODO fetch from c++ + const [recentlyProjects] = useState([{ + key: '1', + name: 'HelloExplosion1', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '2', + name: 'HelloExplosion2', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '3', + name: 'HelloExplosion3', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '4', + name: 'HelloExplosion4', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '5', + name: 'HelloExplosion5', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '6', + name: 'HelloExplosion6', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '7', + name: 'HelloExplosion7', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '8', + name: 'HelloExplosion8', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '9', + name: 'HelloExplosion9', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '10', + name: 'HelloExplosion10', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '11', + name: 'HelloExplosion11', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '12', + name: 'HelloExplosion12', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }, { + key: '13', + name: 'HelloExplosion13', + icon: '/logo.png', + path: '/path/to/HelloExplosion' + }]); + useEffect(() => { new QWebChannel(window.qt.webChannelTransport, (channel: QWebChannel) : void => { window.bridge = channel.objects.bridge; + setEngineVersion(window.bridge.engineVersion); }) }, []); @@ -23,14 +97,39 @@ export default function ProjectHubPage() {
+ description={ +
+ {engineVersion} +
+ } + name='Explosion Game Engine'/>
+ + + + {(item) => ( + +
+ +
+ {item.name} + {item.path} +
+
+
+ )} +
+
+
@@ -39,9 +138,6 @@ export default function ProjectHubPage() {
- -
TODO
-
); diff --git a/Engine/Source/Core/Include/Core/Cmdline.h b/Engine/Source/Core/Include/Core/Cmdline.h index 057c44290..4a88457ab 100644 --- a/Engine/Source/Core/Include/Core/Cmdline.h +++ b/Engine/Source/Core/Include/Core/Cmdline.h @@ -32,7 +32,7 @@ namespace Core { static Cli& Get(); ~Cli(); - std::pair Parse(int argc, char* argv[]); + std::pair Parse(int argc, char* argv[], bool force = false); CmdlineArg* FindArg(const std::string& name) const; CmdlineArg& GetArg(const std::string& name) const; diff --git a/Engine/Source/Core/Include/Core/EngineVersion.h b/Engine/Source/Core/Include/Core/EngineVersion.h new file mode 100644 index 000000000..edbbbcb69 --- /dev/null +++ b/Engine/Source/Core/Include/Core/EngineVersion.h @@ -0,0 +1,9 @@ +// +// Created by johnk on 2025/8/16. +// + +#pragma once + +#define ENGINE_VERSION_MAJOR 0 +#define ENGINE_VERSION_MINOR 0 +#define ENGINE_VERSION_PATCH 1 diff --git a/Engine/Source/Core/Src/Cmdline.cpp b/Engine/Source/Core/Src/Cmdline.cpp index 8f698f333..8a2fc88f8 100644 --- a/Engine/Source/Core/Src/Cmdline.cpp +++ b/Engine/Source/Core/Src/Cmdline.cpp @@ -24,9 +24,11 @@ namespace Core { Cli::~Cli() = default; - std::pair Cli::Parse(const int argc, char* argv[]) + std::pair Cli::Parse(int argc, char* argv[], bool force) { - Assert(!parsed); + if (!force) { + Assert(!parsed); + } parsed = true; Core::Paths::SetExecutableDir(argv[0]); diff --git a/Engine/Source/Core/Src/Module.cpp b/Engine/Source/Core/Src/Module.cpp index 3720c2800..c8105c315 100644 --- a/Engine/Source/Core/Src/Module.cpp +++ b/Engine/Source/Core/Src/Module.cpp @@ -133,7 +133,10 @@ namespace Core { { std::vector searchPaths; searchPaths.reserve(5); - searchPaths.emplace_back(Paths::WorkingDir()); + searchPaths.emplace_back(Paths::ExecutablePath().Parent()); +#if PLATFORM_MACOS + searchPaths.emplace_back(Paths::ExecutablePath().Parent().Parent() / "Frameworks"); +#endif if (Paths::HasSetExecutableDir()) { searchPaths.emplace_back(Paths::EngineBinDir()); searchPaths.emplace_back(Paths::EnginePluginDir()); diff --git a/Engine/Source/Core/Src/Paths.cpp b/Engine/Source/Core/Src/Paths.cpp index 23b16931f..efefd63a6 100644 --- a/Engine/Source/Core/Src/Paths.cpp +++ b/Engine/Source/Core/Src/Paths.cpp @@ -48,7 +48,8 @@ namespace Core { Common::Path Paths::EngineRootDir() { - return WorkingDir().Parent(); + Assert(HasSetExecutableDir()); + return ExecutablePath().Parent().Parent(); } Common::Path Paths::EngineResDir() diff --git a/Engine/Source/Core/Test/CmdlineTest.cpp b/Engine/Source/Core/Test/CmdlineTest.cpp index 5842eb40f..e0a45e651 100644 --- a/Engine/Source/Core/Test/CmdlineTest.cpp +++ b/Engine/Source/Core/Test/CmdlineTest.cpp @@ -33,7 +33,7 @@ TEST(CmdlineTest, BasicTest) const_cast("world"), }; - const auto [result, errorInfo] = Core::Cli::Get().Parse(static_cast(args.size()), args.data()); + const auto [result, errorInfo] = Core::Cli::Get().Parse(static_cast(args.size()), args.data(), true); ASSERT_TRUE(result); ASSERT_TRUE(arg0.GetValue()); ASSERT_EQ(arg1.GetValue(), 1); diff --git a/Engine/Source/RHI-Vulkan/Src/CommandRecorder.cpp b/Engine/Source/RHI-Vulkan/Src/CommandRecorder.cpp index 92ef7f8d8..9a1b12339 100644 --- a/Engine/Source/RHI-Vulkan/Src/CommandRecorder.cpp +++ b/Engine/Source/RHI-Vulkan/Src/CommandRecorder.cpp @@ -369,11 +369,13 @@ namespace RHI::Vulkan { renderingInfo.renderArea = {{0, 0}, {static_cast(textureCreateInfo.width), static_cast(textureCreateInfo.height)}}; renderingInfo.viewMask = 0; + VkRenderingAttachmentInfo depthAttachmentInfo = {}; + VkRenderingAttachmentInfo stencilAttachmentInfo = {}; + if (inBeginInfo.depthStencilAttachment.has_value()) { const auto* depthStencilTextureView = static_cast(inBeginInfo.depthStencilAttachment->view); - VkRenderingAttachmentInfo depthAttachmentInfo = {}; depthAttachmentInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; depthAttachmentInfo.imageView = depthStencilTextureView->GetNative(); depthAttachmentInfo.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; @@ -384,7 +386,6 @@ namespace RHI::Vulkan { renderingInfo.pDepthAttachment = &depthAttachmentInfo; if (!inBeginInfo.depthStencilAttachment->depthReadOnly) { - VkRenderingAttachmentInfo stencilAttachmentInfo = {}; stencilAttachmentInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; stencilAttachmentInfo.imageView = depthStencilTextureView->GetNative(); stencilAttachmentInfo.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; diff --git a/Engine/Source/Test/CMakeLists.txt b/Engine/Source/Test/CMakeLists.txt index fe30a57e9..e73100e2b 100644 --- a/Engine/Source/Test/CMakeLists.txt +++ b/Engine/Source/Test/CMakeLists.txt @@ -3,5 +3,5 @@ AddLibrary( TYPE STATIC SRC Src/Main.cpp PUBLIC_INC Include - LIB googletest + LIB googletest Core ) \ No newline at end of file diff --git a/Engine/Source/Test/Src/Main.cpp b/Engine/Source/Test/Src/Main.cpp index 9f652f261..2bb1eaa92 100644 --- a/Engine/Source/Test/Src/Main.cpp +++ b/Engine/Source/Test/Src/Main.cpp @@ -3,9 +3,11 @@ // #include +#include int main(int argc, char* argv[]) { + Core::Cli::Get().Parse(argc, argv); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/README.md b/README.md index d1d779eaf..b79c9a765 100644 --- a/README.md +++ b/README.md @@ -119,8 +119,12 @@ Thanks all those following projects: * [VulkanMemoryAllocator](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) * [Qt6](https://www.qt.io/product/qt6) * [rapidjson](https://github.com/Tencent/rapidjson) -* [Node.js](https://nodejs.org/zh-cn) * [cpp-httplib](https://github.com/yhirose/cpp-httplib) +* [Node.js](https://nodejs.org/zh-cn) +* [React](https://react.dev) +* [Vite](https://vite.dev) +* [HeroUI](https://www.heroui.com) +* [TailWindCSS](https://tailwindcss.com) # Sponsor diff --git a/Sample/Base/Application.cpp b/Sample/Base/Application.cpp index b28f44981..6052ac498 100644 --- a/Sample/Base/Application.cpp +++ b/Sample/Base/Application.cpp @@ -8,6 +8,7 @@ #include #include #include +#include template <> struct std::hash> { @@ -39,6 +40,8 @@ Application::~Application() bool Application::Initialize(int argc, char* argv[]) { + Core::Cli::Get().Parse(argc, argv); + std::string rhiString; if (const auto cli = ( clipp::option("-w").doc("window width, 1024 by default") & clipp::value("width", windowExtent.x), diff --git a/Sample/CMakeLists.txt b/Sample/CMakeLists.txt index 6c1a5f20f..5ddd74db4 100644 --- a/Sample/CMakeLists.txt +++ b/Sample/CMakeLists.txt @@ -32,6 +32,7 @@ function(AddSample) LIB Sample-Base DEP_TARGET ${PLATFORM_DEP_TARGET} RES ${PATHS} + NOT_INSTALL ) endfunction() @@ -48,6 +49,7 @@ Addlibrary( SRC ${SOURCES} PUBLIC_INC Base LIB RHI glfw clipp ${PLATFORM_EXT_LIBS} Render.Static stb assimp-lib + NOT_INSTALL ) file(GLOB SOURCES RHI-Triangle/*.cpp) diff --git a/ThirdParty/CMakeLists.txt b/ThirdParty/CMakeLists.txt index e630e62e3..5ca1ecbe9 100644 --- a/ThirdParty/CMakeLists.txt +++ b/ThirdParty/CMakeLists.txt @@ -168,6 +168,7 @@ Add3rdBinaryPackage( Darwin-arm64 clang RUNTIME_DEP Windows $/bin/libclang.dll + Darwin $/lib/libclang.dylib ) # Google Test