载入中...
搜索中...
未找到
ParticleGraphRuntime.cpp
浏览该文件的文档.
2
4
5#include <utility>
6
8namespace {
9
10const EditorValue* field(const EditorValue& value, const char* key) {
11 const auto* object = value.getIf<EditorValue::Object>();
12 if (!object) return nullptr;
13 const auto found = object->find(key);
14 return found == object->end() ? nullptr : &found->second;
15}
16
17const EditorValue::Array& array(const EditorValue& value, const char* key) {
19}
20
21float number(const EditorValue& value, const char* key) {
22 return static_cast<float>(*field(value, key)->getIf<double>());
23}
24
25int integer(const EditorValue& value, const char* key) {
26 return static_cast<int>(*field(value, key)->getIf<int64_t>());
27}
28
29const std::string& text(const EditorValue& value, const char* key) {
30 return *field(value, key)->getIf<std::string>();
31}
32
33} // namespace
34
37 const TextureResolver& textures) const {
38 if (!emitter)
39 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.particles.runtime-emitter"),
40 "Live particle emitter is required");
42 const ParticleGraphCompileResult compiled = domain.compile(graph);
43 if (compiled.status != EditorStatus::Applied)
44 return Result<void>::failure(eve::Status(compiled.status, compiled.diagnostics));
45 const EditorValue* emission = field(compiled.configuration, "emission");
46 const EditorValue* motion = field(compiled.configuration, "motion");
47 const EditorValue* collision = field(compiled.configuration, "collision");
48 const EditorValue* renderer = field(compiled.configuration, "renderer");
49 const EditorValue* output = field(compiled.configuration, "output");
50 if (emitter->getBufferSize() != integer(*output, "bufferSize"))
51 return eve::editing::failed<void>(
52 EditorStatus::Conflict, RuleId("editor.particles.runtime-buffer-size"),
53 "Live emitter buffer size differs from the graph output; recreate the emitter");
54 const std::string texture = text(*renderer, "texture");
55 graphics::Texture* resolvedTexture = nullptr;
56 if (!texture.empty()) {
57 if (!textures)
58 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.particles.texture-resolver"),
59 "Particle graph references a texture but no resolver was provided");
60 resolvedTexture = textures(texture);
61 if (!resolvedTexture)
62 return eve::editing::failed<void>(EditorStatus::NotFound, RuleId("editor.particles.texture-not-found"),
63 "Particle texture asset could not be resolved: " + texture);
64 }
65
66 const auto& lifetime = array(*emission, "lifetime");
67 const auto& areaSize = array(*emission, "areaSize");
68 emitter->setEmissionRate(number(*emission, "rate"));
69 emitter->setParticleLifetime(static_cast<float>(*lifetime[0].getIf<double>()),
70 static_cast<float>(*lifetime[1].getIf<double>()));
71 emitter->setEmissionArea(text(*emission, "area"),
72 static_cast<float>(*areaSize[0].getIf<double>()),
73 static_cast<float>(*areaSize[1].getIf<double>()));
74 emitter->setRandomSeed(integer(*emission, "randomSeed"));
75 emitter->setAutoRandomSeed(*field(*emission, "autoRandomSeed")->getIf<bool>());
76 emitter->setLooping(*field(*emission, "looping")->getIf<bool>());
77 emitter->setEmitterLifetime(number(*emission, "emitterLife"));
78
79 if (motion) {
80 const auto& speed = array(*motion, "speed");
81 const auto& gravity = array(*motion, "gravity");
82 emitter->setDirection(number(*motion, "direction"));
83 emitter->setSpread(number(*motion, "spread"));
84 emitter->setSpeed(static_cast<float>(*speed[0].getIf<double>()),
85 static_cast<float>(*speed[1].getIf<double>()));
86 emitter->setGravity(static_cast<float>(*gravity[0].getIf<double>()),
87 static_cast<float>(*gravity[1].getIf<double>()));
88 emitter->setDamping(number(*motion, "damping"));
89 emitter->setSimulationSpace(text(*motion, "simulationSpace"));
90 }
91 if (collision) {
92 emitter->setCollision(text(*collision, "mode"), number(*collision, "radius"),
93 number(*collision, "restitution"), number(*collision, "lifetimeLoss"));
94 emitter->setWorldCollision(*field(*collision, "world")->getIf<bool>());
95 }
96 const auto& size = array(*renderer, "size");
97 emitter->setRenderMode(text(*renderer, "mode"));
98 emitter->setMaterialMode(text(*renderer, "material"));
99 emitter->setParticleSize(static_cast<float>(*size[0].getIf<double>()),
100 static_cast<float>(*size[1].getIf<double>()));
101 emitter->setSortMode(text(*renderer, "sort"));
102 emitter->setGpuSimulation(*field(*renderer, "gpu")->getIf<bool>());
103 emitter->setSoftParticles(*field(*renderer, "softParticles")->getIf<bool>(),
104 number(*renderer, "softDepth"), number(*renderer, "softFade"));
105 if (resolvedTexture) emitter->setTexture(resolvedTexture);
106 emitter->setPriority(integer(*output, "priority"));
107 emitter->setMinimumQuality(integer(*output, "minimumQuality"));
108 emitter->setMaxSpawnPerFrame(integer(*output, "maxSpawnPerFrame"));
109 emitter->setOverflowMode(text(*output, "overflow"));
110 return eve::editing::applied<void>();
111}
112
113} // namespace eve::particles_editing
double value
std::string output
std::uint32_t key
std::string text
std::map< std::string, std::vector< std::string > > graph
Definition Package.cpp:59
std::weak_ptr< const void > lifetime
double number
bool found
double gravity
std::unique_ptr< TrailEmitter > emitter
float size
Definition TreeMesh.cpp:156
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Structured status and zero or more diagnostics for an operation.
Definition Status.h:68
Deterministic owning value tree shared by authoring hosts.
std::vector< Value > Array
std::map< std::string, Value > Object
const T * getIf() const
Return an immediately borrowed typed value.
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Definition Texture.h:18
ECS emitter entity. Script configures components; ParticleSimSystem / ParticleRenderSystem drive per-...
particles.emitter graph domain reflecting core emitter modules.
ParticleGraphCompileResult compile(const GraphDocumentData &graph) const
Compile one acyclic module chain into a runtime-neutral configuration object.
Result< void > apply(const GraphDocumentData &graph, particles::ParticleEmitter *emitter, const TextureResolver &textures={}) const
Applies .
std::function< graphics::Texture *(const std::string &asset)> TextureResolver
const EditorValue * field(const EditorValue &value, const char *name)
int64_t integer(const RuntimeTensor &v, size_t i=0)
Integer.
Immutable graph document value sent to a domain compiler.
Validated particle configuration compiled from a module graph.
std::vector< EditorDiagnostic > diagnostics