diff --git a/app/node/factory.cpp b/app/node/factory.cpp
index 09791c6a5..d276b94da 100644
--- a/app/node/factory.cpp
+++ b/app/node/factory.cpp
@@ -26,6 +26,7 @@
#include "block/gap/gap.h"
#include "block/transition/externaltransition.h"
#include "generator/matrix/matrix.h"
+#include "generator/polygon/polygon.h"
#include "input/media/video/video.h"
#include "input/media/audio/audio.h"
#include "input/time/timeinput.h"
@@ -141,6 +142,8 @@ Node *NodeFactory::CreateInternal(const NodeFactory::InternalID &id)
return new ClipBlock();
case kGapBlock:
return new GapBlock();
+ case kPolygonGenerator:
+ return new PolygonGenerator();
case kMatrixGenerator:
return new MatrixGenerator();
case kVideoInput:
diff --git a/app/node/factory.h b/app/node/factory.h
index c6329de7e..f17a476dd 100644
--- a/app/node/factory.h
+++ b/app/node/factory.h
@@ -36,6 +36,7 @@ public:
kClipBlock,
kGapBlock,
kAudioInput,
+ kPolygonGenerator,
kMatrixGenerator,
kVideoInput,
kTrackOutput,
diff --git a/app/node/generator/CMakeLists.txt b/app/node/generator/CMakeLists.txt
index 9e8d25261..88c7de6d8 100644
--- a/app/node/generator/CMakeLists.txt
+++ b/app/node/generator/CMakeLists.txt
@@ -15,6 +15,7 @@
# along with this program. If not, see .
add_subdirectory(matrix)
+add_subdirectory(polygon)
set(OLIVE_SOURCES
${OLIVE_SOURCES}
diff --git a/app/node/generator/matrix/matrix.cpp b/app/node/generator/matrix/matrix.cpp
index 604e36415..c1b7452ca 100644
--- a/app/node/generator/matrix/matrix.cpp
+++ b/app/node/generator/matrix/matrix.cpp
@@ -90,27 +90,9 @@ void MatrixGenerator::Retranslate()
NodeValueTable MatrixGenerator::Value(NodeValueDatabase &value) const
{
- QMatrix4x4 mat;
-
- // Position translate
- QVector2D pos = value[position_input_].Get(NodeParam::kVec2).value();
- mat.translate(pos);
-
- // Rotation
- mat.rotate(value[rotation_input_].Get(NodeParam::kFloat).toFloat(), 0, 0, 1);
-
- // Scale and Uniform Scale
- QVector2D scale = value[scale_input_].Get(NodeParam::kVec2).value();
- if (value[uniform_scale_input_].Get(NodeParam::kBoolean).toBool()) {
- scale.setY(scale.x());
- }
- mat.scale(scale);
-
- // Anchor Point
- mat.translate(-value[anchor_input_].Get(NodeParam::kVec2).value());
-
// Push matrix output
- NodeValueTable output;
+ QMatrix4x4 mat = GenerateMatrix(value);
+ NodeValueTable output = value.Merge();
output.Push(NodeParam::kMatrix, mat);
return output;
}
@@ -120,10 +102,42 @@ bool MatrixGenerator::HasGizmos() const
return true;
}
-void MatrixGenerator::DrawGizmos(QPainter *p, const QRect& viewport) const
+void MatrixGenerator::DrawGizmos(NodeValueDatabase &db, QPainter *p) const
{
p->setPen(Qt::white);
- p->drawEllipse(viewport);
+
+ // Fold values into a matrix
+ QMatrix4x4 matrix = GenerateMatrix(db);
+
+ // Set QPainter transform to our matrix
+ p->setTransform(matrix.toTransform());
+
+ // Draw ellipse
+ p->drawEllipse(QRect(0, 0, 100, 100));
+}
+
+QMatrix4x4 MatrixGenerator::GenerateMatrix(NodeValueDatabase &value) const
+{
+ QMatrix4x4 mat;
+
+ // Position translate
+ QVector2D pos = value[position_input_].Take(NodeParam::kVec2).value();
+ mat.translate(pos);
+
+ // Rotation
+ mat.rotate(value[rotation_input_].Take(NodeParam::kFloat).toFloat(), 0, 0, 1);
+
+ // Scale and Uniform Scale
+ QVector2D scale = value[scale_input_].Take(NodeParam::kVec2).value();
+ if (value[uniform_scale_input_].Take(NodeParam::kBoolean).toBool()) {
+ scale.setY(scale.x());
+ }
+ mat.scale(scale);
+
+ // Anchor Point
+ mat.translate(-value[anchor_input_].Take(NodeParam::kVec2).value());
+
+ return mat;
}
void MatrixGenerator::UniformScaleChanged()
diff --git a/app/node/generator/matrix/matrix.h b/app/node/generator/matrix/matrix.h
index 116ef1602..2181e5791 100644
--- a/app/node/generator/matrix/matrix.h
+++ b/app/node/generator/matrix/matrix.h
@@ -44,9 +44,11 @@ public:
virtual NodeValueTable Value(NodeValueDatabase& value) const override;
virtual bool HasGizmos() const override;
- virtual void DrawGizmos(QPainter *p, const QRect &viewport) const override;
+ virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p) const override;
private:
+ QMatrix4x4 GenerateMatrix(NodeValueDatabase& value) const;
+
NodeInput* position_input_;
NodeInput* rotation_input_;
diff --git a/app/node/generator/polygon/CMakeLists.txt b/app/node/generator/polygon/CMakeLists.txt
new file mode 100644
index 000000000..a1a4b2cc5
--- /dev/null
+++ b/app/node/generator/polygon/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Olive - Non-Linear Video Editor
+# Copyright (C) 2019 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 .
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ node/generator/polygon/polygon.h
+ node/generator/polygon/polygon.cpp
+ PARENT_SCOPE
+)
diff --git a/app/node/generator/polygon/polygon.cpp b/app/node/generator/polygon/polygon.cpp
new file mode 100644
index 000000000..5b4718c9e
--- /dev/null
+++ b/app/node/generator/polygon/polygon.cpp
@@ -0,0 +1,120 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2019 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 .
+
+***/
+
+#include "polygon.h"
+
+#include
+
+OLIVE_NAMESPACE_ENTER
+
+PolygonGenerator::PolygonGenerator()
+{
+ points_input_ = new NodeInputArray("points_in", NodeParam::kVec2);
+ AddInput(points_input_);
+
+ color_input_ = new NodeInput("color_in", NodeParam::kColor);
+ AddInput(color_input_);
+
+ // Default to "a color" that isn't
+ color_input_->set_standard_value(1.0, 0);
+ color_input_->set_standard_value(1.0, 1);
+ color_input_->set_standard_value(1.0, 2);
+ color_input_->set_standard_value(1.0, 3);
+
+ // FIXME: Test code
+ points_input_->SetSize(5);
+ points_input_->At(0)->set_standard_value(960, 0);
+ points_input_->At(0)->set_standard_value(240, 1);
+ points_input_->At(1)->set_standard_value(640, 0);
+ points_input_->At(1)->set_standard_value(480, 1);
+ points_input_->At(2)->set_standard_value(760, 0);
+ points_input_->At(2)->set_standard_value(800, 1);
+ points_input_->At(3)->set_standard_value(1100, 0);
+ points_input_->At(3)->set_standard_value(800, 1);
+ points_input_->At(4)->set_standard_value(1280, 0);
+ points_input_->At(4)->set_standard_value(480, 1);
+ // End test
+}
+
+Node *PolygonGenerator::copy() const
+{
+ return new PolygonGenerator();
+}
+
+QString PolygonGenerator::Name() const
+{
+ return tr("Polygon");
+}
+
+QString PolygonGenerator::id() const
+{
+ return QStringLiteral("org.olivevideoeditor.Olive.polygon");
+}
+
+QString PolygonGenerator::Category() const
+{
+ return tr("Generator");
+}
+
+QString PolygonGenerator::Description() const
+{
+ return tr("Generate a 2D polygon of any amount of points.");
+}
+
+void PolygonGenerator::Retranslate()
+{
+ points_input_->set_name(tr("Points"));
+ color_input_->set_name(tr("Color"));
+}
+
+Node::Capabilities PolygonGenerator::GetCapabilities(const NodeValueDatabase &) const
+{
+ return kShader;
+}
+
+QString PolygonGenerator::ShaderFragmentCode(const NodeValueDatabase &) const
+{
+ return Node::ReadFileAsString(":/shaders/polygon.frag");
+}
+
+bool PolygonGenerator::HasGizmos() const
+{
+ return true;
+}
+
+void PolygonGenerator::DrawGizmos(NodeValueDatabase &db, QPainter *p) const
+{
+ QVector points(points_input_->GetSize());
+
+ p->setPen(Qt::white);
+ p->setBrush(Qt::white);
+
+ for (int i=0;iGetSize();i++) {
+ points[i] = db[points_input_->At(i)].Take(NodeParam::kVec2).value().toPointF();
+
+ QRectF rect(points[i] - QPointF(10, 10),
+ points[i] + QPointF(10, 10));
+ p->drawRect(rect);
+ }
+
+ p->drawPolyline(points.constData(), points_input_->GetSize());
+}
+
+OLIVE_NAMESPACE_EXIT
diff --git a/app/node/generator/polygon/polygon.h b/app/node/generator/polygon/polygon.h
new file mode 100644
index 000000000..9c4e4d31b
--- /dev/null
+++ b/app/node/generator/polygon/polygon.h
@@ -0,0 +1,63 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2019 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 POLYGONGENERATOR_H
+#define POLYGONGENERATOR_H
+
+#include "node/node.h"
+
+OLIVE_NAMESPACE_ENTER
+
+class PolygonGenerator : public Node
+{
+public:
+ PolygonGenerator();
+
+ virtual Node* copy() const override;
+
+ virtual QString Name() const override;
+ virtual QString id() const override;
+ virtual QString Category() const override;
+ virtual QString Description() const override;
+
+ virtual void Retranslate() override;
+
+ virtual Capabilities GetCapabilities(const NodeValueDatabase&) const override;
+ virtual QString ShaderFragmentCode(const NodeValueDatabase&) const override;
+
+ virtual bool HasGizmos() const override;
+ virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p) const override;
+
+ /*
+ virtual bool GizmoPress(const QPointF &p) override;
+ virtual void GizmoMove(const QPointF &p) override;
+ virtual void GizmoRelease(const QPointF &p) override;
+ */
+
+private:
+ NodeInputArray* points_input_;
+
+ NodeInput* color_input_;
+
+};
+
+OLIVE_NAMESPACE_EXIT
+
+#endif // POLYGONGENERATOR_H
diff --git a/app/node/node.cpp b/app/node/node.cpp
index 76f82484c..f370e0fec 100644
--- a/app/node/node.cpp
+++ b/app/node/node.cpp
@@ -293,7 +293,20 @@ bool Node::HasGizmos() const
return false;
}
-void Node::DrawGizmos(QPainter *, const QRect &) const
+void Node::DrawGizmos(NodeValueDatabase &, QPainter *) const
+{
+}
+
+bool Node::GizmoPress(const QPointF &)
+{
+ return false;
+}
+
+void Node::GizmoMove(const QPointF &)
+{
+}
+
+void Node::GizmoRelease(const QPointF &)
{
}
diff --git a/app/node/node.h b/app/node/node.h
index b623ca1d5..317bebcb4 100644
--- a/app/node/node.h
+++ b/app/node/node.h
@@ -362,7 +362,11 @@ public:
virtual bool HasGizmos() const;
- virtual void DrawGizmos(QPainter* p, const QRect &viewport) const;
+ virtual void DrawGizmos(NodeValueDatabase& db, QPainter* p) const;
+
+ virtual bool GizmoPress(const QPointF& p);
+ virtual void GizmoMove(const QPointF& p);
+ virtual void GizmoRelease(const QPointF& p);
const QString& GetLabel() const;
void SetLabel(const QString& s);
diff --git a/app/node/traverser.cpp b/app/node/traverser.cpp
index c4737cfd1..9f5a1f8f5 100644
--- a/app/node/traverser.cpp
+++ b/app/node/traverser.cpp
@@ -29,21 +29,29 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const TimeRa
NodeValueDatabase database;
// We need to insert tables into the database for each input
- foreach (NodeParam* param, node->parameters()) {
+ QList inputs = node->GetInputsIncludingArrays();
+
+ foreach (NodeInput* input, inputs) {
if (IsCancelled()) {
return NodeValueDatabase();
}
- if (param->type() == NodeParam::kInput) {
- NodeInput* input = static_cast(param);
- TimeRange input_time = node->InputTimeAdjustment(input, range);
+ TimeRange input_time = node->InputTimeAdjustment(input, range);
- NodeValueTable table = ProcessInput(input, input_time);
+ NodeValueTable table = ProcessInput(input, input_time);
- InputProcessingEvent(input, input_time, &table);
+ // Exception for Footage types where we actually retrieve some Footage data from a decoder
+ if (input->data_type() == NodeParam::kFootage) {
+ StreamPtr stream = ResolveStreamFromInput(input);
- database.Insert(input, table);
+ if (stream) {
+
+ FootageProcessingEvent(stream, input_time, &table);
+
+ }
}
+
+ database.Insert(input, table);
}
// Insert global variables
@@ -79,8 +87,21 @@ NodeValueTable NodeTraverser::ProcessNode(const NodeDependency& dep)
NodeValueTable NodeTraverser::RenderBlock(const TrackOutput *track, const TimeRange &range)
{
- // By default, don't bother traversing blocks
- return NodeValueTable();
+ // By default, just follow the in point
+ Block* active_block = track->BlockAtTime(range.in());
+
+ NodeValueTable table;
+
+ if (active_block) {
+ table = ProcessNode(NodeDependency(active_block, range));
+ }
+
+ return table;
+}
+
+StreamPtr NodeTraverser::ResolveStreamFromInput(NodeInput *input)
+{
+ return input->get_standard_value().value();
}
NodeValueTable NodeTraverser::ProcessInput(const NodeInput *input, const TimeRange& range)
diff --git a/app/node/traverser.h b/app/node/traverser.h
index 7897cd7a1..4e80a2a68 100644
--- a/app/node/traverser.h
+++ b/app/node/traverser.h
@@ -37,17 +37,20 @@ public:
NodeValueTable ProcessNode(const NodeDependency &dep);
-protected:
NodeValueDatabase GenerateDatabase(const Node *node, const TimeRange &range);
+protected:
virtual NodeValueTable RenderBlock(const TrackOutput *track, const TimeRange& range);
NodeValueTable ProcessInput(const NodeInput* input, const TimeRange &range);
- virtual void InputProcessingEvent(NodeInput*, const TimeRange&, NodeValueTable*){}
+ virtual void FootageProcessingEvent(StreamPtr, const TimeRange&, NodeValueTable*){}
virtual void ProcessNodeEvent(const Node*, const TimeRange&, NodeValueDatabase&, NodeValueTable&){}
+private:
+ StreamPtr ResolveStreamFromInput(NodeInput* input);
+
};
OLIVE_NAMESPACE_EXIT
diff --git a/app/panel/pixelsampler/pixelsamplerpanel.h b/app/panel/pixelsampler/pixelsamplerpanel.h
index 089de194c..6e91cce2f 100644
--- a/app/panel/pixelsampler/pixelsamplerpanel.h
+++ b/app/panel/pixelsampler/pixelsamplerpanel.h
@@ -22,7 +22,7 @@
#define PIXELSAMPLERPANEL_H
#include "widget/panel/panel.h"
-#include "widget/viewer/pixelsamplerwidget.h"
+#include "widget/pixelsampler/pixelsampler.h"
OLIVE_NAMESPACE_ENTER
diff --git a/app/render/backend/opengl/openglproxy.cpp b/app/render/backend/opengl/openglproxy.cpp
index 05b4e5609..649b2ba15 100644
--- a/app/render/backend/opengl/openglproxy.cpp
+++ b/app/render/backend/opengl/openglproxy.cpp
@@ -110,7 +110,10 @@ void OpenGLProxy::FrameToValue(FramePtr frame, StreamPtr stream, NodeValueTable*
bool has_alpha = PixelFormat::FormatHasAlphaChannel(frame->format());
// Convert frame to float for OCIO
- frame = PixelFormat::ConvertPixelFormat(frame, has_alpha ? PixelFormat::PIX_FMT_RGBA32F : PixelFormat::PIX_FMT_RGB32F);
+ frame = PixelFormat::ConvertPixelFormat(frame,
+ has_alpha
+ ? PixelFormat::PIX_FMT_RGBA32F
+ : PixelFormat::PIX_FMT_RGB32F);
// If alpha is associated, disassociate for the color transform
if (has_alpha && video_stream->premultiplied_alpha()) {
@@ -281,7 +284,25 @@ void OpenGLProxy::RunNodeAccelerated(const Node *node, const TimeRange &range, N
shader->setUniformValue(variable_location, value.toFloat());
break;
case NodeInput::kVec2:
- shader->setUniformValue(variable_location, value.value());
+ if (input->IsArray()) {
+ NodeInputArray* array = static_cast(input);
+ QVector a(array->GetSize());
+
+ for (int i=0;iAt(i)].Get(NodeParam::kVec2).value();
+ }
+
+ shader->setUniformValueArray(variable_location, a.constData(), a.size());
+
+ int count_location = shader->uniformLocation(QStringLiteral("%1_count").arg(input->id()));
+ if (count_location > -1) {
+ shader->setUniformValue(count_location,
+ array->GetSize());
+ }
+
+ } else {
+ shader->setUniformValue(variable_location, value.value());
+ }
break;
case NodeInput::kVec3:
shader->setUniformValue(variable_location, value.value());
diff --git a/app/render/backend/renderworker.cpp b/app/render/backend/renderworker.cpp
index c2b1b2311..04ccb1659 100644
--- a/app/render/backend/renderworker.cpp
+++ b/app/render/backend/renderworker.cpp
@@ -76,11 +76,6 @@ void RenderWorker::RunNodeAccelerated(const Node *node, const TimeRange &range,
Q_UNUSED(output_params)
}
-StreamPtr RenderWorker::ResolveStreamFromInput(NodeInput *input)
-{
- return input->get_standard_value().value();
-}
-
DecoderPtr RenderWorker::ResolveDecoderFromInput(StreamPtr stream)
{
// Access a map of Node inputs and decoder instances and retrieve a frame!
@@ -108,21 +103,12 @@ bool RenderWorker::IsStarted()
return started_;
}
-void RenderWorker::InputProcessingEvent(NodeInput* input, const TimeRange& input_time, NodeValueTable *table)
+void RenderWorker::FootageProcessingEvent(StreamPtr stream, const TimeRange& input_time, NodeValueTable *table)
{
- // Exception for Footage types where we actually retrieve some Footage data from a decoder
- if (input->data_type() == NodeParam::kFootage) {
- StreamPtr stream = ResolveStreamFromInput(input);
+ DecoderPtr decoder = ResolveDecoderFromInput(stream);
- if (stream) {
- DecoderPtr decoder = ResolveDecoderFromInput(stream);
-
- if (decoder) {
-
- FrameToValue(decoder, stream, input_time, table);
-
- }
- }
+ if (decoder) {
+ FrameToValue(decoder, stream, input_time, table);
}
}
diff --git a/app/render/backend/renderworker.h b/app/render/backend/renderworker.h
index 17d8e600f..aa03e7af1 100644
--- a/app/render/backend/renderworker.h
+++ b/app/render/backend/renderworker.h
@@ -59,12 +59,10 @@ protected:
virtual void FrameToValue(DecoderPtr decoder, StreamPtr stream, const TimeRange &range, NodeValueTable* table) = 0;
- virtual void InputProcessingEvent(NodeInput *input, const TimeRange &input_time, NodeValueTable* table) override;
+ virtual void FootageProcessingEvent(StreamPtr stream, const TimeRange &input_time, NodeValueTable* table) override;
virtual void ProcessNodeEvent(const Node *node, const TimeRange &range, NodeValueDatabase &input_params, NodeValueTable &output_params) override;
- StreamPtr ResolveStreamFromInput(NodeInput* input);
-
DecoderPtr ResolveDecoderFromInput(StreamPtr stream);
const NodeDependency& CurrentPath() const;
diff --git a/app/render/backend/videorenderworker.cpp b/app/render/backend/videorenderworker.cpp
index ffc568811..74c23ecd1 100644
--- a/app/render/backend/videorenderworker.cpp
+++ b/app/render/backend/videorenderworker.cpp
@@ -201,20 +201,6 @@ void VideoRenderWorker::ResizeDownloadBuffer()
download_buffer_.resize(PixelFormat::GetBufferSize(video_params_.format(), video_params_.effective_width(), video_params_.effective_height()));
}
-NodeValueTable VideoRenderWorker::RenderBlock(const TrackOutput *track, const TimeRange &range)
-{
- // A frame can only have one active block so we just validate the in point of the range
- Block* active_block = track->BlockAtTime(range.in());
-
- NodeValueTable table;
-
- if (active_block) {
- table = ProcessNode(NodeDependency(active_block, range));
- }
-
- return table;
-}
-
ColorProcessorCache *VideoRenderWorker::color_cache()
{
return &color_cache_;
diff --git a/app/render/backend/videorenderworker.h b/app/render/backend/videorenderworker.h
index a4737fcde..77ba6f2bb 100644
--- a/app/render/backend/videorenderworker.h
+++ b/app/render/backend/videorenderworker.h
@@ -92,14 +92,12 @@ protected:
virtual void ParametersChangedEvent(){}
- virtual void TextureToBuffer(const QVariant& texture, void *buffer, int linesize);
+ void TextureToBuffer(const QVariant& texture, void *buffer, int linesize);
virtual void TextureToBuffer(const QVariant& texture, int width, int height, const QMatrix4x4& matrix, void *buffer, int linesize) = 0;
virtual NodeValueTable RenderInternal(const NodeDependency& CurrentPath, const qint64& job_time) override;
- virtual NodeValueTable RenderBlock(const TrackOutput *track, const TimeRange& range) override;
-
ColorProcessorCache* color_cache();
private:
diff --git a/app/shaders/polygon.frag b/app/shaders/polygon.frag
new file mode 100644
index 000000000..ae45ddf73
--- /dev/null
+++ b/app/shaders/polygon.frag
@@ -0,0 +1,44 @@
+#version 150
+
+uniform vec2[256] points_in;
+uniform int points_in_count;
+uniform vec4 color_in;
+
+uniform vec2 ove_resolution;
+
+in vec2 ove_texcoord;
+
+out vec4 fragColor;
+
+/*
+int pnpoly(int npol, float *xp, float *yp, float x, float y) {
+ int i, j, c = 0;
+ for (i = 0, j = npol-1; i < npol; j = i++) {
+ if ((((yp[i] <= y) && (y < yp[j])) ||
+ ((yp[j] <= y) && (y < yp[i]))) &&
+ (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
+ c = !c;
+ }
+ return c;
+}
+*/
+
+bool pnpoly(vec2 p) {
+ bool c = false;
+ int i, j;
+ for (i = 0, j = points_in_count-1; i < points_in_count; j = i++) {
+ if ((((points_in[i].y <= p.y) && (p.y < points_in[j].y)) ||
+ ((points_in[j].y <= p.y) && (p.y < points_in[i].y))) &&
+ (p.x < (points_in[j].x - points_in[i].x) * (p.y - points_in[i].y) / (points_in[j].y - points_in[i].y) + points_in[i].x))
+ c = !c;
+ }
+ return c;
+}
+
+void main(void) {
+ if (points_in_count > 0 && pnpoly(ove_texcoord * ove_resolution)) {
+ fragColor = color_in;
+ } else {
+ fragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ }
+}
diff --git a/app/shaders/shaders.qrc b/app/shaders/shaders.qrc
index 7e6f4876c..1c7d8d061 100644
--- a/app/shaders/shaders.qrc
+++ b/app/shaders/shaders.qrc
@@ -12,6 +12,7 @@
dropshadow.xml
diptoblack.frag
diptoblack.xml
+ polygon.frag
rgbwaveform.frag
solid.frag
solid.xml
diff --git a/app/widget/CMakeLists.txt b/app/widget/CMakeLists.txt
index f33f5d064..ddc6dfb72 100644
--- a/app/widget/CMakeLists.txt
+++ b/app/widget/CMakeLists.txt
@@ -31,6 +31,7 @@ add_subdirectory(nodecopypaste)
add_subdirectory(nodeview)
add_subdirectory(nodeparamview)
add_subdirectory(panel)
+add_subdirectory(pixelsampler)
add_subdirectory(playbackcontrols)
add_subdirectory(projectexplorer)
add_subdirectory(projecttoolbar)
@@ -41,6 +42,7 @@ add_subdirectory(taskview)
add_subdirectory(timebased)
add_subdirectory(timelinewidget)
add_subdirectory(timeruler)
+add_subdirectory(timetarget)
add_subdirectory(toolbar)
add_subdirectory(viewer)
diff --git a/app/widget/keyframeview/CMakeLists.txt b/app/widget/keyframeview/CMakeLists.txt
index 17f7bce21..713f9bb20 100644
--- a/app/widget/keyframeview/CMakeLists.txt
+++ b/app/widget/keyframeview/CMakeLists.txt
@@ -24,7 +24,5 @@ set(OLIVE_SOURCES
widget/keyframeview/keyframeviewitem.cpp
widget/keyframeview/keyframeviewundo.h
widget/keyframeview/keyframeviewundo.cpp
- widget/keyframeview/timetargetobject.h
- widget/keyframeview/timetargetobject.cpp
PARENT_SCOPE
)
diff --git a/app/widget/keyframeview/keyframeviewbase.h b/app/widget/keyframeview/keyframeviewbase.h
index 000394641..04e7d6096 100644
--- a/app/widget/keyframeview/keyframeviewbase.h
+++ b/app/widget/keyframeview/keyframeviewbase.h
@@ -23,7 +23,7 @@
#include "keyframeviewitem.h"
#include "node/keyframe.h"
-#include "timetargetobject.h"
+#include "widget/timetarget/timetarget.h"
#include "widget/curvewidget/beziercontrolpointitem.h"
#include "widget/timelinewidget/view/timelineviewbase.h"
diff --git a/app/widget/keyframeview/keyframeviewitem.h b/app/widget/keyframeview/keyframeviewitem.h
index ca5a6d660..ee5c06031 100644
--- a/app/widget/keyframeview/keyframeviewitem.h
+++ b/app/widget/keyframeview/keyframeviewitem.h
@@ -24,7 +24,7 @@
#include
#include "node/keyframe.h"
-#include "timetargetobject.h"
+#include "widget/timetarget/timetarget.h"
OLIVE_NAMESPACE_ENTER
diff --git a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h
index 395251099..002b00fc5 100644
--- a/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h
+++ b/app/widget/nodeparamview/nodeparamviewkeyframecontrol.h
@@ -25,7 +25,7 @@
#include
#include "node/input.h"
-#include "widget/keyframeview/timetargetobject.h"
+#include "widget/timetarget/timetarget.h"
OLIVE_NAMESPACE_ENTER
diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.h b/app/widget/nodeparamview/nodeparamviewwidgetbridge.h
index d1543c73e..3d385a7bc 100644
--- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.h
+++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.h
@@ -24,8 +24,8 @@
#include
#include "node/input.h"
-#include "widget/keyframeview/timetargetobject.h"
#include "widget/slider/sliderbase.h"
+#include "widget/timetarget/timetarget.h"
OLIVE_NAMESPACE_ENTER
diff --git a/app/widget/pixelsampler/CMakeLists.txt b/app/widget/pixelsampler/CMakeLists.txt
new file mode 100644
index 000000000..ecf7831f7
--- /dev/null
+++ b/app/widget/pixelsampler/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Olive - Non-Linear Video Editor
+# Copyright (C) 2019 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 .
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ widget/pixelsampler/pixelsampler.h
+ widget/pixelsampler/pixelsampler.cpp
+ PARENT_SCOPE
+)
diff --git a/app/widget/viewer/pixelsamplerwidget.cpp b/app/widget/pixelsampler/pixelsampler.cpp
similarity index 98%
rename from app/widget/viewer/pixelsamplerwidget.cpp
rename to app/widget/pixelsampler/pixelsampler.cpp
index c955d21ed..22cde93f5 100644
--- a/app/widget/viewer/pixelsamplerwidget.cpp
+++ b/app/widget/pixelsampler/pixelsampler.cpp
@@ -18,7 +18,7 @@
***/
-#include "pixelsamplerwidget.h"
+#include "pixelsampler.h"
#include
diff --git a/app/widget/viewer/pixelsamplerwidget.h b/app/widget/pixelsampler/pixelsampler.h
similarity index 100%
rename from app/widget/viewer/pixelsamplerwidget.h
rename to app/widget/pixelsampler/pixelsampler.h
diff --git a/app/widget/timetarget/CMakeLists.txt b/app/widget/timetarget/CMakeLists.txt
new file mode 100644
index 000000000..98f834bd1
--- /dev/null
+++ b/app/widget/timetarget/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Olive - Non-Linear Video Editor
+# Copyright (C) 2019 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 .
+
+set(OLIVE_SOURCES
+ ${OLIVE_SOURCES}
+ widget/timetarget/timetarget.h
+ widget/timetarget/timetarget.cpp
+ PARENT_SCOPE
+)
diff --git a/app/widget/keyframeview/timetargetobject.cpp b/app/widget/timetarget/timetarget.cpp
similarity index 98%
rename from app/widget/keyframeview/timetargetobject.cpp
rename to app/widget/timetarget/timetarget.cpp
index 0ea00d0d9..51ec506d3 100644
--- a/app/widget/keyframeview/timetargetobject.cpp
+++ b/app/widget/timetarget/timetarget.cpp
@@ -18,7 +18,7 @@
***/
-#include "timetargetobject.h"
+#include "timetarget.h"
OLIVE_NAMESPACE_ENTER
diff --git a/app/widget/keyframeview/timetargetobject.h b/app/widget/timetarget/timetarget.h
similarity index 100%
rename from app/widget/keyframeview/timetargetobject.h
rename to app/widget/timetarget/timetarget.h
diff --git a/app/widget/viewer/CMakeLists.txt b/app/widget/viewer/CMakeLists.txt
index e96b9e639..70df051ae 100644
--- a/app/widget/viewer/CMakeLists.txt
+++ b/app/widget/viewer/CMakeLists.txt
@@ -20,8 +20,8 @@ set(OLIVE_SOURCES
widget/viewer/audiowaveformview.cpp
widget/viewer/footageviewer.h
widget/viewer/footageviewer.cpp
- widget/viewer/pixelsamplerwidget.h
- widget/viewer/pixelsamplerwidget.cpp
+ widget/viewer/gizmotraverser.h
+ widget/viewer/gizmotraverser.cpp
widget/viewer/viewer.h
widget/viewer/viewer.cpp
widget/viewer/viewerdisplay.h
diff --git a/app/widget/viewer/gizmotraverser.cpp b/app/widget/viewer/gizmotraverser.cpp
new file mode 100644
index 000000000..1e77fd925
--- /dev/null
+++ b/app/widget/viewer/gizmotraverser.cpp
@@ -0,0 +1,39 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2019 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 .
+
+***/
+
+#include "gizmotraverser.h"
+
+OLIVE_NAMESPACE_ENTER
+
+void GizmoTraverser::FootageProcessingEvent(StreamPtr stream, const TimeRange &/*input_time*/, NodeValueTable *table)
+{
+ if (stream->type() == Stream::kVideo || stream->type() == Stream::kAudio) {
+
+ ImageStreamPtr image_stream = std::static_pointer_cast(stream);
+
+ table->Push(NodeParam::kTexture, QSize(image_stream->width(),
+ image_stream->height()));
+
+ } else if (stream->type() == Stream::kAudio) {
+ // FIXME: Get samples
+ }
+}
+
+OLIVE_NAMESPACE_EXIT
diff --git a/app/widget/viewer/gizmotraverser.h b/app/widget/viewer/gizmotraverser.h
new file mode 100644
index 000000000..97b2cfc43
--- /dev/null
+++ b/app/widget/viewer/gizmotraverser.h
@@ -0,0 +1,40 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2019 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 GIZMOTRAVERSER_H
+#define GIZMOTRAVERSER_H
+
+#include "node/traverser.h"
+
+OLIVE_NAMESPACE_ENTER
+
+class GizmoTraverser : public NodeTraverser
+{
+public:
+ GizmoTraverser() = default;
+
+protected:
+ virtual void FootageProcessingEvent(StreamPtr stream, const TimeRange &input_time, NodeValueTable* table) override;
+
+};
+
+OLIVE_NAMESPACE_EXIT
+
+#endif // GIZMOTRAVERSER_H
diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp
index 6d5ae3976..8fd2bab3a 100644
--- a/app/widget/viewer/viewer.cpp
+++ b/app/widget/viewer/viewer.cpp
@@ -130,6 +130,8 @@ void ViewerWidget::TimeChangedEvent(const int64_t &i)
UpdateTextureFromNode(time_set);
PushScrubbedAudio();
+
+ main_gl_widget()->SetTime(time_set);
}
last_time_ = i;
@@ -335,6 +337,7 @@ ColorManager *ViewerWidget::color_manager() const
void ViewerWidget::SetGizmos(Node *node)
{
+ main_gl_widget()->SetTimeTarget(GetConnectedNode());
main_gl_widget()->SetGizmos(node);
}
@@ -537,6 +540,8 @@ void ViewerWidget::UpdateRendererParameters()
video_renderer_->InvalidateCache(TimeRange(0, GetConnectedNode()->Length()), nullptr);
}
+ main_gl_widget()->SetVideoParams(vparam);
+
AudioRenderingParams aparam(GetConnectedNode()->audio_params(),
SampleFormat::kInternalFormat);
diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp
index 99a0c7d03..ced00dd6b 100644
--- a/app/widget/viewer/viewerdisplay.cpp
+++ b/app/widget/viewer/viewerdisplay.cpp
@@ -30,6 +30,7 @@
#include
#include "common/define.h"
+#include "gizmotraverser.h"
#include "render/backend/opengl/openglrenderfunctions.h"
#include "render/backend/opengl/openglshader.h"
#include "render/pixelformat.h"
@@ -44,7 +45,8 @@ ViewerDisplayWidget::ViewerDisplayWidget(QWidget *parent) :
ManagedDisplayWidget(parent),
has_image_(false),
signal_cursor_color_(false),
- gizmos_(nullptr)
+ gizmos_(nullptr),
+ gizmo_click_(false)
{
}
@@ -169,8 +171,33 @@ void ViewerDisplayWidget::SetGizmos(Node *node)
update();
}
+void ViewerDisplayWidget::SetVideoParams(const VideoRenderingParams ¶ms)
+{
+ gizmo_params_ = params;
+
+ if (gizmos_) {
+ update();
+ }
+}
+
+void ViewerDisplayWidget::SetTime(const rational &time)
+{
+ time_ = time;
+
+ if (gizmos_) {
+ update();
+ }
+}
+
void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event)
{
+ if (gizmos_) {
+ if (gizmos_->GizmoPress(GetTexturePosition(event->pos()))) {
+ gizmo_click_ = true;
+ return;
+ }
+ }
+
QOpenGLWidget::mousePressEvent(event);
emit DragStarted();
@@ -178,6 +205,11 @@ void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event)
void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event)
{
+ if (gizmo_click_) {
+ gizmos_->GizmoMove(GetTexturePosition(event->pos()));
+ return;
+ }
+
QOpenGLWidget::mouseMoveEvent(event);
if (signal_cursor_color_) {
@@ -201,6 +233,18 @@ void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event)
}
}
+void ViewerDisplayWidget::mouseReleaseEvent(QMouseEvent *event)
+{
+ if (gizmo_click_) {
+ gizmos_->GizmoRelease(GetTexturePosition(event->pos()));
+ gizmo_click_ = false;
+
+ return;
+ }
+
+ QOpenGLWidget::mouseReleaseEvent(event);
+}
+
void ViewerDisplayWidget::initializeGL()
{
ManagedDisplayWidget::initializeGL();
@@ -233,7 +277,7 @@ void ViewerDisplayWidget::paintGL()
f->glClear(GL_COLOR_BUFFER_BIT);
// We only draw if we have a pipeline
- if (has_image_ && color_service() && texture_.IsCreated()) {
+ if (has_image_ && color_service()) {
// Bind retrieved texture
f->glBindTexture(GL_TEXTURE_2D, texture_.texture());
@@ -248,8 +292,19 @@ void ViewerDisplayWidget::paintGL()
// Draw gizmos if we have any
if (gizmos_) {
+ GizmoTraverser gt;
+
+ rational node_time = GetAdjustedTime(GetTimeTarget(), gizmos_, time_, NodeParam::kInput);
+
+ NodeValueDatabase db = gt.GenerateDatabase(gizmos_, TimeRange(node_time, node_time));
+
QPainter p(this);
- gizmos_->DrawGizmos(&p, rect());
+
+ // Scale so that gizmos can just draw on the buffer
+ QPointF tex_point = GetTexturePosition(size());
+ p.scale(tex_point.x(), tex_point.y());
+
+ gizmos_->DrawGizmos(db, &p);
}
// Draw action/title safe areas
@@ -285,6 +340,22 @@ void ViewerDisplayWidget::paintGL()
}
}
+QPointF ViewerDisplayWidget::GetTexturePosition(const QPoint &screen_pos)
+{
+ return GetTexturePosition(screen_pos.x(), screen_pos.y());
+}
+
+QPointF ViewerDisplayWidget::GetTexturePosition(const QSize &size)
+{
+ return GetTexturePosition(size.width(), size.height());
+}
+
+QPointF ViewerDisplayWidget::GetTexturePosition(const double &x, const double &y)
+{
+ return QPointF(x / gizmo_params_.width(),
+ y / gizmo_params_.height());
+}
+
#ifdef Q_OS_LINUX
void ViewerDisplayWidget::ShowNouveauWarning()
{
diff --git a/app/widget/viewer/viewerdisplay.h b/app/widget/viewer/viewerdisplay.h
index 4d3abb1da..a9903075e 100644
--- a/app/widget/viewer/viewerdisplay.h
+++ b/app/widget/viewer/viewerdisplay.h
@@ -32,6 +32,7 @@
#include "render/colormanager.h"
#include "viewersafemargininfo.h"
#include "widget/manageddisplay/manageddisplay.h"
+#include "widget/timetarget/timetarget.h"
OLIVE_NAMESPACE_ENTER
@@ -50,7 +51,7 @@ OLIVE_NAMESPACE_ENTER
* the same texture object, use SetTexture() since it will nearly always be faster to just set it than to check *and*
* set it.
*/
-class ViewerDisplayWidget : public ManagedDisplayWidget
+class ViewerDisplayWidget : public ManagedDisplayWidget, public TimeTargetObject
{
Q_OBJECT
public:
@@ -78,6 +79,8 @@ public:
void SetSafeMargins(const ViewerSafeMarginInfo& safe_margin);
void SetGizmos(Node* node);
+ void SetVideoParams(const VideoRenderingParams& params);
+ void SetTime(const rational& time);
public slots:
/**
@@ -126,15 +129,20 @@ signals:
protected:
/**
- * @brief Override the mouse press event simply to emit the DragStarted() signal
+ * @brief Override the mouse press event for the DragStarted() signal and gizmos
*/
virtual void mousePressEvent(QMouseEvent* event) override;
/**
- * @brief Override mouse move to provide functionality for
+ * @brief Override mouse move to signal for the pixel sampler and gizmos
*/
virtual void mouseMoveEvent(QMouseEvent* event) override;
+ /**
+ * @brief Override mouse release event for gizmos
+ */
+ virtual void mouseReleaseEvent(QMouseEvent* event) override;
+
/**
* @brief Initialize function to set up the OpenGL context upon its construction
*
@@ -150,6 +158,10 @@ protected:
virtual void paintGL() override;
private:
+ QPointF GetTexturePosition(const QPoint& screen_pos);
+ QPointF GetTexturePosition(const QSize& size);
+ QPointF GetTexturePosition(const double& x, const double& y);
+
/**
* @brief Internal reference to the OpenGL texture to draw. Set in SetTexture() and used in paintGL().
*/
@@ -177,6 +189,12 @@ private:
Node* gizmos_;
+ VideoRenderingParams gizmo_params_;
+
+ bool gizmo_click_;
+
+ rational time_;
+
private slots:
/**
* @brief Slot to connect just before the OpenGL context is destroyed to clean up resources