shape: add rounded rectangle
This commit is contained in:
@@ -25,10 +25,14 @@ namespace olive {
|
||||
#define super ShapeNodeBase
|
||||
|
||||
QString ShapeNode::kTypeInput = QStringLiteral("type_in");
|
||||
QString ShapeNode::kRadiusInput = QStringLiteral("radius_in");
|
||||
|
||||
ShapeNode::ShapeNode()
|
||||
{
|
||||
PrependInput(kTypeInput, NodeValue::kCombo);
|
||||
|
||||
AddInput(kRadiusInput, NodeValue::kFloat, 20.0);
|
||||
SetInputProperty(kRadiusInput, QStringLiteral("min"), 0.0);
|
||||
}
|
||||
|
||||
QString ShapeNode::Name() const
|
||||
@@ -56,9 +60,10 @@ void ShapeNode::Retranslate()
|
||||
super::Retranslate();
|
||||
|
||||
SetInputName(kTypeInput, tr("Type"));
|
||||
SetInputName(kRadiusInput, tr("Radius"));
|
||||
|
||||
// Coordinate with Type enum
|
||||
SetComboBoxStrings(kTypeInput, {tr("Rectangle"), tr("Ellipse")});
|
||||
SetComboBoxStrings(kTypeInput, {tr("Rectangle"), tr("Ellipse"), tr("Rounded Rectangle")});
|
||||
}
|
||||
|
||||
ShaderCode ShapeNode::GetShaderCode(const ShaderRequest &request) const
|
||||
@@ -81,4 +86,18 @@ void ShapeNode::Value(const NodeValueRow &value, const NodeGlobals &globals, Nod
|
||||
PushMergableJob(value, QVariant::fromValue(job), table);
|
||||
}
|
||||
|
||||
void ShapeNode::InputValueChangedEvent(const QString &input, int element)
|
||||
{
|
||||
if (input == kTypeInput) {
|
||||
InputFlags i = GetInputFlags(kRadiusInput);
|
||||
if (GetStandardValue(kTypeInput).toInt() == kRoundedRectangle) {
|
||||
i &= InputFlag(~kInputFlagHidden);
|
||||
} else {
|
||||
i |= kInputFlagHidden;
|
||||
}
|
||||
SetInputFlags(kRadiusInput, i);
|
||||
}
|
||||
super::InputValueChangedEvent(input, element);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ public:
|
||||
|
||||
enum Type {
|
||||
kRectangle,
|
||||
kEllipse
|
||||
kEllipse,
|
||||
kRoundedRectangle
|
||||
};
|
||||
|
||||
NODE_DEFAULT_FUNCTIONS(ShapeNode)
|
||||
@@ -49,6 +50,10 @@ public:
|
||||
virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override;
|
||||
|
||||
static QString kTypeInput;
|
||||
static QString kRadiusInput;
|
||||
|
||||
protected:
|
||||
virtual void InputValueChangedEvent(const QString &input, int element) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+56
-15
@@ -3,14 +3,35 @@ in vec2 ove_texcoord;
|
||||
out vec4 frag_color;
|
||||
|
||||
// Match with ShapeNode::Type
|
||||
#define SHAPE_RECTANGLE 0
|
||||
#define SHAPE_ELLIPSE 1
|
||||
const int SHAPE_RECTANGLE = 0;
|
||||
const int SHAPE_ELLIPSE = 1;
|
||||
const int SHAPE_ROUNDEDRECT = 2;
|
||||
|
||||
uniform vec2 pos_in;
|
||||
uniform vec2 size_in;
|
||||
uniform int type_in;
|
||||
uniform vec2 resolution_in;
|
||||
uniform vec4 color_in;
|
||||
uniform float radius_in;
|
||||
|
||||
vec4 draw_rect(vec2 real_position, vec2 real_size)
|
||||
{
|
||||
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) {
|
||||
return color_in;
|
||||
} else {
|
||||
return vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
vec4 draw_ellipse(vec2 center, float radius, float aspect_ratio) {
|
||||
vec2 offset = ove_texcoord*resolution_in - center;
|
||||
offset.x /= aspect_ratio;
|
||||
float d = length(offset)-radius;
|
||||
float t = clamp(d, 0.0, 1.0);
|
||||
|
||||
return color_in * (1.0-t);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 p = pos_in + resolution_in*0.5 - size_in*0.5;
|
||||
@@ -20,22 +41,42 @@ void main() {
|
||||
|
||||
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) {
|
||||
switch (type_in) {
|
||||
case SHAPE_RECTANGLE:
|
||||
{
|
||||
col = draw_rect(real_position, real_size);
|
||||
break;
|
||||
}
|
||||
case SHAPE_ELLIPSE:
|
||||
{
|
||||
vec2 center = p+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);
|
||||
col = draw_ellipse(center, radius, aspect_ratio);
|
||||
break;
|
||||
}
|
||||
case SHAPE_ROUNDEDRECT:
|
||||
{
|
||||
// Limit radius so it is never larger than half the shortest size
|
||||
float r = min(radius_in, min(size_in.y*0.5, size_in.x*0.5));
|
||||
vec2 real_rad = vec2(r / resolution_in.x, r / resolution_in.y);
|
||||
if (ove_texcoord.x < real_position.x + real_rad.x && ove_texcoord.y < real_position.y + real_rad.y) {
|
||||
// Top-left
|
||||
col = draw_ellipse(p + r, r, 1.0);
|
||||
} else if (ove_texcoord.x > real_position.x+real_size.x - real_rad.x && ove_texcoord.y < real_position.y + real_rad.y) {
|
||||
// Top-right
|
||||
col = draw_ellipse(vec2(p.x + size_in.x - r, p.y + r), r, 1.0);
|
||||
} else if (ove_texcoord.x < real_position.x + real_rad.x && ove_texcoord.y > real_position.y + real_size.y - real_rad.y) {
|
||||
// Bottom-left
|
||||
col = draw_ellipse(vec2(p.x + r, p.y + size_in.y - r), r, 1.0);
|
||||
} else if (ove_texcoord.x > real_position.x+real_size.x - real_rad.x && ove_texcoord.y > real_position.y + real_size.y - real_rad.y) {
|
||||
// Bottom-right
|
||||
col = draw_ellipse(vec2(p.x + size_in.x - r, p.y + size_in.y - r), r, 1.0);
|
||||
} else {
|
||||
col = draw_rect(real_position, real_size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
frag_color = col;
|
||||
|
||||
Reference in New Issue
Block a user