app: migrate all engine access to the C ABI facade (nm U _ZN5olive = 0)
Every app module now reaches liboakengine exclusively through oakengine_* C calls, EngineEventBridge subscriptions and app-side handle headers (cliphandle/keyframehandle/nodevaluehandle/oakvaluehelper). Direct C++ command construction, engine signal connect()s, and engine type usage in MOC-visible signatures are gone: 557 -> 0 undefined olive:: symbols in oak-editor.
This commit is contained in:
@@ -24,16 +24,31 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "common/nodevaluehandle.h"
|
||||
#include "common/oakvaluehelper.h"
|
||||
#include "core.h"
|
||||
#include "node/nodeundo.h"
|
||||
#include "node/value.h"
|
||||
#include "oakengine/events.h"
|
||||
#include "oakengine/undo.h"
|
||||
#include "oakengine/viewer.h"
|
||||
#include "oakengine/node.h"
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
static int64_t rational_to_node_ts(Node *node, const Rational &time)
|
||||
{
|
||||
int num = 0, den = 1;
|
||||
oakengine_node_frame_time_base(reinterpret_cast<OakEngineNode *>(node),
|
||||
&num, &den);
|
||||
return core::Timecode::time_to_timestamp(time, Rational(num, den));
|
||||
}
|
||||
|
||||
NodeParamViewKeyframeControl::NodeParamViewKeyframeControl(bool right_align,
|
||||
QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, bridge_(new EngineEventBridge(this))
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
@@ -73,6 +88,21 @@ NodeParamViewKeyframeControl::NodeParamViewKeyframeControl(bool right_align,
|
||||
connect(enable_key_btn_, &QPushButton::clicked, this,
|
||||
&NodeParamViewKeyframeControl::keyframe_enable_btn_clicked);
|
||||
|
||||
connect(bridge_, &EngineEventBridge::node_keyframe_enable_changed, this,
|
||||
[this](OakEngineNode *source, const QString &input, int element,
|
||||
bool enabled) {
|
||||
keyframe_enable_changed(
|
||||
NodeInput(reinterpret_cast<Node *>(source), input,
|
||||
element),
|
||||
enabled);
|
||||
});
|
||||
connect(bridge_, &EngineEventBridge::node_keyframe_added, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
connect(bridge_, &EngineEventBridge::node_keyframe_removed, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
connect(bridge_, &EngineEventBridge::node_keyframe_time_changed, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
|
||||
// Set defaults
|
||||
set_input(NodeInput());
|
||||
show_buttons_from_keyframe_enable(false);
|
||||
@@ -81,14 +111,14 @@ NodeParamViewKeyframeControl::NodeParamViewKeyframeControl(bool right_align,
|
||||
void NodeParamViewKeyframeControl::set_input(const NodeInput &input)
|
||||
{
|
||||
if (input_.is_valid()) {
|
||||
disconnect(input_.node(), &Node::keyframe_enable_changed, this,
|
||||
&NodeParamViewKeyframeControl::keyframe_enable_changed);
|
||||
disconnect(input_.node(), &Node::keyframe_added, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
disconnect(input_.node(), &Node::keyframe_removed, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
disconnect(input_.node(), &Node::keyframe_time_changed, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
bridge_->unsubscribe(keyframe_enable_sub_);
|
||||
bridge_->unsubscribe(keyframe_added_sub_);
|
||||
bridge_->unsubscribe(keyframe_removed_sub_);
|
||||
bridge_->unsubscribe(keyframe_time_sub_);
|
||||
keyframe_enable_sub_ = 0;
|
||||
keyframe_added_sub_ = 0;
|
||||
keyframe_removed_sub_ = 0;
|
||||
keyframe_time_sub_ = 0;
|
||||
}
|
||||
|
||||
input_ = input;
|
||||
@@ -101,27 +131,39 @@ void NodeParamViewKeyframeControl::set_input(const NodeInput &input)
|
||||
update_state();
|
||||
|
||||
if (input_.is_valid()) {
|
||||
connect(input_.node(), &Node::keyframe_enable_changed, this,
|
||||
&NodeParamViewKeyframeControl::keyframe_enable_changed);
|
||||
connect(input_.node(), &Node::keyframe_added, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
connect(input_.node(), &Node::keyframe_removed, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
connect(input_.node(), &Node::keyframe_time_changed, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
keyframe_enable_sub_ = bridge_->subscribe(
|
||||
reinterpret_cast<void *>(input_.node()),
|
||||
OAKENGINE_EVENT_NODE_KEYFRAME_ENABLE_CHANGED);
|
||||
keyframe_added_sub_ = bridge_->subscribe(
|
||||
reinterpret_cast<void *>(input_.node()),
|
||||
OAKENGINE_EVENT_NODE_KEYFRAME_ADDED);
|
||||
keyframe_removed_sub_ = bridge_->subscribe(
|
||||
reinterpret_cast<void *>(input_.node()),
|
||||
OAKENGINE_EVENT_NODE_KEYFRAME_REMOVED);
|
||||
keyframe_time_sub_ = bridge_->subscribe(
|
||||
reinterpret_cast<void *>(input_.node()),
|
||||
OAKENGINE_EVENT_NODE_KEYFRAME_TIME_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::TimeTargetDisconnectEvent(ViewerOutput *v)
|
||||
{
|
||||
disconnect(v, &ViewerOutput::playhead_changed, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
if (viewer_sub_ > 0) {
|
||||
oakengine_event_unsubscribe(viewer_sub_);
|
||||
viewer_sub_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::TimeTargetConnectEvent(ViewerOutput *v)
|
||||
{
|
||||
connect(v, &ViewerOutput::playhead_changed, this,
|
||||
&NodeParamViewKeyframeControl::update_state);
|
||||
viewer_sub_ = oakengine_event_subscribe(
|
||||
reinterpret_cast<OakEngineNode *>(v),
|
||||
OAKENGINE_EVENT_VIEWER_PLAYHEAD_CHANGED,
|
||||
[](const oakengine_event *, void *userdata) {
|
||||
static_cast<NodeParamViewKeyframeControl *>(userdata)
|
||||
->update_state();
|
||||
},
|
||||
this);
|
||||
update_state();
|
||||
}
|
||||
|
||||
@@ -171,39 +213,64 @@ void NodeParamViewKeyframeControl::toggle_keyframe(bool e)
|
||||
QVector<NodeKeyframe *> keys =
|
||||
input_.node()->get_keyframes_at_time(input_, node_time);
|
||||
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
void *command = oakengine_undo_command_create_multi();
|
||||
|
||||
int nb_tracks = input_.node()->get_number_of_keyframe_tracks(input_);
|
||||
Node *node = input_.node();
|
||||
const NodeValue::Type declared = node->get_input_data_type(input_.input());
|
||||
|
||||
int nb_tracks = oakengine_node_value_keyframe_track_count(
|
||||
node_value_type_to_c(declared));
|
||||
|
||||
const QByteArray input_utf8 = input_.input().toUtf8();
|
||||
const char *input_id = input_utf8.constData();
|
||||
const int element = input_.element();
|
||||
const int64_t time_ts = rational_to_node_ts(node, node_time);
|
||||
|
||||
if (e && keys.isEmpty()) {
|
||||
// Add a keyframe here (one for each track)
|
||||
for (int i = 0; i < nb_tracks; i++) {
|
||||
NodeKeyframe *key = new NodeKeyframe(
|
||||
node_time,
|
||||
input_.node()->get_split_value_at_time_on_track(input_, node_time, i),
|
||||
input_.node()->get_best_keyframe_type_for_time_on_track(input_,
|
||||
node_time, i),
|
||||
i, input_.element(), input_.input());
|
||||
oak_node_value v;
|
||||
if (oakengine_node_get_input_at_time(
|
||||
reinterpret_cast<OakEngineNode *>(node), input_id, element, -1,
|
||||
time_ts, 1, &v) != OAKENGINE_OK) {
|
||||
oakengine_undo_command_free(command);
|
||||
return;
|
||||
}
|
||||
|
||||
command->add_child(
|
||||
new NodeParamInsertKeyframeCommand(input_.node(), key));
|
||||
for (int i = 0; i < nb_tracks; i++) {
|
||||
void *cmd = oakengine_node_insert_keyframe_command(
|
||||
reinterpret_cast<OakEngineNode *>(node), input_id, element, i,
|
||||
time_ts, &v,
|
||||
NodeKeyframeTypeToFacade(
|
||||
node->get_best_keyframe_type_for_time_on_track(input_,
|
||||
node_time, i)),
|
||||
0, 0, 0, 0);
|
||||
oakengine_undo_command_multi_add_child(command, cmd);
|
||||
}
|
||||
} else if (!e && !keys.isEmpty()) {
|
||||
// Remove all keyframes at this time
|
||||
foreach (NodeKeyframe *key, keys) {
|
||||
command->add_child(new NodeParamRemoveKeyframeCommand(key));
|
||||
void *cmd = oakengine_node_remove_keyframe_command(
|
||||
reinterpret_cast<OakEngineKeyframe *>(key));
|
||||
oakengine_undo_command_multi_add_child(command, cmd);
|
||||
|
||||
if (input_.node()->get_keyframe_tracks(input_).size() == 1) {
|
||||
// If this was the last keyframe on this track, set the standard value to the value at this time too
|
||||
command->add_child(new NodeParamSetStandardValueCommand(
|
||||
NodeKeyframeTrackReference(input_, key->track()),
|
||||
input_.node()->get_split_value_at_time_on_track(input_, node_time,
|
||||
key->track())));
|
||||
if (node->get_keyframe_tracks(input_).size() == 1) {
|
||||
// If this was the last keyframe on this track, set the standard value
|
||||
// to the value at this time too.
|
||||
oak_node_value v;
|
||||
NodeTrackComponentToOakNodeValue(
|
||||
declared,
|
||||
node->get_split_value_at_time_on_track(input_, node_time,
|
||||
key->track()),
|
||||
&v);
|
||||
void *sv = oakengine_node_set_standard_value_command(
|
||||
reinterpret_cast<OakEngineNode *>(node), input_id, element,
|
||||
key->track(), &v);
|
||||
oakengine_undo_command_multi_add_child(command, sv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command, tr("Toggled Keyframe"));
|
||||
oakengine_undo_push(command, tr("Toggled Keyframe").toUtf8().constData());
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::update_state()
|
||||
@@ -232,7 +299,9 @@ void NodeParamViewKeyframeControl::go_to_previous_key()
|
||||
|
||||
if (previous_key && get_time_target()) {
|
||||
Rational key_time = convert_to_viewer_time(previous_key->time());
|
||||
get_time_target()->set_playhead(key_time);
|
||||
oakengine_viewer_set_playhead(
|
||||
reinterpret_cast<OakEngineNode *>(get_time_target()),
|
||||
key_time.numerator(), key_time.denominator());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +314,9 @@ void NodeParamViewKeyframeControl::go_to_next_key()
|
||||
|
||||
if (next_key && get_time_target()) {
|
||||
Rational key_time = convert_to_viewer_time(next_key->time());
|
||||
get_time_target()->set_playhead(key_time);
|
||||
oakengine_viewer_set_playhead(
|
||||
reinterpret_cast<OakEngineNode *>(get_time_target()),
|
||||
key_time.numerator(), key_time.denominator());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,71 +327,106 @@ void NodeParamViewKeyframeControl::keyframe_enable_btn_clicked(bool e)
|
||||
return;
|
||||
}
|
||||
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
Node *node = input_.node();
|
||||
const NodeValue::Type declared = node->get_input_data_type(input_.input());
|
||||
const QByteArray input_utf8 = input_.input().toUtf8();
|
||||
const char *input_id = input_utf8.constData();
|
||||
const int element = input_.element();
|
||||
|
||||
QString command_name;
|
||||
|
||||
if (e) {
|
||||
// Enable keyframing
|
||||
command->add_child(new NodeParamSetKeyframingCommand(input_, true));
|
||||
void *command = oakengine_undo_command_create_multi();
|
||||
|
||||
void *kf = oakengine_node_set_input_keyframing_command(
|
||||
reinterpret_cast<OakEngineNode *>(node), input_id, element, 1);
|
||||
oakengine_undo_command_multi_add_child(command, kf);
|
||||
|
||||
// Create one keyframe across all tracks here
|
||||
const QVector<QVariant> &key_vals =
|
||||
input_.node()->get_split_standard_value(input_);
|
||||
const QVector<QVariant> &key_vals = node->get_split_standard_value(input_);
|
||||
|
||||
for (int i = 0; i < key_vals.size(); i++) {
|
||||
NodeKeyframe *key =
|
||||
new NodeKeyframe(get_current_time_as_node_time(), key_vals.at(i),
|
||||
NodeKeyframe::k_default_type, i,
|
||||
input_.element(), input_.input());
|
||||
|
||||
command->add_child(
|
||||
new NodeParamInsertKeyframeCommand(input_.node(), key));
|
||||
if (!key_vals.isEmpty()) {
|
||||
QVector<oak_node_value> tracks(key_vals.size());
|
||||
bool converted = true;
|
||||
for (int i = 0; i < key_vals.size(); i++) {
|
||||
if (!NodeTrackComponentToOakNodeValue(declared, key_vals.at(i),
|
||||
&tracks[i])) {
|
||||
converted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
oak_node_value v;
|
||||
memset(&v, 0, sizeof(v));
|
||||
if (converted) {
|
||||
oakengine_node_value_combine_tracks(
|
||||
node_value_type_to_c(declared), tracks.constData(),
|
||||
tracks.size(), &v);
|
||||
}
|
||||
const int64_t time_ts =
|
||||
rational_to_node_ts(node, get_current_time_as_node_time());
|
||||
const int type = NodeKeyframeTypeToFacade(static_cast<NodeKeyframe::Type>(oakengine_keyframe_default_type()));
|
||||
for (int i = 0; i < key_vals.size(); i++) {
|
||||
void *cmd = oakengine_node_insert_keyframe_command(
|
||||
reinterpret_cast<OakEngineNode *>(node), input_id, element, i,
|
||||
time_ts, &v, type, 0, 0, 0, 0);
|
||||
oakengine_undo_command_multi_add_child(command, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
command_name =
|
||||
tr("Enabled Keyframing On %1 - %2")
|
||||
.arg(input_.node()->get_label_and_name(), input_.get_input_name());
|
||||
.arg(node->get_label_and_name(), input_.get_input_name());
|
||||
|
||||
oakengine_undo_push(command, command_name.toUtf8().constData());
|
||||
} else {
|
||||
// Confirm the user wants to clear all keyframes
|
||||
if (QMessageBox::warning(
|
||||
this, tr("Warning"),
|
||||
tr("Are you sure you want to disable keyframing on this value? This will clear all existing keyframes."),
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||
void *command = oakengine_undo_command_create_multi();
|
||||
|
||||
// Store value at this time, we'll set this as the persistent value later
|
||||
const QVector<QVariant> &stored_vals =
|
||||
input_.node()->get_split_value_at_time(input_,
|
||||
get_current_time_as_node_time());
|
||||
node->get_split_value_at_time(input_,
|
||||
get_current_time_as_node_time());
|
||||
|
||||
// Delete all keyframes
|
||||
foreach (const NodeKeyframeTrack &track,
|
||||
input_.node()->get_keyframe_tracks(input_)) {
|
||||
node->get_keyframe_tracks(input_)) {
|
||||
for (int i = track.size() - 1; i >= 0; i--) {
|
||||
command->add_child(
|
||||
new NodeParamRemoveKeyframeCommand(track.at(i)));
|
||||
void *cmd = oakengine_node_remove_keyframe_command(
|
||||
reinterpret_cast<OakEngineKeyframe *>(track.at(i)));
|
||||
oakengine_undo_command_multi_add_child(command, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// Update standard value
|
||||
for (int i = 0; i < stored_vals.size(); i++) {
|
||||
command->add_child(new NodeParamSetStandardValueCommand(
|
||||
NodeKeyframeTrackReference(input_, i), stored_vals.at(i)));
|
||||
oak_node_value v;
|
||||
NodeTrackComponentToOakNodeValue(declared, stored_vals.at(i), &v);
|
||||
void *cmd = oakengine_node_set_standard_value_command(
|
||||
reinterpret_cast<OakEngineNode *>(node), input_id, element, i,
|
||||
&v);
|
||||
oakengine_undo_command_multi_add_child(command, cmd);
|
||||
}
|
||||
|
||||
// Disable keyframing
|
||||
command->add_child(
|
||||
new NodeParamSetKeyframingCommand(input_, false));
|
||||
void *kf = oakengine_node_set_input_keyframing_command(
|
||||
reinterpret_cast<OakEngineNode *>(node), input_id, element, 0);
|
||||
oakengine_undo_command_multi_add_child(command, kf);
|
||||
|
||||
command_name = tr("Disabled Keyframing On %1 - %2")
|
||||
.arg(input_.node()->get_label_and_name(),
|
||||
input_.get_input_name());
|
||||
.arg(node->get_label_and_name(),
|
||||
input_.get_input_name());
|
||||
|
||||
oakengine_undo_push(command, command_name.toUtf8().constData());
|
||||
} else {
|
||||
// Disable action has effectively been ignored
|
||||
enable_key_btn_->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command, command_name);
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::keyframe_enable_changed(const NodeInput &input,
|
||||
|
||||
Reference in New Issue
Block a user