diff --git a/Editor/Include/Editor/Widget/WebWidget.h b/Editor/Include/Editor/Widget/WebWidget.h index 1015ca5a..d7619c3f 100644 --- a/Editor/Include/Editor/Widget/WebWidget.h +++ b/Editor/Include/Editor/Widget/WebWidget.h @@ -6,8 +6,20 @@ #include #include +#include namespace Editor { + class WebPage : public QWebEnginePage { + Q_OBJECT + + public: + explicit WebPage(QWidget* inParent = nullptr); + ~WebPage() override; + + protected: + void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) override; + }; + class WebWidget : public QWebEngineView { Q_OBJECT diff --git a/Editor/Resource/ProjectTemplates/3D/CMakeLists.txt b/Editor/Resource/ProjectTemplates/3D/CMakeLists.txt deleted file mode 100644 index 91ab9c5e..00000000 --- a/Editor/Resource/ProjectTemplates/3D/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 3.25) -project(%{projectName}%) - -include(ExternalProject) -include(GenerateExportHeader) diff --git a/Editor/Resource/ProjectTemplates/2D/CMakeLists.txt b/Editor/Resource/ProjectTemplates/Default/CMakeLists.txt similarity index 100% rename from Editor/Resource/ProjectTemplates/2D/CMakeLists.txt rename to Editor/Resource/ProjectTemplates/Default/CMakeLists.txt diff --git a/Editor/Src/WebUIServer.cpp b/Editor/Src/WebUIServer.cpp index 2aa491a2..cd31f55c 100644 --- a/Editor/Src/WebUIServer.cpp +++ b/Editor/Src/WebUIServer.cpp @@ -2,6 +2,9 @@ // Created by johnk on 2025/8/8. // +#include +#include + #include #include #include @@ -19,6 +22,14 @@ static Core::CmdlineArgValue caWebUIDevServerPort( "webUIDevServerPort", "-webUIDevServerPort", 5173, "Port of web ui dev server, which works only when dev mode enabled"); +static Core::CmdlineArgValue caWebUIDebug( + "webUIDebug", "-webUIDebug", false, + "Whether to enable web ui debug (you can attach debugger to qt web engine process)."); + +static Core::CmdlineArgValue caWebUIRemoteDebugPort( + "webUIRemoveDebugPort", "-webUIRemoveDebugPort", 5174, + "Port of web ui debug port, you can attach to the url printed in log to create debug process."); + namespace Editor { WebUIServer& WebUIServer::Get() { @@ -60,6 +71,11 @@ namespace Editor { baseUrl = std::format("http://localhost:{}", serverPort); LogInfo(WebUI, "{} web ui server listening on {}", serverMode, baseUrl); + + if (caWebUIDebug.GetValue()) { + const auto flags = std::format("--remote-debugging-port={}", caWebUIRemoteDebugPort.GetValue()); + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", QByteArrayView(flags.c_str(), static_cast(flags.length()))); + } } void WebUIServer::Stop() diff --git a/Editor/Src/Widget/WebWidget.cpp b/Editor/Src/Widget/WebWidget.cpp index 569325e9..5871b83e 100644 --- a/Editor/Src/Widget/WebWidget.cpp +++ b/Editor/Src/Widget/WebWidget.cpp @@ -5,13 +5,38 @@ #include #include #include +#include #include namespace Editor { + WebPage::WebPage(QWidget* inParent) + : QWebEnginePage(inParent) + { + } + + WebPage::~WebPage() = default; + + void WebPage::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) + { + if (level == InfoMessageLevel) + { + LogInfo(WebUIJavaScript, "{}", message.toStdString()); + } + else if (level == WarningMessageLevel) + { + LogWarning(WebUIJavaScript, "{}", message.toStdString()); + } + else if (level == ErrorMessageLevel) + { + LogError(WebUIJavaScript, "{}", message.toStdString()); + } + } + WebWidget::WebWidget(QWidget* inParent) : QWebEngineView(inParent) { webChannel = new QWebChannel(this); + setPage(new WebPage(this)); page()->setWebChannel(webChannel); } diff --git a/Editor/Web/eslint.config.mjs b/Editor/Web/eslint.config.mjs index 6b26484e..d2f5ad28 100644 --- a/Editor/Web/eslint.config.mjs +++ b/Editor/Web/eslint.config.mjs @@ -100,11 +100,25 @@ export default defineConfig([ "react-hooks/exhaustive-deps": "off", "jsx-a11y/click-events-have-key-events": "warn", "jsx-a11y/interactive-supports-focus": "warn", - "prettier/prettier": "warn", + "prettier/prettier": [ + "warn", + { + "endOfLine": "auto", + "singleQuote": true, + "jsxSingleQuote": true, + "semi": true, + "printWidth": 200, + "tabWidth": 2, + "useTabs": false, + "objectWrap": "collapse", + "bracketSameLine": true, + "arrowParens": "always", + "singleAttributePerLine": false, + } + ], "no-unused-vars": "off", "unused-imports/no-unused-vars": "off", "unused-imports/no-unused-imports": "warn", - "@typescript-eslint/no-unused-vars": [ "warn", { @@ -113,7 +127,6 @@ export default defineConfig([ argsIgnorePattern: "^_.*?$", }, ], - "import/order": [ "warn", { @@ -136,12 +149,10 @@ export default defineConfig([ }, ], - "newlines-between": "always", + "newlines-between": "never", }, ], - "react/self-closing-comp": "warn", - "react/jsx-sort-props": [ "warn", { @@ -150,26 +161,7 @@ export default defineConfig([ noSortAlphabetically: false, reservedFirst: true, }, - ], - - "padding-line-between-statements": [ - "warn", - { - blankLine: "always", - prev: "*", - next: "return", - }, - { - blankLine: "always", - prev: ["const", "let", "var"], - next: "*", - }, - { - blankLine: "any", - prev: ["const", "let", "var"], - next: ["const", "let", "var"], - }, - ], + ] }, }, ]); diff --git a/Editor/Web/src/App.tsx b/Editor/Web/src/App.tsx index 62dbe683..baf24637 100644 --- a/Editor/Web/src/App.tsx +++ b/Editor/Web/src/App.tsx @@ -4,7 +4,7 @@ import ProjectHubPage from '@/pages/project-hub'; function App() { return ( - } path='/project-hub'/> + } path='/project-hub' /> ); } diff --git a/Editor/Web/src/main.tsx b/Editor/Web/src/main.tsx index 2476bdc2..70805e99 100644 --- a/Editor/Web/src/main.tsx +++ b/Editor/Web/src/main.tsx @@ -1,9 +1,8 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; - -import App from './App.tsx'; import { Provider } from './provider.tsx'; +import App from './App.tsx'; import '@/styles/globals.css'; ReactDOM.createRoot(document.getElementById('root')!).render( diff --git a/Editor/Web/src/pages/project-hub.tsx b/Editor/Web/src/pages/project-hub.tsx index bac2aa1d..14d4e383 100644 --- a/Editor/Web/src/pages/project-hub.tsx +++ b/Editor/Web/src/pages/project-hub.tsx @@ -1,15 +1,15 @@ 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, PressEvent} from '@heroui/button'; +import { Button, PressEvent } 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"; +import { ScrollShadow } from '@heroui/scroll-shadow'; import { Select, SelectItem } from '@heroui/react'; +import { QWebChannel } from '@/qwebchannel'; interface RecentProjectInfo { name: string; @@ -27,78 +27,86 @@ export default function ProjectHubPage() { const [projectTemplates, setProjectTemplates] = useState(Array); useEffect(() => { - new QWebChannel(window.qt.webChannelTransport, (channel: QWebChannel) : void => { + new QWebChannel(window.qt.webChannelTransport, (channel: QWebChannel): void => { window.backend = channel.objects.backend; setEngineVersion(window.backend.engineVersion); setRecentProjects(window.backend.recentProjects); setProjectTemplates(window.backend.projectTemplates); - }) + }); }, []); - function onCreateProject() : void - { + function onCreateProject(): void { + // TODO + console.error("onCreateProject()"); window.backend.CreateProject(); } - function onOpenProject(e: PressEvent) : void - { + function onOpenProject(e: PressEvent): void { // TODO const index = parseInt(e.target.getAttribute('data-key') as string); console.error('onOpenProject:', index); } + async function onBrowseProjectPath(): Promise { + // TODO + const dirHandle = await window.showDirectoryPicker({ startIn: 'desktop' }); + console.error(dirHandle); + } + return (
- {engineVersion} + + {engineVersion} +
} - name='Explosion Game Engine'/> + name='Explosion Game Engine' + />
- - - + + + {recentProjects.map((item, i) => ( - -
- -
- {item.name} - {item.path} -
+ +
+ +
+ {item.name} + {item.path}
- +
+
))} - +
- - - - +
+ + +
+ - +
); -}; +} diff --git a/Editor/Web/src/provider.tsx b/Editor/Web/src/provider.tsx index c28d26d1..2f42bec6 100644 --- a/Editor/Web/src/provider.tsx +++ b/Editor/Web/src/provider.tsx @@ -1,5 +1,4 @@ import type { NavigateOptions } from 'react-router-dom'; - import { HeroUIProvider } from '@heroui/system'; import { useHref, useNavigate } from 'react-router-dom'; diff --git a/Editor/Web/src/qwebchannel.d.ts b/Editor/Web/src/qwebchannel.d.ts index 16e0db20..541c4dc3 100644 --- a/Editor/Web/src/qwebchannel.d.ts +++ b/Editor/Web/src/qwebchannel.d.ts @@ -4,5 +4,6 @@ declare global { interface Window { qt: any; backend: any; + showDirectoryPicker: any; } } diff --git a/Engine/Source/Core/Include/Core/Log.h b/Engine/Source/Core/Include/Core/Log.h index 56f2c89c..8e94e24d 100644 --- a/Engine/Source/Core/Include/Core/Log.h +++ b/Engine/Source/Core/Include/Core/Log.h @@ -13,12 +13,10 @@ #include #include -#define LogVerbose(tag, ...) Core::Logger::Get().Log(#tag, "Verbose", std::format(__VA_ARGS__)) -#define LogDebug(tag, ...) Core::Logger::Get().Log(#tag, "Debug", std::format(__VA_ARGS__)) -#define LogHint(tag, ...) Core::Logger::Get().Log(#tag, "Hint", std::format(__VA_ARGS__)) -#define LogInfo(tag, ...) Core::Logger::Get().Log(#tag, "Info", std::format(__VA_ARGS__)) -#define LogWarning(tag, ...) Core::Logger::Get().Log(#tag, "Warning", std::format(__VA_ARGS__)) -#define LogError(tag, ...) Core::Logger::Get().Log(#tag, "Error", std::format(__VA_ARGS__)) +#define LogVerbose(tag, ...) Core::Logger::Get().Log(#tag, Core::LogLevel::verbose, std::format(__VA_ARGS__)) +#define LogInfo(tag, ...) Core::Logger::Get().Log(#tag, Core::LogLevel::info, std::format(__VA_ARGS__)) +#define LogWarning(tag, ...) Core::Logger::Get().Log(#tag, Core::LogLevel::warning, std::format(__VA_ARGS__)) +#define LogError(tag, ...) Core::Logger::Get().Log(#tag, Core::LogLevel::error, std::format(__VA_ARGS__)) namespace Core { class LogStream { @@ -57,8 +55,6 @@ namespace Core { enum class LogLevel : uint8_t { verbose, - debug, - hint, info, warning, error, @@ -73,7 +69,7 @@ namespace Core { NonCopyable(Logger) NonMovable(Logger) - void Log(const std::string& inTag, const std::string& inLevel, const std::string& inContent); + void Log(const std::string& inTag, LogLevel inLevel, const std::string& inContent); void Attach(Common::UniquePtr&& inStream); void Flush(); diff --git a/Engine/Source/Core/Src/Log.cpp b/Engine/Source/Core/Src/Log.cpp index b6c4560e..84b63b4d 100644 --- a/Engine/Source/Core/Src/Log.cpp +++ b/Engine/Source/Core/Src/Log.cpp @@ -59,10 +59,24 @@ namespace Core { Flush(); } - void Logger::Log(const std::string& inTag, const std::string& inLevel, const std::string& inContent) + void Logger::Log(const std::string& inTag, LogLevel inLevel, const std::string& inContent) { + static std::unordered_map LogLevelStringMap = { + { LogLevel::verbose, "Verbose" }, + { LogLevel::info, "Info" }, + { LogLevel::warning, "Warning" }, + { LogLevel::error, "Error" } + }; + + static std::unordered_map LogLevelColorStr = { + { LogLevel::verbose, "" }, + { LogLevel::info, "" }, + { LogLevel::warning, "\033[33m" }, + { LogLevel::error, "\033[31m" } + }; + const auto time = Common::AccurateTime(Common::TimePoint::Now()); - LogInternal(std::format("[{}][{}][{}] {}", time.ToString(), inTag, inLevel, inContent)); + LogInternal(std::format("{}[{}][{}][{}] {}\033[0m", LogLevelColorStr.at(inLevel), time.ToString("hh-mm-ss:mss"), inTag, LogLevelStringMap.at(inLevel), inContent)); } void Logger::Attach(Common::UniquePtr&& inStream) diff --git a/ThirdParty/CMakeLists.txt b/ThirdParty/CMakeLists.txt index 8971cdfe..36bb7f8c 100644 --- a/ThirdParty/CMakeLists.txt +++ b/ThirdParty/CMakeLists.txt @@ -1,8 +1,3 @@ -if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") - add_library(OpenGLDummy INTERFACE) - add_library(opengl::opengl ALIAS OpenGLDummy) -endif () - find_package(httplib REQUIRED GLOBAL) find_package(glfw REQUIRED GLOBAL) find_package(stb REQUIRED GLOBAL)