diff --git a/app/node/factory.cpp b/app/node/factory.cpp
index 9e18f0a99..9f6c7f335 100644
--- a/app/node/factory.cpp
+++ b/app/node/factory.cpp
@@ -33,6 +33,7 @@
#include "distort/transform/transformdistortnode.h"
#include "generator/matrix/matrix.h"
#include "generator/polygon/polygon.h"
+#include "generator/shape/shapenode.h"
#include "generator/solid/solid.h"
#include "generator/text/text.h"
#include "filter/blur/blur.h"
@@ -239,13 +240,14 @@ Node *NodeFactory::CreateFromFactoryIndex(const NodeFactory::InternalID &id)
return new TimeRemapNode();
case kSubtitleBlock:
return new SubtitleBlock();
+ case kShapeGenerator:
+ return new ShapeNode();
case kInternalNodeCount:
break;
}
- // We should never get here
- abort();
+ return nullptr;
}
}
diff --git a/app/node/factory.h b/app/node/factory.h
index 8ba811cd3..a53a3d6ff 100644
--- a/app/node/factory.h
+++ b/app/node/factory.h
@@ -59,6 +59,7 @@ public:
kValueNode,
kTimeRemapNode,
kSubtitleBlock,
+ kShapeGenerator,
// Count value
kInternalNodeCount
diff --git a/app/node/generator/CMakeLists.txt b/app/node/generator/CMakeLists.txt
index 8c5706e50..dfdabb071 100644
--- a/app/node/generator/CMakeLists.txt
+++ b/app/node/generator/CMakeLists.txt
@@ -16,6 +16,7 @@
add_subdirectory(matrix)
add_subdirectory(polygon)
+add_subdirectory(shape)
add_subdirectory(solid)
add_subdirectory(text)
diff --git a/app/node/generator/shape/CMakeLists.txt b/app/node/generator/shape/CMakeLists.txt
new file mode 100644
index 000000000..b3d0fed04
--- /dev/null
+++ b/app/node/generator/shape/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Olive - Non-Linear Video Editor
+# Copyright (C) 2021 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/shape/shapenode.cpp
+ node/generator/shape/shapenode.h
+ node/generator/shape/shapenodebase.cpp
+ node/generator/shape/shapenodebase.h
+ PARENT_SCOPE
+)
diff --git a/app/node/generator/shape/shapenode.cpp b/app/node/generator/shape/shapenode.cpp
new file mode 100644
index 000000000..0c8f258a4
--- /dev/null
+++ b/app/node/generator/shape/shapenode.cpp
@@ -0,0 +1,89 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2021 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 "shapenode.h"
+
+namespace olive {
+
+#define super ShapeNodeBase
+
+QString ShapeNode::kTypeInput = QStringLiteral("type_in");
+
+ShapeNode::ShapeNode()
+{
+ PrependInput(kTypeInput, NodeValue::kCombo);
+}
+
+QString ShapeNode::Name() const
+{
+ return tr("Shape");
+}
+
+QString ShapeNode::id() const
+{
+ return QStringLiteral("org.olivevideoeditor.Olive.shape");
+}
+
+QVector ShapeNode::Category() const
+{
+ return {kCategoryGenerator};
+}
+
+QString ShapeNode::Description() const
+{
+ return tr("Generate a 2D primitive shape.");
+}
+
+void ShapeNode::Retranslate()
+{
+ super::Retranslate();
+
+ SetInputName(kTypeInput, tr("Type"));
+
+ // Coordinate with Type enum
+ SetComboBoxStrings(kTypeInput, {tr("Rectangle"), tr("Ellipse")});
+}
+
+ShaderCode ShapeNode::GetShaderCode(const QString &shader_id) const
+{
+ Q_UNUSED(shader_id)
+
+ return ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/shape.frag")));
+}
+
+NodeValueTable ShapeNode::Value(const QString &output, NodeValueDatabase &value) const
+{
+ Q_UNUSED(output)
+
+ ShaderJob job;
+
+ job.InsertValue(this, kTypeInput, value);
+ job.InsertValue(this, kPositionInput, value);
+ job.InsertValue(this, kSizeInput, value);
+ job.InsertValue(this, kColorInput, value);
+ job.InsertValue(QStringLiteral("resolution_in"), value[QStringLiteral("global")].GetWithMeta(NodeValue::kVec2, QStringLiteral("resolution")));
+ job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn);
+
+ NodeValueTable table = value.Merge();
+ table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this);
+ return table;
+}
+
+}
diff --git a/app/node/generator/shape/shapenode.h b/app/node/generator/shape/shapenode.h
new file mode 100644
index 000000000..0381be00d
--- /dev/null
+++ b/app/node/generator/shape/shapenode.h
@@ -0,0 +1,61 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2021 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 SHAPENODE_H
+#define SHAPENODE_H
+
+#include "shapenodebase.h"
+
+namespace olive {
+
+class ShapeNode : public ShapeNodeBase
+{
+ Q_OBJECT
+public:
+ ShapeNode();
+
+ enum Type {
+ kRectangle,
+ kEllipse
+ };
+
+ NODE_DEFAULT_DESTRUCTOR(ShapeNode)
+ NODE_COPY_FUNCTION(ShapeNode)
+
+ virtual QString Name() const override;
+ virtual QString id() const override;
+ virtual QVector Category() const override;
+ virtual QString Description() const override;
+
+ virtual void Retranslate() override;
+
+ virtual ShaderCode GetShaderCode(const QString& shader_id) const override;
+ virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override;
+
+ static QString kTypeInput;
+
+private:
+
+
+};
+
+}
+
+#endif // SHAPENODE_H
diff --git a/app/node/generator/shape/shapenodebase.cpp b/app/node/generator/shape/shapenodebase.cpp
new file mode 100644
index 000000000..e8e77db77
--- /dev/null
+++ b/app/node/generator/shape/shapenodebase.cpp
@@ -0,0 +1,49 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2021 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 "shapenodebase.h"
+
+#include
+
+namespace olive {
+
+#define super Node
+
+QString ShapeNodeBase::kPositionInput = QStringLiteral("pos_in");
+QString ShapeNodeBase::kSizeInput = QStringLiteral("size_in");
+QString ShapeNodeBase::kColorInput = QStringLiteral("color_in");
+
+ShapeNodeBase::ShapeNodeBase()
+{
+ AddInput(kPositionInput, NodeValue::kVec2, QVector2D(10, 10));
+ AddInput(kSizeInput, NodeValue::kVec2, QVector2D(100, 100));
+ AddInput(kColorInput, NodeValue::kColor, QVariant::fromValue(Color(1.0, 0.0, 0.0, 1.0)));
+}
+
+void ShapeNodeBase::Retranslate()
+{
+ super::Retranslate();
+
+ SetInputName(kPositionInput, tr("Position"));
+ SetInputName(kSizeInput, tr("Size"));
+ SetInputName(kColorInput, tr("Color"));
+}
+
+}
diff --git a/app/node/generator/shape/shapenodebase.h b/app/node/generator/shape/shapenodebase.h
new file mode 100644
index 000000000..368b3f20a
--- /dev/null
+++ b/app/node/generator/shape/shapenodebase.h
@@ -0,0 +1,46 @@
+/***
+
+ Olive - Non-Linear Video Editor
+ Copyright (C) 2021 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 SHAPENODEBASE_H
+#define SHAPENODEBASE_H
+
+#include "node/node.h"
+
+namespace olive {
+
+class ShapeNodeBase : public Node
+{
+ Q_OBJECT
+public:
+ ShapeNodeBase();
+
+ NODE_DEFAULT_DESTRUCTOR(ShapeNodeBase)
+
+ virtual void Retranslate() override;
+
+ static QString kPositionInput;
+ static QString kSizeInput;
+ static QString kColorInput;
+
+};
+
+}
+
+#endif // SHAPENODEBASE_H
diff --git a/app/node/node.h b/app/node/node.h
index 22c02b528..dde2e706f 100644
--- a/app/node/node.h
+++ b/app/node/node.h
@@ -46,7 +46,11 @@
namespace olive {
-#define NODE_DEFAULT_DESTRUCTOR(x) virtual ~x() override {DisconnectAll();}
+#define NODE_DEFAULT_DESTRUCTOR(x) \
+ virtual ~x() override {DisconnectAll();}
+
+#define NODE_COPY_FUNCTION(x) \
+ virtual Node *copy() const override {return new x();}
class NodeGraph;
class Folder;
diff --git a/app/shaders/shape.frag b/app/shaders/shape.frag
new file mode 100644
index 000000000..2c379b586
--- /dev/null
+++ b/app/shaders/shape.frag
@@ -0,0 +1,39 @@
+// Input texture coordinate
+varying vec2 ove_texcoord;
+
+// Match with ShapeNode::Type
+#define SHAPE_RECTANGLE 0
+#define SHAPE_ELLIPSE 1
+
+uniform vec2 pos_in;
+uniform vec2 size_in;
+uniform int type_in;
+uniform vec2 resolution_in;
+uniform vec4 color_in;
+
+void main() {
+ vec2 real_position = pos_in/resolution_in;
+ vec2 real_size = size_in/resolution_in;
+
+ vec4 col = vec4(0.0);
+
+ if (type_in == SHAPE_RECTANGLE) {
+ if (ove_texcoord.x >= real_position.x && ove_texcoord.y >= real_position.y
+ && ove_texcoord.x < real_position.x+real_size.x && ove_texcoord.y < real_position.y+real_size.y) {
+ col = color_in;
+ }
+ } else if (type_in == SHAPE_ELLIPSE) {
+ vec2 center = pos_in+size_in*0.5;
+ float radius = size_in.y*0.5;
+ float aspect_ratio = size_in.x/size_in.y;
+
+ vec2 offset = ove_texcoord*resolution_in - center;
+ offset.x /= aspect_ratio;
+ float d = length(offset)-radius;
+ float t = clamp(d, 0.0, 1.0);
+
+ col = color_in * (1.0-t);
+ }
+
+ gl_FragColor = col;
+}