载入中...
搜索中...
未找到
ActionTimelinePayloadEditor.cpp
浏览该文件的文档.
2
4
5#include <algorithm>
6#include <optional>
7#include <string>
8#include <utility>
9
10namespace eve::editor {
11namespace {
12
13
14struct PayloadItem {
15 LogicalId trackId;
16 LogicalId type;
18 Duration time;
19 Duration end;
21};
22
23std::optional<PayloadItem> findPayloadItem(const action::ActionTimeline& timeline, const LogicalId& itemId) {
24 for (const auto& track : timeline.tracks) {
25 const auto notify = std::find_if(track.notifies.begin(), track.notifies.end(),
26 [&](const auto& value) { return value.id == itemId; });
27 if (notify != track.notifies.end())
28 return PayloadItem{track.id, notify->type, action::ActionTimelineEventKind::Notify, notify->time,
29 notify->time, notify->payload};
30 const auto state = std::find_if(track.states.begin(), track.states.end(),
31 [&](const auto& value) { return value.id == itemId; });
32 if (state != track.states.end())
33 return PayloadItem{track.id, state->type, action::ActionTimelineEventKind::StateEnter, state->start,
34 state->end, state->payload};
35 }
36 return std::nullopt;
37}
38
39} // namespace
40
42 const auto item = findPayloadItem(editor_.target().timeline(), itemId);
43 if (!item)
44 return eve::editing::failed<Value::Object>(EditorStatus::Rejected, RuleId("editor.action.timeline.payload-item-missing"), "Editable action-block payload was not found");
45 return eve::editing::applied<Value::Object>(item->payload);
46}
47
49 const auto item = findPayloadItem(editor_.target().timeline(), itemId);
50 if (!item)
51 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.action.timeline.payload-item-missing"), "Editable action-block payload was not found");
52 auto merged = item->payload;
53 for (auto& [field, value] : fields) merged.insert_or_assign(std::move(field), std::move(value));
54 action::ActionTimelineEvent event{item->kind, item->trackId, itemId, item->type, item->time, merged};
55 auto valid = registry_.validate(event);
56 if (!valid) return Result<void>::failure(valid.status());
57 return editor_.updateItem(itemId, item->type, std::move(merged));
58}
59
61 const auto item = findPayloadItem(editor_.target().timeline(), itemId);
62 if (!item)
63 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.action.timeline.payload-item-missing"), "Editable action-block payload was not found");
65 item->type.format() != "presentation:vfx-state")
66 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.action.timeline.clip-fit-type"), "Only VFX states can fit a block to a clip");
68 if (!binding) return Result<void>::failure(binding.status());
70 if (!duration) return Result<void>::failure(duration.status());
71 auto end = item->time.tryAdd(duration.value());
72 if (!end)
73 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.action.timeline.clip-fit-overflow"), "Fitted VFX block time overflowed");
74 return editor_.editItem(itemId, item->time, end.value(), item->type, item->payload);
75}
76
78 const auto item = findPayloadItem(editor_.target().timeline(), itemId);
79 if (!item)
80 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.action.timeline.payload-item-missing"), "Editable action-block payload was not found");
82 item->type.format() != "presentation:vfx-state")
83 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.action.timeline.clip-fit-type"), "Only VFX states can fit a clip to a block");
85 if (!binding) return Result<void>::failure(binding.status());
86 const double blockDuration =
87 Duration::fromNanoseconds(item->end.nanoseconds() - item->time.nanoseconds()).seconds();
88 auto merged = item->payload;
89 merged.insert_or_assign("clipEndTime", binding.value().clipStartTime + blockDuration);
90 action::ActionTimelineEvent event{item->kind, item->trackId, itemId, item->type, item->time, merged};
91 auto valid = registry_.validate(event);
92 if (!valid) return Result<void>::failure(valid.status());
93 return editor_.editItem(itemId, item->time, item->end, item->type, std::move(merged));
94}
95
98 const auto item = findPayloadItem(editor_.target().timeline(), itemId);
99 if (!item)
100 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.action.timeline.payload-item-missing"), "Editable action-block payload was not found");
102 item->type.format() != "presentation:vfx-state")
103 return eve::editing::failed<void>(EditorStatus::Rejected, RuleId("editor.action.timeline.clip-fit-type"), "Only VFX states can use a resource's natural duration");
104 if (!provider)
105 return eve::editing::failed<void>(
106 EditorStatus::Unsupported, RuleId("editor.action.timeline.vfx-duration-provider-missing"),
107 "VFX natural duration requires a loaded particle provider");
109 if (!binding) return Result<void>::failure(binding.status());
110 auto duration = provider->get().naturalDuration(binding.value().uri);
111 if (!duration) return Result<void>::failure(duration.status());
112 auto merged = item->payload;
113 merged.insert_or_assign("clipEndTime", duration.value().seconds());
114 action::ActionTimelineEvent event{item->kind, item->trackId, itemId, item->type, item->time, merged};
115 auto valid = registry_.validate(event);
116 if (!valid) return Result<void>::failure(valid.status());
117 return editor_.editItem(itemId, item->time, item->end, item->type, std::move(merged));
118}
119
120} // namespace eve::editor
double value
LogicalId trackId
Value::Object payload
Validated partial editing for action-block payloads.
LogicalId itemId
Typed VFX action-block payload contract.
float duration
TokenKind kind
bool valid
eve::action::ActionVfxBinding binding
std::vector< std::string > fields
Definition PlayHost.cpp:111
static Result< Duration > fromSeconds(double seconds)
Convert finite seconds to the nearest nanosecond.
Definition Time.cpp:16
static constexpr Duration fromNanoseconds(std::int64_t nanoseconds) noexcept
Construct an exact duration from nanoseconds.
Definition Time.h:55
double seconds() const noexcept
Return this duration as seconds for legacy/presentation APIs.
Definition Time.cpp:28
Human-readable, scoped identifier in the form namespace:name.
Definition Identity.h:411
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
std::map< std::string, Value > Object
Definition Value.h:34
Result< void > validate(const ActionTimelineEvent &event) const
Validate type, shape and required payload fields.
const ActionTimelineTarget & target() const noexcept
Borrow the authoritative target.
Result< void > editItem(const LogicalId &itemId, Duration start, Duration end, LogicalId type, Value::Object payload)
Atomically replace one item's timing, type and owning payload.
Result< void > updateItem(const LogicalId &itemId, LogicalId type, Value::Object payload)
Replace one item's type and owning payload through one undoable transaction.
Result< void > fitClipToBlock(const LogicalId &itemId)
Extend one VFX state's clip end so its authored interval matches the block duration.
Result< void > fitBlockToClip(const LogicalId &itemId)
Resize one VFX state to its authored clip interval at 1.0x playback.
Result< void > fitClipToNaturalDuration(const LogicalId &itemId, OptionalRef< const action::IActionVfxDurationProvider > provider)
Set one VFX state's clip end to the finite duration reported by its resource provider.
Result< void > patch(const LogicalId &itemId, Value::Object fields)
Merge fields into one payload and commit exactly one validated undo step.
Result< Value::Object > payload(const LogicalId &itemId) const
Return an owning copy of one editable notify or state payload.
const action::ActionTimeline & timeline() const noexcept
Borrow the authoritative timeline until the next mutation.
ActionTimelineEventKind
Boundary emitted by deterministic timeline sampling.
eve::editing::RuleId RuleId
Definition EditorIds.h:32
std::optional< std::reference_wrapper< T > > OptionalRef
Optional borrowed reference; it does not extend T's lifetime.
Definition BorrowedRef.h:24
Owning event projection returned by the runtime sampler.
ActionTimelineEventKind kind
static Result< ActionVfxBinding > fromPayload(const Value::Object &payload, ActionVfxShape shape)
Decode one dynamic VFX payload transactionally.