removed last of the NodeOutput dependencies
Since all Nodes have an output that provides all output values now, we now never need to add an output from a Node derivative. These changes remove the last of them and disable the ability to add more outputs from a derivative.
This commit is contained in:
@@ -24,11 +24,11 @@ BlendNode::BlendNode()
|
||||
{
|
||||
base_input_ = new NodeInput("base_in");
|
||||
base_input_->set_data_type(NodeParam::kTexture);
|
||||
AddParameter(base_input_);
|
||||
AddInput(base_input_);
|
||||
|
||||
blend_input_ = new NodeInput("blend_in");
|
||||
blend_input_->set_data_type(NodeParam::kTexture);
|
||||
AddParameter(blend_input_);
|
||||
AddInput(blend_input_);
|
||||
}
|
||||
|
||||
QString BlendNode::Category() const
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
|
||||
ClipBlock::ClipBlock()
|
||||
{
|
||||
texture_input_ = new NodeInput("tex_in");
|
||||
texture_input_->set_data_type(NodeInput::kTexture);
|
||||
AddParameter(texture_input_);
|
||||
texture_input_ = new NodeInput("buffer_in");
|
||||
texture_input_->set_data_type(NodeInput::kBuffer);
|
||||
AddInput(texture_input_);
|
||||
}
|
||||
|
||||
Node *ClipBlock::copy() const
|
||||
|
||||
@@ -27,11 +27,11 @@ OpacityNode::OpacityNode()
|
||||
opacity_input_->set_value_at_time(0, 100);
|
||||
opacity_input_->set_minimum(0);
|
||||
opacity_input_->set_maximum(100);
|
||||
AddParameter(opacity_input_);
|
||||
AddInput(opacity_input_);
|
||||
|
||||
texture_input_ = new NodeInput("tex_in");
|
||||
texture_input_->set_data_type(NodeParam::kTexture);
|
||||
AddParameter(texture_input_);
|
||||
AddInput(texture_input_);
|
||||
}
|
||||
|
||||
Node *OpacityNode::copy() const
|
||||
@@ -62,6 +62,7 @@ QString OpacityNode::id() const
|
||||
void OpacityNode::Retranslate()
|
||||
{
|
||||
opacity_input_->set_name(tr("Opacity"));
|
||||
texture_input_->set_name(tr("Texture"));
|
||||
}
|
||||
|
||||
QString OpacityNode::Code() const
|
||||
|
||||
@@ -27,20 +27,20 @@ TransformDistort::TransformDistort()
|
||||
{
|
||||
position_input_ = new NodeInput("pos_in");
|
||||
position_input_->set_data_type(NodeParam::kVec2);
|
||||
AddParameter(position_input_);
|
||||
AddInput(position_input_);
|
||||
|
||||
rotation_input_ = new NodeInput("rot_in");
|
||||
rotation_input_->set_data_type(NodeParam::kFloat);
|
||||
AddParameter(rotation_input_);
|
||||
AddInput(rotation_input_);
|
||||
|
||||
scale_input_ = new NodeInput("scale_in");
|
||||
scale_input_->set_data_type(NodeParam::kVec2);
|
||||
scale_input_->set_value_at_time(0, QVector2D(100.0f, 100.0f));
|
||||
AddParameter(scale_input_);
|
||||
AddInput(scale_input_);
|
||||
|
||||
anchor_input_ = new NodeInput("anchor_in");
|
||||
anchor_input_->set_data_type(NodeParam::kVec2);
|
||||
AddParameter(anchor_input_);
|
||||
AddInput(anchor_input_);
|
||||
}
|
||||
|
||||
Node *TransformDistort::copy() const
|
||||
|
||||
@@ -25,7 +25,7 @@ SolidGenerator::SolidGenerator() :
|
||||
{
|
||||
color_input_ = new NodeInput("color_in");
|
||||
color_input_->set_data_type(NodeParam::kColor);
|
||||
AddParameter(color_input_);
|
||||
AddInput(color_input_);
|
||||
}
|
||||
|
||||
Node *SolidGenerator::copy() const
|
||||
@@ -55,7 +55,6 @@ QString SolidGenerator::Description() const
|
||||
|
||||
QString SolidGenerator::Code() const
|
||||
{
|
||||
// FIXME: Not color managed
|
||||
return "#version 110\n"
|
||||
"\n"
|
||||
"uniform vec4 color_in;\n"
|
||||
@@ -64,3 +63,8 @@ QString SolidGenerator::Code() const
|
||||
" gl_FragColor = color_in;\n"
|
||||
"}\n";
|
||||
}
|
||||
|
||||
void SolidGenerator::Retranslate()
|
||||
{
|
||||
color_input_->set_name(tr("Color"));
|
||||
}
|
||||
|
||||
@@ -43,6 +43,8 @@ public:
|
||||
|
||||
virtual QString Code() const override;
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
private:
|
||||
NodeInput* color_input_;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ MediaInput::MediaInput()
|
||||
{
|
||||
footage_input_ = new NodeInput("footage_in");
|
||||
footage_input_->set_data_type(NodeInput::kFootage);
|
||||
AddParameter(footage_input_);
|
||||
AddInput(footage_input_);
|
||||
}
|
||||
|
||||
StreamPtr MediaInput::footage()
|
||||
@@ -36,3 +36,8 @@ void MediaInput::SetFootage(StreamPtr f)
|
||||
{
|
||||
footage_input_->set_value_at_time(0, QVariant::fromValue(f));
|
||||
}
|
||||
|
||||
void MediaInput::Retranslate()
|
||||
{
|
||||
footage_input_->set_name(tr("Footage"));
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ public:
|
||||
StreamPtr footage();
|
||||
void SetFootage(StreamPtr f);
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
protected:
|
||||
NodeInput* footage_input_;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ VideoInput::VideoInput()
|
||||
{
|
||||
matrix_input_ = new NodeInput("matrix_in");
|
||||
matrix_input_->set_data_type(NodeInput::kMatrix);
|
||||
AddParameter(matrix_input_);
|
||||
AddInput(matrix_input_);
|
||||
}
|
||||
|
||||
Node *VideoInput::copy() const
|
||||
@@ -64,190 +64,9 @@ QString VideoInput::Code() const
|
||||
"}\n";
|
||||
}
|
||||
|
||||
/*
|
||||
void VideoInput::Hash(QCryptographicHash *hash, NodeOutput *from, const rational &time)
|
||||
void VideoInput::Retranslate()
|
||||
{
|
||||
Node::Hash(hash, from, time);
|
||||
MediaInput::Retranslate();
|
||||
|
||||
// Use frame value from Decoder
|
||||
if (from == texture_output_) {
|
||||
if (!SetupDecoder()) {
|
||||
qDebug() << "Failed to setup decoder for hashing";
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t timestamp = decoder_->GetTimestampFromTime(time);
|
||||
|
||||
QByteArray pts_bytes;
|
||||
pts_bytes.resize(sizeof(int64_t));
|
||||
memcpy(pts_bytes.data(), ×tamp, sizeof(int64_t));
|
||||
|
||||
hash->addData(pts_bytes);
|
||||
// FIXME: Add OCIO data
|
||||
// FIXME: Add alpha association value
|
||||
}
|
||||
matrix_input_->set_name(tr("Transform"));
|
||||
}
|
||||
|
||||
QVariant VideoInput::Value(NodeOutput *output, const rational &in, const rational &out)
|
||||
{
|
||||
Q_UNUSED(out)
|
||||
|
||||
if (output == texture_output_) {
|
||||
if (footage() == nullptr
|
||||
|| (footage()->type() != Stream::kVideo && footage()->type() != Stream::kImage)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FIXME: Hardcoded value
|
||||
bool alpha_is_associated = false;
|
||||
|
||||
// Find the current Renderer instance
|
||||
RenderInstance* renderer = VideoRendererProcessor::CurrentInstance();
|
||||
|
||||
// If nothing is available, don't return a texture
|
||||
if (renderer == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make sure decoder is set up
|
||||
if (!SetupDecoder()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if we need to get a frame or not
|
||||
if (frame_ == nullptr || frame_->native_timestamp() != decoder_->GetTimestampFromTime(in)) {
|
||||
// Get frame from Decoder
|
||||
frame_ = decoder_->Retrieve(in);
|
||||
|
||||
if (frame_ == nullptr) {
|
||||
qDebug() << "Received a null frame while time was" << in.toDouble();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (color_processor_ == nullptr) {
|
||||
QString colorspace = std::static_pointer_cast<VideoStream>(footage())->colorspace();
|
||||
if (colorspace.isEmpty()) {
|
||||
// FIXME: Should use Footage() to find the Project* it belongs to instead of this
|
||||
colorspace = olive::core.GetActiveProject()->default_input_colorspace();
|
||||
}
|
||||
|
||||
color_processor_ = ColorProcessor::Create(colorspace, OCIO::ROLE_SCENE_LINEAR);
|
||||
}
|
||||
|
||||
// OpenColorIO v1's color transforms can be done on GPU, which improves performance but reduces accuracy. When
|
||||
// online, we prefer accuracy over performance so we use the CPU path instead:
|
||||
// NOTE: OCIO v2 boasts 1:1 results with the CPU and GPU path so this won't be necessary forever
|
||||
if (renderer->params().mode() == olive::RenderMode::kOnline) {
|
||||
// Convert to 32F, which is required for OpenColorIO's color transformation
|
||||
frame_ = PixelService::ConvertPixelFormat(frame_, olive::PIX_FMT_RGBA32F);
|
||||
|
||||
if (alpha_is_associated) {
|
||||
// Unassociate alpha here if associated
|
||||
ColorManager::DisassociateAlpha(frame_);
|
||||
}
|
||||
|
||||
// Transform color to reference space
|
||||
color_processor_->ConvertFrame(frame_);
|
||||
|
||||
if (alpha_is_associated) {
|
||||
// If alpha was associated, reassociate here
|
||||
ColorManager::ReassociateAlpha(frame_);
|
||||
} else {
|
||||
// If alpha was not associated, associate here
|
||||
ColorManager::AssociateAlpha(frame_);
|
||||
}
|
||||
}
|
||||
|
||||
// We use an internal texture to bring the texture into GPU space before performing transformations
|
||||
|
||||
// Ensure the texture is the accurate to the frame
|
||||
if (internal_tex_.width() != frame_->width()
|
||||
|| internal_tex_.height() != frame_->height()
|
||||
|| internal_tex_.format() != frame_->format()) {
|
||||
internal_tex_.Destroy();
|
||||
}
|
||||
|
||||
// Create or upload the new data to the texture
|
||||
if (!internal_tex_.IsCreated()) {
|
||||
internal_tex_.Create(renderer->context(),
|
||||
frame_->width(),
|
||||
frame_->height(),
|
||||
static_cast<olive::PixelFormat>(frame_->format()),
|
||||
frame_->data());
|
||||
} else {
|
||||
internal_tex_.Upload(frame_->data());
|
||||
}
|
||||
}
|
||||
|
||||
// Create new texture in reference space to send throughout the rest of the graph
|
||||
|
||||
RenderTexturePtr output_texture = std::make_shared<RenderTexture>();
|
||||
|
||||
output_texture->Create(renderer->context(),
|
||||
renderer->params().effective_width(),
|
||||
renderer->params().effective_height(),
|
||||
renderer->params().format(),
|
||||
RenderTexture::kDoubleBuffer);
|
||||
|
||||
// Using the transformation matrix, blit our internal texture (in frame format) to our output texture (in
|
||||
// reference format)
|
||||
|
||||
if (renderer->params().mode() == olive::RenderMode::kOffline) {
|
||||
// For offline rendering, OCIO's GPU path is acceptable:
|
||||
// NOTE: OCIO v2 boasts 1:1 results with the CPU and GPU path so this won't be necessary forever
|
||||
|
||||
// Use an OCIO pipeline shader (which wraps in a default pipeline and will also handle alpha association)
|
||||
if (pipeline_ == nullptr) {
|
||||
pipeline_ = olive::ShaderGenerator::OCIOPipeline(renderer->context(),
|
||||
ocio_texture_, // FIXME: A raw GLuint texture, should wrap this up
|
||||
color_processor_->GetProcessor(),
|
||||
alpha_is_associated);
|
||||
|
||||
// Used for cleanup later
|
||||
ocio_ctx_ = renderer->context();
|
||||
}
|
||||
} else if (pipeline_ == nullptr) {
|
||||
// In online, the color transformation was performed on the CPU (see above), so we only need to blit
|
||||
pipeline_ = olive::ShaderGenerator::DefaultPipeline();
|
||||
}
|
||||
|
||||
renderer->context()->functions()->glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
// Draw onto the output texture using the renderer's framebuffer
|
||||
renderer->buffer()->Attach(output_texture);
|
||||
renderer->buffer()->Bind();
|
||||
|
||||
// Draw with the internal texture
|
||||
internal_tex_.Bind();
|
||||
|
||||
QMatrix4x4 transform;
|
||||
|
||||
// Scale texture to a square for incoming matrix transformation
|
||||
transform.scale(2.0f / static_cast<float>(renderer->params().width()),
|
||||
2.0f / static_cast<float>(renderer->params().height()));
|
||||
|
||||
// Multiply by input transformation
|
||||
transform *= matrix_input_->get_value(in).value<QMatrix4x4>();
|
||||
|
||||
// Scale texture to the media size
|
||||
transform.scale(static_cast<float>(frame_->width()), static_cast<float>(frame_->height()));
|
||||
transform.scale(0.5f, 0.5f);
|
||||
|
||||
// Use pipeline to blit using transformation matrix from input
|
||||
if (renderer->params().mode() == olive::RenderMode::kOffline) {
|
||||
olive::gl::OCIOBlit(pipeline_, ocio_texture_, false, transform);
|
||||
} else {
|
||||
olive::gl::Blit(pipeline_, false, transform);
|
||||
}
|
||||
|
||||
// Release everything
|
||||
internal_tex_.Release();
|
||||
renderer->buffer()->Detach();
|
||||
renderer->buffer()->Release();
|
||||
|
||||
return QVariant::fromValue(output_texture);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
|
||||
virtual QString Code() const override;
|
||||
|
||||
//virtual void Hash(QCryptographicHash *hash, NodeOutput* from, const rational &time) override;
|
||||
virtual void Retranslate() override;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -442,6 +442,11 @@ NodeOutput *Node::output() const
|
||||
return output_;
|
||||
}
|
||||
|
||||
void Node::AddInput(NodeInput *input)
|
||||
{
|
||||
AddParameter(input);
|
||||
}
|
||||
|
||||
bool Node::HasParamOfType(NodeParam::Type type, bool must_be_connected) const
|
||||
{
|
||||
foreach (NodeParam* p, params_) {
|
||||
|
||||
+10
-8
@@ -267,14 +267,7 @@ public:
|
||||
NodeOutput* output() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Add a parameter to this node
|
||||
*
|
||||
* The Node takes ownership of this parameter.
|
||||
*
|
||||
* This can be either an output or an input at any time. Parameters will always appear in the order they're added.
|
||||
*/
|
||||
void AddParameter(NodeParam* param);
|
||||
void AddInput(NodeInput* input);
|
||||
|
||||
void ClearCachedValuesInParameters(const rational& start_range, const rational& end_range);
|
||||
|
||||
@@ -304,6 +297,15 @@ signals:
|
||||
void EdgeRemoved(NodeEdgePtr edge);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Add a parameter to this node
|
||||
*
|
||||
* The Node takes ownership of this parameter.
|
||||
*
|
||||
* This can be either an output or an input at any time. Parameters will always appear in the order they're added.
|
||||
*/
|
||||
void AddParameter(NodeParam* param);
|
||||
|
||||
bool HasParamOfType(NodeParam::Type type, bool must_be_connected) const;
|
||||
|
||||
void ConnectInput(NodeInput* input);
|
||||
|
||||
@@ -35,7 +35,7 @@ TimelineOutput::TimelineOutput()
|
||||
for (int i=0;i<kTrackTypeCount;i++) {
|
||||
// Create track input
|
||||
NodeInput* track_input = new NodeInput(QString("track_in_%1").arg(i));
|
||||
AddParameter(track_input);
|
||||
AddInput(track_input);
|
||||
track_inputs_.replace(i, track_input);
|
||||
|
||||
TrackList* list = new TrackList(this, static_cast<TrackType>(i), track_input);
|
||||
@@ -47,9 +47,6 @@ TimelineOutput::TimelineOutput()
|
||||
connect(list, SIGNAL(TrackAdded(TrackOutput*)), this, SLOT(TrackListAddedTrack(TrackOutput*)));
|
||||
connect(list, SIGNAL(TrackRemoved(TrackOutput*)), this, SIGNAL(TrackRemoved(TrackOutput*)));
|
||||
}
|
||||
|
||||
length_output_ = new NodeOutput("length_out");
|
||||
AddParameter(length_output_);
|
||||
}
|
||||
|
||||
Node *TimelineOutput::copy() const
|
||||
@@ -87,11 +84,6 @@ const QVector<TrackOutput *>& TimelineOutput::Tracks() const
|
||||
return track_cache_;
|
||||
}
|
||||
|
||||
NodeOutput *TimelineOutput::length_output() const
|
||||
{
|
||||
return length_output_;
|
||||
}
|
||||
|
||||
const rational &TimelineOutput::timeline_length() const
|
||||
{
|
||||
return length_;
|
||||
@@ -152,6 +144,31 @@ void TimelineOutput::SetTimebase(const rational &timebase)
|
||||
emit TimebaseChanged(timebase_);
|
||||
}
|
||||
|
||||
void TimelineOutput::Retranslate()
|
||||
{
|
||||
for (int i=0;i<track_inputs_.size();i++) {
|
||||
QString input_name;
|
||||
|
||||
switch (static_cast<TrackType>(i)) {
|
||||
case kTrackTypeVideo:
|
||||
input_name = tr("Video Tracks");
|
||||
break;
|
||||
case kTrackTypeAudio:
|
||||
input_name = tr("Audio Tracks");
|
||||
break;
|
||||
case kTrackTypeSubtitle:
|
||||
input_name = tr("Subtitle Tracks");
|
||||
break;
|
||||
case kTrackTypeNone:
|
||||
case kTrackTypeCount:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!input_name.isEmpty())
|
||||
track_inputs_.at(i)->set_name(input_name);
|
||||
}
|
||||
}
|
||||
|
||||
NodeInput *TimelineOutput::track_input(TrackType type) const
|
||||
{
|
||||
return track_inputs_.at(type);
|
||||
|
||||
@@ -52,14 +52,14 @@ public:
|
||||
|
||||
TrackList* track_list(TrackType type) const;
|
||||
|
||||
NodeOutput* length_output() const;
|
||||
|
||||
const rational& timeline_length() const;
|
||||
|
||||
const rational& timebase() const;
|
||||
|
||||
void SetTimebase(const rational &timebase);
|
||||
|
||||
virtual void Retranslate() override;
|
||||
|
||||
signals:
|
||||
void LengthChanged(const rational& length);
|
||||
void TimebaseChanged(const rational &timebase);
|
||||
@@ -80,8 +80,6 @@ private:
|
||||
|
||||
QVector<TrackOutput*> track_cache_;
|
||||
|
||||
NodeOutput* length_output_;
|
||||
|
||||
rational length_;
|
||||
|
||||
rational timebase_;
|
||||
|
||||
@@ -132,12 +132,12 @@ void TrackList::AddTrack()
|
||||
|
||||
if (track_cache_.isEmpty()) {
|
||||
// Connect this track directly to this output
|
||||
NodeParam::ConnectEdge(track->track_output(), track_input_);
|
||||
NodeParam::ConnectEdge(track->output(), track_input_);
|
||||
} else {
|
||||
TrackOutput* current_last_track = track_cache_.last();
|
||||
|
||||
// Connect this track to the current last track
|
||||
NodeParam::ConnectEdge(track->track_output(), current_last_track->track_input());
|
||||
NodeParam::ConnectEdge(track->output(), current_last_track->track_input());
|
||||
|
||||
// FIXME: Test code only
|
||||
if (current_last_track->output()->IsConnected()) {
|
||||
|
||||
@@ -31,17 +31,14 @@ TrackOutput::TrackOutput() :
|
||||
index_(-1)
|
||||
{
|
||||
block_input_ = new NodeInputArray("block_in");
|
||||
AddParameter(block_input_);
|
||||
AddInput(block_input_);
|
||||
connect(block_input_, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(BlockConnected(NodeEdgePtr)));
|
||||
connect(block_input_, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(BlockDisconnected(NodeEdgePtr)));
|
||||
connect(block_input_, SIGNAL(SizeChanged(int)), this, SLOT(BlockListSizeChanged(int)));
|
||||
|
||||
track_input_ = new NodeInput("track_in");
|
||||
track_input_->set_dependent(false);
|
||||
AddParameter(track_input_);
|
||||
|
||||
track_output_ = new NodeOutput("track_out");
|
||||
AddParameter(track_output_);
|
||||
AddInput(track_input_);
|
||||
}
|
||||
|
||||
void TrackOutput::set_track_type(const TrackType &track_type)
|
||||
@@ -106,11 +103,6 @@ NodeInput *TrackOutput::track_input()
|
||||
return track_input_;
|
||||
}
|
||||
|
||||
NodeOutput* TrackOutput::track_output()
|
||||
{
|
||||
return track_output_;
|
||||
}
|
||||
|
||||
Block *TrackOutput::BlockContainingTime(const rational &time) const
|
||||
{
|
||||
foreach (Block* block, block_cache_) {
|
||||
|
||||
@@ -52,8 +52,6 @@ public:
|
||||
|
||||
NodeInput* track_input();
|
||||
|
||||
NodeOutput* track_output();
|
||||
|
||||
Block* BlockContainingTime(const rational& time) const;
|
||||
|
||||
Block* NearestBlockBefore(const rational& time) const;
|
||||
@@ -160,8 +158,6 @@ private:
|
||||
|
||||
NodeInput* track_input_;
|
||||
|
||||
NodeOutput* track_output_;
|
||||
|
||||
TrackType track_type_;
|
||||
|
||||
rational track_length_;
|
||||
|
||||
@@ -24,15 +24,15 @@ ViewerOutput::ViewerOutput()
|
||||
{
|
||||
texture_input_ = new NodeInput("tex_in");
|
||||
texture_input_->set_data_type(NodeInput::kTexture);
|
||||
AddParameter(texture_input_);
|
||||
AddInput(texture_input_);
|
||||
|
||||
samples_input_ = new NodeInput("samples_in");
|
||||
samples_input_->set_data_type(NodeInput::kSamples);
|
||||
AddParameter(samples_input_);
|
||||
AddInput(samples_input_);
|
||||
|
||||
length_input_ = new NodeInput("length_in");
|
||||
length_input_->set_data_type(NodeInput::kRational);
|
||||
AddParameter(length_input_);
|
||||
AddInput(length_input_);
|
||||
}
|
||||
|
||||
Node *ViewerOutput::copy() const
|
||||
|
||||
Reference in New Issue
Block a user