载入中...
搜索中...
未找到
VegetationPresetMaterial.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <cmath>
5#include <iomanip>
6#include <new>
7#include <sstream>
8
9namespace eve::asset_import {
10namespace {
11Result<std::string> shaderGuid(std::string_view shader) {
12 if (shader == "7befaa6f41d00a6478d5f4af21d66518" ||
13 shader == "BOXOPHOBIC/The Vegetation Engine/Geometry/Plant Standard Lit")
14 return Result<std::string>::success("7befaa6f41d00a6478d5f4af21d66518");
15 if (shader == "a933075b367f9b24981408633f72ff34" ||
16 shader == "BOXOPHOBIC/The Vegetation Engine/Geometry/Plant Subsurface Lit")
17 return Result<std::string>::success("a933075b367f9b24981408633f72ff34");
18 if (shader == "6e6307b56f9201d40ad738f21cf03495" ||
19 shader == "BOXOPHOBIC/The Vegetation Engine/Geometry/Prop Standard Lit")
20 return Result<std::string>::success("6e6307b56f9201d40ad738f21cf03495");
21 if (shader == "d9a724745053dee46bf301b216cdd348" ||
22 shader == "BOXOPHOBIC/The Vegetation Engine/Geometry/Prop Subsurface Lit")
23 return Result<std::string>::success("d9a724745053dee46bf301b216cdd348");
25 "vegetation output shader is not an admitted TVE 12.6 target",
26 {}, {}, "asset.import.vegetation-preset.material"));
27}
28
29bool propertyName(std::string_view value) {
30 return !value.empty() && value.size() <= 127 && std::all_of(value.begin(), value.end(), [](unsigned char c) {
31 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_';
32 });
33}
34
35bool finite(const std::array<double, 4>& value) {
36 return std::all_of(value.begin(), value.end(), [](double component) { return std::isfinite(component); });
37}
38
39bool guid(std::string_view value) {
40 return value.size() == 32 && std::all_of(value.begin(), value.end(), [](unsigned char c) {
41 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
42 });
43}
44} // namespace
45
47 const VegetationConversionCandidate& candidate, std::uint64_t maximumBytes) {
48 try {
49 auto shader = shaderGuid(candidate.materialShader);
50 if (!shader) return Result<std::vector<std::uint8_t>>::failure(shader.status());
51 std::map<std::string, std::array<double, 4>> vectors = candidate.materialVectors;
52 for (const auto& [name, value] : candidate.materialColors) {
53 if (const auto found = vectors.find(name); found != vectors.end() && found->second != value)
54 return Result<std::vector<std::uint8_t>>::failure(
55 Diagnostic::error(DiagnosticCode::Conflict, "material vector and color values conflict", name, {},
56 "asset.import.vegetation-preset.material"));
57 vectors[name] = value;
58 }
59 for (const auto& [name, value] : candidate.materialFloats)
60 if (!propertyName(name) || !std::isfinite(value))
61 return Result<std::vector<std::uint8_t>>::failure(
62 Diagnostic::error(DiagnosticCode::InvalidArgument, "invalid vegetation material float", name, {},
63 "asset.import.vegetation-preset.material"));
64 for (const auto& [name, value] : vectors)
65 if (!propertyName(name) || !finite(value))
66 return Result<std::vector<std::uint8_t>>::failure(
67 Diagnostic::error(DiagnosticCode::InvalidArgument, "invalid vegetation material vector", name, {},
68 "asset.import.vegetation-preset.material"));
69 for (const auto& [name, value] : candidate.materialTextures)
70 if (!propertyName(name) || !guid(value))
71 return Result<std::vector<std::uint8_t>>::failure(Diagnostic::error(
72 DiagnosticCode::InvalidArgument, "vegetation material texture requires a lowercase Unity GUID",
73 name, {}, "asset.import.vegetation-preset.material"));
74
75 std::ostringstream text;
76 text << std::setprecision(17);
77 text << "%YAML 1.1\n--- !u!21 &2100000\nMaterial:\n"
78 << " m_Shader: {fileID: 4800000, guid: " << shader.value() << ", type: 3}\n"
79 << " m_ValidKeywords:\n";
80 for (const auto& keyword : candidate.materialKeywords) text << " - " << keyword << '\n';
81 text << " m_EnableInstancingVariants: " << (candidate.materialInstancing ? 1 : 0) << '\n'
82 << " m_SavedProperties:\n serializedVersion: 3\n m_TexEnvs:\n";
83 for (const auto& [name, texture] : candidate.materialTextures) {
84 const auto transform = candidate.materialTextureTransforms.contains(name)
85 ? candidate.materialTextureTransforms.at(name)
86 : std::array<double, 4>{1, 1, 0, 0};
87 if (!finite(transform))
88 return Result<std::vector<std::uint8_t>>::failure(
89 Diagnostic::error(DiagnosticCode::InvalidArgument, "invalid vegetation texture transform", name, {},
90 "asset.import.vegetation-preset.material"));
91 text << " - " << name << ":\n"
92 << " m_Texture: {fileID: 2800000, guid: " << texture << ", type: 3}\n"
93 << " m_Scale: {x: " << transform[0] << ", y: " << transform[1] << "}\n"
94 << " m_Offset: {x: " << transform[2] << ", y: " << transform[3] << "}\n";
95 }
96 text << " m_Ints: []\n m_Floats:\n";
97 for (const auto& [name, value] : candidate.materialFloats) text << " - " << name << ": " << value << '\n';
98 text << " m_Colors:\n";
99 for (const auto& [name, value] : vectors)
100 text << " - " << name << ": {r: " << value[0] << ", g: " << value[1] << ", b: " << value[2]
101 << ", a: " << value[3] << "}\n";
102 const auto encoded = text.str();
103 if (encoded.size() > maximumBytes)
104 return Result<std::vector<std::uint8_t>>::failure(
105 Diagnostic::error(DiagnosticCode::InvalidArgument, "encoded vegetation material exceeds byte budget",
106 {}, {}, "asset.import.vegetation-preset.material"));
107 return Result<std::vector<std::uint8_t>>::success({encoded.begin(), encoded.end()});
108 } catch (const std::bad_alloc&) {
109 return Result<std::vector<std::uint8_t>>::failure(
110 Diagnostic::error(DiagnosticCode::Failed, "vegetation material encoding allocation failed", {}, {},
111 "asset.import.vegetation-preset.material"));
112 }
113}
114} // namespace eve::asset_import
double value
std::int32_t c
std::string text
std::string name
bool finite
Shader * shader
bool found
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
EVENGINE_API_PLATFORM Result< std::vector< std::uint8_t > > encodeUnityVegetationConversionMaterial(const VegetationConversionCandidate &candidate, std::uint64_t maximumBytes=16ull *1024ull *1024ull)
Encode an applied vegetation candidate as a detached Unity text Material for the canonical TVE import...
Owning unpublished material, mesh and texture candidate mutated transactionally by preset commands.
std::map< std::string, std::array< double, 4 > > materialVectors
std::map< std::string, std::array< double, 4 > > materialColors
std::map< std::string, double > materialFloats
std::map< std::string, std::array< double, 4 > > materialTextureTransforms
std::map< std::string, std::string > materialTextures