载入中...
搜索中...
未找到
SpriteStackRuntime.cpp
浏览该文件的文档.
2
3#include "graphics/Graphics.h"
4#include "image/ImageData.h"
5#include "model3d/ModelData.h"
6
7#include <algorithm>
8#include <exception>
9#include <utility>
10
12namespace {
13std::uint64_t checksum(const image::ImageData& image) {
14 const auto* bytes = static_cast<const unsigned char*>(image.getData());
15 std::uint64_t hash = 1469598103934665603ull;
16 for (std::size_t i = 0; i < image.getSize(); ++i) {
17 hash ^= bytes[i];
18 hash *= 1099511628211ull;
19 }
20 return hash;
21}
23 std::size_t covered = 0;
24 for (int y = 0; y < image.getHeight(); ++y)
25 for (int x = 0; x < image.getWidth(); ++x)
26 if (image.getPixel(x, y).a > 0.f) ++covered;
27 const std::size_t pixels = static_cast<std::size_t>(image.getWidth()) * image.getHeight();
28 return {index, image.getWidth(), image.getHeight(), checksum(image),
29 pixels ? static_cast<double>(covered) / pixels : 0.0};
30}
31} // namespace
32
35
37 const SpriteStackDocumentTarget& document, const ISpriteStackModelResolver* resolver) {
38 const auto diagnostics = document.validate();
39 for (const auto& d : diagnostics)
40 if (d.severity() == DiagnosticSeverity::Error)
41 return Result<std::vector<SpriteStackLayerArtifact>>::failure(
42 eve::Status(EditorStatus::Rejected, diagnostics));
43 std::vector<image::ImageData*> raw;
44 try {
45 if (document.value().sourceKind == "primitive")
46 raw = spritestack::slicePrimitiveToLayers(document.value().source, document.value().bake);
47 else {
48 if (!resolver)
49 return eve::editing::failed<std::vector<SpriteStackLayerArtifact>>(
50 EditorStatus::Rejected, RuleId("editor.spritestack.resolver"),
51 "Model SpriteStack bake requires an asset resolver");
52 auto resolved = resolver->resolveModel(document.value().source);
53 if (!resolved.ok() || !resolved.value())
54 return Result<std::vector<SpriteStackLayerArtifact>>::failure(resolved.status());
55 raw = spritestack::sliceModelToLayers(resolved.value(), document.value().bake);
56 }
57 } catch (const std::exception& exception) {
58 for (auto* layer : raw) delete layer;
59 return eve::editing::failed<std::vector<SpriteStackLayerArtifact>>(
60 EditorStatus::Failed, RuleId("editor.spritestack.bake"), exception.what());
61 }
62 if (raw.size() != static_cast<std::size_t>(document.value().bake.layerCount) ||
63 std::any_of(raw.begin(), raw.end(), [](auto* p) { return p == nullptr; })) {
64 for (auto* layer : raw) delete layer;
65 return eve::editing::failed<std::vector<SpriteStackLayerArtifact>>(
66 EditorStatus::Failed, RuleId("editor.spritestack.layer-count"),
67 "SpriteStack baker returned an incomplete generation");
68 }
69 std::vector<std::unique_ptr<image::ImageData>> candidate;
70 std::vector<SpriteStackLayerArtifact> artifacts;
71 candidate.reserve(raw.size());
72 artifacts.reserve(raw.size());
73 for (std::size_t i = 0; i < raw.size(); ++i) {
74 candidate.emplace_back(raw[i]);
75 artifacts.push_back(artifact(*raw[i], static_cast<int>(i)));
76 }
77 layers_ = std::move(candidate);
78 stack_.reset();
79 value_ = document.value();
80 revision_ = document.revision();
81 return eve::editing::applied<std::vector<SpriteStackLayerArtifact>>(std::move(artifacts), diagnostics);
82}
83
85 Revision expectedRevision) {
86 if (expectedRevision != revision_)
87 return eve::editing::failed<spritestack::SpriteStack2D*>(
88 EditorStatus::Conflict, RuleId("editor.spritestack.stale"), "SpriteStack bake generation is stale");
89 if (!graphics || layers_.empty())
90 return eve::editing::failed<spritestack::SpriteStack2D*>(
91 EditorStatus::Rejected, RuleId("editor.spritestack.publish"),
92 "SpriteStack publication requires Graphics and baked layers");
93 auto candidate = std::make_unique<spritestack::SpriteStack2D>();
94 try {
95 candidate->setLayerCount(static_cast<int>(layers_.size()));
96 for (std::size_t i = 0; i < layers_.size(); ++i)
97 candidate->setLayerImage(graphics, layers_[i].get(), static_cast<int>(i));
98 candidate->setThickness(value_.layerOffset);
99 candidate->setSize(value_.displayWidth, value_.displayHeight);
100 candidate->setShadowEnabled(value_.shadow);
101 candidate->setShadowOpacity(value_.shadowOpacity);
102 candidate->setOutline(value_.outlineWidth);
103 } catch (const std::exception& exception) {
104 return eve::editing::failed<spritestack::SpriteStack2D*>(
105 EditorStatus::Failed, RuleId("editor.spritestack.publish"), exception.what());
106 }
107 stack_ = std::move(candidate);
108 return eve::editing::applied<spritestack::SpriteStack2D*>(stack_.get());
109}
110
111} // namespace eve::spritestack_editing
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
glm::vec4 p[6]
std::array< std::uint8_t, 32 > hash
Definition Evpack.cpp:172
vk::UniqueImage image
std::uint64_t bytes
TileLayer * layer
float d
uint8_t * pixels
uint32_t index
int covered
Move-only operation result carrying either a value or Status.
Definition Result.h:155
Structured status and zero or more diagnostics for an operation.
Definition Status.h:68
std::uint64_t revision() const override
Return the current revision.
Represents raw pixel data.
Definition ImageData.h:38
Resolves model assets without coupling the document to AssetDB ownership.
virtual Result< model3d::ModelData * > resolveModel(const std::string &assetId) const =0
Resolve a ready, borrowed ModelData for the duration of bake().
Result< std::vector< SpriteStackLayerArtifact > > bake(const SpriteStackDocumentTarget &document, const ISpriteStackModelResolver *resolver=nullptr)
Bake all layers in temporary ownership before replacing the generation.
~SpriteStackBakeRuntime()
Sprite stack bake runtime.
SpriteStackBakeRuntime()
Sprite stack bake runtime.
Result< spritestack::SpriteStack2D * > publish(graphics::Graphics *graphics, Revision expectedRevision)
Create and populate a live stack from the current baked generation.
Revisioned SpriteStack bake preset with reusable Inspector metadata.
std::vector< EditorDiagnostic > validate() const
Validate source, sampling limits, output memory and presentation values.
const SpriteStackAssetValue & value() const
Value.
std::vector< image::ImageData * > slicePrimitiveToLayers(const std::string &kind, const SliceOptions &opt)
Slice primitive to layers.
EVENGINE_API_WORLD std::vector< image::ImageData * > sliceModelToLayers(model3d::ModelData *, const SliceOptions &)
Assimp-backed bake; compiled only when the model3d module is linked.
Metadata for one immutable baked layer.