colordialog/wheel/gradient: implemented basic UI components for color picking
This commit is contained in:
@@ -18,5 +18,9 @@ set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
dialog/color/colordialog.h
|
||||
dialog/color/colordialog.cpp
|
||||
dialog/color/colorpreviewbox.h
|
||||
dialog/color/colorpreviewbox.cpp
|
||||
dialog/color/colorvalueswidget.h
|
||||
dialog/color/colorvalueswidget.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
@@ -4,25 +4,71 @@
|
||||
#include <QSplitter>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "widget/colorwheel/colorwheelwidget.h"
|
||||
#include "common/qtutils.h"
|
||||
|
||||
ColorDialog::ColorDialog(ColorManager* color_manager, QWidget *parent) :
|
||||
ColorDialog::ColorDialog(ColorManager* color_manager, Color start, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
color_manager_(color_manager)
|
||||
{
|
||||
setWindowTitle(tr("Select Color"));
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
QSplitter* splitter = new QSplitter(Qt::Horizontal);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
ColorWheelWidget* cww1 = new ColorWheelWidget();
|
||||
ColorWheelWidget* cww2 = new ColorWheelWidget();
|
||||
QWidget* wheel_area = new QWidget();
|
||||
QHBoxLayout* wheel_layout = new QHBoxLayout(wheel_area);
|
||||
splitter->addWidget(wheel_area);
|
||||
|
||||
splitter->addWidget(cww1);
|
||||
splitter->addWidget(cww2);
|
||||
color_wheel_ = new ColorWheelGLWidget();
|
||||
wheel_layout->addWidget(color_wheel_);
|
||||
|
||||
hsv_value_gradient_ = new ColorGradientGLWidget(Qt::Vertical);
|
||||
hsv_value_gradient_->setFixedWidth(QFontMetricsWidth(fontMetrics(), QStringLiteral("HHH")));
|
||||
wheel_layout->addWidget(hsv_value_gradient_);
|
||||
|
||||
ColorValuesWidget* cvw = new ColorValuesWidget();
|
||||
splitter->addWidget(cvw);
|
||||
|
||||
connect(color_wheel_, &ColorWheelGLWidget::ColorChanged, cvw, &ColorValuesWidget::SetColor);
|
||||
connect(color_wheel_, &ColorWheelGLWidget::ColorChanged, this, &ColorDialog::UpdateValueGradient);
|
||||
connect(color_wheel_, &ColorWheelGLWidget::DiameterChanged, hsv_value_gradient_, &ColorGradientGLWidget::setFixedHeight);
|
||||
connect(hsv_value_gradient_, &ColorGradientGLWidget::ColorChanged, cvw, &ColorValuesWidget::SetColor);
|
||||
connect(hsv_value_gradient_, &ColorGradientGLWidget::ColorChanged, this, &ColorDialog::UpdateWheelValue);
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
layout->addWidget(buttons);
|
||||
|
||||
UpdateValueGradient(start);
|
||||
UpdateWheelValue(start);
|
||||
cvw->SetColor(start);
|
||||
}
|
||||
|
||||
void ColorDialog::UpdateValueGradient(const Color &c)
|
||||
{
|
||||
float h, s, v;
|
||||
|
||||
c.toHsv(&h, &s, &v);
|
||||
|
||||
Color start = Color::fromHsv(h, s, 1.0f);
|
||||
Color end = Color::fromHsv(h, s, 0.0f);
|
||||
|
||||
hsv_value_gradient_->SetColors(start, end);
|
||||
}
|
||||
|
||||
void ColorDialog::UpdateWheelValue(const Color &c)
|
||||
{
|
||||
float h, s, v;
|
||||
|
||||
c.toHsv(&h, &s, &v);
|
||||
|
||||
color_wheel_->SetHSVValue(v);
|
||||
}
|
||||
|
||||
void ColorDialog::UpdateValueGradientSize(int diameter)
|
||||
{
|
||||
hsv_value_gradient_->setFixedHeight(diameter);
|
||||
}
|
||||
|
||||
@@ -3,17 +3,32 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "colorvalueswidget.h"
|
||||
#include "render/color.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "widget/colorwheel/colorwheelwidget.h"
|
||||
#include "widget/colorwheel/colorgradientwidget.h"
|
||||
|
||||
class ColorDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorDialog(ColorManager* color_manager, QWidget* parent = nullptr);
|
||||
ColorDialog(ColorManager* color_manager, Color start = Color(1.0f, 1.0f, 1.0f), QWidget* parent = nullptr);
|
||||
|
||||
private:
|
||||
ColorManager* color_manager_;
|
||||
|
||||
ColorWheelGLWidget* color_wheel_;
|
||||
|
||||
ColorGradientGLWidget* hsv_value_gradient_;
|
||||
|
||||
private slots:
|
||||
void UpdateValueGradient(const Color& c);
|
||||
|
||||
void UpdateWheelValue(const Color& c);
|
||||
|
||||
void UpdateValueGradientSize(int diameter);
|
||||
|
||||
};
|
||||
|
||||
#endif // COLORDIALOG_H
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "colorpreviewbox.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
ColorPreviewBox::ColorPreviewBox(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ColorPreviewBox::SetColor(const Color &c)
|
||||
{
|
||||
color_ = c;
|
||||
update();
|
||||
}
|
||||
|
||||
void ColorPreviewBox::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
QWidget::paintEvent(e);
|
||||
|
||||
QPainter p(this);
|
||||
|
||||
p.setPen(Qt::black);
|
||||
|
||||
QColor c;
|
||||
c.setRedF(color_.red());
|
||||
c.setGreenF(color_.green());
|
||||
c.setBlueF(color_.blue());
|
||||
p.setBrush(c);
|
||||
|
||||
p.drawRect(rect());
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef COLORPREVIEWBOX_H
|
||||
#define COLORPREVIEWBOX_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "render/color.h"
|
||||
|
||||
class ColorPreviewBox : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorPreviewBox(QWidget* parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void SetColor(const Color& c);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
|
||||
private:
|
||||
Color color_;
|
||||
|
||||
};
|
||||
|
||||
#endif // COLORPREVIEWBOX_H
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "colorvalueswidget.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
|
||||
ColorValuesWidget::ColorValuesWidget(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
QGridLayout* layout = new QGridLayout(this);
|
||||
|
||||
int row = 0;
|
||||
|
||||
layout->addWidget(new QLabel(tr("Preview")), row, 0);
|
||||
|
||||
preview_ = new ColorPreviewBox();
|
||||
preview_->setFixedHeight(fontMetrics().height() * 3 / 2);
|
||||
layout->addWidget(preview_, row, 1);
|
||||
|
||||
row++;
|
||||
|
||||
layout->addWidget(new QLabel(tr("Red")), row, 0);
|
||||
|
||||
red_slider_ = CreateColorSlider();
|
||||
layout->addWidget(red_slider_, row, 1);
|
||||
|
||||
row++;
|
||||
|
||||
layout->addWidget(new QLabel(tr("Green")), row, 0);
|
||||
|
||||
green_slider_ = CreateColorSlider();
|
||||
layout->addWidget(green_slider_, row, 1);
|
||||
|
||||
row++;
|
||||
|
||||
layout->addWidget(new QLabel(tr("Blue")), row, 0);
|
||||
|
||||
blue_slider_ = CreateColorSlider();
|
||||
layout->addWidget(blue_slider_, row, 1);
|
||||
}
|
||||
|
||||
Color ColorValuesWidget::GetColor() const
|
||||
{
|
||||
return Color(red_slider_->GetValue(),
|
||||
green_slider_->GetValue(),
|
||||
blue_slider_->GetValue());
|
||||
}
|
||||
|
||||
void ColorValuesWidget::SetColor(const Color &c)
|
||||
{
|
||||
red_slider_->SetValue(c.red());
|
||||
green_slider_->SetValue(c.green());
|
||||
blue_slider_->SetValue(c.blue());
|
||||
preview_->SetColor(c);
|
||||
}
|
||||
|
||||
FloatSlider *ColorValuesWidget::CreateColorSlider()
|
||||
{
|
||||
FloatSlider* fs = new FloatSlider();
|
||||
fs->SetMinimum(0);
|
||||
fs->SetDragMultiplier(0.01);
|
||||
fs->SetMaximum(1);
|
||||
return fs;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef COLORVALUESWIDGET_H
|
||||
#define COLORVALUESWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "colorpreviewbox.h"
|
||||
#include "render/color.h"
|
||||
#include "widget/slider/floatslider.h"
|
||||
|
||||
class ColorValuesWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorValuesWidget(QWidget* parent = nullptr);
|
||||
|
||||
Color GetColor() const;
|
||||
|
||||
public slots:
|
||||
void SetColor(const Color& c);
|
||||
|
||||
private:
|
||||
static FloatSlider* CreateColorSlider();
|
||||
|
||||
ColorPreviewBox* preview_;
|
||||
|
||||
FloatSlider* red_slider_;
|
||||
FloatSlider* green_slider_;
|
||||
FloatSlider* blue_slider_;
|
||||
|
||||
};
|
||||
|
||||
#endif // COLORVALUESWIDGET_H
|
||||
+1
-1
@@ -93,7 +93,7 @@ public:
|
||||
/**
|
||||
* Floating-point type
|
||||
*
|
||||
* Resolves to `QRgba64`.
|
||||
* Resolves to `Color`.
|
||||
*
|
||||
* Colors passed around the nodes should always be in reference space and preferably use
|
||||
*/
|
||||
|
||||
@@ -205,7 +205,7 @@ void OpenGLProxy::RunNodeAccelerated(const Node *node, const TimeRange &range, c
|
||||
vert_code = OpenGLShader::CodeDefaultVertex();
|
||||
}
|
||||
|
||||
shader = std::make_shared<OpenGLShader>();
|
||||
shader = OpenGLShader::Create();
|
||||
shader->create();
|
||||
shader->addShaderFromSourceCode(QOpenGLShader::Fragment, frag_code);
|
||||
shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vert_code);
|
||||
|
||||
@@ -132,7 +132,13 @@ GLenum OpenGLRenderFunctions::GetPixelType(const PixelFormat::Format &format)
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
void OpenGLRenderFunctions::Blit(OpenGLShaderPtr pipeline, bool flipped, QMatrix4x4 matrix) {
|
||||
void OpenGLRenderFunctions::Blit(OpenGLShaderPtr pipeline, bool flipped, QMatrix4x4 matrix)
|
||||
{
|
||||
Blit(pipeline.get(), flipped, matrix);
|
||||
}
|
||||
|
||||
void OpenGLRenderFunctions::Blit(OpenGLShader *pipeline, bool flipped, QMatrix4x4 matrix)
|
||||
{
|
||||
// FIXME: is currentContext() reliable here?
|
||||
QOpenGLFunctions* func = QOpenGLContext::currentContext()->functions();
|
||||
|
||||
@@ -181,7 +187,12 @@ void OpenGLRenderFunctions::Blit(OpenGLShaderPtr pipeline, bool flipped, QMatrix
|
||||
m_vao.destroy();
|
||||
}
|
||||
|
||||
void OpenGLRenderFunctions::OCIOBlit(OpenGLShaderPtr pipeline,
|
||||
void OpenGLRenderFunctions::OCIOBlit(OpenGLShaderPtr pipeline, GLuint lut, bool flipped, QMatrix4x4 matrix)
|
||||
{
|
||||
OCIOBlit(pipeline.get(), lut, flipped, matrix);
|
||||
}
|
||||
|
||||
void OpenGLRenderFunctions::OCIOBlit(OpenGLShader *pipeline,
|
||||
GLuint lut,
|
||||
bool flipped,
|
||||
QMatrix4x4 matrix)
|
||||
|
||||
@@ -46,8 +46,10 @@ public:
|
||||
* Transformation matrix to use when drawing (defaults to no transform)
|
||||
*/
|
||||
static void Blit(OpenGLShaderPtr pipeline, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
|
||||
static void Blit(OpenGLShader* pipeline, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
|
||||
|
||||
static void OCIOBlit(OpenGLShaderPtr pipeline, GLuint lut, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
|
||||
static void OCIOBlit(OpenGLShader* pipeline, GLuint lut, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
|
||||
|
||||
static void PrepareToDraw(QOpenGLFunctions* f);
|
||||
|
||||
|
||||
@@ -7,9 +7,14 @@ OpenGLShader::OpenGLShader()
|
||||
|
||||
}
|
||||
|
||||
OpenGLShaderPtr OpenGLShader::Create()
|
||||
{
|
||||
return std::make_shared<OpenGLShader>();
|
||||
}
|
||||
|
||||
OpenGLShaderPtr OpenGLShader::CreateDefault(const QString &function_name, const QString &shader_code)
|
||||
{
|
||||
OpenGLShaderPtr program = std::make_shared<OpenGLShader>();
|
||||
OpenGLShaderPtr program = Create();
|
||||
|
||||
// Add shaders to program
|
||||
program->addShaderFromSourceCode(QOpenGLShader::Vertex, CodeDefaultVertex());
|
||||
|
||||
@@ -17,6 +17,8 @@ class OpenGLShader : public QOpenGLShaderProgram {
|
||||
public:
|
||||
OpenGLShader();
|
||||
|
||||
static OpenGLShaderPtr Create();
|
||||
|
||||
static OpenGLShaderPtr CreateDefault(const QString &function_name = QString(),
|
||||
const QString &shader_code = QString());
|
||||
|
||||
|
||||
@@ -1,5 +1,46 @@
|
||||
#include "color.h"
|
||||
|
||||
Color Color::fromHsv(const float &h, const float &s, const float &v)
|
||||
{
|
||||
float C = s * v;
|
||||
float X = C * (1.0f - abs(fmod(h / 60.0f, 2.0f) - 1.0f));
|
||||
float m = v - C;
|
||||
float Rs, Gs, Bs;
|
||||
|
||||
if(h >= 0.0f && h < 60.0f) {
|
||||
Rs = C;
|
||||
Gs = X;
|
||||
Bs = 0.0f;
|
||||
}
|
||||
else if(h >= 60.0f && h < 120.0f) {
|
||||
Rs = X;
|
||||
Gs = C;
|
||||
Bs = 0.0f;
|
||||
}
|
||||
else if(h >= 120.0f && h < 180.0f) {
|
||||
Rs = 0.0f;
|
||||
Gs = C;
|
||||
Bs = X;
|
||||
}
|
||||
else if(h >= 180.0f && h < 240.0f) {
|
||||
Rs = 0.0f;
|
||||
Gs = X;
|
||||
Bs = C;
|
||||
}
|
||||
else if(h >= 240.0f && h < 300.0f) {
|
||||
Rs = X;
|
||||
Gs = 0.0f;
|
||||
Bs = C;
|
||||
}
|
||||
else {
|
||||
Rs = C;
|
||||
Gs = 0.0f;
|
||||
Bs = X;
|
||||
}
|
||||
|
||||
return Color(Rs + m, Gs + m, Bs + m);
|
||||
}
|
||||
|
||||
Color::Color(const char *data, const PixelFormat::Format &format)
|
||||
{
|
||||
OIIO::convert_type(PixelFormat::GetOIIOTypeDesc(format),
|
||||
@@ -12,3 +53,57 @@ Color::Color(const char *data, const PixelFormat::Format &format)
|
||||
set_alpha(1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void Color::toHsv(float *hue, float *sat, float *val) const
|
||||
{
|
||||
float fCMax = qMax(qMax(red(), green()), blue());
|
||||
float fCMin = qMin(qMin(red(), green()), blue());
|
||||
float fDelta = fCMax - fCMin;
|
||||
|
||||
if(fDelta > 0) {
|
||||
if(fCMax == red()) {
|
||||
*hue = 60 * (fmod(((green() - blue()) / fDelta), 6));
|
||||
} else if(fCMax == green()) {
|
||||
*hue = 60 * (((blue() - red()) / fDelta) + 2);
|
||||
} else if(fCMax == blue()) {
|
||||
*hue = 60 * (((red() - green()) / fDelta) + 4);
|
||||
}
|
||||
|
||||
if(fCMax > 0) {
|
||||
*sat = fDelta / fCMax;
|
||||
} else {
|
||||
*sat = 0;
|
||||
}
|
||||
|
||||
*val = fCMax;
|
||||
} else {
|
||||
*hue = 0;
|
||||
*sat = 0;
|
||||
*val = fCMax;
|
||||
}
|
||||
|
||||
if(*hue < 0) {
|
||||
*hue = 360 + *hue;
|
||||
}
|
||||
}
|
||||
|
||||
float Color::hue() const
|
||||
{
|
||||
float h, s, v;
|
||||
toHsv(&h, &s, &v);
|
||||
return h;
|
||||
}
|
||||
|
||||
float Color::saturation() const
|
||||
{
|
||||
float h, s, v;
|
||||
toHsv(&h, &s, &v);
|
||||
return s;
|
||||
}
|
||||
|
||||
float Color::value() const
|
||||
{
|
||||
float h, s, v;
|
||||
toHsv(&h, &s, &v);
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,13 @@ public:
|
||||
data_[3] = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a Color struct from hue/saturation/value
|
||||
*
|
||||
* Hue expects a value between 0.0 and 360.0. Saturation and Value expect a value between 0.0 and 1.0.
|
||||
*/
|
||||
static Color fromHsv(const float& h, const float& s, const float &v);
|
||||
|
||||
Color(const char *data, const PixelFormat::Format &format);
|
||||
|
||||
const float& red() const {return data_[0];}
|
||||
@@ -32,6 +39,11 @@ public:
|
||||
const float& blue() const {return data_[2];}
|
||||
const float& alpha() const {return data_[3];}
|
||||
|
||||
void toHsv(float* hue, float* sat, float* val) const;
|
||||
float hue() const;
|
||||
float saturation() const;
|
||||
float value() const;
|
||||
|
||||
void set_red(const float& red) {data_[0] = red;}
|
||||
void set_green(const float& green) {data_[1] = green;}
|
||||
void set_blue(const float& blue) {data_[2] = blue;}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#version 110
|
||||
|
||||
// Standard inputs
|
||||
uniform vec2 ove_resolution;
|
||||
varying vec2 ove_texcoord;
|
||||
|
||||
// Inputs
|
||||
uniform int orientation;
|
||||
uniform vec3 color_a;
|
||||
uniform vec3 color_b;
|
||||
|
||||
void main(void) {
|
||||
float t;
|
||||
|
||||
// This very roughly conforms to Qt::Orientation
|
||||
if (orientation == 1) {
|
||||
// Horizontal orientation
|
||||
t = ove_texcoord.x;
|
||||
} else {
|
||||
// Vertical orientation
|
||||
t = 1.0 - ove_texcoord.y;
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(mix(color_a, color_b, t), 1.0);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#version 110
|
||||
|
||||
// Standard inputs
|
||||
uniform vec2 ove_resolution;
|
||||
varying vec2 ove_texcoord;
|
||||
|
||||
// Custom inputs
|
||||
uniform float hsv_value;
|
||||
|
||||
// Color wheel uses PI
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
|
||||
vec3 hsv_to_rgb(float H, float S, float V) {
|
||||
float C = S * V;
|
||||
float X = C * (1.0 - abs(mod(H / 60.0, 2.0) - 1.0));
|
||||
float m = V - C;
|
||||
float Rs, Gs, Bs;
|
||||
|
||||
if(H >= 0.0 && H < 60.0) {
|
||||
Rs = C;
|
||||
Gs = X;
|
||||
Bs = 0.0;
|
||||
}
|
||||
else if(H >= 60.0 && H < 120.0) {
|
||||
Rs = X;
|
||||
Gs = C;
|
||||
Bs = 0.0;
|
||||
}
|
||||
else if(H >= 120.0 && H < 180.0) {
|
||||
Rs = 0.0;
|
||||
Gs = C;
|
||||
Bs = X;
|
||||
}
|
||||
else if(H >= 180.0 && H < 240.0) {
|
||||
Rs = 0.0;
|
||||
Gs = X;
|
||||
Bs = C;
|
||||
}
|
||||
else if(H >= 240.0 && H < 300.0) {
|
||||
Rs = X;
|
||||
Gs = 0.0;
|
||||
Bs = C;
|
||||
}
|
||||
else {
|
||||
Rs = C;
|
||||
Gs = 0.0;
|
||||
Bs = X;
|
||||
}
|
||||
|
||||
return vec3(Rs + m, Gs + m, Bs + m);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vec2 center = vec2(0.5, 0.5);
|
||||
float radius = 0.5;
|
||||
|
||||
vec2 flipped_texcoord = vec2(ove_texcoord.x, (1.0 - ove_texcoord.y));
|
||||
|
||||
// Calculate scale
|
||||
if (ove_resolution.x != ove_resolution.y) {
|
||||
// Scale around center
|
||||
flipped_texcoord -= vec2(0.5, 0.5);
|
||||
|
||||
if (ove_resolution.x > ove_resolution.y) {
|
||||
flipped_texcoord.x *= ove_resolution.x / ove_resolution.y;
|
||||
} else {
|
||||
flipped_texcoord.y *= ove_resolution.y / ove_resolution.x;
|
||||
}
|
||||
|
||||
flipped_texcoord += vec2(0.5, 0.5);
|
||||
}
|
||||
|
||||
float dist = distance(flipped_texcoord, center);
|
||||
|
||||
if (dist <= radius) {
|
||||
float opposite = flipped_texcoord.y - center.y;
|
||||
float adjacent = flipped_texcoord.x - center.x;
|
||||
|
||||
float hue = atan(opposite, adjacent) * 180.0 / M_PI + 180.0;
|
||||
float sat = dist / radius;
|
||||
|
||||
// Extremely simple antialiasing, we taper off the edges between (radius) and (radius - 1)
|
||||
float pixel_radius = min(ove_resolution.x, ove_resolution.y) * 0.5;
|
||||
float pixel_dist = (pixel_radius / radius) * dist;
|
||||
float alpha = min((pixel_radius - pixel_dist), 1.0);
|
||||
|
||||
gl_FragColor = vec4(hsv_to_rgb(hue, sat, hsv_value), alpha);
|
||||
} else {
|
||||
gl_FragColor = vec4(0.0);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
<file>alphaover.xml</file>
|
||||
<file>boxblur.frag</file>
|
||||
<file>boxblur.xml</file>
|
||||
<file>colorgradient.frag</file>
|
||||
<file>colorwheel.frag</file>
|
||||
<file>crossdissolve.frag</file>
|
||||
<file>crossdissolve.xml</file>
|
||||
<file>dropshadow.frag</file>
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
ColorButton::ColorButton(QWidget *parent) :
|
||||
QPushButton(parent)
|
||||
{
|
||||
color_ = Color(1.0f, 1.0f, 1.0f);
|
||||
|
||||
connect(this, &ColorButton::clicked, this, &ColorButton::ShowColorDialog);
|
||||
}
|
||||
|
||||
void ColorButton::ShowColorDialog()
|
||||
{
|
||||
ColorDialog cd(nullptr);
|
||||
ColorDialog cd(nullptr, color_, this);
|
||||
cd.exec();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <QPushButton>
|
||||
|
||||
#include "render/color.h"
|
||||
|
||||
class ColorButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -15,6 +17,9 @@ signals:
|
||||
private slots:
|
||||
void ShowColorDialog();
|
||||
|
||||
private:
|
||||
Color color_;
|
||||
|
||||
};
|
||||
|
||||
#endif // COLORBUTTON_H
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
widget/colorwheel/colorgradientwidget.h
|
||||
widget/colorwheel/colorgradientwidget.cpp
|
||||
widget/colorwheel/colorswatchwidget.h
|
||||
widget/colorwheel/colorswatchwidget.cpp
|
||||
widget/colorwheel/colorwheelwidget.h
|
||||
widget/colorwheel/colorwheelwidget.cpp
|
||||
PARENT_SCOPE
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "colorgradientwidget.h"
|
||||
|
||||
#include "common/lerp.h"
|
||||
#include "node/node.h"
|
||||
|
||||
ColorGradientGLWidget::ColorGradientGLWidget(Qt::Orientation orientation, QWidget *parent) :
|
||||
ColorSwatchWidget(parent),
|
||||
orientation_(orientation)
|
||||
{
|
||||
}
|
||||
|
||||
void ColorGradientGLWidget::SetColors(const Color &a, const Color &b)
|
||||
{
|
||||
a_ = a;
|
||||
b_ = b;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
Color ColorGradientGLWidget::GetColorFromCursorPos(const QPoint &p) const
|
||||
{
|
||||
float t;
|
||||
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
t = static_cast<float>(p.x()) / static_cast<float>(width());
|
||||
} else {
|
||||
t = static_cast<float>(p.y()) / static_cast<float>(height());
|
||||
}
|
||||
|
||||
return Color(lerp(a_.red(), b_.red(), t),
|
||||
lerp(a_.green(), b_.green(), t),
|
||||
lerp(a_.blue(), b_.blue(), t));
|
||||
}
|
||||
|
||||
bool ColorGradientGLWidget::PointIsValid(const QPoint &) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
OpenGLShader *ColorGradientGLWidget::CreateShader() const
|
||||
{
|
||||
OpenGLShader* s = new OpenGLShader();
|
||||
|
||||
s->create();
|
||||
s->addShaderFromSourceCode(QOpenGLShader::Vertex, OpenGLShader::CodeDefaultVertex());
|
||||
s->addShaderFromSourceCode(QOpenGLShader::Fragment, Node::ReadFileAsString(QStringLiteral(":/shaders/colorgradient.frag")));
|
||||
s->link();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void ColorGradientGLWidget::SetShaderUniformValues(OpenGLShader *shader) const
|
||||
{
|
||||
shader->setUniformValue("orientation", orientation_);
|
||||
shader->setUniformValue("color_a", a_.red(), a_.green(), a_.blue());
|
||||
shader->setUniformValue("color_b", b_.red(), b_.green(), b_.blue());
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#ifndef COLORGRADIENTGLWIDGET_H
|
||||
#define COLORGRADIENTGLWIDGET_H
|
||||
|
||||
#include "colorswatchwidget.h"
|
||||
#include "render/color.h"
|
||||
|
||||
class ColorGradientGLWidget : public ColorSwatchWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorGradientGLWidget(Qt::Orientation orientation, QWidget* parent = nullptr);
|
||||
|
||||
void SetColors(const Color& a, const Color& b);
|
||||
|
||||
protected:
|
||||
virtual Color GetColorFromCursorPos(const QPoint& p) const override;
|
||||
|
||||
virtual bool PointIsValid(const QPoint& p) const override;
|
||||
|
||||
virtual OpenGLShader* CreateShader() const override;
|
||||
|
||||
virtual void SetShaderUniformValues(OpenGLShader* shader) const override;
|
||||
|
||||
private:
|
||||
Qt::Orientation orientation_;
|
||||
|
||||
Color a_;
|
||||
|
||||
Color b_;
|
||||
|
||||
};
|
||||
|
||||
#endif // COLORGRADIENTGLWIDGET_H
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "colorswatchwidget.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "render/backend/opengl/openglrenderfunctions.h"
|
||||
|
||||
ColorSwatchWidget::ColorSwatchWidget(QWidget *parent) :
|
||||
QOpenGLWidget(parent),
|
||||
shader_(nullptr)
|
||||
{
|
||||
// Render with transparent background
|
||||
setAttribute(Qt::WA_AlwaysStackOnTop);
|
||||
}
|
||||
|
||||
ColorSwatchWidget::~ColorSwatchWidget()
|
||||
{
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::initializeGL()
|
||||
{
|
||||
CleanUp();
|
||||
|
||||
shader_ = CreateShader();
|
||||
|
||||
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &ColorSwatchWidget::CleanUp);
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::paintGL()
|
||||
{
|
||||
shader_->bind();
|
||||
shader_->setUniformValue("ove_resolution", width(), height());
|
||||
SetShaderUniformValues(shader_);
|
||||
shader_->release();
|
||||
|
||||
OpenGLRenderFunctions::Blit(shader_);
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::CleanUp()
|
||||
{
|
||||
delete shader_;
|
||||
shader_ = nullptr;
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
QOpenGLWidget::mousePressEvent(e);
|
||||
|
||||
if (PointIsValid(e->pos())) {
|
||||
emit ColorChanged(GetColorFromCursorPos(e->pos()));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
QOpenGLWidget::mouseMoveEvent(e);
|
||||
|
||||
if (e->buttons() & Qt::LeftButton && PointIsValid(e->pos())) {
|
||||
emit ColorChanged(GetColorFromCursorPos(e->pos()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef COLORSWATCHWIDGET_H
|
||||
#define COLORSWATCHWIDGET_H
|
||||
|
||||
#include <QOpenGLWidget>
|
||||
|
||||
#include "render/backend/opengl/openglshader.h"
|
||||
#include "render/color.h"
|
||||
|
||||
class ColorSwatchWidget : public QOpenGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorSwatchWidget(QWidget* parent = nullptr);
|
||||
|
||||
virtual ~ColorSwatchWidget() override;
|
||||
|
||||
signals:
|
||||
void ColorChanged(const Color& c);
|
||||
|
||||
protected:
|
||||
virtual void initializeGL() override;
|
||||
|
||||
virtual void paintGL() override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent* e) override;
|
||||
|
||||
virtual void mouseMoveEvent(QMouseEvent* e) override;
|
||||
|
||||
virtual void SetShaderUniformValues(OpenGLShader*) const {}
|
||||
|
||||
virtual Color GetColorFromCursorPos(const QPoint& p) const = 0;
|
||||
|
||||
virtual bool PointIsValid(const QPoint& p) const = 0;
|
||||
|
||||
virtual OpenGLShader* CreateShader() const = 0;
|
||||
|
||||
private slots:
|
||||
void CleanUp();
|
||||
|
||||
private:
|
||||
OpenGLShader* shader_;
|
||||
|
||||
};
|
||||
|
||||
#endif // COLORSWATCHWIDGET_H
|
||||
@@ -1,16 +1,81 @@
|
||||
#include "colorwheelwidget.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QtMath>
|
||||
|
||||
#define RADIAN_TO_0_1_RANGE 0.15915494309188486110703542313983
|
||||
#include "node/node.h"
|
||||
|
||||
ColorWheelWidget::ColorWheelWidget(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
#define M_180_OVER_PI 57.295791433133264917914229473464
|
||||
|
||||
ColorWheelGLWidget::ColorWheelGLWidget(QWidget *parent) :
|
||||
ColorSwatchWidget(parent),
|
||||
hsv_value_(1.0f)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ColorWheelGLWidget::SetHSVValue(float val)
|
||||
{
|
||||
hsv_value_ = val;
|
||||
update();
|
||||
}
|
||||
|
||||
Color ColorWheelGLWidget::GetColorFromCursorPos(const QPoint &p) const
|
||||
{
|
||||
QPoint center = rect().center();
|
||||
|
||||
qreal opposite = p.y() - center.y();
|
||||
qreal adjacent = p.x() - center.x();
|
||||
qreal distance = qSqrt(qPow(adjacent, 2) + qPow(opposite, 2));
|
||||
|
||||
qreal hue = qAtan2(opposite, adjacent) * M_180_OVER_PI + 180.0;
|
||||
qreal sat = (distance / GetRadius());
|
||||
qreal value = hsv_value_;
|
||||
|
||||
return Color::fromHsv(hue, sat, value);
|
||||
}
|
||||
|
||||
bool ColorWheelGLWidget::PointIsValid(const QPoint &p) const
|
||||
{
|
||||
QPoint center = rect().center();
|
||||
qreal distance = qSqrt(qPow(p.x() - center.x(), 2) + qPow(p.y() - center.y(), 2));
|
||||
|
||||
return (distance <= GetRadius());
|
||||
}
|
||||
|
||||
OpenGLShader *ColorWheelGLWidget::CreateShader() const
|
||||
{
|
||||
OpenGLShader* s = new OpenGLShader();
|
||||
|
||||
s->create();
|
||||
s->addShaderFromSourceCode(QOpenGLShader::Vertex, OpenGLShader::CodeDefaultVertex());
|
||||
s->addShaderFromSourceCode(QOpenGLShader::Fragment, Node::ReadFileAsString(QStringLiteral(":/shaders/colorwheel.frag")));
|
||||
s->link();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void ColorWheelGLWidget::SetShaderUniformValues(OpenGLShader *shader) const
|
||||
{
|
||||
shader->setUniformValue("hsv_value", hsv_value_);
|
||||
}
|
||||
|
||||
void ColorWheelGLWidget::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
ColorSwatchWidget::resizeEvent(e);
|
||||
|
||||
emit DiameterChanged(GetDiameter());
|
||||
}
|
||||
|
||||
int ColorWheelGLWidget::GetDiameter() const
|
||||
{
|
||||
return qMin(width(), height());
|
||||
}
|
||||
|
||||
qreal ColorWheelGLWidget::GetRadius() const
|
||||
{
|
||||
return GetDiameter() * 0.5;
|
||||
}
|
||||
|
||||
/* Software/QPainter-based color wheel
|
||||
void ColorWheelWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QWidget::paintEvent(event);
|
||||
@@ -20,12 +85,10 @@ void ColorWheelWidget::paintEvent(QPaintEvent *event)
|
||||
qreal radius = qMin(width(), height()) / 2;
|
||||
QPoint center = rect().center();
|
||||
|
||||
p.setPen(Qt::red);
|
||||
|
||||
int x_start = center.x() - radius;
|
||||
int x_end= center.x() + radius;
|
||||
int x_end = center.x() + radius;
|
||||
int y_start = center.y() - radius;
|
||||
int y_end= center.y() + radius;
|
||||
int y_end = center.y() + radius;
|
||||
|
||||
for (int i=x_start;i<x_end;i++) {
|
||||
for (int j=y_start;j<y_end;j++) {
|
||||
@@ -46,4 +109,4 @@ void ColorWheelWidget::paintEvent(QPaintEvent *event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@@ -1,16 +1,51 @@
|
||||
#ifndef COLORWHEELWIDGET_H
|
||||
#define COLORWHEELWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QOpenGLWidget>
|
||||
|
||||
class ColorWheelWidget : public QWidget
|
||||
#include "colorswatchwidget.h"
|
||||
#include "render/backend/opengl/openglshader.h"
|
||||
#include "render/color.h"
|
||||
|
||||
class ColorWheelGLWidget : public ColorSwatchWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorWheelGLWidget(QWidget* parent = nullptr);
|
||||
|
||||
void SetHSVValue(float val);
|
||||
|
||||
signals:
|
||||
void DiameterChanged(int radius);
|
||||
|
||||
protected:
|
||||
virtual Color GetColorFromCursorPos(const QPoint& p) const override;
|
||||
|
||||
virtual bool PointIsValid(const QPoint& p) const override;
|
||||
|
||||
virtual OpenGLShader* CreateShader() const override;
|
||||
|
||||
virtual void SetShaderUniformValues(OpenGLShader* shader) const override;
|
||||
|
||||
virtual void resizeEvent(QResizeEvent* e) override;
|
||||
|
||||
private:
|
||||
int GetDiameter() const;
|
||||
|
||||
qreal GetRadius() const;
|
||||
|
||||
float hsv_value_;
|
||||
|
||||
};
|
||||
|
||||
/*class ColorWheelWidget : public QWidget
|
||||
{
|
||||
public:
|
||||
ColorWheelWidget(QWidget* parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* event) override;
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
|
||||
};
|
||||
};*/
|
||||
|
||||
#endif // COLORWHEELWIDGET_H
|
||||
|
||||
Reference in New Issue
Block a user