载入中...
搜索中...
未找到
CameraAttackVfx.cpp
浏览该文件的文档.
2#include "common/Capability.h"
4
5#include <cstdint>
6#include <map>
7#include <optional>
8#include <string>
9#include <unordered_map>
10#include <utility>
11
12namespace eve::stylize_action {
13namespace {
14
15float resolveParam(const eve::stylize::AttackVfxLayerStartRequest& request, const char* key,
16 float fallback) {
17 if (request.layer) {
18 const auto found = request.layer->floatParams.find(key);
19 if (found != request.layer->floatParams.end()) return found->second;
20 }
21 if (request.skin) {
22 const auto found = request.skin->shakeProfile.find(key);
23 if (found != request.skin->shakeProfile.end()) return found->second;
24 }
25 return fallback;
26}
27
28class CameraAttackVfxExecutor final : public eve::stylize::IAttackVfxLayerExecutor {
29public:
30 eve::stylize::AttackVfxLayerRole role() const noexcept override {
32 }
33
36 if (!request.layer)
38 eve::DiagnosticCode::InvalidArgument, "AttackVfx camera layer is null", "layer"));
39
41 if (!request.layer->uri.empty()) {
42 auto cue = eve::LogicalId::parse(request.layer->uri);
43 if (!cue)
46 "camera layer uri must be a LogicalId cue when set", "uri"));
47 binding.cue = std::move(*cue);
48 } else {
49 auto cue = eve::LogicalId::parse("attackvfx:camera");
50 if (!cue)
52 eve::DiagnosticCode::InvariantViolation, "default camera cue id is invalid", "cue"));
53 binding.cue = std::move(*cue);
54 }
55
56 const float posAmp = resolveParam(request, "posAmp", static_cast<float>(binding.positionAmplitude));
57 const float rotAmp = resolveParam(request, "rotAmp", static_cast<float>(binding.rotationAmplitude));
58 const float fovAmp = resolveParam(request, "fovAmp", static_cast<float>(binding.fovAmplitude));
59 float duration = resolveParam(request, "duration", 0.0f);
60 if (duration <= 0.0f) duration = resolveParam(request, "durationSeconds", 0.25f);
61 if (posAmp < 0.0f || rotAmp < 0.0f || duration <= 0.0f)
63 eve::DiagnosticCode::InvalidArgument, "camera layer amplitudes/duration are invalid",
64 "floatParams"));
65
66 binding.positionAmplitude = posAmp;
67 binding.rotationAmplitude = rotAmp;
68 binding.fovAmplitude = fovAmp;
69 auto parsedDuration = eve::Duration::fromSeconds(duration);
70 if (!parsedDuration)
72 binding.duration = std::move(parsedDuration).takeValue();
73 if (request.playRequest)
74 binding.seed = request.playRequest->sourceId ^ (request.playRequest->targetId << 16);
75
77 std::optional<eve::Result<void>> result;
78 eve::cap::forEachUntil<eve::action::IActionCameraCueSink>([&](eve::action::IActionCameraCueSink* sink) {
79 if (!sink->supports(binding.cue)) return false;
80 result.emplace(sink->trigger(binding, context));
81 return true;
82 });
83 if (!result)
85 eve::DiagnosticCode::NotFound, "no camera sink accepts the AttackVfx cue",
86 binding.cue.format()));
87 if (!*result) return eve::Result<eve::stylize::AttackVfxLayerHandle>::failure(result->status());
88
89 const auto id = ++nextId_;
90 live_.emplace(id, true);
93 }
94
97 if (!live_.contains(handle.id))
99 eve::DiagnosticCode::StaleHandle, "camera AttackVfx layer handle is stale", "handle"));
101 }
102
105 const auto found = live_.find(handle.id);
106 if (found == live_.end())
108 eve::DiagnosticCode::StaleHandle, "camera AttackVfx layer handle is stale", "handle"));
109 // IActionCameraCueSink has no cancel API yet; impulses run for their authored duration.
110 // Clearing the local handle still makes the AttackVfx layer identity stale immediately.
111 live_.erase(found);
113 }
114
115private:
116 std::uint64_t nextId_ = 1;
117 std::unordered_map<std::uint64_t, bool> live_;
118};
119
120CameraAttackVfxExecutor& cameraExecutor() {
121 static CameraAttackVfxExecutor instance;
122 return instance;
123}
124
125bool gCameraRegistered = false;
126
127} // namespace
128
130 if (gCameraRegistered) return;
131 eve::cap::addListener<eve::stylize::IAttackVfxLayerExecutor>(&cameraExecutor());
132 gCameraRegistered = true;
133}
134
136 if (!gCameraRegistered) return;
137 eve::cap::removeListener<eve::stylize::IAttackVfxLayerExecutor>(&cameraExecutor());
138 gCameraRegistered = false;
139}
140
141} // namespace eve::stylize_action
Typed camera-cue action block contract.
Duration start
float duration
Pluggable AttackVfx layer backends registered via capability listeners.
const GltfImportRequest & request
std::uint32_t key
eve::action::ActionVfxBinding binding
PrimitiveHandle handle
bool found
const VegetationPresetContext & context
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
static Result< Duration > fromSeconds(double seconds)
Convert finite seconds to the nearest nanosecond.
Definition Time.cpp:16
static std::optional< LogicalId > parse(std::string_view text)
Parses a scoped logical name.
Definition Identity.cpp:36
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
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
Optional open target for instantaneous action camera cues.
virtual Result< void > trigger(const ActionCameraCueBinding &binding, const ActionNotifyContext &context)=0
Trigger one already validated camera cue.
virtual bool supports(const LogicalId &cue) const noexcept=0
Whether this sink owns the supplied stable cue identity.
Optional open backend for one AttackVfxLayerRole.
AttackVfxLayerRole
Which existing presentation backend a layer binds to.
AttackVfxStopBehavior
Exit policy when a phase or instance stops.
Owning validated camera impulse shared by action runtime and camera targets.
Context linking a routed event to its action execution.
Opaque executor-owned layer instance identity.
Borrowed start context for one layer inside an entering phase.