engine: timeline panel leftover commands migrate to the facade (round 3)
- new primitives: clip_toggle_enabled (per-block flip), clip_set_linked, sequence_add_default_transition (config-driven, sequence timebase), node_set_label_many, node_set_color_label, plus observation getters - toggle-links, default transitions, enable toggles, color labels, and block renaming now go through the facade; the stray empty undo entry from block renaming is gone along the way - nest/multicam/waveform-sync stay as documented composites: they mix redo_now intermediate state, graph surgery, and app-side computation that a single primitive cannot express faithfully - the timeline panel's command execution paths are now fully migrated
This commit is contained in:
@@ -1264,6 +1264,119 @@ int oakengine_sequence_ripple_delete_range(OakEngineSequence *seq,
|
||||
return OAKENGINE_OK;
|
||||
}
|
||||
|
||||
int oakengine_clip_toggle_enabled(OakEngineClip **clips, int count)
|
||||
{
|
||||
set_seq_error(QString());
|
||||
if (count < 0 || (count > 0 && !clips)) {
|
||||
set_seq_error(QStringLiteral("invalid arguments"));
|
||||
return OAKENGINE_E_INVALID;
|
||||
}
|
||||
olive::MultiUndoCommand *command = new olive::MultiUndoCommand();
|
||||
for (int i = 0; i < count; i++) {
|
||||
olive::ClipBlock *clip =
|
||||
reinterpret_cast<olive::ClipBlock *>(clips[i]);
|
||||
if (!clip) {
|
||||
set_seq_error(QStringLiteral("invalid clip at index %1").arg(i));
|
||||
delete command;
|
||||
return OAKENGINE_E_INVALID;
|
||||
}
|
||||
// The panel's toggle: each clip flips its own current state.
|
||||
command->add_child(
|
||||
new olive::BlockEnableDisableCommand(clip, !clip->is_enabled()));
|
||||
}
|
||||
if (count > 0) {
|
||||
push_or_run(command, QStringLiteral("Toggle Clips Enabled"));
|
||||
} else {
|
||||
delete command;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int oakengine_clip_set_linked(OakEngineClip **clips, int count, int linked)
|
||||
{
|
||||
set_seq_error(QString());
|
||||
if (count < 0 || (count > 0 && !clips)) {
|
||||
set_seq_error(QStringLiteral("invalid arguments"));
|
||||
return OAKENGINE_E_INVALID;
|
||||
}
|
||||
if (count == 0) {
|
||||
return OAKENGINE_OK;
|
||||
}
|
||||
QVector<olive::Node *> nodes;
|
||||
nodes.reserve(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
olive::ClipBlock *clip =
|
||||
reinterpret_cast<olive::ClipBlock *>(clips[i]);
|
||||
if (!clip) {
|
||||
set_seq_error(QStringLiteral("invalid clip at index %1").arg(i));
|
||||
return OAKENGINE_E_INVALID;
|
||||
}
|
||||
nodes.append(clip);
|
||||
}
|
||||
push_or_run(new olive::NodeLinkManyCommand(nodes, linked != 0),
|
||||
QStringLiteral("Link Clips"));
|
||||
return OAKENGINE_OK;
|
||||
}
|
||||
|
||||
int oakengine_sequence_add_default_transition(OakEngineSequence *seq,
|
||||
OakEngineClip **clips, int count)
|
||||
{
|
||||
set_seq_error(QString());
|
||||
olive::Sequence *sequence = reinterpret_cast<olive::Sequence *>(seq);
|
||||
if (!sequence || count < 0 || (count > 0 && !clips)) {
|
||||
set_seq_error(QStringLiteral("invalid arguments"));
|
||||
return OAKENGINE_E_INVALID;
|
||||
}
|
||||
if (count == 0) {
|
||||
return OAKENGINE_OK;
|
||||
}
|
||||
olive::Rational tb;
|
||||
if (!time_base_of(sequence, &tb)) {
|
||||
set_seq_error(QStringLiteral("sequence has no valid frame rate"));
|
||||
return OAKENGINE_E_STATE;
|
||||
}
|
||||
QVector<olive::ClipBlock *> blocks;
|
||||
blocks.reserve(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
olive::ClipBlock *clip =
|
||||
reinterpret_cast<olive::ClipBlock *>(clips[i]);
|
||||
if (!clip) {
|
||||
set_seq_error(QStringLiteral("invalid clip at index %1").arg(i));
|
||||
return OAKENGINE_E_INVALID;
|
||||
}
|
||||
blocks.append(clip);
|
||||
}
|
||||
push_or_run(new olive::TimelineAddDefaultTransitionCommand(blocks, tb),
|
||||
QStringLiteral("Add Default Transitions"));
|
||||
return OAKENGINE_OK;
|
||||
}
|
||||
|
||||
int oakengine_clip_is_enabled(const OakEngineClip *self)
|
||||
{
|
||||
if (!self) {
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<const olive::ClipBlock *>(self)->is_enabled() ?
|
||||
1 :
|
||||
0;
|
||||
}
|
||||
|
||||
int oakengine_clip_are_linked(const OakEngineClip *a, const OakEngineClip *b)
|
||||
{
|
||||
if (!a || !b) {
|
||||
return 0;
|
||||
}
|
||||
// Block::are_linked() takes non-const pointers (it is read-only in
|
||||
// practice).
|
||||
return olive::Block::are_linked(
|
||||
const_cast<olive::ClipBlock *>(
|
||||
reinterpret_cast<const olive::ClipBlock *>(a)),
|
||||
const_cast<olive::ClipBlock *>(
|
||||
reinterpret_cast<const olive::ClipBlock *>(b))) ?
|
||||
1 :
|
||||
0;
|
||||
}
|
||||
|
||||
int oakengine_sequence_ripple_delete_in_to_out(OakEngineSequence *seq,
|
||||
int ripple, int64_t in_ts,
|
||||
int64_t out_ts)
|
||||
|
||||
Reference in New Issue
Block a user