载入中...
搜索中...
未找到
AssetCommand.cpp
浏览该文件的文档.
1#include "asset/AssetCooker.h"
2#include "asset/AssetDiff.h"
11
12#include "cmdline/cmdline.h"
13
14#include <CLI11.hpp>
15
16#include <filesystem>
17#include <algorithm>
18#include <fstream>
19#include <iostream>
20#include <iterator>
21#include <limits>
22
23namespace eve::cmd {
24namespace {
25
26using asset_import::PreparedAssetImport;
27using asset_import::ImportPackageIdentity;
28
29Result<std::vector<std::uint8_t>> readFile(const std::filesystem::path& path,
30 std::uint64_t maximumBytes) {
31 std::error_code ec;
32 const auto size = std::filesystem::file_size(path, ec);
33 if (ec || size > maximumBytes || size > std::numeric_limits<std::size_t>::max())
34 return Result<std::vector<std::uint8_t>>::failure(Diagnostic::error(
35 DiagnosticCode::InvalidArgument, "asset input size is outside limits", path.string(), {},
36 "cmd.asset"));
37 std::ifstream input(path, std::ios::binary);
38 if (!input) return Result<std::vector<std::uint8_t>>::failure(Diagnostic::error(
39 DiagnosticCode::NotFound, "cannot open asset input", path.string(), {}, "cmd.asset"));
40 std::vector<std::uint8_t> bytes(static_cast<std::size_t>(size));
41 if (!bytes.empty()) input.read(reinterpret_cast<char*>(bytes.data()), static_cast<std::streamsize>(bytes.size()));
42 if (!input) return Result<std::vector<std::uint8_t>>::failure(Diagnostic::error(
43 DiagnosticCode::Failed, "cannot read complete asset input", path.string(), {}, "cmd.asset"));
44 return Result<std::vector<std::uint8_t>>::success(std::move(bytes));
45}
46
47void printFailure(const Status& status) {
48 const Diagnostic* diagnostic = status.primaryDiagnostic();
49 if (!diagnostic) {
50 std::cerr << "asset operation failed\n";
51 return;
52 }
53 std::cerr << diagnostic->source() << ": " << diagnostic->message();
54 if (!diagnostic->path().empty()) std::cerr << " [" << diagnostic->path() << "]";
55 std::cerr << "\n";
56}
57
58Result<ImportPackageIdentity> packageIdentity(std::string_view id, std::string name,
59 std::string version) {
60 auto parsed = PersistentId::parse(id);
61 if (!parsed || parsed->isNil() || name.empty() || version.empty())
64 "--package-id must be a non-nil canonical UUID and package name/version are required", {}, {},
65 "cmd.asset"));
66 Value::Object provenance{{"provider", Value("local")},
67 {"license", Value(Value::Object{{"redistribution", Value("unknown")}})}};
69 {*parsed, std::move(name), std::move(version), std::move(provenance)});
70}
71
72Result<asset_import::UnitySourceFiles> readTree(const std::filesystem::path& root, std::uint64_t maximumBytes,
73 std::uint64_t maximumFiles = 200000) {
74 std::error_code ec;
75 if (!std::filesystem::is_directory(root, ec))
77 Diagnostic::error(DiagnosticCode::NotFound, "asset project root is not a readable directory", root.string(),
78 {}, "cmd.asset"));
80 std::uint64_t total = 0;
81 for (std::filesystem::recursive_directory_iterator it(root, std::filesystem::directory_options::none, ec), end;
82 !ec && it != end; it.increment(ec)) {
83 if (it->is_symlink(ec) || ec)
85 Diagnostic::error(DiagnosticCode::InvalidArgument, "asset source links cannot be followed",
86 it->path().string(), {}, "cmd.asset"));
87 const bool regular = it->is_regular_file(ec);
88 if (ec) break;
89 if (!regular) continue;
90 const auto size = it->file_size(ec);
91 if (ec) break;
92 if (size > maximumBytes || total > maximumBytes - size || files.size() >= maximumFiles)
94 Diagnostic::error(DiagnosticCode::InvalidArgument, "asset project exceeds source budget",
95 it->path().string(), {}, "cmd.asset"));
96 auto bytes = readFile(it->path(), maximumBytes);
98 const auto utf8Path = it->path().lexically_relative(root).generic_u8string();
99 const std::string relative(reinterpret_cast<const char*>(utf8Path.data()), utf8Path.size());
100 if (relative.empty())
102 DiagnosticCode::Failed, "cannot resolve asset path", it->path().string(), {}, "cmd.asset"));
103 total += size;
104 files.emplace(relative, std::move(bytes).takeValue());
105 }
106 if (ec)
108 DiagnosticCode::Failed, "cannot traverse asset project: " + ec.message(), root.string(), {}, "cmd.asset"));
110}
111
112Result<asset_import::UnitySourceFiles> readUnityInput(const std::string& input,
113 const asset_import::AssetImportLimits& limits) {
114 std::error_code ec;
115 const auto sourcePath = std::filesystem::path(std::u8string(input.begin(), input.end()));
116 if (std::filesystem::is_regular_file(sourcePath, ec)) {
117 auto bytes = readFile(sourcePath, limits.maximumSourceBytes);
120 }
121 const auto assetsRoot = sourcePath / "Assets";
122 if (!std::filesystem::is_directory(assetsRoot, ec))
123 return readTree(sourcePath, limits.maximumSourceBytes, std::uint64_t(limits.maximumAssets) * 2);
124 auto files = readTree(assetsRoot, limits.maximumSourceBytes, std::uint64_t(limits.maximumAssets) * 2);
125 if (!files) return files;
127 for (auto& [path, bytes] : files.value()) prefixed.emplace("Assets/" + path, std::move(bytes));
128 return Result<asset_import::UnitySourceFiles>::success(std::move(prefixed));
129}
130
131std::string_view unityKindName(asset_import::UnitySourceKind kind) {
133 switch (kind) {
134 case Folder: return "folder";
135 case Prefab: return "prefab";
136 case Scene: return "scene";
137 case Model: return "model";
138 case Material: return "material";
139 case Image: return "image";
140 case Animation: return "animation";
141 case Audio: return "audio";
142 case Font: return "font";
143 case Shader: return "shader";
144 case Script: return "script";
145 case Data: return "data";
146 case Other: return "other";
147 }
148 return "other";
149}
150
151struct AssetArgs final : Handler {
152 CLI::App* assetCommand = nullptr;
153 CLI::App* importCommand = nullptr;
154 CLI::App* scanCommand = nullptr;
155 CLI::App* validateCommand = nullptr;
156 CLI::App* inspectCommand = nullptr;
157 CLI::App* cookCommand = nullptr;
158 CLI::App* migrateCommand = nullptr;
159 CLI::App* migrateAnimationCommand = nullptr;
160 CLI::App* diffCommand = nullptr;
161 std::string from, input, secondInput, output, packageId, packageName = "imported.asset", packageVersion = "1.0.0";
162 bool strict = false;
163 std::string descriptor, terrain, terrainDetails, prefab, colorSpace = "srgb", usage = "color", target;
164
165 void setup(CLI::App& app, std::shared_ptr<CLI::Formatter> formatter) override {
166 assetCommand = app.add_subcommand("asset", "Import, validate, inspect and Cook EVEngine asset packages");
167 assetCommand->formatter(formatter);
169 assetCommand->add_subcommand("scan", "Index a Unity package or source directory without importing");
170 scanCommand->add_option("input", input)->required();
171 importCommand = assetCommand->add_subcommand("import", "Import source content into a canonical .eva");
172 importCommand->add_option("input", input)->required();
173 importCommand->add_option("--from", from, "image|gltf|unity|ue5|shader")->required();
174 importCommand->add_option("--out", output)->required();
175 importCommand->add_option("--package-id", packageId)->required();
176 importCommand->add_option("--name", packageName);
177 importCommand->add_option("--version", packageVersion);
178 importCommand->add_option("--descriptor", descriptor, "UE adapter descriptor relative to input root");
179 importCommand->add_option("--terrain", terrain, "Unity TerrainData relative to input root");
180 importCommand->add_option("--terrain-details", terrainDetails,
181 "Unity Terrain Detail sidecar relative to input root");
182 importCommand->add_option("--prefab", prefab, "Unity Prefab relative to input root");
183 importCommand->add_option("--color-space", colorSpace, "srgb|linear");
184 importCommand->add_option("--usage", usage);
185 importCommand->add_flag("--strict", strict,
186 "Reject out-of-range glTF material factors instead of clamping with warnings");
187 validateCommand = assetCommand->add_subcommand("validate", "Fully validate a .eva or .evpack");
188 validateCommand->add_option("input", input)->required();
189 inspectCommand = assetCommand->add_subcommand("inspect", "Print package identities and contents");
190 inspectCommand->add_option("input", input)->required();
191 cookCommand = assetCommand->add_subcommand("cook", "Cook .eva into target-specific .evpack");
192 cookCommand->add_option("input", input)->required();
193 cookCommand->add_option("--target", target)->required();
194 cookCommand->add_option("--out", output)->required();
195 migrateCommand = assetCommand->add_subcommand(
196 "migrate", "Migrate N-1 canonical definitions and atomically publish a new .eva");
197 migrateCommand->add_option("input", input)->required();
198 migrateCommand->add_option("--out", output)->required();
199 migrateAnimationCommand = assetCommand->add_subcommand(
200 "migrate-animation", "Wrap a legacy EVA 1 text fixture as canonical skeleton/clip .eva");
201 migrateAnimationCommand->add_option("input", input)->required();
202 migrateAnimationCommand->add_option("--out", output)->required();
203 migrateAnimationCommand->add_option("--package-id", packageId)->required();
204 migrateAnimationCommand->add_option("--name", packageName);
205 migrateAnimationCommand->add_option("--version", packageVersion);
206 diffCommand = assetCommand->add_subcommand("diff", "Compare canonical assets and dependencies in two .eva files");
207 diffCommand->add_option("before", input)->required();
208 diffCommand->add_option("after", secondInput)->required();
209 }
210
211 int parse(CLI::App&, Cmdline&) override {
212 if (scanCommand && scanCommand->parsed()) return runScan();
213 if (importCommand && importCommand->parsed()) return runImport();
214 if (validateCommand && validateCommand->parsed()) return runValidate(false);
215 if (inspectCommand && inspectCommand->parsed()) return runValidate(true);
216 if (cookCommand && cookCommand->parsed()) return runCook();
217 if (migrateCommand && migrateCommand->parsed()) return runMigrate();
218 if (migrateAnimationCommand && migrateAnimationCommand->parsed()) return runMigrateAnimation();
219 if (diffCommand && diffCommand->parsed()) return runDiff();
220 return -1;
221 }
222
223 int runScan() {
224 auto files = readUnityInput(input, {});
225 if (!files) {
226 printFailure(files.status());
227 return 2;
228 }
229 auto index = asset_import::indexUnitySources(files.value());
230 if (!index) {
231 printFailure(index.status());
232 return 2;
233 }
234 Value::Array assets, findings;
235 for (const auto& entry : index.value().assets) {
236 Value::Array references;
237 for (const auto& reference : entry.references)
238 references.emplace_back(
239 Value::Object{{"guid", Value(reference.guid)}, {"fileID", Value(reference.fileId)}});
240 assets.emplace_back(Value::Object{{"path", Value(entry.path)},
241 {"guid", Value(entry.guid)},
242 {"kind", Value(std::string(unityKindName(entry.kind)))},
243 {"importer", Value(entry.importer)},
244 {"references", Value(std::move(references))}});
245 }
246 for (const auto& finding : index.value().findings)
247 findings.emplace_back(Value::Object{{"path", Value(finding.sourcePath)},
248 {"feature", Value(finding.feature)},
249 {"message", Value(finding.message)}});
250 auto report = Value(Value::Object{{"schema", Value("eve.unity-source-index")},
251 {"schemaVersion", Value(std::int64_t(1))},
252 {"assets", Value(std::move(assets))},
253 {"findings", Value(std::move(findings))}})
254 .toJson();
255 if (!report) {
256 printFailure(report.status());
257 return 2;
258 }
259 std::cout << report.value() << "\n";
260 return 0;
261 }
262
263 int runImport() {
264 auto identity = packageIdentity(packageId, packageName, packageVersion);
265 if (!identity) { printFailure(identity.status()); return 2; }
266 Result<PreparedAssetImport> prepared = Result<PreparedAssetImport>::failure(
267 Diagnostic::error(DiagnosticCode::Unsupported, "unknown importer", from, {}, "cmd.asset"));
268 asset_import::AssetImportLimits limits;
269 if (from == "shader") {
270 auto source = readFile(input, 8 * 1024 * 1024);
271 if (!source) {
272 prepared.ignore();
273 printFailure(source.status());
274 return 2;
275 }
276 prepared.ignore();
278 identity.value(),
279 std::string_view(reinterpret_cast<const char*>(source.value().data()), source.value().size()));
280 } else if (from == "image" || from == "gltf") {
281 auto source = readFile(input, limits.maximumSourceBytes);
282 if (!source) { prepared.ignore(); printFailure(source.status()); return 2; }
283 if (from == "image") {
284 if (colorSpace != "srgb" && colorSpace != "linear") {
285 prepared.ignore(); std::cerr << "--color-space must be srgb or linear\n"; return 2;
286 }
287 prepared.ignore();
289 {identity.value(), std::filesystem::path(input).filename().string(),
290 std::move(source).takeValue(),
292 : asset_import::ImageColorSpace::Linear,
293 usage, limits});
294 } else {
295 std::map<std::string, std::vector<std::uint8_t>> external;
296 std::error_code ec;
297 const auto parent = std::filesystem::path(input).parent_path();
298 for (std::filesystem::directory_iterator it(parent.empty() ? "." : parent, ec), end;
299 !ec && it != end; it.increment(ec)) {
300 if (!it->is_regular_file() || it->path() == std::filesystem::path(input)) continue;
301 auto value = readFile(it->path(), limits.maximumSourceBytes);
302 if (value) external.emplace(it->path().filename().generic_string(), std::move(value).takeValue());
303 }
304 prepared.ignore();
306 {identity.value(), std::filesystem::path(input).filename().string(), std::move(source).takeValue(),
307 std::move(external), limits,
309 }
310 } else if (from == "unity" || from == "ue5") {
311 auto files = from == "unity" ? readUnityInput(input, limits) : readTree(input, limits.maximumSourceBytes);
312 if (!files) { prepared.ignore(); printFailure(files.status()); return 2; }
313 prepared.ignore();
314 if (from == "unity") {
315 asset_import::UnityProjectImportRequest request;
316 request.package = identity.value();
317 request.files = std::move(files).takeValue();
318 request.terrainDataPath = terrain;
319 request.prefabPath = prefab;
320 request.limits = limits;
321 request.terrainDetailsPath = terrainDetails;
323 } else
325 {identity.value(), std::move(files).takeValue(), descriptor, limits});
326 }
327 if (!prepared) { printFailure(prepared.status()); return 2; }
328 asset::AtomicAssetPackageStore store;
329 auto receipt = store.publishEva(output, prepared.value().manifest, prepared.value().entries);
330 if (!receipt) { printFailure(receipt.status()); return 3; }
331 std::cout << "published " << receipt.value().destination << " package="
332 << receipt.value().packageId.format() << " bytes=" << receipt.value().byteSize << "\n";
333 for (const auto& finding : prepared.value().findings)
334 std::cout << (finding.severity == asset_import::ImportSeverity::Warning ? "warning " : "finding ")
335 << static_cast<unsigned>(finding.disposition) << " " << finding.feature << " " << finding.message
336 << "\n";
337 return 0;
338 }
339
340 int runValidate(bool inspect) {
341 asset::EvaArchiveLimits evaLimits;
342 asset::EvpackLimits packLimits;
343 auto source = readFile(input, std::max(evaLimits.maximumArchiveBytes, packLimits.maximumPackageBytes));
344 if (!source) { printFailure(source.status()); return 2; }
345 if (source.value().size() >= 8 &&
346 std::string_view(reinterpret_cast<const char*>(source.value().data()), 6) == "EVPACK") {
347 auto parsed = asset::parseEvpack(source.value(), packLimits);
348 if (!parsed) { printFailure(parsed.status()); return 2; }
349 if (inspect) std::cout << "evpack package=" << parsed.value().packageId().format()
350 << " build=" << parsed.value().buildId().format()
351 << " variants=" << parsed.value().variants().size()
352 << " chunks=" << parsed.value().chunks().size() << "\n";
353 } else {
354 auto parsed = asset::parseEvaArchive(source.value(), evaLimits);
355 if (!parsed) { printFailure(parsed.status()); return 2; }
356 if (inspect) std::cout << "eva package=" << parsed.value().manifest.packageId.format()
357 << " name=" << parsed.value().manifest.packageName
358 << " assets=" << parsed.value().manifest.assets.size()
359 << " entries=" << parsed.value().entries.size() << "\n";
360 }
361 if (!inspect) std::cout << "valid " << input << "\n";
362 return 0;
363 }
364
365 int runCook() {
366 asset::EvaArchiveLimits evaLimits;
367 auto source = readFile(input, evaLimits.maximumArchiveBytes);
368 if (!source) { printFailure(source.status()); return 2; }
369 auto archive = asset::parseEvaArchive(source.value(), evaLimits);
370 if (!archive) { printFailure(archive.status()); return 2; }
372 if (!profile) { printFailure(profile.status()); return 2; }
373 auto cooked = asset::cookEvaToEvpack(archive.value(), profile.value());
374 if (!cooked) { printFailure(cooked.status()); return 3; }
375 asset::AtomicAssetPackageStore store;
376 auto receipt = store.publishEvpack(output, cooked.value().bytes);
377 if (!receipt) { printFailure(receipt.status()); return 3; }
378 std::cout << "published " << receipt.value().destination << " build="
379 << receipt.value().buildId->format() << " chunks=" << cooked.value().chunkCount << "\n";
380 return 0;
381 }
382
383 int runMigrate() {
384 asset::EvaArchiveLimits limits;
385 auto source = readFile(input, limits.maximumArchiveBytes);
386 if (!source) { printFailure(source.status()); return 2; }
387 auto archive = asset::parseEvaArchive(source.value(), limits);
388 if (!archive) { printFailure(archive.status()); return 2; }
389 auto migrated = asset::migrateEvaArchive(std::move(archive).takeValue(), limits);
390 if (!migrated) { printFailure(migrated.status()); return 3; }
391 auto candidate = std::move(migrated).takeValue();
392 asset::AtomicAssetPackageStore store;
393 auto receipt = store.publishEva(output, candidate.manifest, std::move(candidate.entries), limits);
394 if (!receipt) { printFailure(receipt.status()); return 3; }
395 std::cout << "published migrated " << receipt.value().destination << " package="
396 << receipt.value().packageId.format() << "\n";
397 return 0;
398 }
399
400 int runMigrateAnimation() {
401 asset_import::AssetImportLimits limits;
402 auto identity = packageIdentity(packageId, packageName, packageVersion);
403 if (!identity) { printFailure(identity.status()); return 2; }
404 auto source = readFile(input, limits.maximumSourceBytes);
405 if (!source) { printFailure(source.status()); return 2; }
406 std::string text(reinterpret_cast<const char*>(source.value().data()), source.value().size());
408 {identity.value(), std::filesystem::path(input).filename().string(), std::move(text), limits});
409 if (!prepared) { printFailure(prepared.status()); return 2; }
410 auto candidate = std::move(prepared).takeValue();
411 asset::AtomicAssetPackageStore store;
412 auto receipt = store.publishEva(output, candidate.manifest, std::move(candidate.entries));
413 if (!receipt) { printFailure(receipt.status()); return 3; }
414 std::cout << "published animation " << receipt.value().destination << " package="
415 << receipt.value().packageId.format() << "\n";
416 return 0;
417 }
418
419 int runDiff() {
420 asset::EvaArchiveLimits limits;
421 auto beforeBytes = readFile(input, limits.maximumArchiveBytes);
422 auto afterBytes = readFile(secondInput, limits.maximumArchiveBytes);
423 if (!beforeBytes) { printFailure(beforeBytes.status()); return 2; }
424 if (!afterBytes) { printFailure(afterBytes.status()); return 2; }
425 auto before = asset::parseEvaArchive(beforeBytes.value(), limits);
426 auto after = asset::parseEvaArchive(afterBytes.value(), limits);
427 if (!before) { printFailure(before.status()); return 2; }
428 if (!after) { printFailure(after.status()); return 2; }
429 auto difference = asset::diffEvaManifests(before.value().manifest, after.value().manifest);
430 if (!difference) { printFailure(difference.status()); return 3; }
431 for (const auto& change : difference.value().assets) {
432 const char* kind = change.kind == asset::EvaAssetChangeKind::Added ? "added" :
433 change.kind == asset::EvaAssetChangeKind::Removed ? "removed" : "changed";
434 std::cout << kind << " asset://" << change.assetId.format();
435 if (!change.beforeType.empty()) std::cout << " before=" << change.beforeType << "/" << change.beforeVersion.value();
436 if (!change.afterType.empty()) std::cout << " after=" << change.afterType << "/" << change.afterVersion.value();
437 std::cout << "\n";
438 }
439 std::cout << "dependencies +" << difference.value().addedDependencies << " -"
440 << difference.value().removedDependencies << " entrypoints="
441 << (difference.value().entrypointsChanged ? "changed" : "same") << "\n";
442 return 0;
443 }
444};
445
446CMD_REG(AssetArgs);
447
448} // namespace
449} // namespace eve::cmd
LogicalId target
double value
int root
Definition AnimSmr.cpp:119
Vec3 relative
Definition AnimSmr.cpp:164
CLI::App * cookCommand
std::string usage
std::string packageName
CLI::App * importCommand
std::string prefab
CLI::App * diffCommand
CLI::App * scanCommand
std::string packageVersion
CLI::App * inspectCommand
std::string output
std::string packageId
CLI::App * assetCommand
std::string descriptor
CLI::App * migrateAnimationCommand
std::string secondInput
std::string terrain
CLI::App * migrateCommand
std::string colorSpace
std::string from
bool strict
CLI::App * validateCommand
std::string terrainDetails
Deterministic canonical .eva to capability-targeted .evpack Cook.
Deterministic semantic comparison of two `.eva` manifests.
Tool-side image and glTF importers producing canonical .eva candidates.
Transactional migrations for canonical definitions stored in .eva.
Reopen-verified atomic publication for .eva and .evpack files.
AuthorityStoreHandleRef reference
Definition Authority.cpp:24
EvpackChunkInput input
Definition Evpack.cpp:170
std::string message
const GltfImportRequest & request
wgpu::PopErrorScopeStatus status
std::string text
TokenKind kind
std::int32_t parent
Migration of legacy `*.anim.txt` fixtures to `.eva`.
std::uint64_t bytes
std::string name
std::string path
Definition PlayHost.cpp:110
std::string sourcePath
float size
Definition TreeMesh.cpp:156
Direct Unity text-serialization adapter for TerrainData and Prefab assets.
std::vector< ImportFinding > findings
Bounded Unity package ingestion and project identity index.
uint32_t index
const UnitySourceAsset & source
const AssetImportLimits & limits
UE5/M⁴ landscape adapter that does not execute or link Unreal Engine.
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
const std::string & source() const noexcept
Optional producer or subsystem that emitted the diagnostic.
Definition Diagnostic.h:153
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
std::map< std::string, Value > Object
Definition Value.h:34
std::vector< Value > Array
Definition Value.h:33
static std::optional< Id128 > parse(std::string_view text) noexcept
Parses canonical UUID text.
Definition Identity.h:151
#define CMD_REG(name)
Definition cmdline.h:101
Result< UnitySourceFiles > readUnityPackage(std::span< const std::uint8_t > bytes, const AssetImportLimits &limits)
Decode a gzip/tar .unitypackage into project-relative source bytes without extraction.
ImportSeverity
Severity of an importer finding, independent of its conversion disposition.
Result< PreparedAssetImport > prepareLegacyAnimationImport(const LegacyAnimationImportRequest &request)
Convert a legacy text fixture into canonical skeleton and animation-clip assets.
GltfImportMode
Strict rejects invalid material factors; permissive clamps finite factors with warnings.
std::map< std::string, std::vector< std::uint8_t > > UnitySourceFiles
Owning project-relative source bytes, including the original .meta files.
Definition UnitySource.h:12
UnitySourceKind
Source category; classification does not imply runtime conversion support.
Definition UnitySource.h:15
Result< PreparedAssetImport > prepareShaderImport(const ImportPackageIdentity &package, std::string_view json)
Prepare a canonical shader definition for the existing atomic .eva publisher.
ImageColorSpace
Explicit source color semantics; importers never infer platform defaults.
Result< UnitySourceIndex > indexUnitySources(const UnitySourceFiles &files, const AssetImportLimits &limits)
Validate project paths and .meta identities and index serialized GUID/fileID references.
Result< PreparedAssetImport > prepareUnityProjectImport(const UnityProjectImportRequest &request)
Import selected Unity assets, or discover a collection when both selectors are empty.
EVENGINE_API_PLATFORM Result< PreparedAssetImport > prepareImageImport(const ImageImportRequest &request)
Decode image metadata and prepare one canonical eve.image source asset.
Result< PreparedAssetImport > prepareUnrealM4Import(const UnrealProjectImportRequest &request)
Import an M⁴-style Landscape/material/grass slice without launching Unreal.
EVENGINE_API_PLATFORM Result< PreparedAssetImport > prepareGltfImport(const GltfImportRequest &request)
Decode triangle primitives from glTF 2.0 into canonical typed mesh blobs.
Result< Evpack > parseEvpack(std::span< const std::uint8_t > bytes, const EvpackLimits &limits, const EvpackTrust &trust)
Parse, bound-check and hash-verify a complete untrusted .evpack.
Definition Evpack.cpp:542
Result< EvaArchive > parseEvaArchive(std::span< const std::uint8_t > bytes, const EvaArchiveLimits &limits)
Parse and fully verify an untrusted .eva ZIP64 image.
Result< EvaPackageDiff > diffEvaManifests(const EvaManifest &before, const EvaManifest &after)
Compare two admitted manifests without using paths, timestamps or archive order.
Definition AssetDiff.cpp:29
Result< AssetCookReceipt > cookEvaToEvpack(const EvaArchive &source, const AssetCookProfile &profile, const EvaArchiveLimits &evaLimits, const EvpackLimits &evpackLimits)
Cook an admitted source archive into one target-specific runtime pack.
Result< EvaArchive > migrateEvaArchive(EvaArchive source, const EvaArchiveLimits &limits)
Migrate every definition in an owning archive to its current schema.
Result< AssetCookProfile > assetCookProfileForTarget(std::string_view target)
Resolve a stable CLI/tool target name to its exact capability profile.
std::variant< std::monostate, std::int64_t, double, std::string, bool > Value
Definition Database.h:26
eve::Diagnostic Diagnostic
ModelData parse(std::span< const uint8_t > bytes)
Parse.
enum EVENGINE_API_FOUNDATION Other
Any other slot kind.
Definition Runtime.h:123