feat: expand editor scripting asset and viewport flow
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
@@ -64,6 +65,56 @@ Containers::String NormalizePathString(const std::filesystem::path& path) {
|
||||
return Containers::String(path.lexically_normal().generic_string().c_str());
|
||||
}
|
||||
|
||||
bool IsProjectRelativePath(const std::filesystem::path& path) {
|
||||
const std::string generic = path.generic_string();
|
||||
return !generic.empty() &&
|
||||
generic != "." &&
|
||||
generic != ".." &&
|
||||
generic.rfind("../", 0) != 0;
|
||||
}
|
||||
|
||||
Containers::String ToProjectRelativeIfPossible(const std::filesystem::path& path) {
|
||||
const Containers::String& resourceRoot = ResourceManager::Get().GetResourceRoot();
|
||||
const std::filesystem::path normalizedPath = path.lexically_normal();
|
||||
if (!resourceRoot.Empty() && normalizedPath.is_absolute()) {
|
||||
std::error_code ec;
|
||||
const std::filesystem::path relativePath =
|
||||
std::filesystem::relative(normalizedPath, std::filesystem::path(resourceRoot.CStr()), ec);
|
||||
if (!ec && IsProjectRelativePath(relativePath)) {
|
||||
return NormalizePathString(relativePath);
|
||||
}
|
||||
}
|
||||
|
||||
return NormalizePathString(normalizedPath);
|
||||
}
|
||||
|
||||
Containers::String ResolveSourceDependencyPath(const Containers::String& dependencyPath,
|
||||
const Containers::String& sourcePath) {
|
||||
if (dependencyPath.Empty()) {
|
||||
return dependencyPath;
|
||||
}
|
||||
|
||||
std::filesystem::path dependencyFsPath(dependencyPath.CStr());
|
||||
if (dependencyFsPath.is_absolute()) {
|
||||
return NormalizePathString(dependencyFsPath);
|
||||
}
|
||||
|
||||
const std::filesystem::path sourceFsPath(sourcePath.CStr());
|
||||
if (sourceFsPath.is_absolute()) {
|
||||
return ToProjectRelativeIfPossible(sourceFsPath.parent_path() / dependencyFsPath);
|
||||
}
|
||||
|
||||
const Containers::String& resourceRoot = ResourceManager::Get().GetResourceRoot();
|
||||
if (!resourceRoot.Empty()) {
|
||||
return ToProjectRelativeIfPossible(
|
||||
std::filesystem::path(resourceRoot.CStr()) /
|
||||
sourceFsPath.parent_path() /
|
||||
dependencyFsPath);
|
||||
}
|
||||
|
||||
return NormalizePathString(sourceFsPath.parent_path() / dependencyFsPath);
|
||||
}
|
||||
|
||||
Containers::String ResolveArtifactDependencyPath(const Containers::String& dependencyPath,
|
||||
const Containers::String& ownerArtifactPath) {
|
||||
if (dependencyPath.Empty()) {
|
||||
@@ -358,6 +409,125 @@ bool TryParseTagMap(const std::string& objectText, Material* material) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TryParseStringMapObject(
|
||||
const std::string& objectText,
|
||||
const std::function<void(const Containers::String&, const Containers::String&)>& onEntry) {
|
||||
if (!onEntry || objectText.empty() || objectText.front() != '{' || objectText.back() != '}') {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t pos = 1;
|
||||
while (pos < objectText.size()) {
|
||||
pos = SkipWhitespace(objectText, pos);
|
||||
if (pos >= objectText.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (objectText[pos] == '}') {
|
||||
return true;
|
||||
}
|
||||
|
||||
Containers::String key;
|
||||
if (!ParseQuotedString(objectText, pos, key, &pos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pos = SkipWhitespace(objectText, pos);
|
||||
if (pos >= objectText.size() || objectText[pos] != ':') {
|
||||
return false;
|
||||
}
|
||||
|
||||
pos = SkipWhitespace(objectText, pos + 1);
|
||||
Containers::String value;
|
||||
if (!ParseQuotedString(objectText, pos, value, &pos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
onEntry(key, value);
|
||||
|
||||
pos = SkipWhitespace(objectText, pos);
|
||||
if (pos >= objectText.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (objectText[pos] == ',') {
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (objectText[pos] == '}') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TryApplyTexturePath(Material* material,
|
||||
const Containers::String& textureName,
|
||||
const Containers::String& texturePath) {
|
||||
if (material == nullptr || textureName.Empty() || texturePath.Empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
material->SetTexturePath(
|
||||
textureName,
|
||||
ResolveSourceDependencyPath(texturePath, material->GetPath()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryParseMaterialTextureBindings(const std::string& jsonText, Material* material) {
|
||||
if (material == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* const kKnownTextureKeys[] = {
|
||||
"baseColorTexture",
|
||||
"_BaseColorTexture",
|
||||
"_MainTex",
|
||||
"normalTexture",
|
||||
"_BumpMap",
|
||||
"specularTexture",
|
||||
"emissiveTexture",
|
||||
"metallicTexture",
|
||||
"roughnessTexture",
|
||||
"occlusionTexture",
|
||||
"opacityTexture"
|
||||
};
|
||||
|
||||
for (const char* key : kKnownTextureKeys) {
|
||||
if (!HasKey(jsonText, key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Containers::String texturePath;
|
||||
if (!TryParseStringValue(jsonText, key, texturePath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TryApplyTexturePath(material, Containers::String(key), texturePath);
|
||||
}
|
||||
|
||||
if (HasKey(jsonText, "textures")) {
|
||||
std::string texturesObject;
|
||||
if (!TryExtractObject(jsonText, "textures", texturesObject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryParseStringMapObject(
|
||||
texturesObject,
|
||||
[material](const Containers::String& name, const Containers::String& value) {
|
||||
TryApplyTexturePath(material, name, value);
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryParseCullMode(const Containers::String& value, MaterialCullMode& outMode) {
|
||||
const Containers::String normalized = value.Trim().ToLower();
|
||||
if (normalized == "none" || normalized == "off") {
|
||||
@@ -953,6 +1123,10 @@ bool MaterialLoader::ParseMaterialData(const Containers::Array<Core::uint8>& dat
|
||||
}
|
||||
}
|
||||
|
||||
if (!TryParseMaterialTextureBindings(jsonText, material)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user