feat: add mesh component editors and scene hierarchy serialization
This commit is contained in:
111
editor/src/ComponentEditors/AssetReferenceEditorUtils.h
Normal file
111
editor/src/ComponentEditors/AssetReferenceEditorUtils.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include "Application.h"
|
||||
#include "Actions/ProjectActionRouter.h"
|
||||
#include "UI/UI.h"
|
||||
#include "Utils/ProjectFileUtils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <initializer_list>
|
||||
#include <string>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace ComponentEditorAssetUI {
|
||||
|
||||
struct AssetReferenceInteraction {
|
||||
std::string assignedPath;
|
||||
bool clearRequested = false;
|
||||
};
|
||||
|
||||
inline std::string ToProjectRelativeAssetPath(const std::string& assetPath) {
|
||||
if (assetPath.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const std::string& projectPath = Application::Get().GetEditorContext().GetProjectPath();
|
||||
if (projectPath.empty()) {
|
||||
return assetPath;
|
||||
}
|
||||
|
||||
return ProjectFileUtils::MakeProjectRelativePath(projectPath, assetPath);
|
||||
}
|
||||
|
||||
inline bool HasSupportedExtension(
|
||||
const std::string& path,
|
||||
std::initializer_list<const char*> supportedExtensions) {
|
||||
std::string extension = std::filesystem::path(path).extension().string();
|
||||
std::transform(extension.begin(), extension.end(), extension.begin(), [](unsigned char ch) {
|
||||
return static_cast<char>(std::tolower(ch));
|
||||
});
|
||||
|
||||
for (const char* supportedExtension : supportedExtensions) {
|
||||
if (supportedExtension != nullptr && extension == supportedExtension) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline AssetReferenceInteraction DrawAssetReferenceProperty(
|
||||
const char* label,
|
||||
const std::string& currentPath,
|
||||
const char* emptyHint,
|
||||
std::initializer_list<const char*> supportedExtensions) {
|
||||
AssetReferenceInteraction interaction;
|
||||
|
||||
UI::DrawPropertyRow(label, UI::InspectorPropertyLayout(), [&](const UI::PropertyLayoutMetrics& layout) {
|
||||
constexpr float kClearButtonWidth = 52.0f;
|
||||
|
||||
std::array<char, 512> buffer{};
|
||||
if (!currentPath.empty()) {
|
||||
strncpy_s(buffer.data(), buffer.size(), currentPath.c_str(), _TRUNCATE);
|
||||
}
|
||||
|
||||
const float spacing = ImGui::GetStyle().ItemSpacing.x;
|
||||
const float fieldWidth = (std::max)(layout.controlWidth - kClearButtonWidth - spacing, 1.0f);
|
||||
ImGui::SetNextItemWidth(fieldWidth);
|
||||
ImGui::InputTextWithHint(
|
||||
"##AssetPath",
|
||||
emptyHint,
|
||||
buffer.data(),
|
||||
buffer.size(),
|
||||
ImGuiInputTextFlags_ReadOnly);
|
||||
|
||||
if (ImGui::IsItemHovered() && !currentPath.empty()) {
|
||||
ImGui::SetTooltip("%s", currentPath.c_str());
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(
|
||||
Actions::ProjectAssetPayloadType(),
|
||||
ImGuiDragDropFlags_AcceptNoDrawDefaultRect)) {
|
||||
if (payload->Data != nullptr) {
|
||||
const std::string droppedPath(static_cast<const char*>(payload->Data));
|
||||
if (HasSupportedExtension(droppedPath, supportedExtensions)) {
|
||||
interaction.assignedPath = ToProjectRelativeAssetPath(droppedPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::SameLine(0.0f, spacing);
|
||||
ImGui::BeginDisabled(currentPath.empty());
|
||||
interaction.clearRequested = UI::InspectorActionButton("Clear", ImVec2(kClearButtonWidth, 0.0f));
|
||||
ImGui::EndDisabled();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return interaction;
|
||||
}
|
||||
|
||||
} // namespace ComponentEditorAssetUI
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user