mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-07-01 05:46:06 -04:00
05/31/2017
--User changes -Add support for adjusting xform color indices in the palette editor. Fixed palettes can now be displayed there, but they will have no color arrows as they are not editable. -Add support for independent dimension scaling in the EmberRender and EmberAnimate programs to bring them in line with the final render dialog Fractorium. --Bug fixes -File paths with a space in them did not work in the command line programs. -Any Xml file in the search paths would erroneously be treated as a palette file. --Code changes -Change some for loops to while loops when iterating through xforms. -Allow FractoriumEmberController<T>::UpdateXform() to be able to apply the action to an xform at a specific index. -Remove old code blocks build files that were never used. -Make GetPath() return empty string if no path is present in the passed in file path. -GetTotalXform() was always counting the final xform, even if it was unused.
This commit is contained in:
@ -43,7 +43,7 @@ Q_SIGNALS:
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private slots:
|
||||
private Q_SLOTS:
|
||||
void OnColorViewerClicked();
|
||||
void OnTriangleColorChanged(const QColor& col);
|
||||
|
||||
|
@ -97,7 +97,7 @@ public:
|
||||
virtual int heightForWidth(int w) const override;
|
||||
virtual QSize sizeHint() const override;
|
||||
|
||||
signals:
|
||||
Q_SIGNALS:
|
||||
void ColorChanged(const QColor& col);
|
||||
|
||||
protected:
|
||||
|
@ -76,3 +76,52 @@ private:
|
||||
QPolygon m_Area;
|
||||
QColor m_Color;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Thin derivation to handle drawing arrows at the top of the gradient area to
|
||||
/// represent the color indices of each xform.
|
||||
/// </summary>
|
||||
class TopArrow : public GradientArrow
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Default constructor which is only present so this class can be used with containers.
|
||||
/// This should never be used by a caller.
|
||||
/// </summary>
|
||||
TopArrow()
|
||||
: TopArrow(10, 0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which takes the width used to draw the arrow and the xform index
|
||||
/// this arrow represents.
|
||||
/// </summary>
|
||||
/// <param name="width">The width used to draw the arrow</param>
|
||||
/// <param name="index">The xform index this arrow represents</param>
|
||||
TopArrow(int width, size_t index)
|
||||
{
|
||||
QPolygon area;
|
||||
int center = 10;
|
||||
int mid = width / 2;
|
||||
int left = center - mid;
|
||||
int right = center + mid;
|
||||
area << QPoint(left, 0) << QPoint(right, 0) << QPoint(right, 10) << QPoint(center, 15) << QPoint(left, 10) << QPoint(left, 0);
|
||||
Area(area);
|
||||
m_Index = index;
|
||||
m_Width = width;
|
||||
m_Text = QString::number(index + 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Getters.
|
||||
/// </summary>
|
||||
int Width() { return m_Width; }
|
||||
size_t Index() { return m_Index; }
|
||||
QString Text() { return m_Text; }
|
||||
|
||||
private:
|
||||
int m_Width;
|
||||
size_t m_Index;
|
||||
QString m_Text;
|
||||
};
|
@ -73,7 +73,7 @@ void GradientColorsView::SetFocus(size_t position)
|
||||
it.second.Focus(b);
|
||||
}
|
||||
|
||||
if (!focused)
|
||||
if (!focused && !m_Arrows.empty())
|
||||
m_Arrows.begin()->second.Focus(true);
|
||||
|
||||
update();
|
||||
@ -100,6 +100,7 @@ void GradientColorsView::SetFocusColor(const QColor& color)
|
||||
|
||||
/// <summary>
|
||||
/// Add an arrow whose color will be assigned the passed in color.
|
||||
/// This should never be called on a fixed palette.
|
||||
/// </summary>
|
||||
/// <param name="color">The color to assign to the new arrow</param>
|
||||
void GradientColorsView::AddArrow(const QColor& color)
|
||||
@ -202,14 +203,28 @@ void GradientColorsView::DeleteFocusedArrow()
|
||||
/// </summary>
|
||||
void GradientColorsView::InvertColors()
|
||||
{
|
||||
for (auto& it : m_Arrows)
|
||||
if (!m_Arrows.empty())
|
||||
{
|
||||
auto& arrow = it.second;
|
||||
auto col = arrow.Color();
|
||||
arrow.Color(QColor(255 - col.red(), 255 - col.green(), 255 - col.blue()));
|
||||
for (auto& it : m_Arrows)
|
||||
{
|
||||
auto& arrow = it.second;
|
||||
auto col = arrow.Color();
|
||||
arrow.Color(QColor(255 - col.red(), 255 - col.green(), 255 - col.blue()));
|
||||
|
||||
if (arrow.Focus())
|
||||
emit ArrowDoubleClicked(arrow);
|
||||
if (arrow.Focus())
|
||||
emit ArrowDoubleClicked(arrow);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& col : m_Palette.m_Entries)
|
||||
{
|
||||
col.r = 1 - col.r;
|
||||
col.g = 1 - col.g;
|
||||
col.b = 1 - col.b;
|
||||
}
|
||||
|
||||
SetPalette(m_Palette);//Reset associated pixmap etc...
|
||||
}
|
||||
|
||||
update();
|
||||
@ -235,16 +250,20 @@ void GradientColorsView::RandomColors()
|
||||
/// </summary>
|
||||
void GradientColorsView::DistributeColors()
|
||||
{
|
||||
map<float, GradientArrow> arrows;
|
||||
float index = 0, inc = 1.0f / std::max<size_t>(size_t(1), m_Arrows.size() - 1);
|
||||
|
||||
for (auto it : m_Arrows)
|
||||
if (!m_Arrows.empty())
|
||||
{
|
||||
arrows[index] = it.second;
|
||||
index = std::min(1.0f, index + inc);
|
||||
map<float, GradientArrow> arrows;
|
||||
float index = 0, inc = 1.0f / std::max<size_t>(size_t(1), m_Arrows.size() - 1);
|
||||
|
||||
for (auto it : m_Arrows)
|
||||
{
|
||||
arrows[index] = it.second;
|
||||
index = std::min(1.0f, index + inc);
|
||||
}
|
||||
|
||||
m_Arrows = std::move(arrows);
|
||||
}
|
||||
|
||||
m_Arrows = std::move(arrows);
|
||||
update();
|
||||
}
|
||||
|
||||
@ -265,6 +284,7 @@ void GradientColorsView::ResetToDefault()
|
||||
void GradientColorsView::ClearArrows()
|
||||
{
|
||||
m_Arrows.clear();
|
||||
update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -334,20 +354,6 @@ int GradientColorsView::GetFocusedIndex()
|
||||
return index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a pixmap to be used to draw the palette.
|
||||
/// The pixmap is lazily instantiated on the first call, and all subsequent
|
||||
/// calls return a pointer to the same pixmap.
|
||||
/// </summary>
|
||||
/// <returns>The pixmap</returns>
|
||||
QPixmap* GradientColorsView::GetBackGround()
|
||||
{
|
||||
if (!m_Background.get())
|
||||
CreateBackground(m_BackgroundVerSpace, m_BackgroundHorSpace);
|
||||
|
||||
return m_Background.get();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a reference to the arrows map.
|
||||
/// Be very careful what you do with this.
|
||||
@ -366,34 +372,37 @@ map<float, GradientArrow>& GradientColorsView::GetArrows()
|
||||
/// <returns>A reference to the internal map containing the arrows</returns>
|
||||
Palette<float>& GradientColorsView::GetPalette(int size)
|
||||
{
|
||||
QSize imageSize(size, 1);
|
||||
QImage image(imageSize, QImage::Format_ARGB32_Premultiplied);
|
||||
QPainter p;
|
||||
QLinearGradient grad(QPoint(0, 0), QPoint(imageSize.width(), imageSize.height()));
|
||||
m_Palette.m_SourceColors.clear();
|
||||
|
||||
for (auto& it : m_Arrows)
|
||||
if (!m_Arrows.empty())
|
||||
{
|
||||
auto pos = it.first;
|
||||
auto col = it.second.Color();
|
||||
m_Palette.m_SourceColors[pos] = v4F(col.red() / 255.0f, col.green() / 255.0f, col.blue() / 255.0f, 1.0f);
|
||||
grad.setColorAt(pos, col);
|
||||
QPainter p;
|
||||
QSize imageSize(size, 1);
|
||||
QImage image(imageSize, QImage::Format_ARGB32_Premultiplied);
|
||||
QLinearGradient grad(QPoint(0, 0), QPoint(imageSize.width(), imageSize.height()));
|
||||
m_Palette.m_SourceColors.clear();
|
||||
|
||||
for (auto& it : m_Arrows)
|
||||
{
|
||||
auto pos = it.first;
|
||||
auto col = it.second.Color();
|
||||
m_Palette.m_SourceColors[pos] = v4F(col.red() / 255.0f, col.green() / 255.0f, col.blue() / 255.0f, 1.0f);
|
||||
grad.setColorAt(pos, col);
|
||||
}
|
||||
|
||||
p.begin(&image);
|
||||
p.fillRect(image.rect(), grad);
|
||||
p.end();
|
||||
m_Palette.m_Entries.reserve(image.width());
|
||||
|
||||
for (int i = 0; i < image.width(); i++)
|
||||
{
|
||||
QColor col(image.pixel(i, 0));
|
||||
m_Palette[i].r = col.red() / 255.0f;
|
||||
m_Palette[i].g = col.green() / 255.0f;
|
||||
m_Palette[i].b = col.blue() / 255.0f;
|
||||
}
|
||||
}
|
||||
|
||||
p.begin(&image);
|
||||
p.fillRect(image.rect(), grad);
|
||||
p.end();
|
||||
m_Palette.m_Entries.reserve(image.width());
|
||||
|
||||
for (int i = 0; i < image.width(); i++)
|
||||
{
|
||||
QColor col(image.pixel(i, 0));
|
||||
m_Palette[i].r = col.red() / 255.0f;
|
||||
m_Palette[i].g = col.green() / 255.0f;
|
||||
m_Palette[i].b = col.blue() / 255.0f;
|
||||
}
|
||||
|
||||
return m_Palette;
|
||||
return m_Palette;//If fixed palette, just return verbatim.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -406,11 +415,11 @@ Palette<float>& GradientColorsView::GetPalette(int size)
|
||||
/// <param name="palette">The palette whose source colors will be assigned to the arrow map</param>
|
||||
void GradientColorsView::SetPalette(const Palette<float>& palette)
|
||||
{
|
||||
m_Arrows.clear();
|
||||
m_Palette = palette;
|
||||
|
||||
if (palette.m_SourceColors.size() > 1)
|
||||
{
|
||||
m_Palette = palette;
|
||||
m_Arrows.clear();
|
||||
|
||||
for (auto& col : m_Palette.m_SourceColors)
|
||||
{
|
||||
auto& rgb = col.second;
|
||||
@ -418,7 +427,48 @@ void GradientColorsView::SetPalette(const Palette<float>& palette)
|
||||
}
|
||||
|
||||
SetFocus(size_t(0));
|
||||
update();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v = m_Palette.MakeRgbPaletteBlock(m_ViewRect.height());//Make the palette repeat for PALETTE_CELL_HEIGHT rows.
|
||||
auto image = QImage(int(m_Palette.Size()), m_ViewRect.height(), QImage::Format_RGB888);//Create a QImage out of it.
|
||||
memcpy(image.scanLine(0), v.data(), v.size() * sizeof(v[0]));//Memcpy the data in.
|
||||
m_FinalFixedPixmap = QPixmap(QPixmap::fromImage(image));//Create a QPixmap out of the QImage.
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a temporary copy of the xform color indices as a map.
|
||||
/// The keys are the xform indices, and the values are the color indices.
|
||||
/// </summary>
|
||||
/// <param name="palette">The color indices</param>
|
||||
map<size_t, float> GradientColorsView::GetColorIndices() const
|
||||
{
|
||||
map<size_t, float> indices;
|
||||
|
||||
for (auto& it : m_ColorIndicesArrows)
|
||||
indices[it.first] = it.second.first;
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assign the values of the xform color indices to the arrows.
|
||||
/// This will clear out any existing values first.
|
||||
/// </summary>
|
||||
/// <param name="palette">The color indices to assign</param>
|
||||
void GradientColorsView::SetColorIndices(const map<size_t, float>& indices)
|
||||
{
|
||||
QPainter painter(this);
|
||||
m_ColorIndicesArrows.clear();
|
||||
|
||||
for (auto& it : indices)
|
||||
{
|
||||
auto text = QString::number(it.first + 1);//Get text width, which is used to adjust the size of the arrow.
|
||||
QFontMetrics fm = painter.fontMetrics();
|
||||
m_ColorIndicesArrows[it.first] = make_pair(it.second, TopArrow(fm.width(text) + 5, it.first));
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,44 +481,60 @@ void GradientColorsView::paintEvent(QPaintEvent*)
|
||||
m_ViewRect.size().isEmpty() ||
|
||||
m_ViewRect.topLeft() == m_ViewRect.bottomRight())
|
||||
{
|
||||
m_ViewRect = QRect(QPoint(5, 0), QPoint(width() - 15, height() / 3 * 2 - 10));
|
||||
m_ViewRect.translate(5, 5);
|
||||
CreateBackground();
|
||||
resizeEvent(nullptr);//Setup rects.
|
||||
}
|
||||
|
||||
QPainter painter(this);
|
||||
|
||||
if (m_Background.get())
|
||||
painter.drawPixmap(m_ViewRect, *m_Background.get(), m_ViewRect);
|
||||
|
||||
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
QPoint gradStart = QPoint(m_ViewRect.topLeft().x(), m_ViewRect.bottomLeft().y() / 2);
|
||||
QPoint gradStop = QPoint(m_ViewRect.topRight().x(), m_ViewRect.bottomRight().y() / 2);
|
||||
QLinearGradient grad(gradStart, gradStop);
|
||||
|
||||
for (auto& it : m_Arrows)
|
||||
if (!m_Arrows.empty())
|
||||
{
|
||||
GradientArrow& arrow = it.second;
|
||||
grad.setColorAt(it.first, arrow.Color());
|
||||
QPolygon arrowPolygon = arrow.Area();
|
||||
int iPosX = it.first * (width() - 20),
|
||||
iPosY = height() / 3 * 2;
|
||||
arrowPolygon.translate(iPosX, iPosY);
|
||||
QPainterPath paintPath;
|
||||
paintPath.addPolygon(arrowPolygon);
|
||||
painter.setBrush(QBrush(arrow.Color()));
|
||||
QPoint gradStart = QPoint(m_ViewRect.topLeft().x(), m_ViewRect.bottomLeft().y() / 2);
|
||||
QPoint gradStop = QPoint(m_ViewRect.topRight().x(), m_ViewRect.bottomRight().y() / 2);
|
||||
QLinearGradient grad(gradStart, gradStop);
|
||||
|
||||
if (arrow.Focus())
|
||||
paintPath.addRect(iPosX + 5, iPosY + 20, 10, 5);
|
||||
for (auto& it : m_Arrows)
|
||||
{
|
||||
GradientArrow& arrow = it.second;
|
||||
grad.setColorAt(it.first, arrow.Color());
|
||||
QPolygon arrowPolygon = arrow.Area();
|
||||
int iPosX = it.first * RectWidth(),
|
||||
iPosY = m_ViewRect.height() + m_ViewRect.top() + 3;
|
||||
arrowPolygon.translate(iPosX, iPosY);
|
||||
QPainterPath paintPath;
|
||||
paintPath.addPolygon(arrowPolygon);
|
||||
painter.setBrush(QBrush(arrow.Color()));
|
||||
|
||||
painter.drawPath(paintPath);
|
||||
painter.setBrush(QBrush(Qt::NoBrush));
|
||||
if (arrow.Focus())
|
||||
paintPath.addRect(iPosX + 5, iPosY + 20, 10, 5);
|
||||
|
||||
painter.drawPath(paintPath);
|
||||
painter.setBrush(QBrush(Qt::NoBrush));
|
||||
}
|
||||
|
||||
QBrush brush(grad);
|
||||
painter.fillRect(m_ViewRect, brush);
|
||||
painter.drawRect(m_ViewRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.drawPixmap(m_ViewRect, m_FinalFixedPixmap);
|
||||
}
|
||||
|
||||
for (auto& it : m_ColorIndicesArrows)
|
||||
{
|
||||
QPainterPath topArrowPaintPath;
|
||||
auto& topArrow = it.second.second;
|
||||
auto topArrowPolygon = topArrow.Area();
|
||||
topArrowPolygon.translate(it.second.first * RectWidth(), 0);
|
||||
auto topArrowRect = topArrowPolygon.boundingRect();
|
||||
topArrowPaintPath.addPolygon(topArrowPolygon);
|
||||
painter.drawPath(topArrowPaintPath);//When using a separate painter, the sides aren't as thick.
|
||||
//Draw text inside of the arrow.
|
||||
painter.drawText(topArrowRect.x() + (topArrowRect.width() - (topArrow.Width() - 5)) / 2.0, topArrowRect.y() + (topArrowRect.height() - 5), topArrow.Text());
|
||||
}
|
||||
|
||||
QBrush brush(grad);
|
||||
painter.fillRect(m_ViewRect, brush);
|
||||
painter.drawRect(m_ViewRect);
|
||||
painter.end();
|
||||
}
|
||||
|
||||
@ -484,7 +550,7 @@ void GradientColorsView::mousePressEvent(QMouseEvent* e)
|
||||
{
|
||||
auto& arrow = it.second;
|
||||
QPolygon poly = arrow.Area();
|
||||
poly.translate(it.first * (width() - 20), height() / 3 * 2);
|
||||
poly.translate(it.first * m_ViewRectSize.x(), m_ViewRectSize.y());
|
||||
|
||||
if (poly.containsPoint(m_DragStart, Qt::OddEvenFill))
|
||||
{
|
||||
@ -495,6 +561,21 @@ void GradientColorsView::mousePressEvent(QMouseEvent* e)
|
||||
arrow.Focus(false);
|
||||
}
|
||||
|
||||
for (auto& it : m_ColorIndicesArrows)
|
||||
{
|
||||
auto& arrow = it.second.second;
|
||||
QPolygon poly = arrow.Area();
|
||||
poly.translate(it.second.first * m_ViewRectSize.x(), 0);
|
||||
|
||||
if (poly.containsPoint(m_DragStart, Qt::OddEvenFill))
|
||||
{
|
||||
m_ColorIndexArrowMoving = true;
|
||||
arrow.Focus(true);
|
||||
}
|
||||
else
|
||||
arrow.Focus(false);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
@ -508,7 +589,7 @@ void GradientColorsView::mouseDoubleClickEvent(QMouseEvent* e)
|
||||
{
|
||||
auto& arrow = it.second;
|
||||
QPolygon poly = arrow.Area();
|
||||
poly.translate(it.first * (width() - 20), height() / 3 * 2);
|
||||
poly.translate(it.first * m_ViewRectSize.x(), m_ViewRectSize.y());
|
||||
|
||||
if (poly.containsPoint(e->pos(), Qt::OddEvenFill))
|
||||
{
|
||||
@ -526,50 +607,76 @@ void GradientColorsView::mouseDoubleClickEvent(QMouseEvent* e)
|
||||
/// <param name="event">The mouse event</param>
|
||||
void GradientColorsView::mouseMoveEvent(QMouseEvent* e)
|
||||
{
|
||||
if (!m_ArrowMoving) return;
|
||||
if (!m_ArrowMoving && !m_ColorIndexArrowMoving) return;
|
||||
|
||||
size_t index = 0;
|
||||
qreal maxMove = 11.5 / (width() - 20);
|
||||
qreal maxMove = 11.5 / RectWidth();
|
||||
|
||||
for (auto it = m_Arrows.begin(); it != m_Arrows.end(); ++it)
|
||||
if (m_ArrowMoving)
|
||||
{
|
||||
auto& arrow = it->second;
|
||||
|
||||
if (arrow.Focus())
|
||||
for (auto it = m_Arrows.begin(); it != m_Arrows.end(); ++it)
|
||||
{
|
||||
qreal lastPos = it->first;
|
||||
qreal start = m_DragStart.x();
|
||||
qreal end = width() - 20;
|
||||
qreal dPos = ((qreal) e->pos().x() - start) / end;
|
||||
qreal newPos = lastPos + dPos;
|
||||
auto& arrow = it->second;
|
||||
|
||||
if ( (it->first + dPos > 1) || (it->first + dPos < 0) )
|
||||
return;
|
||||
|
||||
if (dPos < 0 && index > 0)
|
||||
if (arrow.Focus())
|
||||
{
|
||||
qreal posBefore = std::prev(it)->first;
|
||||
qreal lastPos = it->first;
|
||||
qreal start = m_DragStart.x();
|
||||
qreal end = RectWidth();
|
||||
qreal dPos = ((qreal)e->pos().x() - start) / end;
|
||||
qreal newPos = lastPos + dPos;
|
||||
|
||||
if ( (lastPos - maxMove + dPos) <= posBefore )
|
||||
if ((lastPos + dPos > 1) || (lastPos + dPos < 0))
|
||||
return;
|
||||
|
||||
if (dPos < 0 && index > 0)
|
||||
{
|
||||
qreal posBefore = std::prev(it)->first;
|
||||
|
||||
if ((lastPos - maxMove + dPos) <= posBefore)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((dPos > 0) && (index < (m_Arrows.size() - 1)))
|
||||
{
|
||||
qreal posAfter = std::next(it)->first;
|
||||
|
||||
if ((lastPos + maxMove + dPos) >= posAfter)
|
||||
return;
|
||||
}
|
||||
|
||||
GradientArrow arrowCopy(it->second);
|
||||
m_Arrows.erase(lastPos);
|
||||
m_Arrows[newPos] = arrowCopy;
|
||||
emit ArrowMove(lastPos, arrow);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((dPos > 0) && (index < (m_Arrows.size() - 1)))
|
||||
{
|
||||
qreal posAfter = std::next(it)->first;
|
||||
|
||||
if ((lastPos + maxMove + dPos) >= posAfter)
|
||||
return;
|
||||
}
|
||||
|
||||
GradientArrow arrowCopy(it->second);
|
||||
m_Arrows.erase(lastPos);
|
||||
m_Arrows[newPos] = arrowCopy;
|
||||
emit ArrowMove(lastPos, arrow);
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
else if (m_ColorIndexArrowMoving)
|
||||
{
|
||||
for (auto& it : m_ColorIndicesArrows)
|
||||
{
|
||||
auto& arrow = it.second.second;
|
||||
|
||||
index++;
|
||||
if (arrow.Focus())
|
||||
{
|
||||
qreal lastPos = it.second.first;
|
||||
qreal start = m_DragStart.x();
|
||||
qreal end = RectWidth();
|
||||
qreal dPos = ((qreal)e->pos().x() - start) / end;
|
||||
qreal newPos = lastPos + dPos;
|
||||
|
||||
if ((lastPos + dPos > 1) || (lastPos + dPos < 0))
|
||||
return;
|
||||
|
||||
it.second.first = newPos;
|
||||
emit ColorIndexMove(it.first, it.second.first);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_DragStart = e->pos();
|
||||
@ -582,6 +689,7 @@ void GradientColorsView::mouseMoveEvent(QMouseEvent* e)
|
||||
void GradientColorsView::mouseReleaseEvent(QMouseEvent*)
|
||||
{
|
||||
m_ArrowMoving = false;
|
||||
m_ColorIndexArrowMoving = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -589,42 +697,25 @@ void GradientColorsView::mouseReleaseEvent(QMouseEvent*)
|
||||
/// </summary>
|
||||
void GradientColorsView::resizeEvent(QResizeEvent*)
|
||||
{
|
||||
m_ViewRect = QRect(QPoint(5, 0), QPoint(width() - 15, height() / 3 * 2 - 10));
|
||||
m_ViewRect.translate(5, 5);
|
||||
m_ViewRectSize = QPoint(RectWidth(), RectHeight());
|
||||
m_ViewRect = QRect(m_ViewRectOffset, QPoint(m_ViewRectSize.x() + 5, m_ViewRectSize.y() - 10));
|
||||
m_ViewRect.translate(m_ViewRectTranslate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the background to represent the palette.
|
||||
/// Return the width used to draw the gradient area.
|
||||
/// </summary>
|
||||
/// <param name="vertLineSpace">The space between vertical lines to use</param>
|
||||
/// <param name="horLineSpace">The space between horizontal lines to use</param>
|
||||
void GradientColorsView::CreateBackground(int vertLineSpace, int horLineSpace)
|
||||
/// <returns>The width</returns>
|
||||
int GradientColorsView::RectWidth()
|
||||
{
|
||||
m_BackgroundVerSpace = vertLineSpace;
|
||||
m_BackgroundHorSpace = horLineSpace;
|
||||
m_Background = make_unique<QPixmap>(QSize(800, 800));
|
||||
m_Background->fill(Qt::white);
|
||||
QPainter painter(m_Background.get());
|
||||
int x = 0;
|
||||
|
||||
while (x < m_Background->width())//Veritcal lines.
|
||||
{
|
||||
const QPoint lineStart(x, 0);
|
||||
const QPoint lineStop(x, m_Background->height());
|
||||
painter.drawLine(lineStart, lineStop);
|
||||
x += vertLineSpace;
|
||||
}
|
||||
|
||||
int y = 0;
|
||||
|
||||
while (y < m_Background->height())//Horizontal lines.
|
||||
{
|
||||
const QPoint lineStart(0, y);
|
||||
const QPoint lineStop(m_Background->width(), y);
|
||||
painter.drawLine(lineStart, lineStop);
|
||||
y += horLineSpace;
|
||||
}
|
||||
|
||||
painter.end();
|
||||
update();
|
||||
return width() - 20;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the height used to draw the gradient area.
|
||||
/// </summary>
|
||||
/// <returns>The height</returns>
|
||||
int GradientColorsView::RectHeight()
|
||||
{
|
||||
return height() / 3 * 2;
|
||||
}
|
||||
|
@ -50,14 +50,16 @@ public:
|
||||
void SetArrows(map<float, GradientArrow>& newArrows);
|
||||
int ArrowCount();
|
||||
int GetFocusedIndex();
|
||||
QPixmap* GetBackGround();
|
||||
map<float, GradientArrow>& GetArrows();
|
||||
Palette<float>& GetPalette(int size);
|
||||
void SetPalette(const Palette<float>& palette);
|
||||
map<size_t, float> GetColorIndices() const;
|
||||
void SetColorIndices(const map<size_t, float>& indices);
|
||||
|
||||
signals:
|
||||
Q_SIGNALS:
|
||||
void ArrowMove(qreal lastPos, const GradientArrow& arrow);
|
||||
void ArrowDoubleClicked(const GradientArrow& arrow);
|
||||
void ColorIndexMove(size_t index, float value);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
@ -68,13 +70,17 @@ protected:
|
||||
virtual void resizeEvent(QResizeEvent*) override;
|
||||
|
||||
private:
|
||||
void CreateBackground(int vertLineSpace = 5, int horLineSpace = 5);
|
||||
int RectWidth();
|
||||
int RectHeight();
|
||||
bool m_ArrowMoving = false;
|
||||
int m_BackgroundVerSpace = 5;
|
||||
int m_BackgroundHorSpace = 5;
|
||||
bool m_ColorIndexArrowMoving = false;
|
||||
QPoint m_ViewRectSize;
|
||||
QPoint m_ViewRectOffset = QPoint(5, 15);
|
||||
QPoint m_ViewRectTranslate = QPoint(5, 5);
|
||||
QRect m_ViewRect;
|
||||
QPoint m_DragStart;
|
||||
unique_ptr<QPixmap> m_Background;
|
||||
map<float, GradientArrow> m_Arrows;
|
||||
map<size_t, pair<float, TopArrow>> m_ColorIndicesArrows;
|
||||
Palette<float> m_Palette;
|
||||
QPixmap m_FinalFixedPixmap;
|
||||
};
|
||||
|
@ -27,6 +27,7 @@ PaletteEditor::PaletteEditor(QWidget* p) :
|
||||
connect(m_ColorPicker, SIGNAL(ColorChanged(const QColor&)), this, SLOT(OnColorPickerColorChanged(const QColor&)));
|
||||
connect(m_GradientColorView, SIGNAL(ArrowMove(qreal, const GradientArrow&)), this, SLOT(OnArrowMoved(qreal, const GradientArrow&)));
|
||||
connect(m_GradientColorView, SIGNAL(ArrowDoubleClicked(const GradientArrow&)), this, SLOT(OnArrowDoubleClicked(const GradientArrow&)));
|
||||
connect(m_GradientColorView, SIGNAL(ColorIndexMove(size_t, float)), this, SLOT(OnColorIndexMove(size_t, float)));
|
||||
connect(ui->CreatePaletteFromImageButton, SIGNAL(clicked()), this, SLOT(OnCreatePaletteFromImageButtonClicked()));
|
||||
connect(ui->CreatePaletteAgainFromImageButton, SIGNAL(clicked()), this, SLOT(OnCreatePaletteAgainFromImageButton()));
|
||||
connect(ui->AddColorButton, SIGNAL(clicked()), this, SLOT(OnAddColorButtonClicked()));
|
||||
@ -54,11 +55,8 @@ PaletteEditor::PaletteEditor(QWidget* p) :
|
||||
|
||||
for (auto& pal : pals)
|
||||
{
|
||||
if (m_PaletteList->IsModifiable(pal.first))//Only add user created palettes.
|
||||
{
|
||||
QFileInfo info(QString::fromStdString(pal.first));
|
||||
ui->PaletteFilenameCombo->addItem(info.fileName());
|
||||
}
|
||||
QFileInfo info(QString::fromStdString(pal.first));
|
||||
ui->PaletteFilenameCombo->addItem(info.fileName());
|
||||
}
|
||||
|
||||
if (ui->PaletteFilenameCombo->count() > 0)
|
||||
@ -74,15 +72,6 @@ bool PaletteEditor::Sync()
|
||||
return ui->SyncCheckBox->isChecked();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a pointer to the palette pixmap from the underlying gradient color view.
|
||||
/// </summary>
|
||||
/// <returns>QPixmap*</returns>
|
||||
QPixmap* PaletteEditor::GetBackGround()
|
||||
{
|
||||
return m_GradientColorView->GetBackGround();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate and retrieve a reference to the palette from the underlying gradient color view
|
||||
/// using the specified number of elements.
|
||||
@ -96,23 +85,43 @@ Palette<float>& PaletteEditor::GetPalette(int size)
|
||||
|
||||
/// <summary>
|
||||
/// Set the palette of the underlying gradient color view.
|
||||
/// Note this assignment will only take place if
|
||||
/// the number of source colors is 2 or more.
|
||||
/// This will only be the case if it was a user created palette made here.
|
||||
/// All palettes gotten from elsewhere are not assignable.
|
||||
/// This can be a modifiable palette or a fixed one.
|
||||
/// </summary>
|
||||
/// <param name="palette">The palette to assign</param>
|
||||
void PaletteEditor::SetPalette(Palette<float>& palette)
|
||||
void PaletteEditor::SetPalette(const Palette<float>& palette)
|
||||
{
|
||||
if (palette.m_SourceColors.size() > 1)
|
||||
{
|
||||
m_PaletteIndex = std::numeric_limits<int>::max();
|
||||
m_GradientColorView->SetPalette(palette);
|
||||
auto& arrows = m_GradientColorView->GetArrows();
|
||||
auto combo = ui->PaletteFilenameCombo;
|
||||
m_PaletteIndex = std::numeric_limits<int>::max();
|
||||
m_GradientColorView->SetPalette(palette);
|
||||
auto& arrows = m_GradientColorView->GetArrows();
|
||||
|
||||
if (!arrows.empty())
|
||||
m_ColorPicker->SetColorPanelColor(arrows.begin()->second.Color());
|
||||
}
|
||||
if (!arrows.empty())
|
||||
m_ColorPicker->SetColorPanelColor(arrows.begin()->second.Color());//Will emit PaletteChanged() if color changed...
|
||||
|
||||
QFileInfo info(QString::fromStdString(*palette.m_Filename.get()));
|
||||
combo->setCurrentIndex(combo->findData(info.fileName(), Qt::DisplayRole));
|
||||
EnablePaletteControls();
|
||||
EmitPaletteChanged();//...So emit here just to be safe.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a temporary copy of the xform color indices as a map.
|
||||
/// The keys are the xform indices, and the values are the color indices.
|
||||
/// </summary>
|
||||
/// <param name="palette">The color indices</param>
|
||||
map<size_t, float> PaletteEditor::GetColorIndices() const
|
||||
{
|
||||
return m_GradientColorView->GetColorIndices();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assign the values of the xform color indices to the arrows.
|
||||
/// This will clear out any existing values first.
|
||||
/// </summary>
|
||||
/// <param name="palette">The color indices to assign</param>
|
||||
void PaletteEditor::SetColorIndices(const map<size_t, float>& indices)
|
||||
{
|
||||
m_GradientColorView->SetColorIndices(indices);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -229,7 +238,9 @@ void PaletteEditor::OnCreatePaletteAgainFromImageButton()
|
||||
void PaletteEditor::OnColorPickerColorChanged(const QColor& col)
|
||||
{
|
||||
m_GradientColorView->SetFocusColor(col);
|
||||
EmitPaletteChanged();
|
||||
|
||||
if (m_GradientColorView->ArrowCount())
|
||||
EmitPaletteChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -252,6 +263,7 @@ void PaletteEditor::OnArrowDoubleClicked(const GradientArrow& arrow)
|
||||
void PaletteEditor::OnSyncCheckBoxStateChanged(int state)
|
||||
{
|
||||
EmitPaletteChanged();
|
||||
EmitColorIndexChanged(std::numeric_limits<size_t>::max(), 0);//Pass special value to update all.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -268,7 +280,7 @@ void PaletteEditor::OnPaletteFilenameComboChanged(const QString& text)
|
||||
::FillPaletteTable(text.toStdString(), paletteTable, m_PaletteList);
|
||||
auto fullname = m_PaletteList->GetFullPathFromFilename(m_CurrentPaletteFilePath);
|
||||
ui->PaletteFilenameCombo->setToolTip(QString::fromStdString(fullname));
|
||||
OnPaletteCellClicked(0, 1);
|
||||
EnablePaletteFileControls();
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,8 +314,11 @@ void PaletteEditor::OnPaletteCellChanged(int row, int col)
|
||||
{
|
||||
if (auto palette = m_PaletteList->GetPaletteByFilename(m_CurrentPaletteFilePath, row))
|
||||
{
|
||||
palette->m_Name = ui->PaletteListTable->item(row, col)->text().toStdString();
|
||||
emit PaletteFileChanged();
|
||||
if (!palette->m_SourceColors.empty())
|
||||
{
|
||||
palette->m_Name = ui->PaletteListTable->item(row, col)->text().toStdString();
|
||||
emit PaletteFileChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -410,6 +425,17 @@ void PaletteEditor::OnArrowMoved(qreal, const GradientArrow&)
|
||||
EmitPaletteChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Emit an xform color index changed event.
|
||||
/// Called when one of the top arrows are moved.
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the xform whose color index has been changed. Special value of size_t max to update all</param>
|
||||
/// <param name="value">The value of the color index</param>
|
||||
void PaletteEditor::OnColorIndexMove(size_t index, float value)
|
||||
{
|
||||
EmitColorIndexChanged(index, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Emit a palette changed event if the sync checkbox is checked.
|
||||
/// </summary>
|
||||
@ -419,6 +445,17 @@ void PaletteEditor::EmitPaletteChanged()
|
||||
emit PaletteChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Emit an xform color index changed event if the sync checkbox is checked.
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the xform whose color index has been changed. Special value of size_t max to update all</param>
|
||||
/// <param name="value">The value of the color index</param>
|
||||
void PaletteEditor::EmitColorIndexChanged(size_t index, float value)
|
||||
{
|
||||
if (ui->SyncCheckBox->isChecked())
|
||||
emit ColorIndexChanged(index, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to lazily instantiate an open file dialog.
|
||||
/// Once created, it will remain alive for the duration of the program run.
|
||||
@ -514,3 +551,31 @@ map<float, GradientArrow> PaletteEditor::GetRandomColorsFromImage(QString filena
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable controls related to switching between modifiable and fixed palette files.
|
||||
/// </summary>
|
||||
void PaletteEditor::EnablePaletteFileControls()
|
||||
{
|
||||
bool b = m_PaletteList->IsModifiable(m_CurrentPaletteFilePath);//At least one in the file is not fixed.
|
||||
ui->DeletePaletteButton->setEnabled(b);
|
||||
ui->CopyPaletteFileButton->setEnabled(b);
|
||||
ui->AppendPaletteButton->setEnabled(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable controls related to switching between modifiable and fixed palettes.
|
||||
/// </summary>
|
||||
void PaletteEditor::EnablePaletteControls()
|
||||
{
|
||||
auto& palette = m_GradientColorView->GetPalette(256);
|
||||
bool b = !palette.m_SourceColors.empty();
|
||||
ui->OverwritePaletteButton->setEnabled(b);
|
||||
ui->AddColorButton->setEnabled(b);
|
||||
ui->DistributeColorsButton->setEnabled(b);
|
||||
ui->AutoDistributeCheckBox->setEnabled(b);
|
||||
ui->RandomColorsButton->setEnabled(b);
|
||||
ui->RemoveColorButton->setEnabled(b);
|
||||
ui->ResetColorsButton->setEnabled(b);
|
||||
ui->ArrowsSpinBox->setEnabled(b);
|
||||
}
|
@ -30,15 +30,17 @@ public:
|
||||
|
||||
public:
|
||||
bool Sync();
|
||||
QPixmap* GetBackGround();
|
||||
Palette<float>& GetPalette(int size);
|
||||
void SetPalette(Palette<float>& palette);
|
||||
void SetPalette(const Palette<float>& palette);
|
||||
map<size_t, float> GetColorIndices() const;
|
||||
void SetColorIndices(const map<size_t, float>& indices);
|
||||
|
||||
signals:
|
||||
Q_SIGNALS:
|
||||
void PaletteChanged();
|
||||
void PaletteFileChanged();
|
||||
void ColorIndexChanged(size_t index, float value);
|
||||
|
||||
private slots:
|
||||
private Q_SLOTS:
|
||||
void OnAddColorButtonClicked();
|
||||
void OnRemoveColorButtonClicked();
|
||||
void OnInvertColorsButtonClicked();
|
||||
@ -51,6 +53,7 @@ private slots:
|
||||
void OnArrowDoubleClicked(const GradientArrow& arrow);
|
||||
void OnSyncCheckBoxStateChanged(int state);
|
||||
void OnArrowMoved(qreal lastPos, const GradientArrow& arrow);
|
||||
void OnColorIndexMove(size_t index, float value);
|
||||
void OnPaletteFilenameComboChanged(const QString& text);
|
||||
void OnPaletteCellClicked(int row, int col);
|
||||
void OnPaletteCellChanged(int row, int col);
|
||||
@ -62,10 +65,12 @@ private slots:
|
||||
|
||||
private:
|
||||
void EmitPaletteChanged();
|
||||
void EmitColorIndexChanged(size_t index, float value);
|
||||
QStringList SetupOpenImagesDialog();
|
||||
void AddArrow(const QColor& color);
|
||||
map<float, GradientArrow> GetRandomColorsFromImage(QString filename, int numPoints);
|
||||
|
||||
void EnablePaletteFileControls();
|
||||
void EnablePaletteControls();
|
||||
bool m_PaletteFileChanged = false;
|
||||
int m_PaletteIndex = 0;
|
||||
QString m_Filename;
|
||||
|
Reference in New Issue
Block a user