/*** Olive - Non-Linear Video Editor Copyright (C) 2022 Olive Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***/ #ifndef NODEVALUE_H #define NODEVALUE_H #include #include #include #include #include "codec/samplebuffer.h" #include "common/bezier.h" #include "node/splitvalue.h" #include "render/color.h" #include "render/texture.h" #include "undo/undocommand.h" namespace olive { class Node; class NodeValue { public: /** * @brief The types of data that can be passed between Nodes */ enum Type { kNone, /** ****************************** SPECIFIC IDENTIFIERS ****************************** */ /** * Integer type * * Resolves to int64_t. */ kInt, /** * Decimal (floating-point) type * * Resolves to `double`. */ kFloat, /** * Decimal (rational) type * * Resolves to `double`. */ kRational, /** * Boolean type * * Resolves to `bool`. */ kBoolean, /** * Floating-point type * * Resolves to `Color`. * * Colors passed around the nodes should always be in reference space and preferably use */ kColor, /** * Matrix type * * Resolves to `QMatrix4x4`. */ kMatrix, /** * Text type * * Resolves to `QString`. */ kText, /** * Font type * * Resolves to `QFont`. */ kFont, /** * File type * * Resolves to a `QString` containing an absolute file path. */ kFile, /** * Image buffer type * * True value type depends on the render engine used. */ kTexture, /** * Audio samples type * * Resolves to `SampleBufferPtr`. */ kSamples, /** * Two-dimensional vector (XY) type * * Resolves to `QVector2D`. */ kVec2, /** * Three-dimensional vector (XYZ) type * * Resolves to `QVector3D`. */ kVec3, /** * Four-dimensional vector (XYZW) type * * Resolves to `QVector4D`. */ kVec4, /** * Cubic bezier type that contains three X/Y coordinates, the main point, and two control points * * Resolves to `Bezier` */ kBezier, /** * ComboBox type * * Resolves to `int` - the index currently selected */ kCombo, /** * Video Parameters type * * Resolves to `VideoParams` */ kVideoParams, /** * Audio Parameters type * * Resolves to `AudioParams` */ kAudioParams, /** * Subtitle Parameters type * * Resolves to `SubtitleParams` */ kSubtitleParams, /** * End of list */ kDataTypeCount }; NodeValue() : type_(kNone), from_(nullptr), array_(false) { } template NodeValue(Type type, const T& data, const Node* from = nullptr, bool array = false, const QString& tag = QString()) : type_(type), from_(from), tag_(tag), array_(array) { set_value(data); } Type type() const { return type_; } template T value() const { return data_.value(); } template void set_value(const T &v) { data_ = QVariant::fromValue(v); } template bool canConvert() const { return data_.canConvert(); } const QString& tag() const { return tag_; } const Node* source() const { return from_; } bool array() const { return array_; } bool operator==(const NodeValue& rhs) const { return type_ == rhs.type_ && tag_ == rhs.tag_ && data_ == rhs.data_; } static QString GetPrettyDataTypeName(Type type); static QString GetDataTypeName(Type type); static NodeValue::Type GetDataTypeFromName(const QString &n); static QString ValueToString(Type data_type, const QVariant& value, bool value_is_a_key_track); static QString ValueToString(const NodeValue &v, bool value_is_a_key_track) { return ValueToString(v.type_, v.data_, value_is_a_key_track); } static QVariant StringToValue(Type data_type, const QString &string, bool value_is_a_key_track); static QVector split_normal_value_into_track_values(Type type, const QVariant &value); static QVariant combine_track_values_into_normal_value(Type type, const QVector& split); SplitValue to_split_value() const { return split_normal_value_into_track_values(type_, data_); } /** * @brief Returns whether a data type can be interpolated or not */ static bool type_can_be_interpolated(NodeValue::Type type) { return type == kFloat || type == kVec2 || type == kVec3 || type == kVec4 || type == kBezier || type == kColor || type == kRational; } static bool type_is_numeric(NodeValue::Type type) { return type == kFloat || type == kInt || type == kRational; } static bool type_is_vector(NodeValue::Type type) { return type == kVec2 || type == kVec3 || type == kVec4; } static bool type_is_buffer(NodeValue::Type type) { return type == kTexture || type == kSamples; } static int get_number_of_keyframe_tracks(Type type); static void ValidateVectorString(QStringList* list, int count); TexturePtr toTexture() const { return value(); } SampleBuffer toSamples() const { return value(); } bool toBool() const { return value(); } double toDouble() const { return value(); } int64_t toInt() const { return value(); } rational toRational() const { return value(); } QString toString() const { return value(); } Color toColor() const { return value(); } QMatrix4x4 toMatrix() const { return value(); } VideoParams toVideoParams() const { return value(); } AudioParams toAudioParams() const { return value(); } QVector2D toVec2() const { return value(); } QVector3D toVec3() const { return value(); } QVector4D toVec4() const { return value(); } Bezier toBezier() const { return value(); } private: Type type_; QVariant data_; const Node* from_; QString tag_; bool array_; }; class NodeValueTable { public: NodeValueTable() = default; NodeValue Get(NodeValue::Type type, const QString& tag = QString()) const { QVector types = {type}; return Get(types, tag); } NodeValue Get(const QVector& type, const QString& tag = QString()) const; NodeValue Take(NodeValue::Type type, const QString& tag = QString()) { QVector types = {type}; return Take(types, tag); } NodeValue Take(const QVector& type, const QString& tag = QString()); void Push(const NodeValue& value) { values_.append(value); } void Push(const NodeValueTable& value) { values_.append(value.values_); } template void Push(NodeValue::Type type, const T& data, const Node *from, bool array = false, const QString& tag = QString()) { Push(NodeValue(type, data, from, array, tag)); } void Prepend(const NodeValue& value) { values_.prepend(value); } template void Prepend(NodeValue::Type type, const T& data, const Node *from, bool array = false, const QString& tag = QString()) { Prepend(NodeValue(type, data, from, array, tag)); } const NodeValue& at(int index) const { return values_.at(index); } NodeValue TakeAt(int index) { return values_.takeAt(index); } int Count() const { return values_.size(); } bool Has(NodeValue::Type type) const; void Remove(const NodeValue& v); void Clear() { values_.clear(); } bool isEmpty() const { return values_.isEmpty(); } int GetValueIndex(const QVector &type, const QString& tag) const; static NodeValueTable Merge(QList tables); private: QVector values_; }; using NodeValueRow = QHash; } Q_DECLARE_METATYPE(olive::NodeValue) Q_DECLARE_METATYPE(olive::NodeValueTable) #endif // NODEVALUE_H