Files
XCEngine/editor/src/ComponentEditors/AssetReferenceEditorUtils.h

112 lines
3.5 KiB
C
Raw Normal View History

#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