Rebuild MetaCore editor on Panda3D with single-window viewport
This commit is contained in:
parent
a637100607
commit
633156e3be
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
build/
|
build/
|
||||||
vcpkg_installed/
|
vcpkg_installed/
|
||||||
downloads/
|
downloads/
|
||||||
|
.metacore/
|
||||||
.vs/
|
.vs/
|
||||||
CMakeUserPresets.json
|
CMakeUserPresets.json
|
||||||
imgui.ini
|
imgui.ini
|
||||||
|
|||||||
@ -1,8 +1,16 @@
|
|||||||
#include "MetaCoreEditor/MetaCoreEditorApp.h"
|
#include "MetaCoreEditor/MetaCoreEditorApp.h"
|
||||||
|
|
||||||
int main() {
|
#include <filesystem>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc > 0) {
|
||||||
|
std::filesystem::current_path(std::filesystem::path(argv[0]).parent_path());
|
||||||
|
}
|
||||||
|
|
||||||
MetaCore::MetaCoreEditorApp editorApp;
|
MetaCore::MetaCoreEditorApp editorApp;
|
||||||
if (!editorApp.Initialize()) {
|
if (!editorApp.Initialize()) {
|
||||||
|
std::cerr << "MetaCoreEditorApp initialize failed\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,67 @@
|
|||||||
|
#include "MetaCorePlatform/MetaCoreWindow.h"
|
||||||
|
#include "MetaCoreRender/MetaCoreEditorViewportRenderer.h"
|
||||||
|
#include "MetaCoreRender/MetaCoreRenderDevice.h"
|
||||||
|
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
||||||
|
#include "MetaCoreScene/MetaCoreScene.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main() {
|
namespace {
|
||||||
std::cout << "MetaCorePlayer 目前保留为后续运行时模块接入入口。\n";
|
|
||||||
|
MetaCore::MetaCoreSceneView MetaCoreBuildPlayerSceneView() {
|
||||||
|
MetaCore::MetaCoreSceneView sceneView;
|
||||||
|
sceneView.CameraPosition = {0.0F, 2.5F, 6.5F};
|
||||||
|
sceneView.CameraTarget = {0.0F, 0.7F, 0.0F};
|
||||||
|
sceneView.CameraUp = {0.0F, 1.0F, 0.0F};
|
||||||
|
sceneView.VerticalFieldOfViewDegrees = 60.0F;
|
||||||
|
return sceneView;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc > 0) {
|
||||||
|
std::filesystem::current_path(std::filesystem::path(argv[0]).parent_path());
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaCore::MetaCoreWindow window;
|
||||||
|
if (!window.Initialize(1280, 720, "MetaCore Player")) {
|
||||||
|
std::cerr << "MetaCorePlayer: window initialize failed\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaCore::MetaCoreRenderDevice renderDevice;
|
||||||
|
if (!renderDevice.Initialize(window)) {
|
||||||
|
std::cerr << "MetaCorePlayer: render device initialize failed\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaCore::MetaCoreEditorViewportRenderer viewportRenderer;
|
||||||
|
if (!viewportRenderer.Initialize(renderDevice)) {
|
||||||
|
std::cerr << "MetaCorePlayer: viewport renderer initialize failed\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaCore::MetaCoreScene scene = MetaCore::MetaCoreCreateDefaultScene();
|
||||||
|
|
||||||
|
while (!window.ShouldClose()) {
|
||||||
|
window.BeginFrame();
|
||||||
|
const auto [windowWidth, windowHeight] = window.GetWindowSize();
|
||||||
|
viewportRenderer.SetViewportRect(MetaCore::MetaCoreViewportRect{
|
||||||
|
0.0F,
|
||||||
|
0.0F,
|
||||||
|
static_cast<float>(windowWidth),
|
||||||
|
static_cast<float>(windowHeight)
|
||||||
|
});
|
||||||
|
viewportRenderer.RenderSceneToViewport(scene, MetaCoreBuildPlayerSceneView());
|
||||||
|
renderDevice.RenderFrame();
|
||||||
|
renderDevice.PresentFrame();
|
||||||
|
window.EndFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
viewportRenderer.Shutdown();
|
||||||
|
renderDevice.Shutdown();
|
||||||
|
window.Shutdown();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
114
CMakeLists.txt
114
CMakeLists.txt
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.26)
|
|||||||
|
|
||||||
project(MetaCore
|
project(MetaCore
|
||||||
VERSION 1.0.0
|
VERSION 1.0.0
|
||||||
DESCRIPTION "MetaCore Unity-like editor prototype"
|
DESCRIPTION "MetaCore Panda3D-based Unity-like editor prototype"
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -10,27 +10,23 @@ set(CMAKE_CXX_STANDARD 20)
|
|||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
option(METACORE_BUILD_TESTS "Build MetaCore tests" ON)
|
if(MSVC)
|
||||||
|
# Debug 使用调试运行库,Release 使用可分发运行库,避免不同配置之间的 CRT 冲突。
|
||||||
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(EXISTS "${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-windows/share/glad/gladConfig.cmake")
|
option(METACORE_BUILD_TESTS "Build MetaCore tests" ON)
|
||||||
|
option(METACORE_AUTO_PREPARE_PANDA3D "Automatically prepare Panda3D SDK during configure" ON)
|
||||||
|
|
||||||
|
list(PREPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
if(EXISTS "${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-windows/share/imgui/imgui-config.cmake")
|
||||||
list(PREPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-windows")
|
list(PREPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-windows")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(METACORE_RUNTIME_BIN_DIR "${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-windows/bin")
|
include(MetaCorePanda3D)
|
||||||
|
metacore_prepare_panda3d()
|
||||||
|
|
||||||
function(metacore_copy_runtime_dlls target_name)
|
|
||||||
if(EXISTS "${METACORE_RUNTIME_BIN_DIR}/glfw3.dll")
|
|
||||||
add_custom_command(TARGET ${target_name} POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
||||||
"${METACORE_RUNTIME_BIN_DIR}/glfw3.dll"
|
|
||||||
"$<TARGET_FILE_DIR:${target_name}>"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
find_package(OpenGL REQUIRED)
|
|
||||||
find_package(glad CONFIG REQUIRED)
|
|
||||||
find_package(glfw3 CONFIG REQUIRED)
|
|
||||||
find_package(glm CONFIG REQUIRED)
|
find_package(glm CONFIG REQUIRED)
|
||||||
find_package(imgui CONFIG REQUIRED)
|
find_package(imgui CONFIG REQUIRED)
|
||||||
|
|
||||||
@ -54,12 +50,15 @@ target_include_directories(MetaCoreFoundation
|
|||||||
Source/MetaCoreFoundation/Public
|
Source/MetaCoreFoundation/Public
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(METACORE_COMMON_WARNINGS)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_compile_options(MetaCoreFoundation PRIVATE /W4 /permissive- /EHsc)
|
set(METACORE_COMMON_WARNINGS /W4 /permissive- /EHsc)
|
||||||
else()
|
else()
|
||||||
target_compile_options(MetaCoreFoundation PRIVATE -Wall -Wextra -Wpedantic)
|
set(METACORE_COMMON_WARNINGS -Wall -Wextra -Wpedantic)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
target_compile_options(MetaCoreFoundation PRIVATE ${METACORE_COMMON_WARNINGS})
|
||||||
|
|
||||||
set(METACORE_PLATFORM_HEADERS
|
set(METACORE_PLATFORM_HEADERS
|
||||||
Source/MetaCorePlatform/Public/MetaCorePlatform/MetaCoreInput.h
|
Source/MetaCorePlatform/Public/MetaCorePlatform/MetaCoreInput.h
|
||||||
Source/MetaCorePlatform/Public/MetaCorePlatform/MetaCoreWindow.h
|
Source/MetaCorePlatform/Public/MetaCorePlatform/MetaCoreWindow.h
|
||||||
@ -83,14 +82,12 @@ target_include_directories(MetaCorePlatform
|
|||||||
target_link_libraries(MetaCorePlatform
|
target_link_libraries(MetaCorePlatform
|
||||||
PUBLIC
|
PUBLIC
|
||||||
MetaCoreFoundation
|
MetaCoreFoundation
|
||||||
glfw
|
MetaCorePanda3D::SDK
|
||||||
|
glm::glm
|
||||||
)
|
)
|
||||||
|
|
||||||
if(MSVC)
|
target_compile_options(MetaCorePlatform PRIVATE ${METACORE_COMMON_WARNINGS})
|
||||||
target_compile_options(MetaCorePlatform PRIVATE /W4 /permissive- /EHsc)
|
target_compile_definitions(MetaCorePlatform PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX)
|
||||||
else()
|
|
||||||
target_compile_options(MetaCorePlatform PRIVATE -Wall -Wextra -Wpedantic)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(METACORE_SCENE_HEADERS
|
set(METACORE_SCENE_HEADERS
|
||||||
Source/MetaCoreScene/Public/MetaCoreScene/MetaCoreComponents.h
|
Source/MetaCoreScene/Public/MetaCoreScene/MetaCoreComponents.h
|
||||||
@ -118,29 +115,19 @@ target_link_libraries(MetaCoreScene
|
|||||||
glm::glm
|
glm::glm
|
||||||
)
|
)
|
||||||
|
|
||||||
if(MSVC)
|
target_compile_options(MetaCoreScene PRIVATE ${METACORE_COMMON_WARNINGS})
|
||||||
target_compile_options(MetaCoreScene PRIVATE /W4 /permissive- /EHsc)
|
|
||||||
else()
|
|
||||||
target_compile_options(MetaCoreScene PRIVATE -Wall -Wextra -Wpedantic)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(METACORE_RENDER_HEADERS
|
set(METACORE_RENDER_HEADERS
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderDevice.h
|
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreShaderProgram.h
|
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreMesh.h
|
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreDebugGeometry.h
|
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderTypes.h
|
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreSceneRenderer.h
|
|
||||||
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h
|
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreEditorViewportRenderer.h
|
||||||
|
Source/MetaCoreRender/Public/MetaCoreRender/MetaCorePandaSceneBridge.h
|
||||||
|
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderDevice.h
|
||||||
|
Source/MetaCoreRender/Public/MetaCoreRender/MetaCoreRenderTypes.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(METACORE_RENDER_SOURCES
|
set(METACORE_RENDER_SOURCES
|
||||||
Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp
|
|
||||||
Source/MetaCoreRender/Private/MetaCoreShaderProgram.cpp
|
|
||||||
Source/MetaCoreRender/Private/MetaCoreMesh.cpp
|
|
||||||
Source/MetaCoreRender/Private/MetaCoreDebugGeometry.cpp
|
|
||||||
Source/MetaCoreRender/Private/MetaCoreSceneRenderer.cpp
|
|
||||||
Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp
|
Source/MetaCoreRender/Private/MetaCoreEditorViewportRenderer.cpp
|
||||||
|
Source/MetaCoreRender/Private/MetaCorePandaSceneBridge.cpp
|
||||||
|
Source/MetaCoreRender/Private/MetaCoreRenderDevice.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(MetaCoreRender STATIC
|
add_library(MetaCoreRender STATIC
|
||||||
@ -156,35 +143,31 @@ target_include_directories(MetaCoreRender
|
|||||||
target_link_libraries(MetaCoreRender
|
target_link_libraries(MetaCoreRender
|
||||||
PUBLIC
|
PUBLIC
|
||||||
MetaCoreFoundation
|
MetaCoreFoundation
|
||||||
MetaCoreScene
|
|
||||||
MetaCorePlatform
|
MetaCorePlatform
|
||||||
OpenGL::GL
|
MetaCoreScene
|
||||||
glad::glad
|
MetaCorePanda3D::SDK
|
||||||
glm::glm
|
glm::glm
|
||||||
)
|
)
|
||||||
|
|
||||||
if(MSVC)
|
target_compile_options(MetaCoreRender PRIVATE ${METACORE_COMMON_WARNINGS})
|
||||||
target_compile_options(MetaCoreRender PRIVATE /W4 /permissive- /EHsc)
|
|
||||||
else()
|
|
||||||
target_compile_options(MetaCoreRender PRIVATE -Wall -Wextra -Wpedantic)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(METACORE_EDITOR_HEADERS
|
set(METACORE_EDITOR_HEADERS
|
||||||
Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorModule.h
|
|
||||||
Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorContext.h
|
|
||||||
Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorApp.h
|
Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorApp.h
|
||||||
|
Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorContext.h
|
||||||
|
Source/MetaCoreEditor/Public/MetaCoreEditor/MetaCoreEditorModule.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(METACORE_EDITOR_PRIVATE_HEADERS
|
set(METACORE_EDITOR_PRIVATE_HEADERS
|
||||||
|
Source/MetaCoreEditor/Private/MetaCoreBuiltinEditorModule.h
|
||||||
Source/MetaCoreEditor/Private/MetaCoreEditorCameraController.h
|
Source/MetaCoreEditor/Private/MetaCoreEditorCameraController.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(METACORE_EDITOR_SOURCES
|
set(METACORE_EDITOR_SOURCES
|
||||||
Source/MetaCoreEditor/Private/MetaCoreEditorModule.cpp
|
|
||||||
Source/MetaCoreEditor/Private/MetaCoreEditorContext.cpp
|
|
||||||
Source/MetaCoreEditor/Private/MetaCoreEditorCameraController.cpp
|
|
||||||
Source/MetaCoreEditor/Private/MetaCoreBuiltinEditorModule.cpp
|
Source/MetaCoreEditor/Private/MetaCoreBuiltinEditorModule.cpp
|
||||||
Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp
|
Source/MetaCoreEditor/Private/MetaCoreEditorApp.cpp
|
||||||
|
Source/MetaCoreEditor/Private/MetaCoreEditorCameraController.cpp
|
||||||
|
Source/MetaCoreEditor/Private/MetaCoreEditorContext.cpp
|
||||||
|
Source/MetaCoreEditor/Private/MetaCoreEditorModule.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(MetaCoreEditor STATIC
|
add_library(MetaCoreEditor STATIC
|
||||||
@ -204,17 +187,14 @@ target_link_libraries(MetaCoreEditor
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
MetaCoreFoundation
|
MetaCoreFoundation
|
||||||
MetaCorePlatform
|
MetaCorePlatform
|
||||||
MetaCoreScene
|
|
||||||
MetaCoreRender
|
MetaCoreRender
|
||||||
|
MetaCoreScene
|
||||||
glm::glm
|
glm::glm
|
||||||
imgui::imgui
|
imgui::imgui
|
||||||
)
|
)
|
||||||
|
|
||||||
if(MSVC)
|
target_compile_options(MetaCoreEditor PRIVATE ${METACORE_COMMON_WARNINGS})
|
||||||
target_compile_options(MetaCoreEditor PRIVATE /W4 /permissive- /EHsc)
|
target_compile_definitions(MetaCoreEditor PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX)
|
||||||
else()
|
|
||||||
target_compile_options(MetaCoreEditor PRIVATE -Wall -Wextra -Wpedantic)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(MetaCoreEditorApp
|
add_executable(MetaCoreEditorApp
|
||||||
Apps/MetaCoreEditor/main.cpp
|
Apps/MetaCoreEditor/main.cpp
|
||||||
@ -224,7 +204,8 @@ target_link_libraries(MetaCoreEditorApp
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
MetaCoreEditor
|
MetaCoreEditor
|
||||||
)
|
)
|
||||||
metacore_copy_runtime_dlls(MetaCoreEditorApp)
|
|
||||||
|
metacore_stage_panda3d_runtime(MetaCoreEditorApp)
|
||||||
|
|
||||||
add_executable(MetaCorePlayer
|
add_executable(MetaCorePlayer
|
||||||
Apps/MetaCorePlayer/main.cpp
|
Apps/MetaCorePlayer/main.cpp
|
||||||
@ -233,21 +214,26 @@ add_executable(MetaCorePlayer
|
|||||||
target_link_libraries(MetaCorePlayer
|
target_link_libraries(MetaCorePlayer
|
||||||
PRIVATE
|
PRIVATE
|
||||||
MetaCoreFoundation
|
MetaCoreFoundation
|
||||||
|
MetaCorePlatform
|
||||||
|
MetaCoreRender
|
||||||
|
MetaCoreScene
|
||||||
|
MetaCorePanda3D::SDK
|
||||||
)
|
)
|
||||||
metacore_copy_runtime_dlls(MetaCorePlayer)
|
|
||||||
|
metacore_stage_panda3d_runtime(MetaCorePlayer)
|
||||||
|
|
||||||
if(METACORE_BUILD_TESTS)
|
if(METACORE_BUILD_TESTS)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
add_executable(MetaCoreSmokeTests
|
add_executable(MetaCoreSmokeTests
|
||||||
Tests/MetaCoreSmokeTests.cpp
|
tests/MetaCoreSmokeTests.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(MetaCoreSmokeTests
|
target_link_libraries(MetaCoreSmokeTests
|
||||||
PRIVATE
|
PRIVATE
|
||||||
MetaCoreEditor
|
MetaCoreEditor
|
||||||
)
|
)
|
||||||
metacore_copy_runtime_dlls(MetaCoreSmokeTests)
|
|
||||||
|
|
||||||
|
metacore_stage_panda3d_runtime(MetaCoreSmokeTests)
|
||||||
add_test(NAME MetaCoreSmokeTests COMMAND MetaCoreSmokeTests)
|
add_test(NAME MetaCoreSmokeTests COMMAND MetaCoreSmokeTests)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"hidden": true,
|
"hidden": true,
|
||||||
"generator": "Visual Studio 17 2022",
|
"generator": "Visual Studio 17 2022",
|
||||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||||
"toolchainFile": "D:/vcpkg/scripts/buildsystems/vcpkg.cmake",
|
"toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_CXX_STANDARD": "20",
|
"CMAKE_CXX_STANDARD": "20",
|
||||||
"METACORE_BUILD_TESTS": "ON"
|
"METACORE_BUILD_TESTS": "ON"
|
||||||
|
|||||||
42
README.md
42
README.md
@ -1,50 +1,64 @@
|
|||||||
# MetaCore
|
# MetaCore
|
||||||
|
|
||||||
MetaCore 是一个以 Unity 工作流为参考的纯 C++ 编辑器原型工程。
|
`MetaCore` 是一个基于 `Panda3D` 进行二次开发的 Unity-like 编辑器与引擎框架原型。
|
||||||
|
|
||||||
## 当前目标
|
## 当前目标
|
||||||
|
|
||||||
- 使用 `GLFW + OpenGL + Dear ImGui Docking` 搭建最小可运行编辑器
|
- 以 `Panda3D` 作为底层引擎与运行时基础
|
||||||
- 使用 `GameObject + Component` 模型组织场景
|
- 以 `Dear ImGui Docking` 搭建 Unity-like 编辑器工作流
|
||||||
|
- 使用 `GameObject + Component` 模型组织编辑器语义层
|
||||||
- 先把 `Hierarchy / Scene / Inspector / Project / Console` 跑通
|
- 先把 `Hierarchy / Scene / Inspector / Project / Console` 跑通
|
||||||
- 先体现清晰的渲染架构,再以模块化方式持续增加功能
|
- 在不破坏主架构的前提下,以模块化方式持续叠加功能
|
||||||
|
|
||||||
## 技术栈
|
## 技术栈
|
||||||
|
|
||||||
- `C++20`
|
- `C++20`
|
||||||
- `CMake`
|
- `CMake`
|
||||||
- `vcpkg`
|
- `vcpkg`
|
||||||
- `GLFW`
|
- `Panda3D 1.10.16`
|
||||||
- `glad`
|
|
||||||
- `OpenGL 3.3`
|
|
||||||
- `glm`
|
- `glm`
|
||||||
- `Dear ImGui Docking`
|
- `Dear ImGui Docking`
|
||||||
|
|
||||||
## 目录结构
|
## 目录结构
|
||||||
|
|
||||||
- `Source/MetaCoreFoundation`:基础服务
|
- `Source/MetaCoreFoundation`:基础服务
|
||||||
- `Source/MetaCorePlatform`:窗口与输入
|
- `Source/MetaCorePlatform`:Panda3D 宿主窗口与输入采集
|
||||||
- `Source/MetaCoreScene`:场景与对象模型
|
- `Source/MetaCoreScene`:场景与对象模型
|
||||||
- `Source/MetaCoreRender`:OpenGL 渲染架构
|
- `Source/MetaCoreRender`:Panda3D 场景桥与显示区域驱动
|
||||||
- `Source/MetaCoreEditor`:编辑器模块与 Unity-like 界面
|
- `Source/MetaCoreEditor`:编辑器模块与 Unity-like 界面
|
||||||
- `Apps/MetaCoreEditor`:编辑器程序入口
|
- `Apps/MetaCoreEditor`:编辑器程序入口
|
||||||
- `Apps/MetaCorePlayer`:运行时占位入口
|
- `Apps/MetaCorePlayer`:运行时壳层入口
|
||||||
- `Tests`:基础烟雾测试
|
- `tests`:基础烟雾测试
|
||||||
|
|
||||||
## 构建
|
## 构建
|
||||||
|
|
||||||
|
前提:
|
||||||
|
|
||||||
|
- 已安装 `vcpkg`
|
||||||
|
- 已设置环境变量 `VCPKG_ROOT`
|
||||||
|
- Windows 环境可联网时,`cmake configure` 会自动准备 `Panda3D 1.10.16` SDK
|
||||||
|
- 如果已经本地安装 Panda3D,可设置环境变量 `PANDA3D_ROOT`
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cmake --preset vs2022-debug
|
cmake --preset vs2022-debug
|
||||||
cmake --build --preset build-debug
|
cmake --build --preset build-debug
|
||||||
ctest --preset test-debug
|
ctest --preset test-debug
|
||||||
```
|
```
|
||||||
|
|
||||||
|
如果希望生成更适合分发的可执行文件,可使用:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cmake --preset vs2022-release
|
||||||
|
cmake --build --preset build-release
|
||||||
|
```
|
||||||
|
|
||||||
## 当前完成内容
|
## 当前完成内容
|
||||||
|
|
||||||
- 单窗口 MetaCore 编辑器主循环
|
- Panda3D 单窗口宿主
|
||||||
- 场景视口离屏渲染
|
- ImGui Docking 编辑器外壳
|
||||||
|
- Panda3D 中央场景 DisplayRegion
|
||||||
- 网格、坐标轴、立方体绘制
|
- 网格、坐标轴、立方体绘制
|
||||||
- `Hierarchy` 选择
|
- `Hierarchy` 选择
|
||||||
- `Inspector` 中编辑 `Transform`
|
- `Inspector` 中编辑 `Transform`
|
||||||
- 轨道/平移/缩放相机控制
|
- `Alt+左键 / 中键 / 滚轮 / F` 相机交互
|
||||||
- 模块注册接口与内置编辑器模块
|
- 模块注册接口与内置编辑器模块
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "DefaultPbr",
|
||||||
|
"shader_family": "simplepbr",
|
||||||
|
"base_color": [1.0, 1.0, 1.0, 1.0],
|
||||||
|
"roughness": 1.0,
|
||||||
|
"metallic": 0.0
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"id": "00005031af6c28bc73f3772350037bcf00000005",
|
||||||
|
"relative_path": "Assets/Materials/default_pbr.material.json",
|
||||||
|
"type": "material"
|
||||||
|
}
|
||||||
10
SandboxProject/Assets/UI/main_menu.rcss
Normal file
10
SandboxProject/Assets/UI/main_menu.rcss
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: #f2f4f8;
|
||||||
|
}
|
||||||
|
.root-panel {
|
||||||
|
width: 420px;
|
||||||
|
margin: 40px auto;
|
||||||
|
padding: 24px;
|
||||||
|
background: rgba(16, 18, 24, 0.85);
|
||||||
|
}
|
||||||
5
SandboxProject/Assets/UI/main_menu.rcss.meta
Normal file
5
SandboxProject/Assets/UI/main_menu.rcss.meta
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"id": "00005031af6c1e30843b82e4691e8cba00000004",
|
||||||
|
"relative_path": "Assets/UI/main_menu.rcss",
|
||||||
|
"type": "ui_stylesheet"
|
||||||
|
}
|
||||||
11
SandboxProject/Assets/UI/main_menu.rml
Normal file
11
SandboxProject/Assets/UI/main_menu.rml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<rml>
|
||||||
|
<head>
|
||||||
|
<link type="text/rcss" href="main_menu.rcss" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="root-panel">
|
||||||
|
<h1>MetaCore</h1>
|
||||||
|
<p>Runtime UI scaffold</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</rml>
|
||||||
5
SandboxProject/Assets/UI/main_menu.rml.meta
Normal file
5
SandboxProject/Assets/UI/main_menu.rml.meta
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"id": "00005031af6bf9783f1fb78dcaa5ed8900000003",
|
||||||
|
"relative_path": "Assets/UI/main_menu.rml",
|
||||||
|
"type": "ui_document"
|
||||||
|
}
|
||||||
19
SandboxProject/Library/AssetDB.json
Normal file
19
SandboxProject/Library/AssetDB.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"id": "00005031af6bf9783f1fb78dcaa5ed8900000003",
|
||||||
|
"relative_path": "Assets/UI/main_menu.rml",
|
||||||
|
"type": "ui_document"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "00005031af6c1e30843b82e4691e8cba00000004",
|
||||||
|
"relative_path": "Assets/UI/main_menu.rcss",
|
||||||
|
"type": "ui_stylesheet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "00005031af6c28bc73f3772350037bcf00000005",
|
||||||
|
"relative_path": "Assets/Materials/default_pbr.material.json",
|
||||||
|
"type": "material"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
Shell=MetaCoreOverlayShell, Menus=3, ToolbarGroups=3, Sections=7, Hierarchy=3, Assets=3, Inspector=Demo Cube, DrawCommands=11, DrawVertices=2698, DrawIndices=6627, DrawLists=9
|
||||||
|
MetaCoreOverlayShell composition
|
||||||
|
[Menu] 文件 actions=2
|
||||||
|
- 新建场景 [Ctrl+N]
|
||||||
|
- 保存场景 [Ctrl+S]
|
||||||
|
[Menu] 编辑 actions=4
|
||||||
|
- 创建空对象 [Ctrl+Shift+N]
|
||||||
|
- 删除所选 [Delete]
|
||||||
|
- 重命名所选 [F2]
|
||||||
|
- 聚焦所选 [F]
|
||||||
|
[Menu] 视图 actions=5
|
||||||
|
- 切换层级
|
||||||
|
- 切换检查器
|
||||||
|
- 切换项目
|
||||||
|
- 切换控制台
|
||||||
|
- 切换运行时预览
|
||||||
|
[Toolbar] 场景 actions=3
|
||||||
|
- 创建空对象
|
||||||
|
- 删除所选
|
||||||
|
- 重命名所选
|
||||||
|
[Toolbar] 选择 actions=1
|
||||||
|
- 聚焦所选
|
||||||
|
[Toolbar] 视图 actions=5
|
||||||
|
- 切换层级
|
||||||
|
- 切换检查器
|
||||||
|
- 切换项目
|
||||||
|
- 切换控制台
|
||||||
|
- 切换运行时预览
|
||||||
|
[Section] panels=1
|
||||||
|
- 主菜单 (main_menu)
|
||||||
|
[Section] panels=1
|
||||||
|
- 工具栏 (toolbar)
|
||||||
|
[Section] panels=2
|
||||||
|
- 层级 (hierarchy)
|
||||||
|
- 项目 (project)
|
||||||
|
[Section] panels=1
|
||||||
|
- 视口 (viewport)
|
||||||
|
[Section] panels=1
|
||||||
|
- 检查器 (inspector)
|
||||||
|
[Section] panels=1
|
||||||
|
- 控制台 (console)
|
||||||
|
[Section] panels=1
|
||||||
|
- 运行时预览 (runtime_preview)
|
||||||
|
[Inspector] Demo Cube
|
||||||
|
- 标识: 00005031af7e8fac310b0d408494fcfb00000008
|
||||||
|
- 位置: 0.000000, 0.000000, 0.000000
|
||||||
|
- 旋转: 0.000000, 0.000000, 0.000000
|
||||||
|
- 缩放: 1.000000, 1.000000, 1.000000
|
||||||
|
- 网格: builtin://box
|
||||||
|
[Console]
|
||||||
|
- [System] MetaEditor initialized
|
||||||
|
[Viewport]
|
||||||
|
- Selection: Demo Cube
|
||||||
|
- SelectionId: 00005031af7e8fac310b0d408494fcfb00000008
|
||||||
|
- Operation: Translate
|
||||||
|
- Space: Local
|
||||||
|
- SnapEnabled: false
|
||||||
|
- SnapValues: 1, 1, 1
|
||||||
|
- Camera: 0.5, -2.5, 2
|
||||||
|
- Position: 0, 0, 0
|
||||||
|
- Rotation: 0, 0, 0
|
||||||
|
- Scale: 1, 1, 1
|
||||||
|
- FocusTarget: 00005031af7e8fac310b0d408494fcfb00000008
|
||||||
|
[DrawData]
|
||||||
|
- CommandCount: 11
|
||||||
|
- VertexCount: 2698
|
||||||
|
- IndexCount: 6627
|
||||||
|
- DrawLists: 9
|
||||||
9
SandboxProject/Library/Layout/editor_layout.json
Normal file
9
SandboxProject/Library/Layout/editor_layout.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"console_visible": true,
|
||||||
|
"hierarchy_visible": true,
|
||||||
|
"inspector_visible": true,
|
||||||
|
"layout_name": "Default",
|
||||||
|
"project_visible": true,
|
||||||
|
"runtime_preview_visible": true,
|
||||||
|
"toolbar_visible": true
|
||||||
|
}
|
||||||
8
SandboxProject/MetaCore.project.json
Normal file
8
SandboxProject/MetaCore.project.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "MetaCoreSample",
|
||||||
|
"scenes": [
|
||||||
|
"Scenes/Main.mcscene.json"
|
||||||
|
],
|
||||||
|
"startup_scene": "Scenes/Main.mcscene.json",
|
||||||
|
"version": "0.1.0"
|
||||||
|
}
|
||||||
108
SandboxProject/Scenes/Main.mcscene.json
Normal file
108
SandboxProject/Scenes/Main.mcscene.json
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"name": "Main",
|
||||||
|
"objects": [
|
||||||
|
{
|
||||||
|
"camera": {
|
||||||
|
"far_clip": 1000,
|
||||||
|
"fov_degrees": 60,
|
||||||
|
"near_clip": 0.100000001490116,
|
||||||
|
"primary": true
|
||||||
|
},
|
||||||
|
"editor_metadata": {
|
||||||
|
"editor_only": false,
|
||||||
|
"locked": false,
|
||||||
|
"selected": false
|
||||||
|
},
|
||||||
|
"id": "00005031af666d280adc4216764a07c100000001",
|
||||||
|
"name": "Main Camera",
|
||||||
|
"parent_id": "",
|
||||||
|
"transform": {
|
||||||
|
"position": [
|
||||||
|
0,
|
||||||
|
-10,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"editor_metadata": {
|
||||||
|
"editor_only": false,
|
||||||
|
"locked": false,
|
||||||
|
"selected": false
|
||||||
|
},
|
||||||
|
"id": "00005031af669a14494b5bcf7b0288f500000002",
|
||||||
|
"light": {
|
||||||
|
"color": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"intensity": 1,
|
||||||
|
"range": 10,
|
||||||
|
"spot_angle_degrees": 45,
|
||||||
|
"type": "directional"
|
||||||
|
},
|
||||||
|
"name": "Directional Light",
|
||||||
|
"parent_id": "",
|
||||||
|
"transform": {
|
||||||
|
"position": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"editor_metadata": {
|
||||||
|
"editor_only": false,
|
||||||
|
"locked": false,
|
||||||
|
"selected": false
|
||||||
|
},
|
||||||
|
"id": "00005031af7e8fac310b0d408494fcfb00000008",
|
||||||
|
"mesh_renderer": {
|
||||||
|
"material_asset_id": "builtin://editor-default",
|
||||||
|
"mesh_asset_id": "builtin://box",
|
||||||
|
"visible": true
|
||||||
|
},
|
||||||
|
"name": "Demo Cube",
|
||||||
|
"parent_id": "",
|
||||||
|
"transform": {
|
||||||
|
"position": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "MetaCoreEditor/MetaCoreEditorContext.h"
|
#include "MetaCoreEditor/MetaCoreEditorContext.h"
|
||||||
#include "MetaCoreEditorCameraController.h"
|
#include "MetaCoreEditorCameraController.h"
|
||||||
|
#include "MetaCorePlatform/MetaCoreInput.h"
|
||||||
#include "MetaCorePlatform/MetaCoreWindow.h"
|
#include "MetaCorePlatform/MetaCoreWindow.h"
|
||||||
#include "MetaCoreRender/MetaCoreEditorViewportRenderer.h"
|
#include "MetaCoreRender/MetaCoreEditorViewportRenderer.h"
|
||||||
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
||||||
@ -9,7 +10,6 @@
|
|||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -62,7 +62,7 @@ public:
|
|||||||
editorContext.SetDockLayoutBuilt(false);
|
editorContext.SetDockLayoutBuilt(false);
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("退出")) {
|
if (ImGui::MenuItem("退出")) {
|
||||||
glfwSetWindowShouldClose(editorContext.GetWindow().GetNativeHandle(), GLFW_TRUE);
|
editorContext.GetWindow().RequestClose();
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginMenu("帮助")) {
|
if (ImGui::BeginMenu("帮助")) {
|
||||||
ImGui::MenuItem("MetaCore Unity-like Prototype", nullptr, false, false);
|
ImGui::MenuItem("MetaCore Panda3D Editor Prototype", nullptr, false, false);
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,27 +138,6 @@ public:
|
|||||||
|
|
||||||
void DrawPanel(MetaCoreEditorContext& editorContext) override {
|
void DrawPanel(MetaCoreEditorContext& editorContext) override {
|
||||||
MetaCoreSceneViewportState& viewportState = editorContext.GetSceneViewportState();
|
MetaCoreSceneViewportState& viewportState = editorContext.GetSceneViewportState();
|
||||||
viewportState.Hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem);
|
|
||||||
viewportState.Focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows);
|
|
||||||
|
|
||||||
if (viewportState.Focused && editorContext.GetInput().WasKeyPressed(GLFW_KEY_F)) {
|
|
||||||
if (MetaCoreGameObject* selectedObject = editorContext.GetSelectedGameObject(); selectedObject != nullptr) {
|
|
||||||
editorContext.GetCameraController().FocusGameObject(*selectedObject);
|
|
||||||
editorContext.AddConsoleMessage(MetaCoreLogLevel::Info, "Scene", "相机已聚焦到当前对象");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
editorContext.GetCameraController().Update(viewportState, editorContext.GetInput());
|
|
||||||
|
|
||||||
ImGui::Text("对象数: %d", static_cast<int>(editorContext.GetScene().GetGameObjects().size()));
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (const MetaCoreGameObject* selectedObject = editorContext.GetSelectedGameObject(); selectedObject != nullptr) {
|
|
||||||
ImGui::Text("当前对象: %s", selectedObject->Name.c_str());
|
|
||||||
} else {
|
|
||||||
ImGui::TextUnformatted("当前对象: 无");
|
|
||||||
}
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
ImVec2 viewportSize = ImGui::GetContentRegionAvail();
|
ImVec2 viewportSize = ImGui::GetContentRegionAvail();
|
||||||
if (viewportSize.x < 1.0F) {
|
if (viewportSize.x < 1.0F) {
|
||||||
viewportSize.x = 1.0F;
|
viewportSize.x = 1.0F;
|
||||||
@ -167,30 +146,52 @@ public:
|
|||||||
viewportSize.y = 1.0F;
|
viewportSize.y = 1.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ImVec2 viewportScreenPosition = ImGui::GetCursorScreenPos();
|
||||||
|
ImGui::InvisibleButton("MetaCoreSceneViewport", viewportSize, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonMiddle);
|
||||||
|
|
||||||
|
const ImVec2 mainViewportPosition = ImGui::GetMainViewport()->Pos;
|
||||||
|
viewportState.Left = viewportScreenPosition.x - mainViewportPosition.x;
|
||||||
|
viewportState.Top = viewportScreenPosition.y - mainViewportPosition.y;
|
||||||
viewportState.Width = viewportSize.x;
|
viewportState.Width = viewportSize.x;
|
||||||
viewportState.Height = viewportSize.y;
|
viewportState.Height = viewportSize.y;
|
||||||
|
viewportState.Hovered = ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem);
|
||||||
|
viewportState.Focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows);
|
||||||
|
|
||||||
editorContext.GetViewportRenderer().Resize(static_cast<int>(viewportSize.x), static_cast<int>(viewportSize.y));
|
if (viewportState.Focused && !ImGui::GetIO().WantCaptureKeyboard && editorContext.GetInput().WasKeyPressed(MetaCoreInputKey::Focus)) {
|
||||||
|
if (MetaCoreGameObject* selectedObject = editorContext.GetSelectedGameObject(); selectedObject != nullptr) {
|
||||||
|
editorContext.GetCameraController().FocusGameObject(*selectedObject);
|
||||||
|
editorContext.AddConsoleMessage(MetaCoreLogLevel::Info, "Scene", "相机已聚焦到当前对象");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MetaCoreSceneView sceneView;
|
editorContext.GetCameraController().Update(viewportState, editorContext.GetInput());
|
||||||
sceneView.ViewMatrix = editorContext.GetCameraController().BuildViewMatrix();
|
|
||||||
sceneView.ProjectionMatrix = editorContext.GetCameraController().BuildProjectionMatrix(viewportSize.x / viewportSize.y);
|
MetaCoreSceneView sceneView = editorContext.GetCameraController().BuildSceneView();
|
||||||
sceneView.CameraPosition = editorContext.GetCameraController().GetCameraPosition();
|
|
||||||
sceneView.SelectedObjectId = editorContext.GetSelectedObjectId();
|
sceneView.SelectedObjectId = editorContext.GetSelectedObjectId();
|
||||||
|
editorContext.GetViewportRenderer().SetViewportRect(MetaCoreViewportRect{
|
||||||
|
viewportState.Left,
|
||||||
|
viewportState.Top,
|
||||||
|
viewportState.Width,
|
||||||
|
viewportState.Height
|
||||||
|
});
|
||||||
editorContext.GetViewportRenderer().RenderSceneToViewport(editorContext.GetScene(), sceneView);
|
editorContext.GetViewportRenderer().RenderSceneToViewport(editorContext.GetScene(), sceneView);
|
||||||
|
|
||||||
ImGui::Image(
|
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||||
reinterpret_cast<void*>(static_cast<intptr_t>(editorContext.GetViewportRenderer().GetColorTextureHandle())),
|
drawList->AddRect(
|
||||||
viewportSize,
|
viewportScreenPosition,
|
||||||
ImVec2(0.0F, 1.0F),
|
ImVec2(viewportScreenPosition.x + viewportSize.x, viewportScreenPosition.y + viewportSize.y),
|
||||||
ImVec2(1.0F, 0.0F)
|
IM_COL32(96, 108, 122, 220),
|
||||||
|
0.0F,
|
||||||
|
0,
|
||||||
|
1.0F
|
||||||
);
|
);
|
||||||
|
|
||||||
viewportState.Hovered = ImGui::IsItemHovered();
|
const char* helpText = "Alt+左键 环绕 | 中键 平移 | 滚轮 缩放 | F 聚焦";
|
||||||
viewportState.Focused = viewportState.Focused || ImGui::IsItemFocused();
|
drawList->AddText(
|
||||||
|
ImVec2(viewportScreenPosition.x + 12.0F, viewportScreenPosition.y + 10.0F),
|
||||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 28.0F);
|
IM_COL32(220, 224, 230, 220),
|
||||||
ImGui::TextDisabled("Alt+左键 环绕 | 中键 平移 | 滚轮 缩放 | F 聚焦");
|
helpText
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,13 @@
|
|||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_internal.h>
|
#include <imgui_internal.h>
|
||||||
#include <imgui_impl_glfw.h>
|
|
||||||
#include <imgui_impl_opengl3.h>
|
#include <imgui_impl_opengl3.h>
|
||||||
|
#include <imgui_impl_win32.h>
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@ -14,6 +19,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -27,7 +34,7 @@ void MetaCoreApplyEditorStyle() {
|
|||||||
style.WindowBorderSize = 1.0F;
|
style.WindowBorderSize = 1.0F;
|
||||||
style.FramePadding = ImVec2(8.0F, 4.0F);
|
style.FramePadding = ImVec2(8.0F, 4.0F);
|
||||||
style.ItemSpacing = ImVec2(8.0F, 5.0F);
|
style.ItemSpacing = ImVec2(8.0F, 5.0F);
|
||||||
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.11F, 0.12F, 0.14F, 1.0F);
|
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.11F, 0.12F, 0.14F, 0.97F);
|
||||||
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.10F, 0.11F, 0.13F, 1.0F);
|
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.10F, 0.11F, 0.13F, 1.0F);
|
||||||
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.14F, 0.15F, 0.17F, 1.0F);
|
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.14F, 0.15F, 0.17F, 1.0F);
|
||||||
style.Colors[ImGuiCol_Header] = ImVec4(0.17F, 0.20F, 0.24F, 1.0F);
|
style.Colors[ImGuiCol_Header] = ImVec4(0.17F, 0.20F, 0.24F, 1.0F);
|
||||||
@ -37,6 +44,7 @@ void MetaCoreApplyEditorStyle() {
|
|||||||
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.27F, 0.33F, 0.39F, 1.0F);
|
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.27F, 0.33F, 0.39F, 1.0F);
|
||||||
style.Colors[ImGuiCol_Tab] = ImVec4(0.12F, 0.14F, 0.16F, 1.0F);
|
style.Colors[ImGuiCol_Tab] = ImVec4(0.12F, 0.14F, 0.16F, 1.0F);
|
||||||
style.Colors[ImGuiCol_TabSelected] = ImVec4(0.20F, 0.26F, 0.34F, 1.0F);
|
style.Colors[ImGuiCol_TabSelected] = ImVec4(0.20F, 0.26F, 0.34F, 1.0F);
|
||||||
|
style.Colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.0F, 0.0F, 0.0F, 0.0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaCoreConfigureChineseFont() {
|
void MetaCoreConfigureChineseFont() {
|
||||||
@ -87,7 +95,16 @@ bool MetaCoreEditorApp::Initialize() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RenderDevice_.Initialize(Window_.GetNativeHandle())) {
|
Window_.SetNativeWindowMessageHandler([](void* nativeWindowHandle, unsigned int message, std::uintptr_t wparam, std::intptr_t lparam) {
|
||||||
|
ImGui_ImplWin32_WndProcHandler(
|
||||||
|
static_cast<HWND>(nativeWindowHandle),
|
||||||
|
message,
|
||||||
|
static_cast<WPARAM>(wparam),
|
||||||
|
static_cast<LPARAM>(lparam)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!RenderDevice_.Initialize(Window_)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +112,7 @@ bool MetaCoreEditorApp::Initialize() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ViewportRenderer_.Initialize()) {
|
if (!ViewportRenderer_.Initialize(RenderDevice_)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +140,7 @@ bool MetaCoreEditorApp::Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EditorContext_->AddConsoleMessage(MetaCoreLogLevel::Info, "System", "MetaCore 编辑器已初始化");
|
EditorContext_->AddConsoleMessage(MetaCoreLogLevel::Info, "System", "MetaCore 编辑器已初始化");
|
||||||
EditorContext_->AddConsoleMessage(MetaCoreLogLevel::Info, "Render", "OpenGL 场景视口已准备完成");
|
EditorContext_->AddConsoleMessage(MetaCoreLogLevel::Info, "Render", "Panda3D 场景视口已准备完成");
|
||||||
|
|
||||||
Initialized_ = true;
|
Initialized_ = true;
|
||||||
return true;
|
return true;
|
||||||
@ -134,15 +151,15 @@ int MetaCoreEditorApp::Run() {
|
|||||||
Window_.BeginFrame();
|
Window_.BeginFrame();
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
ImGui_ImplGlfw_NewFrame();
|
ImGui_ImplWin32_NewFrame();
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
DrawEditorFrame();
|
DrawEditorFrame();
|
||||||
|
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
const auto [framebufferWidth, framebufferHeight] = Window_.GetFramebufferSize();
|
RenderDevice_.RenderFrame();
|
||||||
RenderDevice_.BeginFrame(framebufferWidth, framebufferHeight, glm::vec4(0.08F, 0.09F, 0.11F, 1.0F));
|
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
RenderDevice_.PresentFrame();
|
||||||
Window_.EndFrame();
|
Window_.EndFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,11 +192,11 @@ bool MetaCoreEditorApp::InitializeImGui() {
|
|||||||
MetaCoreConfigureChineseFont();
|
MetaCoreConfigureChineseFont();
|
||||||
MetaCoreApplyEditorStyle();
|
MetaCoreApplyEditorStyle();
|
||||||
|
|
||||||
if (!ImGui_ImplGlfw_InitForOpenGL(Window_.GetNativeHandle(), true)) {
|
if (!ImGui_ImplWin32_InitForOpenGL(Window_.GetNativeWindowHandle())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ImGui_ImplOpenGL3_Init("#version 330")) {
|
if (!ImGui_ImplOpenGL3_Init("#version 130")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +205,7 @@ bool MetaCoreEditorApp::InitializeImGui() {
|
|||||||
|
|
||||||
void MetaCoreEditorApp::ShutdownImGui() {
|
void MetaCoreEditorApp::ShutdownImGui() {
|
||||||
ImGui_ImplOpenGL3_Shutdown();
|
ImGui_ImplOpenGL3_Shutdown();
|
||||||
ImGui_ImplGlfw_Shutdown();
|
ImGui_ImplWin32_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +220,7 @@ void MetaCoreEditorApp::DrawEditorFrame() {
|
|||||||
ImGuiWindowFlags_NoCollapse |
|
ImGuiWindowFlags_NoCollapse |
|
||||||
ImGuiWindowFlags_NoResize |
|
ImGuiWindowFlags_NoResize |
|
||||||
ImGuiWindowFlags_NoMove |
|
ImGuiWindowFlags_NoMove |
|
||||||
|
ImGuiWindowFlags_NoBackground |
|
||||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||||
ImGuiWindowFlags_NoNavFocus |
|
ImGuiWindowFlags_NoNavFocus |
|
||||||
ImGuiWindowFlags_MenuBar;
|
ImGuiWindowFlags_MenuBar;
|
||||||
@ -225,15 +243,80 @@ void MetaCoreEditorApp::DrawEditorFrame() {
|
|||||||
EnsureDefaultDockLayout(dockSpaceId);
|
EnsureDefaultDockLayout(dockSpaceId);
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
|
MetaCoreIEditorPanelProvider* scenePanelProvider = nullptr;
|
||||||
for (const auto& panelProvider : ModuleRegistry_.GetPanelProviders()) {
|
for (const auto& panelProvider : ModuleRegistry_.GetPanelProviders()) {
|
||||||
|
if (panelProvider->GetPanelId() == "Scene") {
|
||||||
|
scenePanelProvider = panelProvider.get();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
bool& panelOpen = ModuleRegistry_.AccessPanelOpenState(panelProvider->GetPanelId());
|
bool& panelOpen = ModuleRegistry_.AccessPanelOpenState(panelProvider->GetPanelId());
|
||||||
if (!panelOpen) {
|
if (!panelOpen) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Begin(panelProvider->GetPanelTitle().c_str(), &panelOpen);
|
bool pushedTransparentColors = false;
|
||||||
|
if (panelProvider->WantsTransparentBackground()) {
|
||||||
|
ImGui::SetNextWindowBgAlpha(0.0F);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0F, 0.0F, 0.0F, 0.0F));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.0F, 0.0F, 0.0F, 0.0F));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.0F, 0.0F, 0.0F, 0.0F));
|
||||||
|
pushedTransparentColors = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pushedPadding = false;
|
||||||
|
if (panelProvider->WantsZeroPadding()) {
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0F, 0.0F));
|
||||||
|
pushedPadding = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImGuiWindowFlags panelWindowFlags = static_cast<ImGuiWindowFlags>(panelProvider->GetWindowFlags());
|
||||||
|
ImGui::Begin(panelProvider->GetPanelTitle().c_str(), &panelOpen, panelWindowFlags);
|
||||||
panelProvider->DrawPanel(*EditorContext_);
|
panelProvider->DrawPanel(*EditorContext_);
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
|
if (pushedPadding) {
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pushedTransparentColors) {
|
||||||
|
ImGui::PopStyleColor(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scenePanelProvider != nullptr && ModuleRegistry_.IsPanelOpen("Scene")) {
|
||||||
|
ImGuiDockNode* centralNode = ImGui::DockBuilderGetCentralNode(dockSpaceId);
|
||||||
|
if (centralNode != nullptr) {
|
||||||
|
const ImVec2 overlayPosition = centralNode->Pos;
|
||||||
|
const ImVec2 overlaySize = centralNode->Size;
|
||||||
|
|
||||||
|
ImGui::SetNextWindowPos(overlayPosition);
|
||||||
|
ImGui::SetNextWindowSize(overlaySize);
|
||||||
|
ImGui::SetNextWindowBgAlpha(0.0F);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0F);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0F);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0F, 0.0F));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0F, 0.0F, 0.0F, 0.0F));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.0F, 0.0F, 0.0F, 0.0F));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.0F, 0.0F, 0.0F, 0.0F));
|
||||||
|
|
||||||
|
constexpr ImGuiWindowFlags sceneOverlayFlags =
|
||||||
|
ImGuiWindowFlags_NoDecoration |
|
||||||
|
ImGuiWindowFlags_NoDocking |
|
||||||
|
ImGuiWindowFlags_NoMove |
|
||||||
|
ImGuiWindowFlags_NoSavedSettings |
|
||||||
|
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||||
|
ImGuiWindowFlags_NoNavFocus |
|
||||||
|
ImGuiWindowFlags_NoBackground;
|
||||||
|
|
||||||
|
bool sceneOpen = true;
|
||||||
|
ImGui::Begin("MetaCoreSceneOverlay", &sceneOpen, sceneOverlayFlags);
|
||||||
|
scenePanelProvider->DrawPanel(*EditorContext_);
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
|
ImGui::PopStyleColor(3);
|
||||||
|
ImGui::PopStyleVar(3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +335,6 @@ void MetaCoreEditorApp::EnsureDefaultDockLayout(unsigned int dockSpaceId) {
|
|||||||
const ImGuiID bottomNodeId = ImGui::DockBuilderSplitNode(mainNodeId, ImGuiDir_Down, 0.28F, nullptr, &mainNodeId);
|
const ImGuiID bottomNodeId = ImGui::DockBuilderSplitNode(mainNodeId, ImGuiDir_Down, 0.28F, nullptr, &mainNodeId);
|
||||||
|
|
||||||
ImGui::DockBuilderDockWindow("层级", leftNodeId);
|
ImGui::DockBuilderDockWindow("层级", leftNodeId);
|
||||||
ImGui::DockBuilderDockWindow("场景", mainNodeId);
|
|
||||||
ImGui::DockBuilderDockWindow("检查器", rightNodeId);
|
ImGui::DockBuilderDockWindow("检查器", rightNodeId);
|
||||||
ImGui::DockBuilderDockWindow("项目", bottomNodeId);
|
ImGui::DockBuilderDockWindow("项目", bottomNodeId);
|
||||||
ImGui::DockBuilderDockWindow("控制台", bottomNodeId);
|
ImGui::DockBuilderDockWindow("控制台", bottomNodeId);
|
||||||
|
|||||||
@ -5,9 +5,8 @@
|
|||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <glm/geometric.hpp>
|
||||||
#include <glm/ext/matrix_clip_space.hpp>
|
#include <glm/trigonometric.hpp>
|
||||||
#include <glm/ext/matrix_transform.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -20,13 +19,16 @@ void MetaCoreEditorCameraController::Update(const MetaCoreSceneViewportState& vi
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
if (io.WantCaptureMouse) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (viewportState.Hovered && std::abs(io.MouseWheel) > 0.001F) {
|
if (viewportState.Hovered && std::abs(io.MouseWheel) > 0.001F) {
|
||||||
Distance_ *= (io.MouseWheel > 0.0F) ? 0.88F : 1.12F;
|
Distance_ *= (io.MouseWheel > 0.0F) ? 0.88F : 1.12F;
|
||||||
Distance_ = std::clamp(Distance_, 1.5F, 40.0F);
|
Distance_ = std::clamp(Distance_, 1.5F, 40.0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool altDown = input.IsKeyDown(GLFW_KEY_LEFT_ALT) || input.IsKeyDown(GLFW_KEY_RIGHT_ALT);
|
const bool altDown = input.IsKeyDown(MetaCoreInputKey::LeftAlt) || input.IsKeyDown(MetaCoreInputKey::RightAlt);
|
||||||
if (viewportState.Hovered && altDown && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
|
if (viewportState.Hovered && altDown && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
|
||||||
YawDegrees_ += io.MouseDelta.x * 0.35F;
|
YawDegrees_ += io.MouseDelta.x * 0.35F;
|
||||||
PitchDegrees_ -= io.MouseDelta.y * 0.35F;
|
PitchDegrees_ -= io.MouseDelta.y * 0.35F;
|
||||||
@ -48,13 +50,13 @@ void MetaCoreEditorCameraController::FocusGameObject(const MetaCoreGameObject& g
|
|||||||
Distance_ = std::max(3.5F, scaleRadius * 4.0F + 2.5F);
|
Distance_ = std::max(3.5F, scaleRadius * 4.0F + 2.5F);
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 MetaCoreEditorCameraController::BuildViewMatrix() const {
|
MetaCoreSceneView MetaCoreEditorCameraController::BuildSceneView() const {
|
||||||
return glm::lookAt(GetCameraPosition(), Target_, glm::vec3(0.0F, 1.0F, 0.0F));
|
MetaCoreSceneView sceneView;
|
||||||
}
|
sceneView.CameraPosition = GetCameraPosition();
|
||||||
|
sceneView.CameraTarget = Target_;
|
||||||
glm::mat4 MetaCoreEditorCameraController::BuildProjectionMatrix(float aspectRatio) const {
|
sceneView.CameraUp = glm::vec3(0.0F, 1.0F, 0.0F);
|
||||||
aspectRatio = (aspectRatio > 0.01F) ? aspectRatio : 1.0F;
|
sceneView.VerticalFieldOfViewDegrees = FieldOfViewDegrees_;
|
||||||
return glm::perspective(glm::radians(FieldOfViewDegrees_), aspectRatio, 0.1F, 200.0F);
|
return sceneView;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 MetaCoreEditorCameraController::GetCameraPosition() const {
|
glm::vec3 MetaCoreEditorCameraController::GetCameraPosition() const {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "MetaCoreEditor/MetaCoreEditorContext.h"
|
#include "MetaCoreEditor/MetaCoreEditorContext.h"
|
||||||
|
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
||||||
|
|
||||||
#include <glm/mat4x4.hpp>
|
|
||||||
#include <glm/vec3.hpp>
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
@ -10,13 +10,11 @@ namespace MetaCore {
|
|||||||
class MetaCoreInput;
|
class MetaCoreInput;
|
||||||
struct MetaCoreGameObject;
|
struct MetaCoreGameObject;
|
||||||
|
|
||||||
// 负责场景视口相机的轨道、平移、缩放与聚焦控制。
|
|
||||||
class MetaCoreEditorCameraController {
|
class MetaCoreEditorCameraController {
|
||||||
public:
|
public:
|
||||||
void Update(const MetaCoreSceneViewportState& viewportState, const MetaCoreInput& input);
|
void Update(const MetaCoreSceneViewportState& viewportState, const MetaCoreInput& input);
|
||||||
void FocusGameObject(const MetaCoreGameObject& gameObject);
|
void FocusGameObject(const MetaCoreGameObject& gameObject);
|
||||||
[[nodiscard]] glm::mat4 BuildViewMatrix() const;
|
[[nodiscard]] MetaCoreSceneView BuildSceneView() const;
|
||||||
[[nodiscard]] glm::mat4 BuildProjectionMatrix(float aspectRatio) const;
|
|
||||||
[[nodiscard]] glm::vec3 GetCameraPosition() const;
|
[[nodiscard]] glm::vec3 GetCameraPosition() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@ -17,15 +17,15 @@ struct MetaCoreGameObject;
|
|||||||
class MetaCoreEditorModuleRegistry;
|
class MetaCoreEditorModuleRegistry;
|
||||||
class MetaCoreEditorCameraController;
|
class MetaCoreEditorCameraController;
|
||||||
|
|
||||||
// 描述场景视口当前的尺寸与焦点状态。
|
|
||||||
struct MetaCoreSceneViewportState {
|
struct MetaCoreSceneViewportState {
|
||||||
|
float Left = 0.0F;
|
||||||
|
float Top = 0.0F;
|
||||||
float Width = 1.0F;
|
float Width = 1.0F;
|
||||||
float Height = 1.0F;
|
float Height = 1.0F;
|
||||||
bool Hovered = false;
|
bool Hovered = false;
|
||||||
bool Focused = false;
|
bool Focused = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 在编辑器各模块之间共享运行时状态。
|
|
||||||
class MetaCoreEditorContext {
|
class MetaCoreEditorContext {
|
||||||
public:
|
public:
|
||||||
MetaCoreEditorContext(
|
MetaCoreEditorContext(
|
||||||
|
|||||||
@ -10,7 +10,6 @@ namespace MetaCore {
|
|||||||
class MetaCoreEditorContext;
|
class MetaCoreEditorContext;
|
||||||
struct MetaCoreGameObject;
|
struct MetaCoreGameObject;
|
||||||
|
|
||||||
// 定义可向编辑器注册菜单的扩展接口。
|
|
||||||
class MetaCoreIMenuProvider {
|
class MetaCoreIMenuProvider {
|
||||||
public:
|
public:
|
||||||
virtual ~MetaCoreIMenuProvider() = default;
|
virtual ~MetaCoreIMenuProvider() = default;
|
||||||
@ -18,17 +17,18 @@ public:
|
|||||||
virtual void DrawMenuBar(MetaCoreEditorContext& editorContext) = 0;
|
virtual void DrawMenuBar(MetaCoreEditorContext& editorContext) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 定义可向编辑器注册面板的扩展接口。
|
|
||||||
class MetaCoreIEditorPanelProvider {
|
class MetaCoreIEditorPanelProvider {
|
||||||
public:
|
public:
|
||||||
virtual ~MetaCoreIEditorPanelProvider() = default;
|
virtual ~MetaCoreIEditorPanelProvider() = default;
|
||||||
[[nodiscard]] virtual std::string GetPanelId() const = 0;
|
[[nodiscard]] virtual std::string GetPanelId() const = 0;
|
||||||
[[nodiscard]] virtual std::string GetPanelTitle() const = 0;
|
[[nodiscard]] virtual std::string GetPanelTitle() const = 0;
|
||||||
[[nodiscard]] virtual bool IsOpenByDefault() const = 0;
|
[[nodiscard]] virtual bool IsOpenByDefault() const = 0;
|
||||||
|
[[nodiscard]] virtual int GetWindowFlags() const { return 0; }
|
||||||
|
[[nodiscard]] virtual bool WantsTransparentBackground() const { return false; }
|
||||||
|
[[nodiscard]] virtual bool WantsZeroPadding() const { return false; }
|
||||||
virtual void DrawPanel(MetaCoreEditorContext& editorContext) = 0;
|
virtual void DrawPanel(MetaCoreEditorContext& editorContext) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 定义可向 Inspector 注册组件绘制器的扩展接口。
|
|
||||||
class MetaCoreIInspectorDrawer {
|
class MetaCoreIInspectorDrawer {
|
||||||
public:
|
public:
|
||||||
virtual ~MetaCoreIInspectorDrawer() = default;
|
virtual ~MetaCoreIInspectorDrawer() = default;
|
||||||
@ -37,7 +37,6 @@ public:
|
|||||||
virtual void DrawInspector(MetaCoreEditorContext& editorContext, MetaCoreGameObject& gameObject) = 0;
|
virtual void DrawInspector(MetaCoreEditorContext& editorContext, MetaCoreGameObject& gameObject) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 管理编辑器中全部可扩展菜单、面板和 Inspector 绘制器。
|
|
||||||
class MetaCoreEditorModuleRegistry {
|
class MetaCoreEditorModuleRegistry {
|
||||||
public:
|
public:
|
||||||
void RegisterMenuProvider(std::unique_ptr<MetaCoreIMenuProvider> provider);
|
void RegisterMenuProvider(std::unique_ptr<MetaCoreIMenuProvider> provider);
|
||||||
@ -58,7 +57,6 @@ private:
|
|||||||
std::unordered_map<std::string, bool> PanelOpenStates_{};
|
std::unordered_map<std::string, bool> PanelOpenStates_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// 定义一个可注册到编辑器中的模块生命周期接口。
|
|
||||||
class MetaCoreIModule {
|
class MetaCoreIModule {
|
||||||
public:
|
public:
|
||||||
virtual ~MetaCoreIModule() = default;
|
virtual ~MetaCoreIModule() = default;
|
||||||
|
|||||||
@ -1,53 +1,49 @@
|
|||||||
#include "MetaCorePlatform/MetaCoreInput.h"
|
#include "MetaCorePlatform/MetaCoreInput.h"
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
void MetaCoreInput::BeginFrame(GLFWwindow* nativeWindow) {
|
void MetaCoreInput::BeginFrame() {
|
||||||
PreviousKeyStates_ = CurrentKeyStates_;
|
PreviousKeyStates_ = CurrentKeyStates_;
|
||||||
PreviousMouseStates_ = CurrentMouseStates_;
|
PreviousMouseStates_ = CurrentMouseStates_;
|
||||||
|
PreviousCursorPosition_ = CursorPosition_;
|
||||||
for (int key = 0; key < static_cast<int>(CurrentKeyStates_.size()); ++key) {
|
CursorDelta_ = glm::vec2(0.0F, 0.0F);
|
||||||
CurrentKeyStates_[static_cast<std::size_t>(key)] = glfwGetKey(nativeWindow, key) == GLFW_PRESS;
|
MouseWheelDelta_ = 0.0F;
|
||||||
}
|
|
||||||
|
|
||||||
for (int button = 0; button < static_cast<int>(CurrentMouseStates_.size()); ++button) {
|
|
||||||
CurrentMouseStates_[static_cast<std::size_t>(button)] = glfwGetMouseButton(nativeWindow, button) == GLFW_PRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
double cursorX = 0.0;
|
|
||||||
double cursorY = 0.0;
|
|
||||||
glfwGetCursorPos(nativeWindow, &cursorX, &cursorY);
|
|
||||||
|
|
||||||
const glm::vec2 previousPosition = CursorPosition_;
|
|
||||||
CursorPosition_ = glm::vec2(static_cast<float>(cursorX), static_cast<float>(cursorY));
|
|
||||||
CursorDelta_ = CursorPosition_ - previousPosition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MetaCoreInput::IsKeyDown(int key) const {
|
void MetaCoreInput::SetKeyState(MetaCoreInputKey key, bool isDown) {
|
||||||
if (key < 0 || key >= static_cast<int>(CurrentKeyStates_.size())) {
|
CurrentKeyStates_[static_cast<std::size_t>(key)] = isDown;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
void MetaCoreInput::SetMouseButtonState(MetaCoreMouseButton button, bool isDown) {
|
||||||
|
CurrentMouseStates_[static_cast<std::size_t>(button)] = isDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaCoreInput::SetCursorPosition(const glm::vec2& cursorPosition) {
|
||||||
|
CursorPosition_ = cursorPosition;
|
||||||
|
CursorDelta_ = CursorPosition_ - PreviousCursorPosition_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaCoreInput::AddMouseWheelDelta(float delta) {
|
||||||
|
MouseWheelDelta_ += delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetaCoreInput::IsKeyDown(MetaCoreInputKey key) const {
|
||||||
return CurrentKeyStates_[static_cast<std::size_t>(key)];
|
return CurrentKeyStates_[static_cast<std::size_t>(key)];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MetaCoreInput::WasKeyPressed(int key) const {
|
bool MetaCoreInput::WasKeyPressed(MetaCoreInputKey key) const {
|
||||||
if (key < 0 || key >= static_cast<int>(CurrentKeyStates_.size())) {
|
const std::size_t keyIndex = static_cast<std::size_t>(key);
|
||||||
return false;
|
return CurrentKeyStates_[keyIndex] && !PreviousKeyStates_[keyIndex];
|
||||||
}
|
|
||||||
|
|
||||||
const std::size_t index = static_cast<std::size_t>(key);
|
|
||||||
return CurrentKeyStates_[index] && !PreviousKeyStates_[index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MetaCoreInput::IsMouseButtonDown(int button) const {
|
bool MetaCoreInput::IsMouseButtonDown(MetaCoreMouseButton button) const {
|
||||||
if (button < 0 || button >= static_cast<int>(CurrentMouseStates_.size())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return CurrentMouseStates_[static_cast<std::size_t>(button)];
|
return CurrentMouseStates_[static_cast<std::size_t>(button)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float MetaCoreInput::GetMouseWheelDelta() const {
|
||||||
|
return MouseWheelDelta_;
|
||||||
|
}
|
||||||
|
|
||||||
const glm::vec2& MetaCoreInput::GetCursorPosition() const {
|
const glm::vec2& MetaCoreInput::GetCursorPosition() const {
|
||||||
return CursorPosition_;
|
return CursorPosition_;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,99 +1,259 @@
|
|||||||
#include "MetaCorePlatform/MetaCoreWindow.h"
|
#include "MetaCorePlatform/MetaCoreWindow.h"
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#include "graphicsWindow.h"
|
||||||
|
#include "graphicsWindowProc.h"
|
||||||
|
#include "load_prc_file.h"
|
||||||
|
#include "nativeWindowHandle.h"
|
||||||
|
#include "pandaFramework.h"
|
||||||
|
#include "windowFramework.h"
|
||||||
|
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void MetaCoreConfigurePanda3D(const std::string& title) {
|
||||||
|
static bool configured = false;
|
||||||
|
if (configured) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
load_prc_file_data("", "load-display pandagl\n");
|
||||||
|
load_prc_file_data("", "aux-display p3windisplay\n");
|
||||||
|
load_prc_file_data("", "window-type onscreen\n");
|
||||||
|
load_prc_file_data("", "model-path ./models\n");
|
||||||
|
load_prc_file_data("", "sync-video false\n");
|
||||||
|
load_prc_file_data("", "notify-level warning\n");
|
||||||
|
load_prc_file_data("", "audio-library-name null\n");
|
||||||
|
load_prc_file_data("", "textures-power-2 none\n");
|
||||||
|
load_prc_file_data("", "editor-window-title " + title + "\n");
|
||||||
|
configured = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND MetaCoreResolveNativeWindowHandle(GraphicsWindow* graphicsWindow) {
|
||||||
|
if (graphicsWindow == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowHandle* windowHandle = graphicsWindow->get_window_handle();
|
||||||
|
if (windowHandle == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reinterpret_cast<HWND>(windowHandle->get_int_handle());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetaCoreIsVirtualKeyDown(int virtualKey) {
|
||||||
|
return (GetAsyncKeyState(virtualKey) & 0x8000) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class MetaCoreWindow::MetaCoreWindowImpl {
|
||||||
|
public:
|
||||||
|
PandaFramework Framework{};
|
||||||
|
WindowFramework* WindowFrameworkHandle = nullptr;
|
||||||
|
GraphicsWindow* GraphicsWindowHandle = nullptr;
|
||||||
|
HWND NativeHandle = nullptr;
|
||||||
|
MetaCoreInput Input{};
|
||||||
|
MetaCoreNativeWindowMessageHandler MessageHandler{};
|
||||||
|
std::unique_ptr<class MetaCoreWindowMessageProc> MessageProc{};
|
||||||
|
std::chrono::steady_clock::time_point LastFrameTime = std::chrono::steady_clock::now();
|
||||||
|
float DeltaSeconds = 1.0F / 60.0F;
|
||||||
|
bool Initialized = false;
|
||||||
|
bool CloseRequested = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MetaCoreWindowMessageProc final : public GraphicsWindowProc {
|
||||||
|
public:
|
||||||
|
explicit MetaCoreWindowMessageProc(MetaCoreWindow::MetaCoreWindowImpl& owner)
|
||||||
|
: Owner_(owner) {
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG wnd_proc(GraphicsWindow*, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MetaCoreWindow::MetaCoreWindowImpl& Owner_;
|
||||||
|
};
|
||||||
|
|
||||||
|
LONG MetaCoreWindowMessageProc::wnd_proc(GraphicsWindow*, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||||
|
if (Owner_.MessageHandler) {
|
||||||
|
Owner_.MessageHandler(hwnd, msg, static_cast<std::uintptr_t>(wparam), static_cast<std::intptr_t>(lparam));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg == WM_MOUSEWHEEL) {
|
||||||
|
Owner_.Input.AddMouseWheelDelta(static_cast<float>(GET_WHEEL_DELTA_WPARAM(wparam)) / static_cast<float>(WHEEL_DELTA));
|
||||||
|
} else if (msg == WM_CLOSE) {
|
||||||
|
Owner_.CloseRequested = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaCoreWindow::MetaCoreWindow()
|
||||||
|
: Impl_(std::make_unique<MetaCoreWindowImpl>()) {
|
||||||
|
}
|
||||||
|
|
||||||
MetaCoreWindow::~MetaCoreWindow() {
|
MetaCoreWindow::~MetaCoreWindow() {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MetaCoreWindow::Initialize(int width, int height, const std::string& title) {
|
bool MetaCoreWindow::Initialize(int width, int height, const std::string& title) {
|
||||||
if (NativeHandle_ != nullptr) {
|
if (Impl_->Initialized) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glfwInit() != GLFW_TRUE) {
|
MetaCoreConfigurePanda3D(title);
|
||||||
|
Impl_->Framework.open_framework();
|
||||||
|
Impl_->Framework.set_window_title(title);
|
||||||
|
|
||||||
|
WindowProperties windowProperties;
|
||||||
|
windowProperties.set_size(width, height);
|
||||||
|
windowProperties.set_title(title);
|
||||||
|
windowProperties.set_foreground(true);
|
||||||
|
|
||||||
|
Impl_->WindowFrameworkHandle = Impl_->Framework.open_window(windowProperties, 0);
|
||||||
|
if (Impl_->WindowFrameworkHandle == nullptr) {
|
||||||
|
Shutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
Impl_->GraphicsWindowHandle = Impl_->WindowFrameworkHandle->get_graphics_window();
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
Impl_->NativeHandle = MetaCoreResolveNativeWindowHandle(Impl_->GraphicsWindowHandle);
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
if (Impl_->GraphicsWindowHandle == nullptr || Impl_->NativeHandle == nullptr) {
|
||||||
#if defined(__APPLE__)
|
Shutdown();
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NativeHandle_ = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
|
|
||||||
if (NativeHandle_ == nullptr) {
|
|
||||||
glfwTerminate();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwMakeContextCurrent(NativeHandle_);
|
Impl_->MessageProc = std::make_unique<MetaCoreWindowMessageProc>(*Impl_);
|
||||||
glfwSwapInterval(1);
|
if (Impl_->GraphicsWindowHandle->supports_window_procs()) {
|
||||||
LastFrameTime_ = glfwGetTime();
|
Impl_->GraphicsWindowHandle->add_window_proc(Impl_->MessageProc.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->CloseRequested = false;
|
||||||
|
Impl_->LastFrameTime = std::chrono::steady_clock::now();
|
||||||
|
Impl_->Initialized = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaCoreWindow::Shutdown() {
|
void MetaCoreWindow::Shutdown() {
|
||||||
if (NativeHandle_ != nullptr) {
|
if (!Impl_->Initialized) {
|
||||||
glfwDestroyWindow(NativeHandle_);
|
return;
|
||||||
NativeHandle_ = nullptr;
|
|
||||||
glfwTerminate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Impl_->GraphicsWindowHandle != nullptr && Impl_->MessageProc != nullptr && Impl_->GraphicsWindowHandle->supports_window_procs()) {
|
||||||
|
Impl_->GraphicsWindowHandle->remove_window_proc(Impl_->MessageProc.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->MessageProc.reset();
|
||||||
|
|
||||||
|
if (Impl_->WindowFrameworkHandle != nullptr) {
|
||||||
|
Impl_->Framework.close_window(Impl_->WindowFrameworkHandle);
|
||||||
|
Impl_->WindowFrameworkHandle = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->GraphicsWindowHandle = nullptr;
|
||||||
|
Impl_->NativeHandle = nullptr;
|
||||||
|
Impl_->Framework.close_framework();
|
||||||
|
Impl_->Initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaCoreWindow::BeginFrame() {
|
void MetaCoreWindow::BeginFrame() {
|
||||||
glfwPollEvents();
|
if (!Impl_->Initialized) {
|
||||||
|
return;
|
||||||
const double currentTime = glfwGetTime();
|
|
||||||
DeltaSeconds_ = static_cast<float>(currentTime - LastFrameTime_);
|
|
||||||
LastFrameTime_ = currentTime;
|
|
||||||
|
|
||||||
if (DeltaSeconds_ <= 0.0F) {
|
|
||||||
DeltaSeconds_ = 1.0F / 60.0F;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Input_.BeginFrame(NativeHandle_);
|
const auto now = std::chrono::steady_clock::now();
|
||||||
|
Impl_->DeltaSeconds = std::chrono::duration<float>(now - Impl_->LastFrameTime).count();
|
||||||
|
if (Impl_->DeltaSeconds <= 0.0F) {
|
||||||
|
Impl_->DeltaSeconds = 1.0F / 60.0F;
|
||||||
|
}
|
||||||
|
Impl_->LastFrameTime = now;
|
||||||
|
|
||||||
|
Impl_->Input.BeginFrame();
|
||||||
|
|
||||||
|
if (Impl_->GraphicsWindowHandle != nullptr) {
|
||||||
|
Impl_->GraphicsWindowHandle->process_events();
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->Input.SetKeyState(MetaCoreInputKey::LeftAlt, MetaCoreIsVirtualKeyDown(VK_LMENU));
|
||||||
|
Impl_->Input.SetKeyState(MetaCoreInputKey::RightAlt, MetaCoreIsVirtualKeyDown(VK_RMENU));
|
||||||
|
Impl_->Input.SetKeyState(MetaCoreInputKey::Focus, MetaCoreIsVirtualKeyDown('F'));
|
||||||
|
Impl_->Input.SetMouseButtonState(MetaCoreMouseButton::Left, MetaCoreIsVirtualKeyDown(VK_LBUTTON));
|
||||||
|
Impl_->Input.SetMouseButtonState(MetaCoreMouseButton::Right, MetaCoreIsVirtualKeyDown(VK_RBUTTON));
|
||||||
|
Impl_->Input.SetMouseButtonState(MetaCoreMouseButton::Middle, MetaCoreIsVirtualKeyDown(VK_MBUTTON));
|
||||||
|
|
||||||
|
POINT cursorPosition{};
|
||||||
|
if (GetCursorPos(&cursorPosition) != FALSE && ScreenToClient(Impl_->NativeHandle, &cursorPosition) != FALSE) {
|
||||||
|
Impl_->Input.SetCursorPosition(glm::vec2(static_cast<float>(cursorPosition.x), static_cast<float>(cursorPosition.y)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaCoreWindow::EndFrame() const {
|
void MetaCoreWindow::EndFrame() {
|
||||||
glfwSwapBuffers(NativeHandle_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MetaCoreWindow::ShouldClose() const {
|
bool MetaCoreWindow::ShouldClose() const {
|
||||||
return NativeHandle_ == nullptr || glfwWindowShouldClose(NativeHandle_) == GLFW_TRUE;
|
return !Impl_->Initialized || Impl_->CloseRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWwindow* MetaCoreWindow::GetNativeHandle() const {
|
void MetaCoreWindow::RequestClose() {
|
||||||
return NativeHandle_;
|
Impl_->CloseRequested = true;
|
||||||
|
if (Impl_->GraphicsWindowHandle != nullptr) {
|
||||||
|
Impl_->GraphicsWindowHandle->request_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MetaCoreWindow::GetNativeWindowHandle() const {
|
||||||
|
return Impl_->NativeHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MetaCoreWindow::GetNativeFrameworkHandle() const {
|
||||||
|
return &Impl_->Framework;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MetaCoreWindow::GetNativeWindowFrameworkHandle() const {
|
||||||
|
return Impl_->WindowFrameworkHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MetaCoreWindow::GetNativeGraphicsWindowHandle() const {
|
||||||
|
return Impl_->GraphicsWindowHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaCoreInput& MetaCoreWindow::GetInput() {
|
MetaCoreInput& MetaCoreWindow::GetInput() {
|
||||||
return Input_;
|
return Impl_->Input;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MetaCoreInput& MetaCoreWindow::GetInput() const {
|
const MetaCoreInput& MetaCoreWindow::GetInput() const {
|
||||||
return Input_;
|
return Impl_->Input;
|
||||||
}
|
}
|
||||||
|
|
||||||
float MetaCoreWindow::GetDeltaSeconds() const {
|
float MetaCoreWindow::GetDeltaSeconds() const {
|
||||||
return DeltaSeconds_;
|
return Impl_->DeltaSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int, int> MetaCoreWindow::GetWindowSize() const {
|
std::pair<int, int> MetaCoreWindow::GetWindowSize() const {
|
||||||
int width = 0;
|
if (Impl_->GraphicsWindowHandle == nullptr) {
|
||||||
int height = 0;
|
return {0, 0};
|
||||||
glfwGetWindowSize(NativeHandle_, &width, &height);
|
}
|
||||||
return {width, height};
|
|
||||||
|
const WindowProperties windowProperties = Impl_->GraphicsWindowHandle->get_properties();
|
||||||
|
return {windowProperties.get_x_size(), windowProperties.get_y_size()};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int, int> MetaCoreWindow::GetFramebufferSize() const {
|
std::pair<int, int> MetaCoreWindow::GetFramebufferSize() const {
|
||||||
int width = 0;
|
return GetWindowSize();
|
||||||
int height = 0;
|
}
|
||||||
glfwGetFramebufferSize(NativeHandle_, &width, &height);
|
|
||||||
return {width, height};
|
void MetaCoreWindow::SetNativeWindowMessageHandler(MetaCoreNativeWindowMessageHandler handler) {
|
||||||
|
Impl_->MessageHandler = std::move(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace MetaCore
|
} // namespace MetaCore
|
||||||
|
|||||||
@ -4,38 +4,72 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
// 统一封装窗口轮询后的键鼠状态,避免上层直接依赖 GLFW 轮询细节。
|
// 定义编辑器当前阶段需要识别的按键。
|
||||||
|
enum class MetaCoreInputKey : unsigned int {
|
||||||
|
LeftAlt = 0,
|
||||||
|
RightAlt,
|
||||||
|
Focus,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
// 定义编辑器当前阶段需要识别的鼠标按键。
|
||||||
|
enum class MetaCoreMouseButton : unsigned int {
|
||||||
|
Left = 0,
|
||||||
|
Right,
|
||||||
|
Middle,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
// 统一封装窗口层采集后的输入状态,避免上层直接依赖 Win32 或 Panda3D 细节。
|
||||||
class MetaCoreInput {
|
class MetaCoreInput {
|
||||||
public:
|
public:
|
||||||
// 由窗口层在每帧轮询事件后刷新一次输入状态。
|
// 在每帧开始时重置瞬时状态并保存上一帧快照。
|
||||||
void BeginFrame(GLFWwindow* nativeWindow);
|
void BeginFrame();
|
||||||
|
|
||||||
|
// 由窗口层写入按键状态。
|
||||||
|
void SetKeyState(MetaCoreInputKey key, bool isDown);
|
||||||
|
|
||||||
|
// 由窗口层写入鼠标按键状态。
|
||||||
|
void SetMouseButtonState(MetaCoreMouseButton button, bool isDown);
|
||||||
|
|
||||||
|
// 由窗口层写入当前鼠标位置。
|
||||||
|
void SetCursorPosition(const glm::vec2& cursorPosition);
|
||||||
|
|
||||||
|
// 由窗口消息累加滚轮值,正值表示向前滚动。
|
||||||
|
void AddMouseWheelDelta(float delta);
|
||||||
|
|
||||||
// 判断按键当前是否处于按下状态。
|
// 判断按键当前是否处于按下状态。
|
||||||
[[nodiscard]] bool IsKeyDown(int key) const;
|
[[nodiscard]] bool IsKeyDown(MetaCoreInputKey key) const;
|
||||||
|
|
||||||
// 判断按键是否在本帧刚刚按下。
|
// 判断按键是否在本帧刚刚按下。
|
||||||
[[nodiscard]] bool WasKeyPressed(int key) const;
|
[[nodiscard]] bool WasKeyPressed(MetaCoreInputKey key) const;
|
||||||
|
|
||||||
// 判断鼠标按键当前是否按下。
|
// 判断鼠标按键当前是否按下。
|
||||||
[[nodiscard]] bool IsMouseButtonDown(int button) const;
|
[[nodiscard]] bool IsMouseButtonDown(MetaCoreMouseButton button) const;
|
||||||
|
|
||||||
|
// 返回当前帧累计的滚轮值。
|
||||||
|
[[nodiscard]] float GetMouseWheelDelta() const;
|
||||||
|
|
||||||
// 返回当前鼠标位置。
|
// 返回当前鼠标位置。
|
||||||
[[nodiscard]] const glm::vec2& GetCursorPosition() const;
|
[[nodiscard]] const glm::vec2& GetCursorPosition() const;
|
||||||
|
|
||||||
// 返回本帧鼠标相对上一帧的位移。
|
// 返回相对上一帧的鼠标位移。
|
||||||
[[nodiscard]] const glm::vec2& GetCursorDelta() const;
|
[[nodiscard]] const glm::vec2& GetCursorDelta() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<bool, 512> CurrentKeyStates_{};
|
static constexpr std::size_t KeyCount_ = static_cast<std::size_t>(MetaCoreInputKey::Count);
|
||||||
std::array<bool, 512> PreviousKeyStates_{};
|
static constexpr std::size_t MouseButtonCount_ = static_cast<std::size_t>(MetaCoreMouseButton::Count);
|
||||||
std::array<bool, 8> CurrentMouseStates_{};
|
|
||||||
std::array<bool, 8> PreviousMouseStates_{};
|
std::array<bool, KeyCount_> CurrentKeyStates_{};
|
||||||
|
std::array<bool, KeyCount_> PreviousKeyStates_{};
|
||||||
|
std::array<bool, MouseButtonCount_> CurrentMouseStates_{};
|
||||||
|
std::array<bool, MouseButtonCount_> PreviousMouseStates_{};
|
||||||
glm::vec2 CursorPosition_{0.0F, 0.0F};
|
glm::vec2 CursorPosition_{0.0F, 0.0F};
|
||||||
|
glm::vec2 PreviousCursorPosition_{0.0F, 0.0F};
|
||||||
glm::vec2 CursorDelta_{0.0F, 0.0F};
|
glm::vec2 CursorDelta_{0.0F, 0.0F};
|
||||||
|
float MouseWheelDelta_ = 0.0F;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MetaCore
|
} // namespace MetaCore
|
||||||
|
|||||||
@ -2,55 +2,75 @@
|
|||||||
|
|
||||||
#include "MetaCorePlatform/MetaCoreInput.h"
|
#include "MetaCorePlatform/MetaCoreInput.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
struct GLFWwindow;
|
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
// 负责管理主窗口、时间步进和最基础的事件轮询。
|
class MetaCoreRenderDevice;
|
||||||
|
|
||||||
|
// 定义宿主窗口层向上暴露的原生消息回调,用于把 Win32 消息转交给 ImGui。
|
||||||
|
using MetaCoreNativeWindowMessageHandler = std::function<void(void*, unsigned int, std::uintptr_t, std::intptr_t)>;
|
||||||
|
|
||||||
|
// 封装 Panda3D 窗口、时间步进与基础输入采集。
|
||||||
class MetaCoreWindow {
|
class MetaCoreWindow {
|
||||||
public:
|
public:
|
||||||
MetaCoreWindow() = default;
|
class MetaCoreWindowImpl;
|
||||||
|
|
||||||
|
MetaCoreWindow();
|
||||||
~MetaCoreWindow();
|
~MetaCoreWindow();
|
||||||
|
|
||||||
// 创建主窗口并初始化 OpenGL 上下文。
|
// 创建 Panda3D 主窗口并准备输入采集。
|
||||||
bool Initialize(int width, int height, const std::string& title);
|
bool Initialize(int width, int height, const std::string& title);
|
||||||
|
|
||||||
// 释放窗口及 GLFW 资源。
|
// 释放窗口与 Panda3D 宿主资源。
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
// 轮询事件并刷新输入状态。
|
// 处理窗口事件、更新时间步进并刷新输入状态。
|
||||||
void BeginFrame();
|
void BeginFrame();
|
||||||
|
|
||||||
// 交换前后缓冲区。
|
// 为未来扩展保留的帧结束入口。
|
||||||
void EndFrame() const;
|
void EndFrame();
|
||||||
|
|
||||||
// 返回窗口是否请求关闭。
|
// 返回窗口是否请求退出。
|
||||||
[[nodiscard]] bool ShouldClose() const;
|
[[nodiscard]] bool ShouldClose() const;
|
||||||
|
|
||||||
// 返回原生 GLFW 窗口指针。
|
// 主动请求窗口退出。
|
||||||
[[nodiscard]] GLFWwindow* GetNativeHandle() const;
|
void RequestClose();
|
||||||
|
|
||||||
|
// 返回原生窗口句柄,供 ImGui Win32 backend 初始化使用。
|
||||||
|
[[nodiscard]] void* GetNativeWindowHandle() const;
|
||||||
|
|
||||||
|
// 返回 PandaFramework 原生对象指针,仅供底层桥接层使用。
|
||||||
|
[[nodiscard]] void* GetNativeFrameworkHandle() const;
|
||||||
|
|
||||||
|
// 返回 WindowFramework 原生对象指针,仅供底层桥接层使用。
|
||||||
|
[[nodiscard]] void* GetNativeWindowFrameworkHandle() const;
|
||||||
|
|
||||||
|
// 返回 GraphicsWindow 原生对象指针,仅供底层桥接层使用。
|
||||||
|
[[nodiscard]] void* GetNativeGraphicsWindowHandle() const;
|
||||||
|
|
||||||
// 返回当前输入对象。
|
// 返回当前输入对象。
|
||||||
[[nodiscard]] MetaCoreInput& GetInput();
|
[[nodiscard]] MetaCoreInput& GetInput();
|
||||||
[[nodiscard]] const MetaCoreInput& GetInput() const;
|
[[nodiscard]] const MetaCoreInput& GetInput() const;
|
||||||
|
|
||||||
// 返回当前帧的时间间隔,单位为秒。
|
// 返回当前帧耗时,单位为秒。
|
||||||
[[nodiscard]] float GetDeltaSeconds() const;
|
[[nodiscard]] float GetDeltaSeconds() const;
|
||||||
|
|
||||||
// 返回窗口尺寸。
|
// 返回当前窗口尺寸。
|
||||||
[[nodiscard]] std::pair<int, int> GetWindowSize() const;
|
[[nodiscard]] std::pair<int, int> GetWindowSize() const;
|
||||||
|
|
||||||
// 返回帧缓冲尺寸。
|
// 返回当前帧缓冲尺寸。
|
||||||
[[nodiscard]] std::pair<int, int> GetFramebufferSize() const;
|
[[nodiscard]] std::pair<int, int> GetFramebufferSize() const;
|
||||||
|
|
||||||
|
// 注册原生消息回调。
|
||||||
|
void SetNativeWindowMessageHandler(MetaCoreNativeWindowMessageHandler handler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLFWwindow* NativeHandle_ = nullptr;
|
std::unique_ptr<MetaCoreWindowImpl> Impl_{};
|
||||||
MetaCoreInput Input_{};
|
|
||||||
float DeltaSeconds_ = 1.0F / 60.0F;
|
|
||||||
double LastFrameTime_ = 0.0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MetaCore
|
} // namespace MetaCore
|
||||||
|
|||||||
@ -1,110 +0,0 @@
|
|||||||
#include "MetaCoreRender/MetaCoreDebugGeometry.h"
|
|
||||||
|
|
||||||
#include <glm/vec3.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace MetaCore {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
MetaCoreVertex MetaCoreMakeVertex(const glm::vec3& position, const glm::vec3& normal, const glm::vec4& color) {
|
|
||||||
return MetaCoreVertex{position, normal, color};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
bool MetaCoreDebugGeometry::Initialize() {
|
|
||||||
std::vector<MetaCoreVertex> gridVertices;
|
|
||||||
std::vector<std::uint32_t> gridIndices;
|
|
||||||
std::uint32_t gridIndex = 0;
|
|
||||||
|
|
||||||
constexpr int gridHalfExtent = 10;
|
|
||||||
for (int step = -gridHalfExtent; step <= gridHalfExtent; ++step) {
|
|
||||||
const bool isCenterLine = step == 0;
|
|
||||||
const glm::vec4 lineColor = isCenterLine
|
|
||||||
? glm::vec4(0.34F, 0.38F, 0.42F, 1.0F)
|
|
||||||
: glm::vec4(0.22F, 0.24F, 0.28F, 1.0F);
|
|
||||||
|
|
||||||
gridVertices.push_back(MetaCoreMakeVertex(glm::vec3(static_cast<float>(step), 0.0F, -static_cast<float>(gridHalfExtent)), glm::vec3(0.0F), lineColor));
|
|
||||||
gridVertices.push_back(MetaCoreMakeVertex(glm::vec3(static_cast<float>(step), 0.0F, static_cast<float>(gridHalfExtent)), glm::vec3(0.0F), lineColor));
|
|
||||||
gridIndices.push_back(gridIndex++);
|
|
||||||
gridIndices.push_back(gridIndex++);
|
|
||||||
|
|
||||||
gridVertices.push_back(MetaCoreMakeVertex(glm::vec3(-static_cast<float>(gridHalfExtent), 0.0F, static_cast<float>(step)), glm::vec3(0.0F), lineColor));
|
|
||||||
gridVertices.push_back(MetaCoreMakeVertex(glm::vec3(static_cast<float>(gridHalfExtent), 0.0F, static_cast<float>(step)), glm::vec3(0.0F), lineColor));
|
|
||||||
gridIndices.push_back(gridIndex++);
|
|
||||||
gridIndices.push_back(gridIndex++);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<MetaCoreVertex> axesVertices{
|
|
||||||
MetaCoreMakeVertex(glm::vec3(0.0F), glm::vec3(0.0F), glm::vec4(0.95F, 0.28F, 0.24F, 1.0F)),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(1.5F, 0.0F, 0.0F), glm::vec3(0.0F), glm::vec4(0.95F, 0.28F, 0.24F, 1.0F)),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(0.0F), glm::vec3(0.0F), glm::vec4(0.30F, 0.78F, 0.32F, 1.0F)),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(0.0F, 1.5F, 0.0F), glm::vec3(0.0F), glm::vec4(0.30F, 0.78F, 0.32F, 1.0F)),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(0.0F), glm::vec3(0.0F), glm::vec4(0.28F, 0.53F, 0.95F, 1.0F)),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(0.0F, 0.0F, 1.5F), glm::vec3(0.0F), glm::vec4(0.28F, 0.53F, 0.95F, 1.0F))
|
|
||||||
};
|
|
||||||
std::vector<std::uint32_t> axesIndices{0, 1, 2, 3, 4, 5};
|
|
||||||
|
|
||||||
const glm::vec4 cubeColor(1.0F, 1.0F, 1.0F, 1.0F);
|
|
||||||
std::vector<MetaCoreVertex> cubeVertices{
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, -0.5F, 0.5F), glm::vec3(0.0F, 0.0F, 1.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, -0.5F, 0.5F), glm::vec3(0.0F, 0.0F, 1.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, 0.5F, 0.5F), glm::vec3(0.0F, 0.0F, 1.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, 0.5F, 0.5F), glm::vec3(0.0F, 0.0F, 1.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, -0.5F, -0.5F), glm::vec3(0.0F, 0.0F, -1.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, -0.5F, -0.5F), glm::vec3(0.0F, 0.0F, -1.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, 0.5F, -0.5F), glm::vec3(0.0F, 0.0F, -1.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, 0.5F, -0.5F), glm::vec3(0.0F, 0.0F, -1.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, 0.5F, 0.5F), glm::vec3(-1.0F, 0.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, 0.5F, -0.5F), glm::vec3(-1.0F, 0.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, -0.5F, -0.5F), glm::vec3(-1.0F, 0.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, -0.5F, 0.5F), glm::vec3(-1.0F, 0.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, 0.5F, 0.5F), glm::vec3(1.0F, 0.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, 0.5F, -0.5F), glm::vec3(1.0F, 0.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, -0.5F, -0.5F), glm::vec3(1.0F, 0.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, -0.5F, 0.5F), glm::vec3(1.0F, 0.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, 0.5F, -0.5F), glm::vec3(0.0F, 1.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, 0.5F, -0.5F), glm::vec3(0.0F, 1.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, 0.5F, 0.5F), glm::vec3(0.0F, 1.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, 0.5F, 0.5F), glm::vec3(0.0F, 1.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, -0.5F, -0.5F), glm::vec3(0.0F, -1.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, -0.5F, -0.5F), glm::vec3(0.0F, -1.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3( 0.5F, -0.5F, 0.5F), glm::vec3(0.0F, -1.0F, 0.0F), cubeColor),
|
|
||||||
MetaCoreMakeVertex(glm::vec3(-0.5F, -0.5F, 0.5F), glm::vec3(0.0F, -1.0F, 0.0F), cubeColor)
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<std::uint32_t> cubeIndices{
|
|
||||||
0, 1, 2, 0, 2, 3,
|
|
||||||
4, 6, 5, 4, 7, 6,
|
|
||||||
8, 9, 10, 8, 10, 11,
|
|
||||||
12, 14, 13, 12, 15, 14,
|
|
||||||
16, 17, 18, 16, 18, 19,
|
|
||||||
20, 22, 21, 20, 23, 22
|
|
||||||
};
|
|
||||||
|
|
||||||
return GridMesh_.Build(gridVertices, gridIndices, MetaCorePrimitiveType::Lines)
|
|
||||||
&& AxesMesh_.Build(axesVertices, axesIndices, MetaCorePrimitiveType::Lines)
|
|
||||||
&& CubeMesh_.Build(cubeVertices, cubeIndices, MetaCorePrimitiveType::Triangles);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreDebugGeometry::Shutdown() {
|
|
||||||
GridMesh_.Shutdown();
|
|
||||||
AxesMesh_.Shutdown();
|
|
||||||
CubeMesh_.Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
const MetaCoreMesh& MetaCoreDebugGeometry::GetGridMesh() const {
|
|
||||||
return GridMesh_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MetaCoreMesh& MetaCoreDebugGeometry::GetAxesMesh() const {
|
|
||||||
return AxesMesh_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MetaCoreMesh& MetaCoreDebugGeometry::GetCubeMesh() const {
|
|
||||||
return CubeMesh_;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace MetaCore
|
|
||||||
@ -1,116 +1,43 @@
|
|||||||
#include "MetaCoreRender/MetaCoreEditorViewportRenderer.h"
|
#include "MetaCoreRender/MetaCoreEditorViewportRenderer.h"
|
||||||
|
|
||||||
#include "MetaCoreRender/MetaCoreSceneRenderer.h"
|
#include "MetaCoreRender/MetaCoreRenderDevice.h"
|
||||||
#include "MetaCoreScene/MetaCoreScene.h"
|
#include "MetaCoreScene/MetaCoreScene.h"
|
||||||
|
|
||||||
#include <glad/glad.h>
|
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
bool MetaCoreEditorViewportRenderer::Initialize() {
|
bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevice) {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
|
||||||
SceneRenderer_ = new MetaCoreSceneRenderer();
|
if (!SceneBridge_.Initialize(renderDevice)) {
|
||||||
if (!SceneRenderer_->Initialize()) {
|
|
||||||
Shutdown();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RebuildFramebuffer();
|
RenderDevice_ = &renderDevice;
|
||||||
return FramebufferHandle_ != 0;
|
ViewportRect_ = MetaCoreViewportRect{};
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaCoreEditorViewportRenderer::Shutdown() {
|
void MetaCoreEditorViewportRenderer::Shutdown() {
|
||||||
DestroyFramebuffer();
|
SceneBridge_.Shutdown();
|
||||||
|
RenderDevice_ = nullptr;
|
||||||
if (SceneRenderer_ != nullptr) {
|
ViewportRect_ = MetaCoreViewportRect{};
|
||||||
SceneRenderer_->Shutdown();
|
|
||||||
delete SceneRenderer_;
|
|
||||||
SceneRenderer_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaCoreEditorViewportRenderer::Resize(int width, int height) {
|
void MetaCoreEditorViewportRenderer::SetViewportRect(const MetaCoreViewportRect& viewportRect) {
|
||||||
width = (width > 1) ? width : 1;
|
ViewportRect_ = viewportRect;
|
||||||
height = (height > 1) ? height : 1;
|
if (RenderDevice_ != nullptr) {
|
||||||
|
RenderDevice_->SetSceneViewportRect(ViewportRect_);
|
||||||
if (width == Width_ && height == Height_) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Width_ = width;
|
|
||||||
Height_ = height;
|
|
||||||
RebuildFramebuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaCoreEditorViewportRenderer::RenderSceneToViewport(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView) {
|
void MetaCoreEditorViewportRenderer::RenderSceneToViewport(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView) {
|
||||||
if (FramebufferHandle_ == 0 || SceneRenderer_ == nullptr) {
|
if (RenderDevice_ == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferHandle_);
|
RenderDevice_->SetSceneViewportRect(ViewportRect_);
|
||||||
glViewport(0, 0, Width_, Height_);
|
SceneBridge_.ApplySceneView(sceneView);
|
||||||
glEnable(GL_DEPTH_TEST);
|
SceneBridge_.SyncScene(scene);
|
||||||
glClearColor(0.09F, 0.10F, 0.12F, 1.0F);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
SceneRenderer_->RenderScene(scene, sceneView);
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MetaCoreEditorViewportRenderer::GetColorTextureHandle() const {
|
|
||||||
return ColorTextureHandle_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MetaCoreEditorViewportRenderer::GetWidth() const {
|
|
||||||
return Width_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int MetaCoreEditorViewportRenderer::GetHeight() const {
|
|
||||||
return Height_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreEditorViewportRenderer::RebuildFramebuffer() {
|
|
||||||
DestroyFramebuffer();
|
|
||||||
|
|
||||||
glGenFramebuffers(1, &FramebufferHandle_);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferHandle_);
|
|
||||||
|
|
||||||
glGenTextures(1, &ColorTextureHandle_);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, ColorTextureHandle_);
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width_, Height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
|
||||||
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);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ColorTextureHandle_, 0);
|
|
||||||
|
|
||||||
glGenRenderbuffers(1, &DepthStencilHandle_);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, DepthStencilHandle_);
|
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, Width_, Height_);
|
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, DepthStencilHandle_);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreEditorViewportRenderer::DestroyFramebuffer() {
|
|
||||||
if (DepthStencilHandle_ != 0) {
|
|
||||||
glDeleteRenderbuffers(1, &DepthStencilHandle_);
|
|
||||||
DepthStencilHandle_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ColorTextureHandle_ != 0) {
|
|
||||||
glDeleteTextures(1, &ColorTextureHandle_);
|
|
||||||
ColorTextureHandle_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FramebufferHandle_ != 0) {
|
|
||||||
glDeleteFramebuffers(1, &FramebufferHandle_);
|
|
||||||
FramebufferHandle_ = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace MetaCore
|
} // namespace MetaCore
|
||||||
|
|||||||
@ -1,82 +0,0 @@
|
|||||||
#include "MetaCoreRender/MetaCoreMesh.h"
|
|
||||||
|
|
||||||
#include <glad/glad.h>
|
|
||||||
|
|
||||||
namespace MetaCore {
|
|
||||||
|
|
||||||
MetaCoreMesh::~MetaCoreMesh() {
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MetaCoreMesh::Build(const std::vector<MetaCoreVertex>& vertices, const std::vector<std::uint32_t>& indices, MetaCorePrimitiveType primitiveType) {
|
|
||||||
Shutdown();
|
|
||||||
|
|
||||||
PrimitiveType_ = primitiveType;
|
|
||||||
IndexCount_ = static_cast<std::uint32_t>(indices.size());
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &VertexArrayHandle_);
|
|
||||||
glGenBuffers(1, &VertexBufferHandle_);
|
|
||||||
glGenBuffers(1, &IndexBufferHandle_);
|
|
||||||
|
|
||||||
glBindVertexArray(VertexArrayHandle_);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferHandle_);
|
|
||||||
glBufferData(
|
|
||||||
GL_ARRAY_BUFFER,
|
|
||||||
static_cast<GLsizeiptr>(vertices.size() * sizeof(MetaCoreVertex)),
|
|
||||||
vertices.data(),
|
|
||||||
GL_STATIC_DRAW
|
|
||||||
);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferHandle_);
|
|
||||||
glBufferData(
|
|
||||||
GL_ELEMENT_ARRAY_BUFFER,
|
|
||||||
static_cast<GLsizeiptr>(indices.size() * sizeof(std::uint32_t)),
|
|
||||||
indices.data(),
|
|
||||||
GL_STATIC_DRAW
|
|
||||||
);
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(MetaCoreVertex), reinterpret_cast<const void*>(offsetof(MetaCoreVertex, Position)));
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MetaCoreVertex), reinterpret_cast<const void*>(offsetof(MetaCoreVertex, Normal)));
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(2);
|
|
||||||
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(MetaCoreVertex), reinterpret_cast<const void*>(offsetof(MetaCoreVertex, Color)));
|
|
||||||
|
|
||||||
glBindVertexArray(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreMesh::Shutdown() {
|
|
||||||
if (IndexBufferHandle_ != 0) {
|
|
||||||
glDeleteBuffers(1, &IndexBufferHandle_);
|
|
||||||
IndexBufferHandle_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VertexBufferHandle_ != 0) {
|
|
||||||
glDeleteBuffers(1, &VertexBufferHandle_);
|
|
||||||
VertexBufferHandle_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VertexArrayHandle_ != 0) {
|
|
||||||
glDeleteVertexArrays(1, &VertexArrayHandle_);
|
|
||||||
VertexArrayHandle_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
IndexCount_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreMesh::Draw() const {
|
|
||||||
glBindVertexArray(VertexArrayHandle_);
|
|
||||||
glDrawElements(
|
|
||||||
PrimitiveType_ == MetaCorePrimitiveType::Triangles ? GL_TRIANGLES : GL_LINES,
|
|
||||||
static_cast<GLsizei>(IndexCount_),
|
|
||||||
GL_UNSIGNED_INT,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace MetaCore
|
|
||||||
317
Source/MetaCoreRender/Private/MetaCorePandaSceneBridge.cpp
Normal file
317
Source/MetaCoreRender/Private/MetaCorePandaSceneBridge.cpp
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
#include "MetaCoreRender/MetaCorePandaSceneBridge.h"
|
||||||
|
|
||||||
|
#include "MetaCoreRender/MetaCoreRenderDevice.h"
|
||||||
|
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
||||||
|
#include "MetaCoreScene/MetaCoreComponents.h"
|
||||||
|
#include "MetaCoreScene/MetaCoreScene.h"
|
||||||
|
|
||||||
|
#include "ambientLight.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "directionalLight.h"
|
||||||
|
#include "lineSegs.h"
|
||||||
|
#include "loader.h"
|
||||||
|
#include "nodePath.h"
|
||||||
|
#include "perspectiveLens.h"
|
||||||
|
#include "pandaNode.h"
|
||||||
|
#include "windowFramework.h"
|
||||||
|
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
#include <glm/ext/matrix_transform.hpp>
|
||||||
|
#include <glm/gtx/euler_angles.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace MetaCore {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
glm::mat4 MetaCoreBuildBasisSwapMatrix() {
|
||||||
|
glm::mat4 basis(1.0F);
|
||||||
|
basis[0] = glm::vec4(1.0F, 0.0F, 0.0F, 0.0F);
|
||||||
|
basis[1] = glm::vec4(0.0F, 0.0F, 1.0F, 0.0F);
|
||||||
|
basis[2] = glm::vec4(0.0F, 1.0F, 0.0F, 0.0F);
|
||||||
|
basis[3] = glm::vec4(0.0F, 0.0F, 0.0F, 1.0F);
|
||||||
|
return basis;
|
||||||
|
}
|
||||||
|
|
||||||
|
LMatrix4f MetaCoreConvertTransformToPanda(const MetaCoreTransformComponent& transform) {
|
||||||
|
const glm::mat4 translation = glm::translate(glm::mat4(1.0F), transform.Position);
|
||||||
|
const glm::mat4 rotation = glm::yawPitchRoll(
|
||||||
|
glm::radians(transform.RotationEulerDegrees.y),
|
||||||
|
glm::radians(transform.RotationEulerDegrees.x),
|
||||||
|
glm::radians(transform.RotationEulerDegrees.z)
|
||||||
|
);
|
||||||
|
const glm::mat4 scale = glm::scale(glm::mat4(1.0F), transform.Scale);
|
||||||
|
|
||||||
|
const glm::mat4 metaCoreMatrix = translation * rotation * scale;
|
||||||
|
const glm::mat4 basis = MetaCoreBuildBasisSwapMatrix();
|
||||||
|
const glm::mat4 pandaMatrix = basis * metaCoreMatrix * basis;
|
||||||
|
|
||||||
|
LMatrix4f result;
|
||||||
|
for (int row = 0; row < 4; ++row) {
|
||||||
|
for (int column = 0; column < 4; ++column) {
|
||||||
|
result.set_cell(row, column, pandaMatrix[column][row]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPoint3f MetaCoreToPandaPoint(const glm::vec3& value) {
|
||||||
|
return LPoint3f(value.x, value.z, value.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
LVector3f MetaCoreToPandaVector(const glm::vec3& value) {
|
||||||
|
return LVector3f(value.x, value.z, value.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodePath MetaCoreCreateGridNode(const NodePath& parentNode) {
|
||||||
|
LineSegs gridBuilder("MetaCoreGrid");
|
||||||
|
gridBuilder.set_thickness(1.0F);
|
||||||
|
|
||||||
|
constexpr int gridHalfExtent = 10;
|
||||||
|
for (int lineIndex = -gridHalfExtent; lineIndex <= gridHalfExtent; ++lineIndex) {
|
||||||
|
const bool isAxisLine = (lineIndex == 0);
|
||||||
|
gridBuilder.set_color(isAxisLine ? 0.42F : 0.30F, isAxisLine ? 0.45F : 0.33F, isAxisLine ? 0.50F : 0.36F, 1.0F);
|
||||||
|
gridBuilder.move_to(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(lineIndex), 0.0F, static_cast<float>(-gridHalfExtent))));
|
||||||
|
gridBuilder.draw_to(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(lineIndex), 0.0F, static_cast<float>(gridHalfExtent))));
|
||||||
|
gridBuilder.move_to(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(-gridHalfExtent), 0.0F, static_cast<float>(lineIndex))));
|
||||||
|
gridBuilder.draw_to(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(gridHalfExtent), 0.0F, static_cast<float>(lineIndex))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return parentNode.attach_new_node(gridBuilder.create());
|
||||||
|
}
|
||||||
|
|
||||||
|
NodePath MetaCoreCreateAxisNode(const NodePath& parentNode) {
|
||||||
|
LineSegs axisBuilder("MetaCoreAxis");
|
||||||
|
axisBuilder.set_thickness(3.0F);
|
||||||
|
|
||||||
|
axisBuilder.set_color(0.92F, 0.26F, 0.26F, 1.0F);
|
||||||
|
axisBuilder.move_to(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
||||||
|
axisBuilder.draw_to(MetaCoreToPandaPoint(glm::vec3(2.0F, 0.0F, 0.0F)));
|
||||||
|
|
||||||
|
axisBuilder.set_color(0.28F, 0.86F, 0.36F, 1.0F);
|
||||||
|
axisBuilder.move_to(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
||||||
|
axisBuilder.draw_to(MetaCoreToPandaPoint(glm::vec3(0.0F, 2.0F, 0.0F)));
|
||||||
|
|
||||||
|
axisBuilder.set_color(0.32F, 0.56F, 0.96F, 1.0F);
|
||||||
|
axisBuilder.move_to(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
||||||
|
axisBuilder.draw_to(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 2.0F)));
|
||||||
|
|
||||||
|
return parentNode.attach_new_node(axisBuilder.create());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class MetaCorePandaSceneBridge::MetaCorePandaSceneBridgeImpl {
|
||||||
|
public:
|
||||||
|
struct MetaCorePandaObjectState {
|
||||||
|
NodePath RootNode{};
|
||||||
|
NodePath MeshNode{};
|
||||||
|
NodePath LightNode{};
|
||||||
|
};
|
||||||
|
|
||||||
|
MetaCoreRenderDevice* RenderDevice = nullptr;
|
||||||
|
NodePath GridNode{};
|
||||||
|
NodePath AxisNode{};
|
||||||
|
NodePath AmbientLightNode{};
|
||||||
|
MetaCoreId SelectedObjectId = 0;
|
||||||
|
std::unordered_map<MetaCoreId, MetaCorePandaObjectState> ObjectStates{};
|
||||||
|
};
|
||||||
|
|
||||||
|
MetaCorePandaSceneBridge::MetaCorePandaSceneBridge()
|
||||||
|
: Impl_(std::make_unique<MetaCorePandaSceneBridgeImpl>()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaCorePandaSceneBridge::~MetaCorePandaSceneBridge() {
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetaCorePandaSceneBridge::Initialize(MetaCoreRenderDevice& renderDevice) {
|
||||||
|
Shutdown();
|
||||||
|
|
||||||
|
auto* windowFrameworkHandle = static_cast<WindowFramework*>(renderDevice.GetNativeWindowFrameworkHandle());
|
||||||
|
auto* sceneRootHandle = static_cast<NodePath*>(renderDevice.GetNativeSceneRootHandle());
|
||||||
|
if (windowFrameworkHandle == nullptr || sceneRootHandle == nullptr || sceneRootHandle->is_empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->RenderDevice = &renderDevice;
|
||||||
|
Impl_->GridNode = MetaCoreCreateGridNode(*sceneRootHandle);
|
||||||
|
Impl_->AxisNode = MetaCoreCreateAxisNode(*sceneRootHandle);
|
||||||
|
Impl_->GridNode.set_light_off(1);
|
||||||
|
Impl_->AxisNode.set_light_off(1);
|
||||||
|
|
||||||
|
PT(AmbientLight) ambientLight = new AmbientLight("MetaCoreAmbientLight");
|
||||||
|
ambientLight->set_color(LColor(0.85F, 0.85F, 0.85F, 1.0F));
|
||||||
|
Impl_->AmbientLightNode = sceneRootHandle->attach_new_node(ambientLight);
|
||||||
|
sceneRootHandle->set_light(Impl_->AmbientLightNode);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaCorePandaSceneBridge::Shutdown() {
|
||||||
|
if (Impl_ == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& [objectId, objectState] : Impl_->ObjectStates) {
|
||||||
|
(void)objectId;
|
||||||
|
if (!objectState.RootNode.is_empty()) {
|
||||||
|
objectState.RootNode.remove_node();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Impl_->ObjectStates.clear();
|
||||||
|
|
||||||
|
if (!Impl_->AmbientLightNode.is_empty()) {
|
||||||
|
Impl_->AmbientLightNode.remove_node();
|
||||||
|
Impl_->AmbientLightNode = NodePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Impl_->AxisNode.is_empty()) {
|
||||||
|
Impl_->AxisNode.remove_node();
|
||||||
|
Impl_->AxisNode = NodePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Impl_->GridNode.is_empty()) {
|
||||||
|
Impl_->GridNode.remove_node();
|
||||||
|
Impl_->GridNode = NodePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->RenderDevice = nullptr;
|
||||||
|
Impl_->SelectedObjectId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaCorePandaSceneBridge::SyncScene(const MetaCoreScene& scene) {
|
||||||
|
if (Impl_->RenderDevice == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* windowFrameworkHandle = static_cast<WindowFramework*>(Impl_->RenderDevice->GetNativeWindowFrameworkHandle());
|
||||||
|
auto* sceneRootHandle = static_cast<NodePath*>(Impl_->RenderDevice->GetNativeSceneRootHandle());
|
||||||
|
if (windowFrameworkHandle == nullptr || sceneRootHandle == nullptr || sceneRootHandle->is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<MetaCoreId> aliveObjectIds;
|
||||||
|
|
||||||
|
for (const MetaCoreGameObject& gameObject : scene.GetGameObjects()) {
|
||||||
|
aliveObjectIds.insert(gameObject.Id);
|
||||||
|
auto [iterator, inserted] = Impl_->ObjectStates.try_emplace(gameObject.Id);
|
||||||
|
MetaCorePandaSceneBridgeImpl::MetaCorePandaObjectState& objectState = iterator->second;
|
||||||
|
|
||||||
|
if (inserted || objectState.RootNode.is_empty()) {
|
||||||
|
PT(PandaNode) rootNode = new PandaNode(gameObject.Name);
|
||||||
|
objectState.RootNode = sceneRootHandle->attach_new_node(rootNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
objectState.RootNode.set_name(gameObject.Name);
|
||||||
|
objectState.RootNode.set_mat(MetaCoreConvertTransformToPanda(gameObject.Transform));
|
||||||
|
|
||||||
|
if (gameObject.ParentId != 0) {
|
||||||
|
const auto parentIterator = Impl_->ObjectStates.find(gameObject.ParentId);
|
||||||
|
if (parentIterator != Impl_->ObjectStates.end() && !parentIterator->second.RootNode.is_empty()) {
|
||||||
|
objectState.RootNode.reparent_to(parentIterator->second.RootNode);
|
||||||
|
} else {
|
||||||
|
objectState.RootNode.reparent_to(*sceneRootHandle);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
objectState.RootNode.reparent_to(*sceneRootHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gameObject.MeshRenderer.has_value()) {
|
||||||
|
if (objectState.MeshNode.is_empty()) {
|
||||||
|
objectState.MeshNode = windowFrameworkHandle->load_model(objectState.RootNode, Filename("models/box"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!objectState.MeshNode.is_empty()) {
|
||||||
|
objectState.MeshNode.set_texture_off(1);
|
||||||
|
objectState.MeshNode.set_material_off(1);
|
||||||
|
objectState.MeshNode.set_shader_off(1);
|
||||||
|
objectState.MeshNode.set_light_off(1);
|
||||||
|
objectState.MeshNode.set_two_sided(true);
|
||||||
|
objectState.MeshNode.set_color(
|
||||||
|
gameObject.MeshRenderer->BaseColor.r,
|
||||||
|
gameObject.MeshRenderer->BaseColor.g,
|
||||||
|
gameObject.MeshRenderer->BaseColor.b,
|
||||||
|
1.0F
|
||||||
|
);
|
||||||
|
|
||||||
|
if (gameObject.MeshRenderer->Visible) {
|
||||||
|
objectState.MeshNode.show();
|
||||||
|
} else {
|
||||||
|
objectState.MeshNode.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gameObject.Id == Impl_->SelectedObjectId) {
|
||||||
|
objectState.MeshNode.set_color_scale(1.18F, 1.02F, 0.72F, 1.0F);
|
||||||
|
} else {
|
||||||
|
objectState.MeshNode.clear_color_scale();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!objectState.MeshNode.is_empty()) {
|
||||||
|
objectState.MeshNode.remove_node();
|
||||||
|
objectState.MeshNode = NodePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gameObject.Light.has_value()) {
|
||||||
|
if (objectState.LightNode.is_empty()) {
|
||||||
|
PT(DirectionalLight) directionalLight = new DirectionalLight(gameObject.Name);
|
||||||
|
objectState.LightNode = objectState.RootNode.attach_new_node(directionalLight);
|
||||||
|
sceneRootHandle->set_light(objectState.LightNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* directionalLight = DCAST(DirectionalLight, objectState.LightNode.node());
|
||||||
|
if (directionalLight != nullptr) {
|
||||||
|
directionalLight->set_color(LColor(
|
||||||
|
gameObject.Light->Color.r * gameObject.Light->Intensity,
|
||||||
|
gameObject.Light->Color.g * gameObject.Light->Intensity,
|
||||||
|
gameObject.Light->Color.b * gameObject.Light->Intensity,
|
||||||
|
1.0F
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else if (!objectState.LightNode.is_empty()) {
|
||||||
|
sceneRootHandle->clear_light(objectState.LightNode);
|
||||||
|
objectState.LightNode.remove_node();
|
||||||
|
objectState.LightNode = NodePath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto iterator = Impl_->ObjectStates.begin(); iterator != Impl_->ObjectStates.end();) {
|
||||||
|
if (!aliveObjectIds.contains(iterator->first)) {
|
||||||
|
if (!iterator->second.RootNode.is_empty()) {
|
||||||
|
iterator->second.RootNode.remove_node();
|
||||||
|
}
|
||||||
|
iterator = Impl_->ObjectStates.erase(iterator);
|
||||||
|
} else {
|
||||||
|
++iterator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaCorePandaSceneBridge::ApplySceneView(const MetaCoreSceneView& sceneView) {
|
||||||
|
if (Impl_->RenderDevice == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* editorCameraHandle = static_cast<NodePath*>(Impl_->RenderDevice->GetNativeEditorCameraHandle());
|
||||||
|
if (editorCameraHandle == nullptr || editorCameraHandle->is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->SelectedObjectId = sceneView.SelectedObjectId;
|
||||||
|
|
||||||
|
editorCameraHandle->set_pos(MetaCoreToPandaPoint(sceneView.CameraPosition));
|
||||||
|
editorCameraHandle->look_at(MetaCoreToPandaPoint(sceneView.CameraTarget), MetaCoreToPandaVector(sceneView.CameraUp));
|
||||||
|
|
||||||
|
auto* cameraNode = DCAST(Camera, editorCameraHandle->node());
|
||||||
|
if (cameraNode != nullptr) {
|
||||||
|
auto* perspectiveLens = DCAST(PerspectiveLens, cameraNode->get_lens());
|
||||||
|
if (perspectiveLens != nullptr) {
|
||||||
|
perspectiveLens->set_fov(sceneView.VerticalFieldOfViewDegrees);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace MetaCore
|
||||||
@ -1,45 +1,170 @@
|
|||||||
#include "MetaCoreRender/MetaCoreRenderDevice.h"
|
#include "MetaCoreRender/MetaCoreRenderDevice.h"
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include "MetaCorePlatform/MetaCoreWindow.h"
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
#include "camera.h"
|
||||||
|
#include "displayRegion.h"
|
||||||
|
#include "graphicsEngine.h"
|
||||||
|
#include "graphicsWindow.h"
|
||||||
|
#include "pandaFramework.h"
|
||||||
|
#include "pandaNode.h"
|
||||||
|
#include "perspectiveLens.h"
|
||||||
|
#include "windowFramework.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
bool MetaCoreRenderDevice::Initialize(GLFWwindow* nativeWindow) {
|
class MetaCoreRenderDevice::MetaCoreRenderDeviceImpl {
|
||||||
if (Initialized_) {
|
public:
|
||||||
|
MetaCoreWindow* Window = nullptr;
|
||||||
|
PandaFramework* Framework = nullptr;
|
||||||
|
WindowFramework* WindowFrameworkHandle = nullptr;
|
||||||
|
GraphicsWindow* GraphicsWindowHandle = nullptr;
|
||||||
|
GraphicsEngine* GraphicsEngineHandle = nullptr;
|
||||||
|
DisplayRegion* SceneDisplayRegion = nullptr;
|
||||||
|
NodePath SceneRoot{};
|
||||||
|
NodePath EditorCamera{};
|
||||||
|
bool Initialized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
MetaCoreRenderDevice::MetaCoreRenderDevice()
|
||||||
|
: Impl_(std::make_unique<MetaCoreRenderDeviceImpl>()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaCoreRenderDevice::~MetaCoreRenderDevice() {
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetaCoreRenderDevice::Initialize(MetaCoreWindow& window) {
|
||||||
|
if (Impl_->Initialized) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress)) == 0) {
|
auto* frameworkHandle = static_cast<PandaFramework*>(window.GetNativeFrameworkHandle());
|
||||||
|
auto* windowFrameworkHandle = static_cast<WindowFramework*>(window.GetNativeWindowFrameworkHandle());
|
||||||
|
auto* graphicsWindowHandle = static_cast<GraphicsWindow*>(window.GetNativeGraphicsWindowHandle());
|
||||||
|
if (frameworkHandle == nullptr || windowFrameworkHandle == nullptr || graphicsWindowHandle == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
Impl_->Window = &window;
|
||||||
glEnable(GL_CULL_FACE);
|
Impl_->Framework = frameworkHandle;
|
||||||
glCullFace(GL_BACK);
|
Impl_->WindowFrameworkHandle = windowFrameworkHandle;
|
||||||
glFrontFace(GL_CCW);
|
Impl_->GraphicsWindowHandle = graphicsWindowHandle;
|
||||||
glDisable(GL_BLEND);
|
Impl_->GraphicsEngineHandle = frameworkHandle->get_graphics_engine();
|
||||||
Initialized_ = nativeWindow != nullptr;
|
if (Impl_->GraphicsEngineHandle == nullptr) {
|
||||||
return Initialized_;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->GraphicsEngineHandle->set_auto_flip(false);
|
||||||
|
Impl_->GraphicsEngineHandle->open_windows();
|
||||||
|
|
||||||
|
if (Impl_->WindowFrameworkHandle->get_display_region_2d() != nullptr) {
|
||||||
|
Impl_->WindowFrameworkHandle->get_display_region_2d()->set_active(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->SceneDisplayRegion = Impl_->WindowFrameworkHandle->get_display_region_3d();
|
||||||
|
if (Impl_->SceneDisplayRegion == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->GraphicsWindowHandle->set_clear_color_active(true);
|
||||||
|
Impl_->GraphicsWindowHandle->set_clear_color(LColor(0.38F, 0.48F, 0.62F, 1.0F));
|
||||||
|
|
||||||
|
PT(PandaNode) sceneRootNode = new PandaNode("MetaCoreSceneRoot");
|
||||||
|
Impl_->SceneRoot = Impl_->WindowFrameworkHandle->get_render().attach_new_node(sceneRootNode);
|
||||||
|
Impl_->SceneRoot.set_shader_auto();
|
||||||
|
|
||||||
|
Impl_->EditorCamera = Impl_->WindowFrameworkHandle->make_camera();
|
||||||
|
Impl_->SceneDisplayRegion->set_camera(Impl_->EditorCamera);
|
||||||
|
Impl_->SceneDisplayRegion->set_sort(0);
|
||||||
|
Impl_->SceneDisplayRegion->set_scissor_enabled(true);
|
||||||
|
Impl_->SceneDisplayRegion->set_clear_color_active(false);
|
||||||
|
|
||||||
|
if (auto* cameraNode = DCAST(Camera, Impl_->EditorCamera.node()); cameraNode != nullptr) {
|
||||||
|
PT(PerspectiveLens) lens = new PerspectiveLens();
|
||||||
|
lens->set_fov(60.0F);
|
||||||
|
lens->set_near_far(0.05F, 500.0F);
|
||||||
|
cameraNode->set_lens(lens);
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->Initialized = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaCoreRenderDevice::Shutdown() {
|
void MetaCoreRenderDevice::Shutdown() {
|
||||||
Initialized_ = false;
|
if (!Impl_->Initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Impl_->EditorCamera.is_empty()) {
|
||||||
|
Impl_->EditorCamera.remove_node();
|
||||||
|
Impl_->EditorCamera = NodePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Impl_->SceneRoot.is_empty()) {
|
||||||
|
Impl_->SceneRoot.remove_node();
|
||||||
|
Impl_->SceneRoot = NodePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
Impl_->SceneDisplayRegion = nullptr;
|
||||||
|
Impl_->GraphicsEngineHandle = nullptr;
|
||||||
|
Impl_->GraphicsWindowHandle = nullptr;
|
||||||
|
Impl_->WindowFrameworkHandle = nullptr;
|
||||||
|
Impl_->Framework = nullptr;
|
||||||
|
Impl_->Window = nullptr;
|
||||||
|
Impl_->Initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaCoreRenderDevice::BeginFrame(int width, int height, const glm::vec4& clearColor) const {
|
void MetaCoreRenderDevice::RenderFrame() const {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
if (Impl_->GraphicsEngineHandle != nullptr) {
|
||||||
glViewport(0, 0, width, height);
|
Impl_->GraphicsEngineHandle->render_frame();
|
||||||
Clear(clearColor);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetaCoreRenderDevice::Clear(const glm::vec4& clearColor) const {
|
void MetaCoreRenderDevice::PresentFrame() const {
|
||||||
glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
|
if (Impl_->GraphicsEngineHandle != nullptr) {
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
Impl_->GraphicsEngineHandle->flip_frame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MetaCoreRenderDevice::IsInitialized() const {
|
void MetaCoreRenderDevice::SetSceneViewportRect(const MetaCoreViewportRect& viewportRect) {
|
||||||
return Initialized_;
|
if (Impl_->SceneDisplayRegion == nullptr || Impl_->Window == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto [framebufferWidth, framebufferHeight] = Impl_->Window->GetFramebufferSize();
|
||||||
|
if (framebufferWidth <= 0 || framebufferHeight <= 0 || viewportRect.Width <= 1.0F || viewportRect.Height <= 1.0F) {
|
||||||
|
Impl_->SceneDisplayRegion->set_active(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float clampedLeft = std::clamp(viewportRect.Left / static_cast<float>(framebufferWidth), 0.0F, 1.0F);
|
||||||
|
const float clampedRight = std::clamp((viewportRect.Left + viewportRect.Width) / static_cast<float>(framebufferWidth), 0.0F, 1.0F);
|
||||||
|
const float clampedTop = std::clamp(viewportRect.Top / static_cast<float>(framebufferHeight), 0.0F, 1.0F);
|
||||||
|
const float clampedBottom = std::clamp((viewportRect.Top + viewportRect.Height) / static_cast<float>(framebufferHeight), 0.0F, 1.0F);
|
||||||
|
|
||||||
|
Impl_->SceneDisplayRegion->set_active(true);
|
||||||
|
Impl_->SceneDisplayRegion->set_dimensions(
|
||||||
|
clampedLeft,
|
||||||
|
clampedRight,
|
||||||
|
1.0F - clampedBottom,
|
||||||
|
1.0F - clampedTop
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MetaCoreRenderDevice::GetNativeWindowFrameworkHandle() const {
|
||||||
|
return Impl_->WindowFrameworkHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MetaCoreRenderDevice::GetNativeSceneRootHandle() const {
|
||||||
|
return Impl_->SceneRoot.is_empty() ? nullptr : static_cast<void*>(&Impl_->SceneRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MetaCoreRenderDevice::GetNativeEditorCameraHandle() const {
|
||||||
|
return Impl_->EditorCamera.is_empty() ? nullptr : static_cast<void*>(&Impl_->EditorCamera);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace MetaCore
|
} // namespace MetaCore
|
||||||
|
|||||||
@ -1,209 +0,0 @@
|
|||||||
#include "MetaCoreRender/MetaCoreSceneRenderer.h"
|
|
||||||
|
|
||||||
#include "MetaCoreRender/MetaCoreDebugGeometry.h"
|
|
||||||
#include "MetaCoreRender/MetaCoreShaderProgram.h"
|
|
||||||
#include "MetaCoreScene/MetaCoreScene.h"
|
|
||||||
|
|
||||||
#include <glm/ext/matrix_transform.hpp>
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace MetaCore {
|
|
||||||
|
|
||||||
class MetaCoreSceneRenderer::MetaCoreSceneRendererImpl {
|
|
||||||
public:
|
|
||||||
MetaCoreDebugGeometry DebugGeometry{};
|
|
||||||
MetaCoreShaderProgram LineShader{};
|
|
||||||
MetaCoreShaderProgram LitShader{};
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
glm::mat4 MetaCoreBuildTransformMatrix(const MetaCoreTransformComponent& transform) {
|
|
||||||
glm::mat4 model(1.0F);
|
|
||||||
model = glm::translate(model, transform.Position);
|
|
||||||
model = glm::rotate(model, glm::radians(transform.RotationEulerDegrees.x), glm::vec3(1.0F, 0.0F, 0.0F));
|
|
||||||
model = glm::rotate(model, glm::radians(transform.RotationEulerDegrees.y), glm::vec3(0.0F, 1.0F, 0.0F));
|
|
||||||
model = glm::rotate(model, glm::radians(transform.RotationEulerDegrees.z), glm::vec3(0.0F, 0.0F, 1.0F));
|
|
||||||
model = glm::scale(model, transform.Scale);
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 MetaCoreResolveLightDirection(const MetaCoreScene& scene) {
|
|
||||||
for (const MetaCoreGameObject& object : scene.GetGameObjects()) {
|
|
||||||
if (object.Light.has_value()) {
|
|
||||||
glm::mat4 rotation(1.0F);
|
|
||||||
rotation = glm::rotate(rotation, glm::radians(object.Transform.RotationEulerDegrees.x), glm::vec3(1.0F, 0.0F, 0.0F));
|
|
||||||
rotation = glm::rotate(rotation, glm::radians(object.Transform.RotationEulerDegrees.y), glm::vec3(0.0F, 1.0F, 0.0F));
|
|
||||||
rotation = glm::rotate(rotation, glm::radians(object.Transform.RotationEulerDegrees.z), glm::vec3(0.0F, 0.0F, 1.0F));
|
|
||||||
return glm::normalize(glm::vec3(rotation * glm::vec4(0.15F, -1.0F, -0.35F, 0.0F)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return glm::normalize(glm::vec3(0.15F, -1.0F, -0.35F));
|
|
||||||
}
|
|
||||||
|
|
||||||
float MetaCoreResolveLightIntensity(const MetaCoreScene& scene) {
|
|
||||||
for (const MetaCoreGameObject& object : scene.GetGameObjects()) {
|
|
||||||
if (object.Light.has_value()) {
|
|
||||||
return object.Light->Intensity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1.5F;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 MetaCoreResolveLightColor(const MetaCoreScene& scene) {
|
|
||||||
for (const MetaCoreGameObject& object : scene.GetGameObjects()) {
|
|
||||||
if (object.Light.has_value()) {
|
|
||||||
return object.Light->Color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return glm::vec3(1.0F, 1.0F, 1.0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
bool MetaCoreSceneRenderer::Initialize() {
|
|
||||||
Shutdown();
|
|
||||||
|
|
||||||
Impl_ = new MetaCoreSceneRendererImpl();
|
|
||||||
if (!Impl_->DebugGeometry.Initialize()) {
|
|
||||||
Shutdown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string errorMessage;
|
|
||||||
|
|
||||||
const std::string lineVertexShader = R"(
|
|
||||||
#version 330 core
|
|
||||||
layout (location = 0) in vec3 aPosition;
|
|
||||||
layout (location = 2) in vec4 aColor;
|
|
||||||
|
|
||||||
uniform mat4 uView;
|
|
||||||
uniform mat4 uProjection;
|
|
||||||
uniform mat4 uModel;
|
|
||||||
|
|
||||||
out vec4 vColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vColor = aColor;
|
|
||||||
gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
const std::string lineFragmentShader = R"(
|
|
||||||
#version 330 core
|
|
||||||
in vec4 vColor;
|
|
||||||
out vec4 FragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
FragColor = vColor;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
const std::string litVertexShader = R"(
|
|
||||||
#version 330 core
|
|
||||||
layout (location = 0) in vec3 aPosition;
|
|
||||||
layout (location = 1) in vec3 aNormal;
|
|
||||||
|
|
||||||
uniform mat4 uView;
|
|
||||||
uniform mat4 uProjection;
|
|
||||||
uniform mat4 uModel;
|
|
||||||
|
|
||||||
out vec3 vWorldPosition;
|
|
||||||
out vec3 vWorldNormal;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 worldPosition = uModel * vec4(aPosition, 1.0);
|
|
||||||
vWorldPosition = worldPosition.xyz;
|
|
||||||
vWorldNormal = normalize(mat3(transpose(inverse(uModel))) * aNormal);
|
|
||||||
gl_Position = uProjection * uView * worldPosition;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
const std::string litFragmentShader = R"(
|
|
||||||
#version 330 core
|
|
||||||
in vec3 vWorldPosition;
|
|
||||||
in vec3 vWorldNormal;
|
|
||||||
|
|
||||||
uniform vec3 uBaseColor;
|
|
||||||
uniform vec3 uLightDirection;
|
|
||||||
uniform vec3 uLightColor;
|
|
||||||
uniform float uLightIntensity;
|
|
||||||
|
|
||||||
out vec4 FragColor;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec3 normal = normalize(vWorldNormal);
|
|
||||||
vec3 lightDirection = normalize(-uLightDirection);
|
|
||||||
float diffuse = max(dot(normal, lightDirection), 0.0);
|
|
||||||
vec3 ambient = uBaseColor * 0.28;
|
|
||||||
vec3 lighting = ambient + (uBaseColor * uLightColor * diffuse * uLightIntensity);
|
|
||||||
FragColor = vec4(lighting, 1.0);
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
if (!Impl_->LineShader.BuildFromSource(lineVertexShader, lineFragmentShader, errorMessage)) {
|
|
||||||
Shutdown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Impl_->LitShader.BuildFromSource(litVertexShader, litFragmentShader, errorMessage)) {
|
|
||||||
Shutdown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreSceneRenderer::Shutdown() {
|
|
||||||
if (Impl_ != nullptr) {
|
|
||||||
Impl_->DebugGeometry.Shutdown();
|
|
||||||
Impl_->LineShader.Shutdown();
|
|
||||||
Impl_->LitShader.Shutdown();
|
|
||||||
delete Impl_;
|
|
||||||
Impl_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreSceneRenderer::RenderScene(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView) const {
|
|
||||||
if (Impl_ == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Impl_->LineShader.Bind();
|
|
||||||
Impl_->LineShader.SetMatrix4("uView", sceneView.ViewMatrix);
|
|
||||||
Impl_->LineShader.SetMatrix4("uProjection", sceneView.ProjectionMatrix);
|
|
||||||
Impl_->LineShader.SetMatrix4("uModel", glm::mat4(1.0F));
|
|
||||||
Impl_->DebugGeometry.GetGridMesh().Draw();
|
|
||||||
Impl_->DebugGeometry.GetAxesMesh().Draw();
|
|
||||||
|
|
||||||
const glm::vec3 lightDirection = MetaCoreResolveLightDirection(scene);
|
|
||||||
const glm::vec3 lightColor = MetaCoreResolveLightColor(scene);
|
|
||||||
const float lightIntensity = MetaCoreResolveLightIntensity(scene);
|
|
||||||
|
|
||||||
Impl_->LitShader.Bind();
|
|
||||||
Impl_->LitShader.SetMatrix4("uView", sceneView.ViewMatrix);
|
|
||||||
Impl_->LitShader.SetMatrix4("uProjection", sceneView.ProjectionMatrix);
|
|
||||||
Impl_->LitShader.SetVector3("uLightDirection", lightDirection);
|
|
||||||
Impl_->LitShader.SetVector3("uLightColor", lightColor);
|
|
||||||
Impl_->LitShader.SetFloat("uLightIntensity", lightIntensity);
|
|
||||||
|
|
||||||
for (const MetaCoreGameObject& object : scene.GetGameObjects()) {
|
|
||||||
if (!object.MeshRenderer.has_value() || !object.MeshRenderer->Visible) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 baseColor = object.MeshRenderer->BaseColor;
|
|
||||||
if (object.Id == sceneView.SelectedObjectId) {
|
|
||||||
baseColor = glm::mix(baseColor, glm::vec3(1.0F, 0.62F, 0.18F), 0.55F);
|
|
||||||
}
|
|
||||||
|
|
||||||
Impl_->LitShader.SetMatrix4("uModel", MetaCoreBuildTransformMatrix(object.Transform));
|
|
||||||
Impl_->LitShader.SetVector3("uBaseColor", baseColor);
|
|
||||||
Impl_->DebugGeometry.GetCubeMesh().Draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace MetaCore
|
|
||||||
@ -1,110 +0,0 @@
|
|||||||
#include "MetaCoreRender/MetaCoreShaderProgram.h"
|
|
||||||
|
|
||||||
#include <glad/glad.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace MetaCore {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
bool MetaCoreCompileShader(unsigned int shaderHandle, const std::string& source, std::string& outError) {
|
|
||||||
const char* rawSource = source.c_str();
|
|
||||||
glShaderSource(shaderHandle, 1, &rawSource, nullptr);
|
|
||||||
glCompileShader(shaderHandle);
|
|
||||||
|
|
||||||
int compileStatus = 0;
|
|
||||||
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileStatus);
|
|
||||||
if (compileStatus == GL_TRUE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int logLength = 0;
|
|
||||||
glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &logLength);
|
|
||||||
std::vector<char> logBuffer(static_cast<std::size_t>((logLength > 1) ? logLength : 1), '\0');
|
|
||||||
glGetShaderInfoLog(shaderHandle, logLength, nullptr, logBuffer.data());
|
|
||||||
outError.assign(logBuffer.data());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
MetaCoreShaderProgram::~MetaCoreShaderProgram() {
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MetaCoreShaderProgram::BuildFromSource(const std::string& vertexSource, const std::string& fragmentSource, std::string& outError) {
|
|
||||||
Shutdown();
|
|
||||||
|
|
||||||
const unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
const unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
|
|
||||||
if (!MetaCoreCompileShader(vertexShader, vertexSource, outError)) {
|
|
||||||
glDeleteShader(vertexShader);
|
|
||||||
glDeleteShader(fragmentShader);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MetaCoreCompileShader(fragmentShader, fragmentSource, outError)) {
|
|
||||||
glDeleteShader(vertexShader);
|
|
||||||
glDeleteShader(fragmentShader);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgramHandle_ = glCreateProgram();
|
|
||||||
glAttachShader(ProgramHandle_, vertexShader);
|
|
||||||
glAttachShader(ProgramHandle_, fragmentShader);
|
|
||||||
glLinkProgram(ProgramHandle_);
|
|
||||||
|
|
||||||
int linkStatus = 0;
|
|
||||||
glGetProgramiv(ProgramHandle_, GL_LINK_STATUS, &linkStatus);
|
|
||||||
|
|
||||||
glDeleteShader(vertexShader);
|
|
||||||
glDeleteShader(fragmentShader);
|
|
||||||
|
|
||||||
if (linkStatus == GL_TRUE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int logLength = 0;
|
|
||||||
glGetProgramiv(ProgramHandle_, GL_INFO_LOG_LENGTH, &logLength);
|
|
||||||
std::vector<char> logBuffer(static_cast<std::size_t>((logLength > 1) ? logLength : 1), '\0');
|
|
||||||
glGetProgramInfoLog(ProgramHandle_, logLength, nullptr, logBuffer.data());
|
|
||||||
outError.assign(logBuffer.data());
|
|
||||||
|
|
||||||
glDeleteProgram(ProgramHandle_);
|
|
||||||
ProgramHandle_ = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreShaderProgram::Shutdown() {
|
|
||||||
if (ProgramHandle_ != 0) {
|
|
||||||
glDeleteProgram(ProgramHandle_);
|
|
||||||
ProgramHandle_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreShaderProgram::Bind() const {
|
|
||||||
glUseProgram(ProgramHandle_);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int MetaCoreShaderProgram::GetNativeHandle() const {
|
|
||||||
return ProgramHandle_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreShaderProgram::SetMatrix4(const char* name, const glm::mat4& value) const {
|
|
||||||
const int location = glGetUniformLocation(ProgramHandle_, name);
|
|
||||||
glUniformMatrix4fv(location, 1, GL_FALSE, &value[0][0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreShaderProgram::SetVector3(const char* name, const glm::vec3& value) const {
|
|
||||||
const int location = glGetUniformLocation(ProgramHandle_, name);
|
|
||||||
glUniform3fv(location, 1, &value[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetaCoreShaderProgram::SetFloat(const char* name, float value) const {
|
|
||||||
const int location = glGetUniformLocation(ProgramHandle_, name);
|
|
||||||
glUniform1f(location, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace MetaCore
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "MetaCoreRender/MetaCoreMesh.h"
|
|
||||||
|
|
||||||
namespace MetaCore {
|
|
||||||
|
|
||||||
// 负责构建第一阶段需要的内置几何体。
|
|
||||||
class MetaCoreDebugGeometry {
|
|
||||||
public:
|
|
||||||
// 创建网格、坐标轴和立方体三类内置几何。
|
|
||||||
bool Initialize();
|
|
||||||
|
|
||||||
// 释放全部几何资源。
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
// 返回地面网格。
|
|
||||||
[[nodiscard]] const MetaCoreMesh& GetGridMesh() const;
|
|
||||||
|
|
||||||
// 返回坐标轴。
|
|
||||||
[[nodiscard]] const MetaCoreMesh& GetAxesMesh() const;
|
|
||||||
|
|
||||||
// 返回立方体。
|
|
||||||
[[nodiscard]] const MetaCoreMesh& GetCubeMesh() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
MetaCoreMesh GridMesh_{};
|
|
||||||
MetaCoreMesh AxesMesh_{};
|
|
||||||
MetaCoreMesh CubeMesh_{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace MetaCore
|
|
||||||
@ -1,45 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "MetaCoreRender/MetaCorePandaSceneBridge.h"
|
||||||
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
|
class MetaCoreRenderDevice;
|
||||||
class MetaCoreScene;
|
class MetaCoreScene;
|
||||||
|
|
||||||
// 管理编辑器场景视口所需的离屏帧缓冲。
|
// 管理编辑器中央场景面板与 Panda3D DisplayRegion 之间的同步。
|
||||||
class MetaCoreEditorViewportRenderer {
|
class MetaCoreEditorViewportRenderer {
|
||||||
public:
|
public:
|
||||||
// 初始化离屏渲染器和场景渲染器。
|
// 初始化 Panda3D 场景桥接与显示区域驱动。
|
||||||
bool Initialize();
|
bool Initialize(MetaCoreRenderDevice& renderDevice);
|
||||||
|
|
||||||
// 释放离屏缓冲与场景渲染器资源。
|
// 释放桥接层与内部缓存。
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
// 根据新的视口尺寸重建帧缓冲。
|
// 写入当前 Scene 面板像素矩形。
|
||||||
void Resize(int width, int height);
|
void SetViewportRect(const MetaCoreViewportRect& viewportRect);
|
||||||
|
|
||||||
// 将场景渲染到当前离屏纹理中。
|
// 将场景状态同步到 Panda3D,并更新编辑器相机。
|
||||||
void RenderSceneToViewport(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView);
|
void RenderSceneToViewport(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView);
|
||||||
|
|
||||||
// 返回颜色纹理句柄。
|
|
||||||
[[nodiscard]] unsigned int GetColorTextureHandle() const;
|
|
||||||
|
|
||||||
// 返回视口宽度。
|
|
||||||
[[nodiscard]] int GetWidth() const;
|
|
||||||
|
|
||||||
// 返回视口高度。
|
|
||||||
[[nodiscard]] int GetHeight() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RebuildFramebuffer();
|
MetaCoreRenderDevice* RenderDevice_ = nullptr;
|
||||||
void DestroyFramebuffer();
|
MetaCorePandaSceneBridge SceneBridge_{};
|
||||||
|
MetaCoreViewportRect ViewportRect_{};
|
||||||
unsigned int FramebufferHandle_ = 0;
|
|
||||||
unsigned int ColorTextureHandle_ = 0;
|
|
||||||
unsigned int DepthStencilHandle_ = 0;
|
|
||||||
int Width_ = 1;
|
|
||||||
int Height_ = 1;
|
|
||||||
class MetaCoreSceneRenderer* SceneRenderer_ = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MetaCore
|
} // namespace MetaCore
|
||||||
|
|||||||
@ -1,47 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <glm/vec3.hpp>
|
|
||||||
#include <glm/vec4.hpp>
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace MetaCore {
|
|
||||||
|
|
||||||
// 表示渲染层使用的统一顶点格式。
|
|
||||||
struct MetaCoreVertex {
|
|
||||||
glm::vec3 Position{0.0F, 0.0F, 0.0F};
|
|
||||||
glm::vec3 Normal{0.0F, 0.0F, 0.0F};
|
|
||||||
glm::vec4 Color{1.0F, 1.0F, 1.0F, 1.0F};
|
|
||||||
};
|
|
||||||
|
|
||||||
// 标识网格的基础绘制模式。
|
|
||||||
enum class MetaCorePrimitiveType {
|
|
||||||
Triangles,
|
|
||||||
Lines
|
|
||||||
};
|
|
||||||
|
|
||||||
// 封装 VAO/VBO/EBO,并对外暴露简单的 Draw 接口。
|
|
||||||
class MetaCoreMesh {
|
|
||||||
public:
|
|
||||||
MetaCoreMesh() = default;
|
|
||||||
~MetaCoreMesh();
|
|
||||||
|
|
||||||
// 根据给定顶点和索引创建一个 GPU 网格。
|
|
||||||
bool Build(const std::vector<MetaCoreVertex>& vertices, const std::vector<std::uint32_t>& indices, MetaCorePrimitiveType primitiveType);
|
|
||||||
|
|
||||||
// 销毁 GPU 资源。
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
// 提交一次绘制调用。
|
|
||||||
void Draw() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int VertexArrayHandle_ = 0;
|
|
||||||
unsigned int VertexBufferHandle_ = 0;
|
|
||||||
unsigned int IndexBufferHandle_ = 0;
|
|
||||||
std::uint32_t IndexCount_ = 0;
|
|
||||||
MetaCorePrimitiveType PrimitiveType_ = MetaCorePrimitiveType::Triangles;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace MetaCore
|
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace MetaCore {
|
||||||
|
|
||||||
|
class MetaCoreRenderDevice;
|
||||||
|
class MetaCoreScene;
|
||||||
|
struct MetaCoreSceneView;
|
||||||
|
|
||||||
|
// 负责在 MetaCoreScene 与 Panda3D NodePath 场景之间建立同步关系。
|
||||||
|
class MetaCorePandaSceneBridge {
|
||||||
|
public:
|
||||||
|
MetaCorePandaSceneBridge();
|
||||||
|
~MetaCorePandaSceneBridge();
|
||||||
|
|
||||||
|
// 准备 Panda3D 场景根节点、调试网格与编辑器相机。
|
||||||
|
bool Initialize(MetaCoreRenderDevice& renderDevice);
|
||||||
|
|
||||||
|
// 释放桥接层创建的 Panda3D 节点。
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
// 将 MetaCoreScene 当前状态同步到 Panda3D 场景图。
|
||||||
|
void SyncScene(const MetaCoreScene& scene);
|
||||||
|
|
||||||
|
// 更新编辑器相机与当前选中对象高亮状态。
|
||||||
|
void ApplySceneView(const MetaCoreSceneView& sceneView);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class MetaCorePandaSceneBridgeImpl;
|
||||||
|
std::unique_ptr<MetaCorePandaSceneBridgeImpl> Impl_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace MetaCore
|
||||||
@ -1,31 +1,49 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <glm/vec4.hpp>
|
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
||||||
|
|
||||||
struct GLFWwindow;
|
#include <memory>
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
// 负责初始化 glad,并管理当前 OpenGL 上下文的基础状态。
|
class MetaCoreEditorViewportRenderer;
|
||||||
|
class MetaCorePandaSceneBridge;
|
||||||
|
class MetaCoreWindow;
|
||||||
|
|
||||||
|
// 封装 Panda3D 图形引擎、主窗口和中央场景显示区域。
|
||||||
class MetaCoreRenderDevice {
|
class MetaCoreRenderDevice {
|
||||||
public:
|
public:
|
||||||
// 初始化 OpenGL 函数加载与默认渲染状态。
|
MetaCoreRenderDevice();
|
||||||
bool Initialize(GLFWwindow* nativeWindow);
|
~MetaCoreRenderDevice();
|
||||||
|
|
||||||
// 关闭设备并重置初始化状态。
|
// 绑定 Panda3D 窗口与图形引擎,准备后续场景渲染。
|
||||||
|
bool Initialize(MetaCoreWindow& window);
|
||||||
|
|
||||||
|
// 释放 Panda3D 渲染相关资源。
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
// 开始绘制默认帧缓冲。
|
// 提交 Panda3D 场景绘制。
|
||||||
void BeginFrame(int width, int height, const glm::vec4& clearColor) const;
|
void RenderFrame() const;
|
||||||
|
|
||||||
// 清理默认帧缓冲。
|
// 提交当前帧翻转,确保 ImGui 叠加结果显示出来。
|
||||||
void Clear(const glm::vec4& clearColor) const;
|
void PresentFrame() const;
|
||||||
|
|
||||||
// 返回设备是否已初始化。
|
// 根据 ImGui 场景面板像素矩形更新 Panda3D DisplayRegion。
|
||||||
[[nodiscard]] bool IsInitialized() const;
|
void SetSceneViewportRect(const MetaCoreViewportRect& viewportRect);
|
||||||
|
|
||||||
|
// 返回 WindowFramework 原生对象指针,仅供 Panda3D 桥接层使用。
|
||||||
|
[[nodiscard]] void* GetNativeWindowFrameworkHandle() const;
|
||||||
|
|
||||||
|
// 返回场景根节点原生对象指针,仅供 Panda3D 桥接层使用。
|
||||||
|
[[nodiscard]] void* GetNativeSceneRootHandle() const;
|
||||||
|
|
||||||
|
// 返回编辑器相机节点原生对象指针,仅供 Panda3D 桥接层使用。
|
||||||
|
[[nodiscard]] void* GetNativeEditorCameraHandle() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Initialized_ = false;
|
class MetaCoreRenderDeviceImpl;
|
||||||
|
|
||||||
|
std::unique_ptr<MetaCoreRenderDeviceImpl> Impl_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace MetaCore
|
} // namespace MetaCore
|
||||||
|
|||||||
@ -2,16 +2,24 @@
|
|||||||
|
|
||||||
#include "MetaCoreFoundation/MetaCoreId.h"
|
#include "MetaCoreFoundation/MetaCoreId.h"
|
||||||
|
|
||||||
#include <glm/mat4x4.hpp>
|
|
||||||
#include <glm/vec3.hpp>
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
namespace MetaCore {
|
namespace MetaCore {
|
||||||
|
|
||||||
// 描述一次场景渲染所需的视图参数。
|
// 描述场景在宿主窗口中的像素矩形区域。
|
||||||
|
struct MetaCoreViewportRect {
|
||||||
|
float Left = 0.0F;
|
||||||
|
float Top = 0.0F;
|
||||||
|
float Width = 1.0F;
|
||||||
|
float Height = 1.0F;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 描述一次 Panda3D 场景同步所需的相机与选择参数。
|
||||||
struct MetaCoreSceneView {
|
struct MetaCoreSceneView {
|
||||||
glm::mat4 ViewMatrix{1.0F};
|
glm::vec3 CameraPosition{0.0F, 2.2F, 6.5F};
|
||||||
glm::mat4 ProjectionMatrix{1.0F};
|
glm::vec3 CameraTarget{0.0F, 0.7F, 0.0F};
|
||||||
glm::vec3 CameraPosition{0.0F, 0.0F, 0.0F};
|
glm::vec3 CameraUp{0.0F, 1.0F, 0.0F};
|
||||||
|
float VerticalFieldOfViewDegrees = 60.0F;
|
||||||
MetaCoreId SelectedObjectId = 0;
|
MetaCoreId SelectedObjectId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "MetaCoreRender/MetaCoreRenderTypes.h"
|
|
||||||
|
|
||||||
namespace MetaCore {
|
|
||||||
|
|
||||||
class MetaCoreScene;
|
|
||||||
|
|
||||||
// 负责把 MetaCoreScene 中的对象绘制到当前激活的 OpenGL 目标上。
|
|
||||||
class MetaCoreSceneRenderer {
|
|
||||||
public:
|
|
||||||
// 初始化 shader 和内置几何资源。
|
|
||||||
bool Initialize();
|
|
||||||
|
|
||||||
// 释放渲染器创建的 GPU 资源。
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
// 根据给定场景和视图参数提交绘制。
|
|
||||||
void RenderScene(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class MetaCoreSceneRendererImpl;
|
|
||||||
MetaCoreSceneRendererImpl* Impl_ = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace MetaCore
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <glm/mat4x4.hpp>
|
|
||||||
#include <glm/vec3.hpp>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace MetaCore {
|
|
||||||
|
|
||||||
// 封装最基础的 OpenGL Shader Program 生命周期和常用 uniform 设置。
|
|
||||||
class MetaCoreShaderProgram {
|
|
||||||
public:
|
|
||||||
MetaCoreShaderProgram() = default;
|
|
||||||
~MetaCoreShaderProgram();
|
|
||||||
|
|
||||||
// 根据传入的顶点和片元源码创建程序对象。
|
|
||||||
bool BuildFromSource(const std::string& vertexSource, const std::string& fragmentSource, std::string& outError);
|
|
||||||
|
|
||||||
// 销毁当前程序对象。
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
// 绑定当前 shader program。
|
|
||||||
void Bind() const;
|
|
||||||
|
|
||||||
// 返回当前程序句柄。
|
|
||||||
[[nodiscard]] unsigned int GetNativeHandle() const;
|
|
||||||
|
|
||||||
// 设置 mat4 uniform。
|
|
||||||
void SetMatrix4(const char* name, const glm::mat4& value) const;
|
|
||||||
|
|
||||||
// 设置 vec3 uniform。
|
|
||||||
void SetVector3(const char* name, const glm::vec3& value) const;
|
|
||||||
|
|
||||||
// 设置 float uniform。
|
|
||||||
void SetFloat(const char* name, float value) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int ProgramHandle_ = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace MetaCore
|
|
||||||
7
TestProject/Assets/Materials/default_pbr.material.json
Normal file
7
TestProject/Assets/Materials/default_pbr.material.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "DefaultPbr",
|
||||||
|
"shader_family": "simplepbr",
|
||||||
|
"base_color": [1.0, 1.0, 1.0, 1.0],
|
||||||
|
"roughness": 1.0,
|
||||||
|
"metallic": 0.0
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"id": "00005052332aa8d4625dd7775e94e6d800000005",
|
||||||
|
"relative_path": "Assets/Materials/default_pbr.material.json",
|
||||||
|
"type": "material"
|
||||||
|
}
|
||||||
10
TestProject/Assets/UI/main_menu.rcss
Normal file
10
TestProject/Assets/UI/main_menu.rcss
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: #f2f4f8;
|
||||||
|
}
|
||||||
|
.root-panel {
|
||||||
|
width: 420px;
|
||||||
|
margin: 40px auto;
|
||||||
|
padding: 24px;
|
||||||
|
background: rgba(16, 18, 24, 0.85);
|
||||||
|
}
|
||||||
5
TestProject/Assets/UI/main_menu.rcss.meta
Normal file
5
TestProject/Assets/UI/main_menu.rcss.meta
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"id": "00005052332a9f74171e39271225dd0800000004",
|
||||||
|
"relative_path": "Assets/UI/main_menu.rcss",
|
||||||
|
"type": "ui_stylesheet"
|
||||||
|
}
|
||||||
11
TestProject/Assets/UI/main_menu.rml
Normal file
11
TestProject/Assets/UI/main_menu.rml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<rml>
|
||||||
|
<head>
|
||||||
|
<link type="text/rcss" href="main_menu.rcss" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="root-panel">
|
||||||
|
<h1>MetaCore</h1>
|
||||||
|
<p>Runtime UI scaffold</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</rml>
|
||||||
5
TestProject/Assets/UI/main_menu.rml.meta
Normal file
5
TestProject/Assets/UI/main_menu.rml.meta
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"id": "00005052332a822841724324849eccb900000003",
|
||||||
|
"relative_path": "Assets/UI/main_menu.rml",
|
||||||
|
"type": "ui_document"
|
||||||
|
}
|
||||||
19
TestProject/Library/AssetDB.json
Normal file
19
TestProject/Library/AssetDB.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"records": [
|
||||||
|
{
|
||||||
|
"id": "00005052332a822841724324849eccb900000003",
|
||||||
|
"relative_path": "Assets/UI/main_menu.rml",
|
||||||
|
"type": "ui_document"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "00005052332a9f74171e39271225dd0800000004",
|
||||||
|
"relative_path": "Assets/UI/main_menu.rcss",
|
||||||
|
"type": "ui_stylesheet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "00005052332aa8d4625dd7775e94e6d800000005",
|
||||||
|
"relative_path": "Assets/Materials/default_pbr.material.json",
|
||||||
|
"type": "material"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
9
TestProject/Library/Layout/editor_layout.json
Normal file
9
TestProject/Library/Layout/editor_layout.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"layout_name": "Default",
|
||||||
|
"hierarchy_visible": true,
|
||||||
|
"inspector_visible": true,
|
||||||
|
"project_visible": true,
|
||||||
|
"console_visible": true,
|
||||||
|
"runtime_preview_visible": true,
|
||||||
|
"toolbar_visible": true
|
||||||
|
}
|
||||||
8
TestProject/MetaCore.project.json
Normal file
8
TestProject/MetaCore.project.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "MetaCoreTest",
|
||||||
|
"scenes": [
|
||||||
|
"Scenes/Main.mcscene.json"
|
||||||
|
],
|
||||||
|
"startup_scene": "Scenes/Main.mcscene.json",
|
||||||
|
"version": "0.1.0"
|
||||||
|
}
|
||||||
76
TestProject/Scenes/Main.mcscene.json
Normal file
76
TestProject/Scenes/Main.mcscene.json
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"name": "Main",
|
||||||
|
"objects": [
|
||||||
|
{
|
||||||
|
"camera": {
|
||||||
|
"far_clip": 1000,
|
||||||
|
"fov_degrees": 60,
|
||||||
|
"near_clip": 0.100000001490116,
|
||||||
|
"primary": true
|
||||||
|
},
|
||||||
|
"editor_metadata": {
|
||||||
|
"editor_only": false,
|
||||||
|
"locked": false,
|
||||||
|
"selected": false
|
||||||
|
},
|
||||||
|
"id": "0000505233216b341f8e0361195336fe00000001",
|
||||||
|
"name": "Main Camera",
|
||||||
|
"parent_id": "",
|
||||||
|
"transform": {
|
||||||
|
"position": [
|
||||||
|
0,
|
||||||
|
-10,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"editor_metadata": {
|
||||||
|
"editor_only": false,
|
||||||
|
"locked": false,
|
||||||
|
"selected": false
|
||||||
|
},
|
||||||
|
"id": "00005052332197bcd649b574240bc6be00000002",
|
||||||
|
"light": {
|
||||||
|
"color": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"intensity": 1,
|
||||||
|
"range": 10,
|
||||||
|
"spot_angle_degrees": 45,
|
||||||
|
"type": "directional"
|
||||||
|
},
|
||||||
|
"name": "Directional Light",
|
||||||
|
"parent_id": "",
|
||||||
|
"transform": {
|
||||||
|
"position": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
108
TestProject/Scenes/Test.mcscene.json
Normal file
108
TestProject/Scenes/Test.mcscene.json
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"name": "Main",
|
||||||
|
"objects": [
|
||||||
|
{
|
||||||
|
"camera": {
|
||||||
|
"far_clip": 1000,
|
||||||
|
"fov_degrees": 60,
|
||||||
|
"near_clip": 0.100000001490116,
|
||||||
|
"primary": true
|
||||||
|
},
|
||||||
|
"editor_metadata": {
|
||||||
|
"editor_only": false,
|
||||||
|
"locked": false,
|
||||||
|
"selected": false
|
||||||
|
},
|
||||||
|
"id": "00005052333cdf54bd42defb639e412c00000006",
|
||||||
|
"name": "Main Camera",
|
||||||
|
"parent_id": "",
|
||||||
|
"transform": {
|
||||||
|
"position": [
|
||||||
|
0,
|
||||||
|
-10,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"editor_metadata": {
|
||||||
|
"editor_only": false,
|
||||||
|
"locked": false,
|
||||||
|
"selected": false
|
||||||
|
},
|
||||||
|
"id": "00005052333ceef49f76de9c4d0fd70200000007",
|
||||||
|
"light": {
|
||||||
|
"color": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"intensity": 1,
|
||||||
|
"range": 10,
|
||||||
|
"spot_angle_degrees": 45,
|
||||||
|
"type": "directional"
|
||||||
|
},
|
||||||
|
"name": "Directional Light",
|
||||||
|
"parent_id": "",
|
||||||
|
"transform": {
|
||||||
|
"position": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"editor_metadata": {
|
||||||
|
"editor_only": false,
|
||||||
|
"locked": false,
|
||||||
|
"selected": false
|
||||||
|
},
|
||||||
|
"id": "00005052333cf6c426b72f1a10f785ee00000008",
|
||||||
|
"mesh_renderer": {
|
||||||
|
"material_asset_id": "",
|
||||||
|
"mesh_asset_id": "mesh.cube",
|
||||||
|
"visible": true
|
||||||
|
},
|
||||||
|
"name": "Cube",
|
||||||
|
"parent_id": "",
|
||||||
|
"transform": {
|
||||||
|
"position": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
114
cmake/MetaCorePanda3D.cmake
Normal file
114
cmake/MetaCorePanda3D.cmake
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
set(METACORE_PANDA3D_VERSION "1.10.16" CACHE STRING "Pinned Panda3D SDK version used by MetaCore")
|
||||||
|
set(METACORE_PANDA3D_ARCH "x64" CACHE STRING "Pinned Panda3D Windows architecture used by MetaCore")
|
||||||
|
set(METACORE_PANDA3D_LOCAL_ROOT "${CMAKE_SOURCE_DIR}/.metacore/deps/panda3d/${METACORE_PANDA3D_VERSION}-${METACORE_PANDA3D_ARCH}" CACHE PATH "Local Panda3D SDK cache directory")
|
||||||
|
|
||||||
|
function(metacore_prepare_panda3d)
|
||||||
|
if(WIN32)
|
||||||
|
if(DEFINED ENV{PANDA3D_ROOT} AND NOT "$ENV{PANDA3D_ROOT}" STREQUAL "")
|
||||||
|
set(_metacore_panda3d_root "$ENV{PANDA3D_ROOT}")
|
||||||
|
elseif(DEFINED PANDA3D_ROOT AND NOT "${PANDA3D_ROOT}" STREQUAL "")
|
||||||
|
set(_metacore_panda3d_root "${PANDA3D_ROOT}")
|
||||||
|
else()
|
||||||
|
set(_metacore_panda3d_root "${METACORE_PANDA3D_LOCAL_ROOT}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(TO_CMAKE_PATH "${_metacore_panda3d_root}" _metacore_panda3d_root)
|
||||||
|
|
||||||
|
if(NOT EXISTS "${_metacore_panda3d_root}/include/pandaFramework.h")
|
||||||
|
if(METACORE_AUTO_PREPARE_PANDA3D)
|
||||||
|
message(STATUS "MetaCore will prepare Panda3D SDK into ${_metacore_panda3d_root}")
|
||||||
|
execute_process(
|
||||||
|
COMMAND
|
||||||
|
powershell
|
||||||
|
-NoProfile
|
||||||
|
-ExecutionPolicy Bypass
|
||||||
|
-File "${CMAKE_SOURCE_DIR}/scripts/PrepareMetaCorePanda3D.ps1"
|
||||||
|
-Version "${METACORE_PANDA3D_VERSION}"
|
||||||
|
-Architecture "${METACORE_PANDA3D_ARCH}"
|
||||||
|
-InstallDir "${_metacore_panda3d_root}"
|
||||||
|
RESULT_VARIABLE _metacore_prepare_result
|
||||||
|
)
|
||||||
|
if(NOT _metacore_prepare_result EQUAL 0)
|
||||||
|
message(FATAL_ERROR "MetaCore failed to prepare Panda3D SDK. Set PANDA3D_ROOT manually or inspect scripts/PrepareMetaCorePanda3D.ps1 output.")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Panda3D SDK was not found. Set PANDA3D_ROOT or enable METACORE_AUTO_PREPARE_PANDA3D.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(METACORE_PANDA3D_ROOT "${_metacore_panda3d_root}" CACHE PATH "Resolved Panda3D SDK root used by MetaCore" FORCE)
|
||||||
|
set(METACORE_PANDA3D_INCLUDE_DIR "${METACORE_PANDA3D_ROOT}/include" CACHE PATH "Resolved Panda3D include directory" FORCE)
|
||||||
|
set(METACORE_PANDA3D_LIB_DIR "${METACORE_PANDA3D_ROOT}/lib" CACHE PATH "Resolved Panda3D library directory" FORCE)
|
||||||
|
set(METACORE_PANDA3D_BIN_DIR "${METACORE_PANDA3D_ROOT}/bin" CACHE PATH "Resolved Panda3D runtime directory" FORCE)
|
||||||
|
set(METACORE_PANDA3D_ETC_DIR "${METACORE_PANDA3D_ROOT}/etc" CACHE PATH "Resolved Panda3D config directory" FORCE)
|
||||||
|
set(METACORE_PANDA3D_MODELS_DIR "${METACORE_PANDA3D_ROOT}/models" CACHE PATH "Resolved Panda3D models directory" FORCE)
|
||||||
|
set(METACORE_PANDA3D_PLUGINS_DIR "${METACORE_PANDA3D_ROOT}/plugins" CACHE PATH "Resolved Panda3D plugins directory" FORCE)
|
||||||
|
|
||||||
|
set(_metacore_panda3d_libraries
|
||||||
|
"${METACORE_PANDA3D_LIB_DIR}/libp3framework.lib"
|
||||||
|
"${METACORE_PANDA3D_LIB_DIR}/libpanda.lib"
|
||||||
|
"${METACORE_PANDA3D_LIB_DIR}/libpandafx.lib"
|
||||||
|
"${METACORE_PANDA3D_LIB_DIR}/libpandaexpress.lib"
|
||||||
|
"${METACORE_PANDA3D_LIB_DIR}/libpandagl.lib"
|
||||||
|
"${METACORE_PANDA3D_LIB_DIR}/libp3windisplay.lib"
|
||||||
|
"${METACORE_PANDA3D_LIB_DIR}/libp3dtool.lib"
|
||||||
|
"${METACORE_PANDA3D_LIB_DIR}/libp3dtoolconfig.lib"
|
||||||
|
opengl32
|
||||||
|
gdi32
|
||||||
|
user32
|
||||||
|
shell32
|
||||||
|
advapi32
|
||||||
|
ws2_32
|
||||||
|
winmm
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(MetaCorePanda3D::SDK INTERFACE IMPORTED GLOBAL)
|
||||||
|
set_target_properties(MetaCorePanda3D::SDK PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${METACORE_PANDA3D_INCLUDE_DIR}"
|
||||||
|
INTERFACE_LINK_LIBRARIES "${_metacore_panda3d_libraries}"
|
||||||
|
)
|
||||||
|
|
||||||
|
file(GLOB METACORE_PANDA3D_RUNTIME_DLLS "${METACORE_PANDA3D_BIN_DIR}/*.dll")
|
||||||
|
set(METACORE_PANDA3D_RUNTIME_DLLS "${METACORE_PANDA3D_RUNTIME_DLLS}" CACHE INTERNAL "Resolved Panda3D runtime DLL list")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "MetaCore Panda3D V1 currently supports Windows only.")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(metacore_stage_panda3d_runtime target_name)
|
||||||
|
if(NOT TARGET ${target_name})
|
||||||
|
message(FATAL_ERROR "Target ${target_name} does not exist.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
foreach(_metacore_runtime_dll IN LISTS METACORE_PANDA3D_RUNTIME_DLLS)
|
||||||
|
add_custom_command(TARGET ${target_name} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${_metacore_runtime_dll}"
|
||||||
|
"$<TARGET_FILE_DIR:${target_name}>"
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(EXISTS "${METACORE_PANDA3D_ETC_DIR}")
|
||||||
|
add_custom_command(TARGET ${target_name} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
"${METACORE_PANDA3D_ETC_DIR}"
|
||||||
|
"$<TARGET_FILE_DIR:${target_name}>/etc"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(EXISTS "${METACORE_PANDA3D_MODELS_DIR}")
|
||||||
|
add_custom_command(TARGET ${target_name} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
"${METACORE_PANDA3D_MODELS_DIR}"
|
||||||
|
"$<TARGET_FILE_DIR:${target_name}>/models"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(EXISTS "${METACORE_PANDA3D_PLUGINS_DIR}")
|
||||||
|
add_custom_command(TARGET ${target_name} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
"${METACORE_PANDA3D_PLUGINS_DIR}"
|
||||||
|
"$<TARGET_FILE_DIR:${target_name}>/plugins"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
60
scripts/PrepareMetaCorePanda3D.ps1
Normal file
60
scripts/PrepareMetaCorePanda3D.ps1
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Version,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Architecture,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$InstallDir
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
if (Test-Path (Join-Path $InstallDir "include\\pandaFramework.h")) {
|
||||||
|
Write-Host "MetaCore Panda3D SDK already prepared at $InstallDir"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
$installParent = Split-Path -Parent $InstallDir
|
||||||
|
New-Item -ItemType Directory -Force -Path $installParent | Out-Null
|
||||||
|
|
||||||
|
$downloadCacheDir = Join-Path $PSScriptRoot "..\\.metacore\\downloads"
|
||||||
|
New-Item -ItemType Directory -Force -Path $downloadCacheDir | Out-Null
|
||||||
|
|
||||||
|
$installerName = "Panda3D-SDK-$Version-$Architecture.exe"
|
||||||
|
$installerPath = Join-Path $downloadCacheDir $installerName
|
||||||
|
$downloadUrl = "https://www.panda3d.org/download/panda3d-$Version/$installerName"
|
||||||
|
|
||||||
|
if (-not (Test-Path $installerPath)) {
|
||||||
|
Write-Host "MetaCore downloading Panda3D SDK from $downloadUrl"
|
||||||
|
& curl.exe -L --fail --output $installerPath $downloadUrl
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "MetaCore failed to download Panda3D SDK."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path $InstallDir) {
|
||||||
|
Remove-Item -Recurse -Force $InstallDir
|
||||||
|
}
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
|
||||||
|
|
||||||
|
$installDirFullPath = (Resolve-Path $InstallDir).Path
|
||||||
|
Write-Host "MetaCore installing Panda3D SDK into $installDirFullPath"
|
||||||
|
|
||||||
|
$installerLaunchPath = Join-Path $downloadCacheDir ("launch-" + $installerName)
|
||||||
|
Copy-Item -Force $installerPath $installerLaunchPath
|
||||||
|
|
||||||
|
$installProcess = Start-Process -FilePath $installerLaunchPath -ArgumentList @("/S", "/D=$installDirFullPath") -Wait -PassThru
|
||||||
|
if ($installProcess.ExitCode -ne 0) {
|
||||||
|
throw "MetaCore Panda3D installer failed with exit code $($installProcess.ExitCode)."
|
||||||
|
}
|
||||||
|
|
||||||
|
Remove-Item -Force $installerLaunchPath -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
if (-not (Test-Path (Join-Path $installDirFullPath "include\\pandaFramework.h"))) {
|
||||||
|
throw "MetaCore Panda3D installation finished but expected headers were not found."
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "MetaCore Panda3D SDK is ready at $installDirFullPath"
|
||||||
@ -2,20 +2,13 @@
|
|||||||
"name": "metacore",
|
"name": "metacore",
|
||||||
"version-string": "1.0.0",
|
"version-string": "1.0.0",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
{
|
|
||||||
"name": "glad",
|
|
||||||
"features": [
|
|
||||||
"gl-api-33"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"glfw3",
|
|
||||||
"glm",
|
"glm",
|
||||||
{
|
{
|
||||||
"name": "imgui",
|
"name": "imgui",
|
||||||
"default-features": false,
|
"default-features": false,
|
||||||
"features": [
|
"features": [
|
||||||
"docking-experimental",
|
"docking-experimental",
|
||||||
"glfw-binding",
|
"win32-binding",
|
||||||
"opengl3-binding"
|
"opengl3-binding"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user