Stabilize editor startup and refactor scene interaction handling
This commit is contained in:
parent
2ed3737c90
commit
79fe8fb906
@ -1,20 +1,126 @@
|
||||
#include "MetaCoreEditor/MetaCoreEditorApp.h"
|
||||
|
||||
#include <csignal>
|
||||
#include <cstdio>
|
||||
#include <crtdbg.h>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <new>
|
||||
|
||||
namespace {
|
||||
|
||||
void MetaCoreWriteCrashLog(const std::string& message) {
|
||||
std::ofstream stream("editor.crash.log", std::ios::app);
|
||||
if (!stream.is_open()) {
|
||||
return;
|
||||
}
|
||||
stream << message << '\n';
|
||||
}
|
||||
|
||||
void MetaCoreWriteCrashLogRaw(const char* message) {
|
||||
if (message == nullptr) {
|
||||
return;
|
||||
}
|
||||
FILE* file = nullptr;
|
||||
if (fopen_s(&file, "editor.crash.log", "a") == 0 && file != nullptr) {
|
||||
std::fputs(message, file);
|
||||
std::fputs("\n", file);
|
||||
std::fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
void MetaCoreInvalidParameterHandler(
|
||||
const wchar_t* expression,
|
||||
const wchar_t* functionName,
|
||||
const wchar_t* fileName,
|
||||
unsigned int line,
|
||||
uintptr_t reserved
|
||||
) {
|
||||
(void)reserved;
|
||||
MetaCoreWriteCrashLog("invalid_parameter triggered");
|
||||
if (expression != nullptr) {
|
||||
MetaCoreWriteCrashLog("expression: <non-null>");
|
||||
}
|
||||
if (functionName != nullptr) {
|
||||
MetaCoreWriteCrashLog("function: <non-null>");
|
||||
}
|
||||
if (fileName != nullptr) {
|
||||
MetaCoreWriteCrashLog("file: <non-null>");
|
||||
}
|
||||
MetaCoreWriteCrashLog("line: " + std::to_string(line));
|
||||
}
|
||||
|
||||
void MetaCorePureCallHandler() {
|
||||
MetaCoreWriteCrashLog("purecall handler triggered");
|
||||
}
|
||||
|
||||
void MetaCoreSignalHandler(int signalValue) {
|
||||
MetaCoreWriteCrashLog("signal: " + std::to_string(signalValue));
|
||||
}
|
||||
|
||||
void MetaCoreTerminateHandler() {
|
||||
MetaCoreWriteCrashLog("std::terminate triggered");
|
||||
if (std::exception_ptr exceptionPtr = std::current_exception(); exceptionPtr != nullptr) {
|
||||
try {
|
||||
std::rethrow_exception(exceptionPtr);
|
||||
} catch (const std::exception& exceptionObject) {
|
||||
MetaCoreWriteCrashLog(std::string("exception: ") + exceptionObject.what());
|
||||
} catch (...) {
|
||||
MetaCoreWriteCrashLog("exception: <non-std exception>");
|
||||
}
|
||||
} else {
|
||||
MetaCoreWriteCrashLog("exception: <none>");
|
||||
}
|
||||
std::_Exit(3);
|
||||
}
|
||||
|
||||
void MetaCoreInstallDebugCrashHooks() {
|
||||
#if defined(_DEBUG)
|
||||
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
|
||||
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
|
||||
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
|
||||
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
|
||||
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
|
||||
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
|
||||
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
|
||||
|
||||
_set_invalid_parameter_handler(&MetaCoreInvalidParameterHandler);
|
||||
_set_purecall_handler(&MetaCorePureCallHandler);
|
||||
std::set_terminate(&MetaCoreTerminateHandler);
|
||||
std::signal(SIGABRT, &MetaCoreSignalHandler);
|
||||
MetaCoreWriteCrashLog("debug crash hooks installed");
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
MetaCoreInstallDebugCrashHooks();
|
||||
MetaCoreWriteCrashLogRaw("main: hooks installed");
|
||||
if (argc > 0) {
|
||||
MetaCoreWriteCrashLogRaw("main: set current_path begin");
|
||||
std::filesystem::current_path(std::filesystem::path(argv[0]).parent_path());
|
||||
MetaCoreWriteCrashLogRaw("main: set current_path done");
|
||||
}
|
||||
|
||||
MetaCoreWriteCrashLogRaw("main: construct app begin");
|
||||
MetaCore::MetaCoreEditorApp editorApp;
|
||||
MetaCoreWriteCrashLogRaw("main: construct app done");
|
||||
MetaCoreWriteCrashLogRaw("main: initialize begin");
|
||||
if (!editorApp.Initialize()) {
|
||||
MetaCoreWriteCrashLogRaw("main: initialize failed");
|
||||
std::cerr << "MetaCoreEditorApp initialize failed\n";
|
||||
return 1;
|
||||
}
|
||||
MetaCoreWriteCrashLogRaw("main: initialize done");
|
||||
|
||||
MetaCoreWriteCrashLogRaw("main: run begin");
|
||||
const int exitCode = editorApp.Run();
|
||||
MetaCoreWriteCrashLogRaw("main: run done");
|
||||
editorApp.Shutdown();
|
||||
MetaCoreWriteCrashLogRaw("main: shutdown done");
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
if(MSVC)
|
||||
# Debug 使用调试运行库,Release 使用可分发运行库,避免不同配置之间的 CRT 冲突。
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL")
|
||||
endif()
|
||||
|
||||
option(METACORE_BUILD_TESTS "Build MetaCore tests" ON)
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
@ -35,6 +36,29 @@ namespace MetaCore {
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(_DEBUG)
|
||||
void MetaCoreTraceStartup(const char* message) {
|
||||
if (message == nullptr) {
|
||||
return;
|
||||
}
|
||||
FILE* file = nullptr;
|
||||
if (fopen_s(&file, "editor.crash.log", "a") == 0 && file != nullptr) {
|
||||
std::fputs(message, file);
|
||||
std::fputs("\n", file);
|
||||
std::fclose(file);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void MetaCoreTraceStartup(const char*) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG)
|
||||
constexpr bool GMetaCoreEnableImGuizmo = false;
|
||||
#else
|
||||
constexpr bool GMetaCoreEnableImGuizmo = true;
|
||||
#endif
|
||||
|
||||
void MetaCoreApplyEditorStyle() {
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
ImGui::StyleColorsDark();
|
||||
@ -62,6 +86,7 @@ void MetaCoreConfigureChineseFont() {
|
||||
io.Fonts->AddFontDefault();
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if !defined(_DEBUG)
|
||||
std::vector<std::filesystem::path> candidatePaths;
|
||||
char* windowsDirectory = nullptr;
|
||||
std::size_t windowsDirectoryLength = 0;
|
||||
@ -75,19 +100,26 @@ void MetaCoreConfigureChineseFont() {
|
||||
|
||||
for (const auto& candidatePath : candidatePaths) {
|
||||
if (std::filesystem::exists(candidatePath)) {
|
||||
ImFont* chineseFont = io.Fonts->AddFontFromFileTTF(
|
||||
candidatePath.string().c_str(),
|
||||
18.0F,
|
||||
nullptr,
|
||||
io.Fonts->GetGlyphRangesChineseFull()
|
||||
);
|
||||
if (chineseFont != nullptr) {
|
||||
io.FontDefault = chineseFont;
|
||||
try {
|
||||
// ChineseFull glyph range may allocate a very large atlas in Debug builds.
|
||||
// Use Common range for stability; fallback to default font if allocation fails.
|
||||
ImFont* chineseFont = io.Fonts->AddFontFromFileTTF(
|
||||
candidatePath.string().c_str(),
|
||||
17.0F,
|
||||
nullptr,
|
||||
io.Fonts->GetGlyphRangesChineseSimplifiedCommon()
|
||||
);
|
||||
if (chineseFont != nullptr) {
|
||||
io.FontDefault = chineseFont;
|
||||
break;
|
||||
}
|
||||
} catch (const std::bad_alloc&) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
glm::mat4 MetaCoreBuildTransformMatrix(const MetaCoreTransformComponent& transform) {
|
||||
@ -179,14 +211,19 @@ MetaCoreEditorApp::~MetaCoreEditorApp() {
|
||||
}
|
||||
|
||||
bool MetaCoreEditorApp::Initialize() {
|
||||
MetaCoreTraceStartup("init: begin");
|
||||
if (Initialized_) {
|
||||
MetaCoreTraceStartup("init: already initialized");
|
||||
return true;
|
||||
}
|
||||
|
||||
MetaCoreTraceStartup("init: window");
|
||||
if (!Window_.Initialize(1600, 900, "MetaCore Editor")) {
|
||||
MetaCoreTraceStartup("init: window failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
MetaCoreTraceStartup("init: message handler");
|
||||
Window_.SetNativeWindowMessageHandler([](void* nativeWindowHandle, unsigned int message, std::uintptr_t wparam, std::intptr_t lparam) {
|
||||
return ImGui_ImplWin32_WndProcHandler(
|
||||
static_cast<HWND>(nativeWindowHandle),
|
||||
@ -196,24 +233,34 @@ bool MetaCoreEditorApp::Initialize() {
|
||||
) != 0;
|
||||
});
|
||||
|
||||
MetaCoreTraceStartup("init: render device");
|
||||
if (!RenderDevice_.Initialize(Window_)) {
|
||||
MetaCoreTraceStartup("init: render device failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
MetaCoreTraceStartup("init: imgui");
|
||||
if (!InitializeImGui()) {
|
||||
MetaCoreTraceStartup("init: imgui failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
MetaCoreTraceStartup("init: viewport renderer");
|
||||
if (!ViewportRenderer_.Initialize(RenderDevice_)) {
|
||||
MetaCoreTraceStartup("init: viewport renderer failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
MetaCoreTraceStartup("init: create default scene");
|
||||
Scene_ = MetaCoreCreateDefaultScene();
|
||||
MetaCoreTraceStartup("init: create modules");
|
||||
Modules_.push_back(MetaCoreCreateBuiltinEditorModule());
|
||||
MetaCoreTraceStartup("init: startup modules");
|
||||
for (const auto& module : Modules_) {
|
||||
module->Startup(ModuleRegistry_);
|
||||
}
|
||||
|
||||
MetaCoreTraceStartup("init: create editor context");
|
||||
EditorContext_ = std::make_unique<MetaCoreEditorContext>(
|
||||
Window_,
|
||||
RenderDevice_,
|
||||
@ -223,6 +270,7 @@ bool MetaCoreEditorApp::Initialize() {
|
||||
ModuleRegistry_
|
||||
);
|
||||
|
||||
MetaCoreTraceStartup("init: select default cube");
|
||||
for (const MetaCoreGameObject& object : Scene_.GetGameObjects()) {
|
||||
if (object.Name == "Cube") {
|
||||
EditorContext_->SetSelectedObjectId(object.Id);
|
||||
@ -231,21 +279,26 @@ bool MetaCoreEditorApp::Initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
MetaCoreTraceStartup("init: add console messages");
|
||||
EditorContext_->AddConsoleMessage(MetaCoreLogLevel::Info, "System", "MetaCore 编辑器已初始化");
|
||||
EditorContext_->AddConsoleMessage(MetaCoreLogLevel::Info, "Render", "Panda3D 场景视口已准备完成");
|
||||
|
||||
Initialized_ = true;
|
||||
MetaCoreTraceStartup("init: done");
|
||||
return true;
|
||||
}
|
||||
|
||||
int MetaCoreEditorApp::Run() {
|
||||
MetaCoreTraceStartup("main: run loop enter");
|
||||
while (!Window_.ShouldClose()) {
|
||||
Window_.BeginFrame();
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
ImGuizmo::BeginFrame();
|
||||
if (GMetaCoreEnableImGuizmo) {
|
||||
ImGuizmo::BeginFrame();
|
||||
}
|
||||
|
||||
DrawEditorFrame();
|
||||
|
||||
@ -277,21 +330,35 @@ void MetaCoreEditorApp::Shutdown() {
|
||||
}
|
||||
|
||||
bool MetaCoreEditorApp::InitializeImGui() {
|
||||
MetaCoreTraceStartup("imgui: begin");
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
MetaCoreTraceStartup("imgui: context created");
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
#if defined(_DEBUG)
|
||||
// Avoid loading persisted docking/layout ini in Debug; malformed/legacy ini may trigger large allocations.
|
||||
io.IniFilename = nullptr;
|
||||
io.LogFilename = nullptr;
|
||||
#endif
|
||||
MetaCoreTraceStartup("imgui: configure font begin");
|
||||
MetaCoreConfigureChineseFont();
|
||||
MetaCoreTraceStartup("imgui: configure font done");
|
||||
MetaCoreApplyEditorStyle();
|
||||
MetaCoreTraceStartup("imgui: style done");
|
||||
|
||||
if (!ImGui_ImplWin32_InitForOpenGL(Window_.GetNativeWindowHandle())) {
|
||||
MetaCoreTraceStartup("imgui: win32 init failed");
|
||||
return false;
|
||||
}
|
||||
MetaCoreTraceStartup("imgui: win32 init done");
|
||||
|
||||
if (!ImGui_ImplOpenGL3_Init("#version 130")) {
|
||||
MetaCoreTraceStartup("imgui: opengl3 init failed");
|
||||
return false;
|
||||
}
|
||||
MetaCoreTraceStartup("imgui: opengl3 init done");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -433,117 +500,93 @@ void MetaCoreEditorApp::DrawEditorFrame() {
|
||||
bool gizmoHovering = false;
|
||||
bool gizmoUsing = false;
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(centralNode->Pos.x, centralNode->Pos.y + sceneToolbarHeight));
|
||||
ImGui::SetNextWindowSize(ImVec2(viewportState.Width, viewportState.Height));
|
||||
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));
|
||||
if (GMetaCoreEnableImGuizmo) {
|
||||
ImGui::SetNextWindowPos(ImVec2(centralNode->Pos.x, centralNode->Pos.y + sceneToolbarHeight));
|
||||
ImGui::SetNextWindowSize(ImVec2(viewportState.Width, viewportState.Height));
|
||||
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));
|
||||
|
||||
constexpr ImGuiWindowFlags gizmoCanvasFlags =
|
||||
ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_NoDocking |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||
ImGuiWindowFlags_NoNavFocus |
|
||||
ImGuiWindowFlags_NoBackground |
|
||||
ImGuiWindowFlags_NoInputs;
|
||||
constexpr ImGuiWindowFlags gizmoCanvasFlags =
|
||||
ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_NoDocking |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus |
|
||||
ImGuiWindowFlags_NoNavFocus |
|
||||
ImGuiWindowFlags_NoBackground |
|
||||
ImGuiWindowFlags_NoInputs;
|
||||
|
||||
bool gizmoCanvasOpen = true;
|
||||
ImGui::Begin("MetaCoreSceneGizmoCanvas", &gizmoCanvasOpen, gizmoCanvasFlags);
|
||||
bool gizmoCanvasOpen = true;
|
||||
ImGui::Begin("MetaCoreSceneGizmoCanvas", &gizmoCanvasOpen, gizmoCanvasFlags);
|
||||
|
||||
// Guard against degenerate camera and aspect ratio.
|
||||
const float cameraDistance = glm::distance(sceneView.CameraPosition, sceneView.CameraTarget);
|
||||
const float gizmoAspect = viewportState.Width / viewportState.Height;
|
||||
const float cameraDistance = glm::distance(sceneView.CameraPosition, sceneView.CameraTarget);
|
||||
const float gizmoAspect = viewportState.Width / viewportState.Height;
|
||||
|
||||
MetaCoreGameObject* selectedObject = EditorContext_->GetSelectedGameObject();
|
||||
if (selectedObject != nullptr &&
|
||||
EditorContext_->GetGizmoOperation() != MetaCoreGizmoOperation::None &&
|
||||
cameraDistance >= 0.001F &&
|
||||
gizmoAspect >= 0.001F) {
|
||||
MetaCoreGameObject* selectedObject = EditorContext_->GetSelectedGameObject();
|
||||
if (selectedObject != nullptr &&
|
||||
EditorContext_->GetGizmoOperation() != MetaCoreGizmoOperation::None &&
|
||||
cameraDistance >= 0.001F &&
|
||||
gizmoAspect >= 0.001F) {
|
||||
glm::mat4 gizmoViewMatrix(1.0F);
|
||||
glm::mat4 gizmoProjectionMatrix(1.0F);
|
||||
if (!RenderDevice_.TryGetEditorCameraMatrices(gizmoViewMatrix, gizmoProjectionMatrix)) {
|
||||
gizmoProjectionMatrix = glm::perspective(
|
||||
glm::radians(sceneView.VerticalFieldOfViewDegrees),
|
||||
gizmoAspect, 0.05F, 500.0F
|
||||
);
|
||||
}
|
||||
|
||||
// Per reference guide: use Panda matrices directly.
|
||||
// MetaCoreConvertPandaMatrixToGlm correctly handles Panda row-major→GLM column-major.
|
||||
// TryGetEditorCameraMatrices returns:
|
||||
// viewMatrix = inverse(EditorCamera.get_mat(SceneRoot))
|
||||
// projectionMatrix = lens->get_projection_mat()
|
||||
glm::mat4 gizmoViewMatrix(1.0F);
|
||||
glm::mat4 gizmoProjectionMatrix(1.0F);
|
||||
if (!RenderDevice_.TryGetEditorCameraMatrices(gizmoViewMatrix, gizmoProjectionMatrix)) {
|
||||
gizmoProjectionMatrix = glm::perspective(
|
||||
glm::radians(sceneView.VerticalFieldOfViewDegrees),
|
||||
gizmoAspect, 0.05F, 500.0F
|
||||
glm::mat4 transformMatrix = MetaCoreBuildPandaSpaceTransformMatrix(selectedObject->Transform);
|
||||
(void)ViewportRenderer_.TryGetObjectWorldMatrix(selectedObject->Id, transformMatrix);
|
||||
const glm::mat4 originalTransformMatrix = transformMatrix;
|
||||
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::Enable(true);
|
||||
ImGuizmo::AllowAxisFlip(true);
|
||||
ImGuizmo::SetGizmoSizeClipSpace(0.30F);
|
||||
ImGuizmo::SetDrawlist(ImGui::GetWindowDrawList());
|
||||
ImGuizmo::SetRect(
|
||||
ImGui::GetWindowPos().x,
|
||||
ImGui::GetWindowPos().y,
|
||||
viewportState.Width,
|
||||
viewportState.Height
|
||||
);
|
||||
ImGuizmo::Manipulate(
|
||||
glm::value_ptr(gizmoViewMatrix),
|
||||
glm::value_ptr(gizmoProjectionMatrix),
|
||||
MetaCoreToImGuizmoOperation(EditorContext_->GetGizmoOperation()),
|
||||
MetaCoreToImGuizmoMode(EditorContext_->GetGizmoMode()),
|
||||
glm::value_ptr(transformMatrix)
|
||||
);
|
||||
}
|
||||
|
||||
// Model matrix: Panda world matrix used directly.
|
||||
glm::mat4 transformMatrix = MetaCoreBuildPandaSpaceTransformMatrix(selectedObject->Transform);
|
||||
(void)ViewportRenderer_.TryGetObjectWorldMatrix(selectedObject->Id, transformMatrix);
|
||||
const glm::mat4 originalTransformMatrix = transformMatrix;
|
||||
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
ImGuizmo::Enable(true);
|
||||
ImGuizmo::AllowAxisFlip(true);
|
||||
ImGuizmo::SetGizmoSizeClipSpace(0.30F);
|
||||
ImGuizmo::SetDrawlist(ImGui::GetWindowDrawList());
|
||||
ImGuizmo::SetRect(
|
||||
ImGui::GetWindowPos().x,
|
||||
ImGui::GetWindowPos().y,
|
||||
viewportState.Width,
|
||||
viewportState.Height
|
||||
);
|
||||
ImGuizmo::Manipulate(
|
||||
glm::value_ptr(gizmoViewMatrix),
|
||||
glm::value_ptr(gizmoProjectionMatrix),
|
||||
MetaCoreToImGuizmoOperation(EditorContext_->GetGizmoOperation()),
|
||||
MetaCoreToImGuizmoMode(EditorContext_->GetGizmoMode()),
|
||||
glm::value_ptr(transformMatrix)
|
||||
);
|
||||
|
||||
gizmoHovering = ImGuizmo::IsOver();
|
||||
gizmoUsing = ImGuizmo::IsUsing();
|
||||
SceneInteractionService_.HandleGizmoBeginUse(*EditorContext_, gizmoUsing);
|
||||
if (gizmoUsing) {
|
||||
// transformMatrix is in Panda space — apply directly.
|
||||
switch (EditorContext_->GetGizmoOperation()) {
|
||||
case MetaCoreGizmoOperation::Translate:
|
||||
MetaCoreApplyTranslationFromPandaSpaceMatrix(transformMatrix, selectedObject->Transform);
|
||||
break;
|
||||
case MetaCoreGizmoOperation::Rotate:
|
||||
case MetaCoreGizmoOperation::Scale:
|
||||
MetaCoreApplyTransformFromPandaSpaceMatrix(transformMatrix, selectedObject->Transform);
|
||||
break;
|
||||
case MetaCoreGizmoOperation::None:
|
||||
default:
|
||||
transformMatrix = originalTransformMatrix;
|
||||
break;
|
||||
gizmoHovering = ImGuizmo::IsOver();
|
||||
gizmoUsing = ImGuizmo::IsUsing();
|
||||
SceneInteractionService_.HandleGizmoBeginUse(*EditorContext_, gizmoUsing);
|
||||
if (gizmoUsing) {
|
||||
switch (EditorContext_->GetGizmoOperation()) {
|
||||
case MetaCoreGizmoOperation::Translate:
|
||||
MetaCoreApplyTranslationFromPandaSpaceMatrix(transformMatrix, selectedObject->Transform);
|
||||
break;
|
||||
case MetaCoreGizmoOperation::Rotate:
|
||||
case MetaCoreGizmoOperation::Scale:
|
||||
MetaCoreApplyTransformFromPandaSpaceMatrix(transformMatrix, selectedObject->Transform);
|
||||
break;
|
||||
case MetaCoreGizmoOperation::None:
|
||||
default:
|
||||
transformMatrix = originalTransformMatrix;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr float viewManipulateSize = 112.0F;
|
||||
const ImVec2 canvasPosition = ImGui::GetWindowPos();
|
||||
ImGuizmo::ViewManipulate(
|
||||
glm::value_ptr(gizmoViewMatrix),
|
||||
cameraDistance,
|
||||
ImVec2(canvasPosition.x + viewportState.Width - viewManipulateSize - 16.0F, canvasPosition.y + 16.0F),
|
||||
ImVec2(viewManipulateSize, viewManipulateSize),
|
||||
IM_COL32(26, 30, 36, 180)
|
||||
);
|
||||
|
||||
if (ImGuizmo::IsUsingViewManipulate()) {
|
||||
// gizmoViewMatrix modified → camera moved. Extract Panda-space camera pos.
|
||||
const glm::mat4 newCameraWorld = glm::inverse(gizmoViewMatrix);
|
||||
const glm::vec3 newPandaEye = glm::vec3(newCameraWorld[3]);
|
||||
MetaCoreSceneView manipulatedSceneView = sceneView;
|
||||
manipulatedSceneView.CameraPosition = MetaCoreFromPandaSpacePoint(newPandaEye);
|
||||
manipulatedSceneView.CameraTarget = selectedObject->Transform.Position;
|
||||
EditorContext_->GetCameraController().ApplySceneView(manipulatedSceneView);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar(3);
|
||||
} else {
|
||||
gizmoHovering = false;
|
||||
gizmoUsing = false;
|
||||
}
|
||||
|
||||
if (!gizmoUsing) {
|
||||
EditorContext_->GetCameraController().Update(viewportState, EditorContext_->GetInput());
|
||||
|
||||
@ -12,6 +12,10 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
@ -20,6 +24,31 @@ namespace MetaCore {
|
||||
|
||||
namespace {
|
||||
|
||||
void MetaCoreWindowTrace(const char* message) {
|
||||
if (message == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const auto time = std::chrono::system_clock::to_time_t(now);
|
||||
struct tm timeInfo {};
|
||||
localtime_s(&timeInfo, &time);
|
||||
|
||||
char timeBuffer[32]{};
|
||||
std::strftime(timeBuffer, sizeof(timeBuffer), "[%H:%M:%S] ", &timeInfo);
|
||||
|
||||
FILE* file = nullptr;
|
||||
if (fopen_s(&file, "editor.crash.log", "a") == 0 && file != nullptr) {
|
||||
std::fputs(timeBuffer, file);
|
||||
std::fputs(message, file);
|
||||
std::fputs("\n", file);
|
||||
std::fflush(file);
|
||||
std::fclose(file);
|
||||
}
|
||||
|
||||
std::printf("%s%s\n", timeBuffer, message);
|
||||
}
|
||||
|
||||
void MetaCoreConfigurePanda3D(const std::string& title) {
|
||||
static bool configured = false;
|
||||
if (configured) {
|
||||
@ -34,7 +63,11 @@ void MetaCoreConfigurePanda3D(const std::string& title) {
|
||||
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");
|
||||
|
||||
// Use window-title PrC variable instead of WindowProperties::set_title to avoid ABI mismatch in Debug builds.
|
||||
const std::string configData = "window-title " + title + "\n";
|
||||
load_prc_file_data("", configData);
|
||||
|
||||
configured = true;
|
||||
}
|
||||
|
||||
@ -116,41 +149,73 @@ MetaCoreWindow::~MetaCoreWindow() {
|
||||
}
|
||||
|
||||
bool MetaCoreWindow::Initialize(int width, int height, const std::string& title) {
|
||||
if (Impl_->Initialized) {
|
||||
try {
|
||||
MetaCoreWindowTrace("window:init enter");
|
||||
if (Impl_->Initialized) {
|
||||
MetaCoreWindowTrace("window:init already initialized");
|
||||
return true;
|
||||
}
|
||||
|
||||
MetaCoreWindowTrace("window:init configure panda");
|
||||
MetaCoreConfigurePanda3D(title);
|
||||
MetaCoreWindowTrace("window:init open framework");
|
||||
Impl_->Framework.open_framework();
|
||||
|
||||
MetaCoreWindowTrace("window:init setup window properties start");
|
||||
WindowProperties windowProperties;
|
||||
|
||||
MetaCoreWindowTrace("window:init windowProperties.set_size");
|
||||
windowProperties.set_size(width, height);
|
||||
|
||||
MetaCoreWindowTrace("window:init skip windowProperties.set_title due to ABI issues");
|
||||
// windowProperties.set_title(title); // This triggers bad_alloc in VS2022 Debug vs Panda3D VS2019 SDK
|
||||
|
||||
MetaCoreWindowTrace("window:init windowProperties.set_foreground");
|
||||
windowProperties.set_foreground(true);
|
||||
|
||||
MetaCoreWindowTrace("window:init open window");
|
||||
Impl_->WindowFrameworkHandle = Impl_->Framework.open_window(windowProperties, 0);
|
||||
if (Impl_->WindowFrameworkHandle == nullptr) {
|
||||
MetaCoreWindowTrace("window:init open window returned null");
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
MetaCoreWindowTrace("window:init get graphics window");
|
||||
Impl_->GraphicsWindowHandle = Impl_->WindowFrameworkHandle->get_graphics_window();
|
||||
MetaCoreWindowTrace("window:init resolve native handle");
|
||||
Impl_->NativeHandle = MetaCoreResolveNativeWindowHandle(Impl_->GraphicsWindowHandle);
|
||||
if (Impl_->GraphicsWindowHandle == nullptr || Impl_->NativeHandle == nullptr) {
|
||||
MetaCoreWindowTrace("window:init graphics/native handle invalid");
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
MetaCoreWindowTrace("window:init subclass window proc");
|
||||
MetaCoreGetWindowMap()[Impl_->NativeHandle] = Impl_.get();
|
||||
Impl_->OriginalWindowProc = reinterpret_cast<WNDPROC>(
|
||||
SetWindowLongPtr(Impl_->NativeHandle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&MetaCoreWindowSubclassProc))
|
||||
);
|
||||
|
||||
Impl_->CloseRequested = false;
|
||||
Impl_->LastFrameTime = std::chrono::steady_clock::now();
|
||||
Impl_->Initialized = true;
|
||||
MetaCoreWindowTrace("window:init success");
|
||||
return 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) {
|
||||
} catch (const std::bad_alloc&) {
|
||||
MetaCoreWindowTrace("window:init exception bad_alloc");
|
||||
Shutdown();
|
||||
return false;
|
||||
} catch (const std::exception& exceptionObject) {
|
||||
MetaCoreWindowTrace("window:init exception std::exception");
|
||||
MetaCoreWindowTrace(exceptionObject.what());
|
||||
Shutdown();
|
||||
return false;
|
||||
} catch (...) {
|
||||
MetaCoreWindowTrace("window:init exception unknown");
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
Impl_->GraphicsWindowHandle = Impl_->WindowFrameworkHandle->get_graphics_window();
|
||||
Impl_->NativeHandle = MetaCoreResolveNativeWindowHandle(Impl_->GraphicsWindowHandle);
|
||||
if (Impl_->GraphicsWindowHandle == nullptr || Impl_->NativeHandle == nullptr) {
|
||||
Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
MetaCoreGetWindowMap()[Impl_->NativeHandle] = Impl_.get();
|
||||
Impl_->OriginalWindowProc = reinterpret_cast<WNDPROC>(
|
||||
SetWindowLongPtr(Impl_->NativeHandle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&MetaCoreWindowSubclassProc))
|
||||
);
|
||||
|
||||
Impl_->CloseRequested = false;
|
||||
Impl_->LastFrameTime = std::chrono::steady_clock::now();
|
||||
Impl_->Initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MetaCoreWindow::Shutdown() {
|
||||
@ -212,7 +277,14 @@ void MetaCoreWindow::EndFrame() {
|
||||
}
|
||||
|
||||
bool MetaCoreWindow::ShouldClose() const {
|
||||
return !Impl_->Initialized || Impl_->CloseRequested;
|
||||
if (!Impl_->Initialized) {
|
||||
return true;
|
||||
}
|
||||
if (Impl_->CloseRequested) {
|
||||
MetaCoreWindowTrace("window: should_close true (close requested)");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MetaCoreWindow::RequestClose() {
|
||||
|
||||
@ -3,17 +3,55 @@
|
||||
#include "MetaCoreRender/MetaCoreRenderDevice.h"
|
||||
#include "MetaCoreScene/MetaCoreScene.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
|
||||
namespace MetaCore {
|
||||
|
||||
namespace {
|
||||
|
||||
void MetaCoreTrace(const char* message) {
|
||||
if (message == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const auto time = std::chrono::system_clock::to_time_t(now);
|
||||
struct tm timeInfo {};
|
||||
localtime_s(&timeInfo, &time);
|
||||
|
||||
char timeBuffer[32]{};
|
||||
std::strftime(timeBuffer, sizeof(timeBuffer), "[%H:%M:%S] ", &timeInfo);
|
||||
|
||||
FILE* file = nullptr;
|
||||
if (fopen_s(&file, "editor.crash.log", "a") == 0 && file != nullptr) {
|
||||
std::fputs(timeBuffer, file);
|
||||
std::fputs(message, file);
|
||||
std::fputs("\n", file);
|
||||
std::fflush(file);
|
||||
std::fclose(file);
|
||||
}
|
||||
|
||||
std::printf("%s%s\n", timeBuffer, message);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool MetaCoreEditorViewportRenderer::Initialize(MetaCoreRenderDevice& renderDevice) {
|
||||
MetaCoreTrace("viewport_renderer:init enter");
|
||||
Shutdown();
|
||||
|
||||
MetaCoreTrace("viewport_renderer:init scene bridge begin");
|
||||
if (!SceneBridge_.Initialize(renderDevice)) {
|
||||
MetaCoreTrace("viewport_renderer:init scene bridge failed");
|
||||
return false;
|
||||
}
|
||||
MetaCoreTrace("viewport_renderer:init scene bridge done");
|
||||
|
||||
RenderDevice_ = &renderDevice;
|
||||
ViewportRect_ = MetaCoreViewportRect{};
|
||||
MetaCoreTrace("viewport_renderer:init success");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "directionalLight.h"
|
||||
#include "geom.h"
|
||||
#include "geomNode.h"
|
||||
#include "geomLines.h"
|
||||
#include "geomTriangles.h"
|
||||
#include "geomVertexData.h"
|
||||
#include "geomVertexFormat.h"
|
||||
@ -26,6 +27,9 @@
|
||||
#include <glm/gtx/euler_angles.hpp>
|
||||
#include <glm/mat4x4.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
@ -34,6 +38,31 @@ namespace MetaCore {
|
||||
|
||||
namespace {
|
||||
|
||||
void MetaCoreTrace(const char* message) {
|
||||
if (message == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const auto time = std::chrono::system_clock::to_time_t(now);
|
||||
struct tm timeInfo {};
|
||||
localtime_s(&timeInfo, &time);
|
||||
|
||||
char timeBuffer[32]{};
|
||||
std::strftime(timeBuffer, sizeof(timeBuffer), "[%H:%M:%S] ", &timeInfo);
|
||||
|
||||
FILE* file = nullptr;
|
||||
if (fopen_s(&file, "editor.crash.log", "a") == 0 && file != nullptr) {
|
||||
std::fputs(timeBuffer, file);
|
||||
std::fputs(message, file);
|
||||
std::fputs("\n", file);
|
||||
std::fflush(file);
|
||||
std::fclose(file);
|
||||
}
|
||||
|
||||
std::printf("%s%s\n", timeBuffer, message);
|
||||
}
|
||||
|
||||
glm::mat4 MetaCoreBuildBasisSwapMatrix() {
|
||||
glm::mat4 basis(1.0F);
|
||||
basis[0] = glm::vec4(1.0F, 0.0F, 0.0F, 0.0F);
|
||||
@ -66,9 +95,6 @@ LMatrix4f MetaCoreConvertTransformToPanda(const MetaCoreTransformComponent& tran
|
||||
}
|
||||
|
||||
LPoint3f MetaCoreToPandaPoint(const glm::vec3& value) {
|
||||
// MetaCore 使用右手系的 X 右 / Y 上 / Z 前。
|
||||
// Panda3D 使用右手系的 X 右 / Y 前 / Z 上。
|
||||
// 仅交换 Y/Z 会引入镜像,因此这里同时对前向轴取反,保持手性一致。
|
||||
return LPoint3f(value.x, -value.z, value.y);
|
||||
}
|
||||
|
||||
@ -91,39 +117,105 @@ void MetaCoreApplyTransformToPandaNode(const MetaCoreTransformComponent& transfo
|
||||
}
|
||||
|
||||
NodePath MetaCoreCreateGridNode(const NodePath& parentNode) {
|
||||
LineSegs gridBuilder("MetaCoreGrid");
|
||||
gridBuilder.set_thickness(1.0F);
|
||||
MetaCoreTrace("create_grid: begin");
|
||||
try {
|
||||
MetaCoreTrace("create_grid: create vertex data");
|
||||
PT(GeomVertexData) vertexData = new GeomVertexData(
|
||||
"MetaCoreGrid",
|
||||
GeomVertexFormat::get_v3c4(),
|
||||
Geom::UH_static
|
||||
);
|
||||
|
||||
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))));
|
||||
GeomVertexWriter vertexWriter(vertexData, "vertex");
|
||||
GeomVertexWriter colorWriter(vertexData, "color");
|
||||
|
||||
MetaCoreTrace("create_grid: loop start");
|
||||
constexpr int gridHalfExtent = 10;
|
||||
int vertexCount = 0;
|
||||
for (int lineIndex = -gridHalfExtent; lineIndex <= gridHalfExtent; ++lineIndex) {
|
||||
const bool isAxisLine = (lineIndex == 0);
|
||||
const LColor color(isAxisLine ? 0.42F : 0.30F, isAxisLine ? 0.45F : 0.33F, isAxisLine ? 0.50F : 0.36F, 1.0F);
|
||||
|
||||
// X-direction lines
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(lineIndex), 0.0F, static_cast<float>(-gridHalfExtent))));
|
||||
colorWriter.add_data4(color);
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(lineIndex), 0.0F, static_cast<float>(gridHalfExtent))));
|
||||
colorWriter.add_data4(color);
|
||||
|
||||
// Z-direction lines
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(-gridHalfExtent), 0.0F, static_cast<float>(lineIndex))));
|
||||
colorWriter.add_data4(color);
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(static_cast<float>(gridHalfExtent), 0.0F, static_cast<float>(lineIndex))));
|
||||
colorWriter.add_data4(color);
|
||||
|
||||
vertexCount += 4;
|
||||
}
|
||||
MetaCoreTrace("create_grid: loop end");
|
||||
|
||||
MetaCoreTrace("create_grid: create primitive");
|
||||
PT(GeomLines) lines = new GeomLines(Geom::UH_static);
|
||||
for (int i = 0; i < vertexCount; i += 2) {
|
||||
lines->add_vertices(i, i + 1);
|
||||
}
|
||||
|
||||
MetaCoreTrace("create_grid: create geom");
|
||||
PT(Geom) geom = new Geom(vertexData);
|
||||
geom->add_primitive(lines.p());
|
||||
|
||||
PT(GeomNode) geomNode = new GeomNode("MetaCoreGridNode");
|
||||
geomNode->add_geom(geom);
|
||||
|
||||
return parentNode.attach_new_node(geomNode);
|
||||
} catch (...) {
|
||||
return NodePath();
|
||||
}
|
||||
|
||||
return parentNode.attach_new_node(gridBuilder.create());
|
||||
}
|
||||
|
||||
NodePath MetaCoreCreateAxisNode(const NodePath& parentNode) {
|
||||
LineSegs axisBuilder("MetaCoreAxis");
|
||||
axisBuilder.set_thickness(3.0F);
|
||||
MetaCoreTrace("create_axis: begin");
|
||||
try {
|
||||
PT(GeomVertexData) vertexData = new GeomVertexData(
|
||||
"MetaCoreAxis",
|
||||
GeomVertexFormat::get_v3c4(),
|
||||
Geom::UH_static
|
||||
);
|
||||
|
||||
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)));
|
||||
GeomVertexWriter vertexWriter(vertexData, "vertex");
|
||||
GeomVertexWriter colorWriter(vertexData, "color");
|
||||
|
||||
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)));
|
||||
// X Axis (Red)
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
||||
colorWriter.add_data4(LColor(0.92F, 0.26F, 0.26F, 1.0F));
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(2.0F, 0.0F, 0.0F)));
|
||||
colorWriter.add_data4(LColor(0.92F, 0.26F, 0.26F, 1.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)));
|
||||
// Y Axis (Green)
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
||||
colorWriter.add_data4(LColor(0.28F, 0.86F, 0.36F, 1.0F));
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 2.0F, 0.0F)));
|
||||
colorWriter.add_data4(LColor(0.28F, 0.86F, 0.36F, 1.0F));
|
||||
|
||||
return parentNode.attach_new_node(axisBuilder.create());
|
||||
// Z Axis (Blue)
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 0.0F)));
|
||||
colorWriter.add_data4(LColor(0.32F, 0.56F, 0.96F, 1.0F));
|
||||
vertexWriter.add_data3(MetaCoreToPandaPoint(glm::vec3(0.0F, 0.0F, 2.0F)));
|
||||
colorWriter.add_data4(LColor(0.32F, 0.56F, 0.96F, 1.0F));
|
||||
|
||||
PT(GeomLines) lines = new GeomLines(Geom::UH_static);
|
||||
lines->add_vertices(0, 1);
|
||||
lines->add_vertices(2, 3);
|
||||
lines->add_vertices(4, 5);
|
||||
|
||||
PT(Geom) geom = new Geom(vertexData);
|
||||
geom->add_primitive(lines.p());
|
||||
|
||||
PT(GeomNode) geomNode = new GeomNode("MetaCoreAxisNode");
|
||||
geomNode->add_geom(geom);
|
||||
|
||||
return parentNode.attach_new_node(geomNode);
|
||||
} catch (...) {
|
||||
return NodePath();
|
||||
}
|
||||
}
|
||||
|
||||
NodePath MetaCoreCreateUnitCubeNode(const NodePath& parentNode) {
|
||||
@ -196,7 +288,6 @@ glm::mat4 MetaCoreConvertPandaMatrixToGlm(const LMatrix4f& matrix) {
|
||||
glm::mat4 result(1.0F);
|
||||
for (int col = 0; col < 4; ++col) {
|
||||
for (int row = 0; row < 4; ++row) {
|
||||
// Transpose mathematical matrix to switch from Panda's v*M to GLM's M*v.
|
||||
result[col][row] = matrix.get_cell(col, row);
|
||||
}
|
||||
}
|
||||
@ -239,8 +330,10 @@ bool MetaCorePandaSceneBridge::Initialize(MetaCoreRenderDevice& renderDevice) {
|
||||
}
|
||||
|
||||
Impl_->RenderDevice = &renderDevice;
|
||||
|
||||
Impl_->GridNode = MetaCoreCreateGridNode(*sceneRootHandle);
|
||||
Impl_->AxisNode = MetaCoreCreateAxisNode(*sceneRootHandle);
|
||||
|
||||
Impl_->GridNode.set_light_off(1);
|
||||
Impl_->AxisNode.set_light_off(1);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user