colordialog/picker/wheel: finished color picker UI
Dialog is still unmanaged, but that's the only remaining step.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#ifndef OLIVECOMMONDEFINE_H
|
||||
#define OLIVECOMMONDEFINE_H
|
||||
|
||||
const int kHSVChannels = 3;
|
||||
const int kRGBChannels = 3;
|
||||
const int kRGBAChannels = 4;
|
||||
|
||||
|
||||
@@ -15,60 +15,43 @@ ColorDialog::ColorDialog(ColorManager* color_manager, Color start, QWidget *pare
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
QSplitter* splitter = new QSplitter(Qt::Horizontal);
|
||||
splitter->setChildrenCollapsible(false);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
QWidget* wheel_area = new QWidget();
|
||||
QHBoxLayout* wheel_layout = new QHBoxLayout(wheel_area);
|
||||
splitter->addWidget(wheel_area);
|
||||
|
||||
color_wheel_ = new ColorWheelGLWidget();
|
||||
color_wheel_ = new ColorWheelWidget();
|
||||
wheel_layout->addWidget(color_wheel_);
|
||||
|
||||
hsv_value_gradient_ = new ColorGradientGLWidget(Qt::Vertical);
|
||||
hsv_value_gradient_ = new ColorGradientWidget(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);
|
||||
splitter->setSizes({INT_MAX, 0});
|
||||
|
||||
connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, cvw, &ColorValuesWidget::SetColor);
|
||||
connect(color_wheel_, &ColorWheelWidget::SelectedColorChanged, hsv_value_gradient_, &ColorGradientWidget::SetSelectedColor);
|
||||
connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, cvw, &ColorValuesWidget::SetColor);
|
||||
connect(hsv_value_gradient_, &ColorGradientWidget::SelectedColorChanged, color_wheel_, &ColorWheelWidget::SetSelectedColor);
|
||||
|
||||
connect(color_wheel_, &ColorWheelWidget::DiameterChanged, hsv_value_gradient_, &ColorGradientWidget::setFixedHeight);
|
||||
|
||||
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);
|
||||
color_wheel_->SetSelectedColor(start);
|
||||
hsv_value_gradient_->SetSelectedColor(start);
|
||||
cvw->SetColor(start);
|
||||
}
|
||||
|
||||
void ColorDialog::UpdateValueGradient(const Color &c)
|
||||
const Color &ColorDialog::GetSelectedColor() const
|
||||
{
|
||||
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);
|
||||
return color_wheel_->GetSelectedColor();
|
||||
}
|
||||
|
||||
@@ -15,19 +15,14 @@ class ColorDialog : public QDialog
|
||||
public:
|
||||
ColorDialog(ColorManager* color_manager, Color start = Color(1.0f, 1.0f, 1.0f), QWidget* parent = nullptr);
|
||||
|
||||
const Color& GetSelectedColor() const;
|
||||
|
||||
private:
|
||||
ColorManager* color_manager_;
|
||||
|
||||
ColorWheelGLWidget* color_wheel_;
|
||||
ColorWheelWidget* color_wheel_;
|
||||
|
||||
ColorGradientGLWidget* hsv_value_gradient_;
|
||||
|
||||
private slots:
|
||||
void UpdateValueGradient(const Color& c);
|
||||
|
||||
void UpdateWheelValue(const Color& c);
|
||||
|
||||
void UpdateValueGradientSize(int diameter);
|
||||
ColorGradientWidget* hsv_value_gradient_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+76
-2
@@ -87,14 +87,14 @@ void Color::toHsv(float *hue, float *sat, float *val) const
|
||||
}
|
||||
}
|
||||
|
||||
float Color::hue() const
|
||||
float Color::hsv_hue() const
|
||||
{
|
||||
float h, s, v;
|
||||
toHsv(&h, &s, &v);
|
||||
return h;
|
||||
}
|
||||
|
||||
float Color::saturation() const
|
||||
float Color::hsv_saturation() const
|
||||
{
|
||||
float h, s, v;
|
||||
toHsv(&h, &s, &v);
|
||||
@@ -107,3 +107,77 @@ float Color::value() const
|
||||
toHsv(&h, &s, &v);
|
||||
return v;
|
||||
}
|
||||
|
||||
void Color::toHsl(float *hue, float *sat, float *lightness) const
|
||||
{
|
||||
float fCMin = qMin(red(), qMin(green(), blue()));
|
||||
float fCMax = qMax(red(), qMax(green(), blue()));
|
||||
|
||||
*lightness = 0.5 * (fCMin + fCMax);
|
||||
|
||||
if (fCMin == fCMax)
|
||||
{
|
||||
*sat = 0;
|
||||
*hue = 0;
|
||||
return;
|
||||
|
||||
}
|
||||
else if (*lightness < 0.5)
|
||||
{
|
||||
*sat = (fCMax - fCMin) / (fCMax + fCMin);
|
||||
}
|
||||
else
|
||||
{
|
||||
*sat = (fCMax - fCMin) / (2.0 - fCMax - fCMin);
|
||||
}
|
||||
|
||||
if (fCMax == red())
|
||||
{
|
||||
*hue = 60 * (green() - blue()) / (fCMax - fCMin);
|
||||
}
|
||||
if (fCMax == green())
|
||||
{
|
||||
*hue = 60 * (blue() - red()) / (fCMax - fCMin) + 120;
|
||||
}
|
||||
if (fCMax == blue())
|
||||
{
|
||||
*hue = 60 * (red() - green()) / (fCMax - fCMin) + 240;
|
||||
}
|
||||
if (*hue < 0)
|
||||
{
|
||||
*hue = *hue + 360;
|
||||
}
|
||||
}
|
||||
|
||||
float Color::hsl_hue() const
|
||||
{
|
||||
float h, s, l;
|
||||
toHsl(&h, &s, &l);
|
||||
return h;
|
||||
}
|
||||
|
||||
float Color::hsl_saturation() const
|
||||
{
|
||||
float h, s, l;
|
||||
toHsl(&h, &s, &l);
|
||||
return s;
|
||||
}
|
||||
|
||||
float Color::lightness() const
|
||||
{
|
||||
float h, s, l;
|
||||
toHsl(&h, &s, &l);
|
||||
return l;
|
||||
}
|
||||
|
||||
QColor Color::toQColor() const
|
||||
{
|
||||
QColor c;
|
||||
|
||||
c.setRedF(red());
|
||||
c.setGreenF(green());
|
||||
c.setBlueF(blue());
|
||||
c.setAlphaF(alpha());
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
+11
-2
@@ -1,6 +1,8 @@
|
||||
#ifndef COLOR_H
|
||||
#define COLOR_H
|
||||
|
||||
#include <QColor>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
@@ -40,10 +42,15 @@ public:
|
||||
const float& alpha() const {return data_[3];}
|
||||
|
||||
void toHsv(float* hue, float* sat, float* val) const;
|
||||
float hue() const;
|
||||
float saturation() const;
|
||||
float hsv_hue() const;
|
||||
float hsv_saturation() const;
|
||||
float value() const;
|
||||
|
||||
void toHsl(float* hue, float* sat, float* lightness) const;
|
||||
float hsl_hue() const;
|
||||
float hsl_saturation() const;
|
||||
float lightness() 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;}
|
||||
@@ -54,6 +61,8 @@ public:
|
||||
|
||||
static Color fromData(const char* data, const PixelFormat::Format& format);
|
||||
|
||||
QColor toQColor() const;
|
||||
|
||||
private:
|
||||
float data_[kRGBAChannels];
|
||||
|
||||
|
||||
@@ -8,10 +8,21 @@ ColorButton::ColorButton(QWidget *parent) :
|
||||
color_ = Color(1.0f, 1.0f, 1.0f);
|
||||
|
||||
connect(this, &ColorButton::clicked, this, &ColorButton::ShowColorDialog);
|
||||
|
||||
UpdateColor();
|
||||
}
|
||||
|
||||
void ColorButton::ShowColorDialog()
|
||||
{
|
||||
ColorDialog cd(nullptr, color_, this);
|
||||
cd.exec();
|
||||
|
||||
if (cd.exec() == QDialog::Accepted) {
|
||||
color_ = cd.GetSelectedColor();
|
||||
UpdateColor();
|
||||
}
|
||||
}
|
||||
|
||||
void ColorButton::UpdateColor()
|
||||
{
|
||||
setStyleSheet(QStringLiteral("ColorButton {background: %1;}").arg(color_.toQColor().name()));
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ private slots:
|
||||
void ShowColorDialog();
|
||||
|
||||
private:
|
||||
void UpdateColor();
|
||||
|
||||
Color color_;
|
||||
|
||||
};
|
||||
|
||||
@@ -1,57 +1,82 @@
|
||||
#include "colorgradientwidget.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "common/clamp.h"
|
||||
#include "common/lerp.h"
|
||||
#include "node/node.h"
|
||||
|
||||
ColorGradientGLWidget::ColorGradientGLWidget(Qt::Orientation orientation, QWidget *parent) :
|
||||
ColorGradientWidget::ColorGradientWidget(Qt::Orientation orientation, QWidget *parent) :
|
||||
ColorSwatchWidget(parent),
|
||||
orientation_(orientation)
|
||||
orientation_(orientation),
|
||||
val_(1.0)
|
||||
{
|
||||
}
|
||||
|
||||
void ColorGradientGLWidget::SetColors(const Color &a, const Color &b)
|
||||
Color ColorGradientWidget::GetColorFromScreenPos(const QPoint &p) const
|
||||
{
|
||||
a_ = a;
|
||||
b_ = b;
|
||||
|
||||
update();
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
return LerpColor(start_, end_, p.x(), width());
|
||||
} else {
|
||||
return LerpColor(start_, end_, p.y(), height());
|
||||
}
|
||||
}
|
||||
|
||||
Color ColorGradientGLWidget::GetColorFromCursorPos(const QPoint &p) const
|
||||
void ColorGradientWidget::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
float t;
|
||||
QWidget::paintEvent(e);
|
||||
|
||||
QPainter p(this);
|
||||
|
||||
int min;
|
||||
int max;
|
||||
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
t = static_cast<float>(p.x()) / static_cast<float>(width());
|
||||
min = height();
|
||||
max = width();
|
||||
} else {
|
||||
t = static_cast<float>(p.y()) / static_cast<float>(height());
|
||||
min = width();
|
||||
max = height();
|
||||
}
|
||||
|
||||
return Color(lerp(a_.red(), b_.red(), t),
|
||||
lerp(a_.green(), b_.green(), t),
|
||||
lerp(a_.blue(), b_.blue(), t));
|
||||
for (int i=0;i<max;i++) {
|
||||
Color c = LerpColor(start_, end_, i, max);
|
||||
p.setPen(c.toQColor());
|
||||
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
p.drawLine(i, 0, i, height());
|
||||
} else {
|
||||
p.drawLine(0, i, width(), i);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw selector
|
||||
int selector_radius = qMax(2, min / 8);
|
||||
p.setPen(QPen(GetUISelectorColor(), qMax(1, selector_radius / 2)));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
p.drawRect(qRound(width() * (1.0 - val_)) - selector_radius, 0, selector_radius * 2, height());
|
||||
} else {
|
||||
p.drawRect(0, qRound(height() * (1.0 - val_)) - selector_radius, width(), selector_radius * 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool ColorGradientGLWidget::PointIsValid(const QPoint &) const
|
||||
void ColorGradientWidget::SelectedColorChangedEvent(const Color &c)
|
||||
{
|
||||
return true;
|
||||
float hue, sat;
|
||||
|
||||
c.toHsv(&hue, &sat, &val_);
|
||||
|
||||
start_ = Color::fromHsv(hue, sat, 1.0);
|
||||
end_ = Color::fromHsv(hue, sat, 0.0);
|
||||
}
|
||||
|
||||
OpenGLShader *ColorGradientGLWidget::CreateShader() const
|
||||
Color ColorGradientWidget::LerpColor(const Color &a, const Color &b, int i, int max)
|
||||
{
|
||||
OpenGLShader* s = new OpenGLShader();
|
||||
float t = clamp(static_cast<float>(i) / static_cast<float>(max), 0.0f, 1.0f);
|
||||
|
||||
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());
|
||||
return Color(lerp(a.red(), b.red(), t),
|
||||
lerp(a.green(), b.green(), t),
|
||||
lerp(a.blue(), b.blue(), t));
|
||||
}
|
||||
|
||||
@@ -4,29 +4,29 @@
|
||||
#include "colorswatchwidget.h"
|
||||
#include "render/color.h"
|
||||
|
||||
class ColorGradientGLWidget : public ColorSwatchWidget
|
||||
class ColorGradientWidget : public ColorSwatchWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorGradientGLWidget(Qt::Orientation orientation, QWidget* parent = nullptr);
|
||||
|
||||
void SetColors(const Color& a, const Color& b);
|
||||
ColorGradientWidget(Qt::Orientation orientation, QWidget* parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual Color GetColorFromCursorPos(const QPoint& p) const override;
|
||||
virtual Color GetColorFromScreenPos(const QPoint& p) const override;
|
||||
|
||||
virtual bool PointIsValid(const QPoint& p) const override;
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
|
||||
virtual OpenGLShader* CreateShader() const override;
|
||||
|
||||
virtual void SetShaderUniformValues(OpenGLShader* shader) const override;
|
||||
virtual void SelectedColorChangedEvent(const Color& c) override;
|
||||
|
||||
private:
|
||||
static Color LerpColor(const Color& a, const Color& b, int i, int max);
|
||||
|
||||
Qt::Orientation orientation_;
|
||||
|
||||
Color a_;
|
||||
Color start_;
|
||||
|
||||
Color b_;
|
||||
Color end_;
|
||||
|
||||
float val_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -5,57 +5,51 @@
|
||||
#include "render/backend/opengl/openglrenderfunctions.h"
|
||||
|
||||
ColorSwatchWidget::ColorSwatchWidget(QWidget *parent) :
|
||||
QOpenGLWidget(parent),
|
||||
shader_(nullptr)
|
||||
QWidget(parent)
|
||||
{
|
||||
// Render with transparent background
|
||||
setAttribute(Qt::WA_AlwaysStackOnTop);
|
||||
}
|
||||
|
||||
ColorSwatchWidget::~ColorSwatchWidget()
|
||||
const Color &ColorSwatchWidget::GetSelectedColor() const
|
||||
{
|
||||
CleanUp();
|
||||
return selected_color_;
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::initializeGL()
|
||||
void ColorSwatchWidget::SetSelectedColor(const Color &c)
|
||||
{
|
||||
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;
|
||||
selected_color_ = c;
|
||||
SelectedColorChangedEvent(c);
|
||||
update();
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
QOpenGLWidget::mousePressEvent(e);
|
||||
QWidget::mousePressEvent(e);
|
||||
|
||||
if (PointIsValid(e->pos())) {
|
||||
emit ColorChanged(GetColorFromCursorPos(e->pos()));
|
||||
}
|
||||
SetSelectedColor(GetColorFromScreenPos(e->pos()));
|
||||
emit SelectedColorChanged(GetSelectedColor());
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
QOpenGLWidget::mouseMoveEvent(e);
|
||||
QWidget::mouseMoveEvent(e);
|
||||
|
||||
if (e->buttons() & Qt::LeftButton && PointIsValid(e->pos())) {
|
||||
emit ColorChanged(GetColorFromCursorPos(e->pos()));
|
||||
if (e->buttons() & Qt::LeftButton) {
|
||||
SetSelectedColor(GetColorFromScreenPos(e->pos()));
|
||||
emit SelectedColorChanged(GetSelectedColor());
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::SelectedColorChangedEvent(const Color &)
|
||||
{
|
||||
}
|
||||
|
||||
Qt::GlobalColor ColorSwatchWidget::GetUISelectorColor() const
|
||||
{
|
||||
float rough_color_luma = (GetSelectedColor().red()+GetSelectedColor().red()+GetSelectedColor().blue()+GetSelectedColor().green()+GetSelectedColor().green()+GetSelectedColor().green())/6;
|
||||
|
||||
if (rough_color_luma > 0.66) {
|
||||
return Qt::black;
|
||||
} else {
|
||||
return Qt::white;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,39 +6,33 @@
|
||||
#include "render/backend/opengl/openglshader.h"
|
||||
#include "render/color.h"
|
||||
|
||||
class ColorSwatchWidget : public QOpenGLWidget
|
||||
class ColorSwatchWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorSwatchWidget(QWidget* parent = nullptr);
|
||||
|
||||
virtual ~ColorSwatchWidget() override;
|
||||
const Color& GetSelectedColor() const;
|
||||
|
||||
public slots:
|
||||
void SetSelectedColor(const Color& c);
|
||||
|
||||
signals:
|
||||
void ColorChanged(const Color& c);
|
||||
void SelectedColorChanged(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 GetColorFromScreenPos(const QPoint& p) const = 0;
|
||||
|
||||
virtual Color GetColorFromCursorPos(const QPoint& p) const = 0;
|
||||
virtual void SelectedColorChangedEvent(const Color& c);
|
||||
|
||||
virtual bool PointIsValid(const QPoint& p) const = 0;
|
||||
|
||||
virtual OpenGLShader* CreateShader() const = 0;
|
||||
|
||||
private slots:
|
||||
void CleanUp();
|
||||
Qt::GlobalColor GetUISelectorColor() const;
|
||||
|
||||
private:
|
||||
OpenGLShader* shader_;
|
||||
Color selected_color_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,112 +1,152 @@
|
||||
#include "colorwheelwidget.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QtMath>
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
#define M_180_OVER_PI 57.295791433133264917914229473464
|
||||
#define M_RADIAN_TO_0_1 0.15915497620314795810531730409296
|
||||
|
||||
ColorWheelGLWidget::ColorWheelGLWidget(QWidget *parent) :
|
||||
ColorWheelWidget::ColorWheelWidget(QWidget *parent) :
|
||||
ColorSwatchWidget(parent),
|
||||
hsv_value_(1.0f)
|
||||
val_(1.0f),
|
||||
force_redraw_(false)
|
||||
{
|
||||
}
|
||||
|
||||
void ColorWheelGLWidget::SetHSVValue(float val)
|
||||
Color ColorWheelWidget::GetColorFromScreenPos(const QPoint &p) const
|
||||
{
|
||||
hsv_value_ = val;
|
||||
update();
|
||||
return GetColorFromTriangle(GetTriangleFromCoords(rect().center(), p));
|
||||
}
|
||||
|
||||
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)
|
||||
void ColorWheelWidget::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
ColorSwatchWidget::resizeEvent(e);
|
||||
|
||||
emit DiameterChanged(GetDiameter());
|
||||
}
|
||||
|
||||
int ColorWheelGLWidget::GetDiameter() const
|
||||
void ColorWheelWidget::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
return qMin(width(), height());
|
||||
}
|
||||
ColorSwatchWidget::paintEvent(e);
|
||||
|
||||
qreal ColorWheelGLWidget::GetRadius() const
|
||||
{
|
||||
return GetDiameter() * 0.5;
|
||||
}
|
||||
int diameter = GetDiameter();
|
||||
|
||||
/* Software/QPainter-based color wheel
|
||||
void ColorWheelWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QWidget::paintEvent(event);
|
||||
// Half diameter (add one to ensure the division rounds up)
|
||||
int radius = (diameter + 1) / 2;
|
||||
|
||||
QPainter p(this);
|
||||
if (cached_wheel_.width() != diameter || force_redraw_) {
|
||||
cached_wheel_ = QPixmap(QSize(diameter, diameter));
|
||||
cached_wheel_.fill(Qt::transparent);
|
||||
force_redraw_ = false;
|
||||
|
||||
qreal radius = qMin(width(), height()) / 2;
|
||||
QPoint center = rect().center();
|
||||
QPainter p(&cached_wheel_);
|
||||
QPoint center(radius, radius);
|
||||
|
||||
int x_start = center.x() - radius;
|
||||
int x_end = center.x() + radius;
|
||||
int y_start = center.y() - radius;
|
||||
int y_end = center.y() + radius;
|
||||
for (int i=0;i<diameter;i++) {
|
||||
for (int j=0;j<diameter;j++) {
|
||||
Triangle tri = GetTriangleFromCoords(center, j, i);
|
||||
|
||||
for (int i=x_start;i<x_end;i++) {
|
||||
for (int j=y_start;j<y_end;j++) {
|
||||
qreal opposite = j - center.y();
|
||||
qreal adjacent = i - center.x();
|
||||
qreal pix_len = qSqrt(qPow(adjacent, 2) + qPow(opposite, 2));
|
||||
if (tri.hypotenuse <= radius) {
|
||||
QColor c = GetColorFromTriangle(tri).toQColor();
|
||||
|
||||
if (pix_len <= radius) {
|
||||
qreal hue = qAtan2(opposite, adjacent) * RADIAN_TO_0_1_RANGE + 0.5;
|
||||
qreal sat = (pix_len / radius);
|
||||
qreal value = 1.0;
|
||||
// Very basic antialiasing around the edges of the wheel
|
||||
qreal alpha = qMin(1.0, radius - tri.hypotenuse);
|
||||
c.setAlphaF(alpha);
|
||||
|
||||
QColor c;
|
||||
c.setHsvF(hue, sat, value);
|
||||
p.setPen(c);
|
||||
|
||||
p.drawPoint(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
QPainter p(this);
|
||||
|
||||
// Draw wheel pixmap
|
||||
int x, y;
|
||||
|
||||
if (width() == height()) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
} else if (width() > height()) {
|
||||
x = (width() - height()) / 2;
|
||||
y = 0;
|
||||
} else {
|
||||
x = 0;
|
||||
y = (height() - width()) / 2;
|
||||
}
|
||||
|
||||
p.drawPixmap(x, y, cached_wheel_);
|
||||
|
||||
|
||||
// Draw selection
|
||||
// Really rough algorithm for determining whether the selector UI should be white or black
|
||||
|
||||
|
||||
int selector_radius = qMax(1, radius / 32);
|
||||
p.setPen(QPen(GetUISelectorColor(), qMax(1, selector_radius / 4)));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
p.drawEllipse(GetCoordsFromColor(GetSelectedColor()), selector_radius, selector_radius);
|
||||
}
|
||||
|
||||
void ColorWheelWidget::SelectedColorChangedEvent(const Color &c)
|
||||
{
|
||||
force_redraw_ = true;
|
||||
val_ = c.value();
|
||||
}
|
||||
|
||||
int ColorWheelWidget::GetDiameter() const
|
||||
{
|
||||
return qMin(width(), height());
|
||||
}
|
||||
|
||||
qreal ColorWheelWidget::GetRadius() const
|
||||
{
|
||||
return GetDiameter() * 0.5;
|
||||
}
|
||||
|
||||
ColorWheelWidget::Triangle ColorWheelWidget::GetTriangleFromCoords(const QPoint ¢er, const QPoint &p) const
|
||||
{
|
||||
return GetTriangleFromCoords(center, p.y(), p.x());
|
||||
}
|
||||
|
||||
ColorWheelWidget::Triangle ColorWheelWidget::GetTriangleFromCoords(const QPoint ¢er, qreal y, qreal x) const
|
||||
{
|
||||
qreal opposite = y - center.y();
|
||||
qreal adjacent = x - center.x();
|
||||
qreal hypotenuse = qSqrt(qPow(adjacent, 2) + qPow(opposite, 2));
|
||||
|
||||
return {opposite, adjacent, hypotenuse};
|
||||
}
|
||||
|
||||
Color ColorWheelWidget::GetColorFromTriangle(const ColorWheelWidget::Triangle &tri) const
|
||||
{
|
||||
qreal hue = qAtan2(tri.opposite, tri.adjacent) * M_180_OVER_PI + 180.0;
|
||||
qreal sat = qMin(1.0, (tri.hypotenuse / GetRadius()));
|
||||
|
||||
return Color::fromHsv(hue, sat, val_);
|
||||
}
|
||||
|
||||
QPoint ColorWheelWidget::GetCoordsFromColor(const Color &c) const
|
||||
{
|
||||
float hue, sat, val;
|
||||
c.toHsv(&hue, &sat, &val);
|
||||
|
||||
qreal hypotenuse = sat * GetRadius();
|
||||
|
||||
qreal radian_angle = (hue - 180.0) / M_180_OVER_PI;
|
||||
|
||||
qreal opposite = qSin(radian_angle) * hypotenuse;
|
||||
|
||||
qreal adjacent = qCos(radian_angle) * hypotenuse;
|
||||
|
||||
QPoint pos(qRound(adjacent), qRound(opposite));
|
||||
|
||||
pos += rect().center();
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
@@ -7,45 +7,47 @@
|
||||
#include "render/backend/opengl/openglshader.h"
|
||||
#include "render/color.h"
|
||||
|
||||
class ColorWheelGLWidget : public ColorSwatchWidget
|
||||
class ColorWheelWidget : public ColorSwatchWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorWheelGLWidget(QWidget* parent = nullptr);
|
||||
|
||||
void SetHSVValue(float val);
|
||||
ColorWheelWidget(QWidget* parent = nullptr);
|
||||
|
||||
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 Color GetColorFromScreenPos(const QPoint& p) const override;
|
||||
|
||||
virtual void resizeEvent(QResizeEvent* e) override;
|
||||
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
|
||||
virtual void SelectedColorChangedEvent(const Color& c) override;
|
||||
|
||||
private:
|
||||
int GetDiameter() const;
|
||||
|
||||
qreal GetRadius() const;
|
||||
|
||||
float hsv_value_;
|
||||
struct Triangle {
|
||||
qreal opposite;
|
||||
qreal adjacent;
|
||||
qreal hypotenuse;
|
||||
};
|
||||
|
||||
Triangle GetTriangleFromCoords(const QPoint ¢er, const QPoint& p) const;
|
||||
Triangle GetTriangleFromCoords(const QPoint ¢er, qreal y, qreal x) const;
|
||||
|
||||
Color GetColorFromTriangle(const Triangle& tri) const;
|
||||
QPoint GetCoordsFromColor(const Color& c) const;
|
||||
|
||||
QPixmap cached_wheel_;
|
||||
|
||||
float val_;
|
||||
|
||||
bool force_redraw_;
|
||||
|
||||
};
|
||||
|
||||
/*class ColorWheelWidget : public QWidget
|
||||
{
|
||||
public:
|
||||
ColorWheelWidget(QWidget* parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
|
||||
};*/
|
||||
|
||||
#endif // COLORWHEELWIDGET_H
|
||||
|
||||
Reference in New Issue
Block a user