mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-07-01 05:46:06 -04:00
--User changes:
-Show common folder locations such as documents, downloads, pictures in the sidebar in all file dialogs. -Warning message about exceeding memory in final render dialog now suggests strips as the solution to the problem. -Strips now has a tooltip explaining what it does. -Allow more digits in the spinners on the color section the flame tab. -Add manually adjustable size spinners in the final render dialog. Percentage scale and absolute size are fully synced. -Default prefix in final render is now the filename when doing animations (coming from sequence section of the library tab). -Changed the elliptic variation back to using a less precise version for float, and a more precise version for double. The last release had it always using double. -New applied xaos table that shows a read-only view of actual weights by taking the base xform weights and multiplying them by the xaos values. -New table in the xaos tab that gives a graphical representation of the probability that each xform is chosen, with and without xaos. -Add button to transpose the xaos rows and columns. -Add support for importing .chaos files from Chaotica. --Pasting back to Chaotica will work for most, but not all, variations due to incompatible parameter names in some. -Curves are now splines instead of Bezier. This adds compatibility with Chaotica, but breaks it for Apophysis. Xmls are still pastable, but the color curves will look different. --The curve editor on the palette tab can now add points by clicking on the lines and remove points by clicking on the points themselves, just like Chaotica. --Splines are saved in four new xml fields: overall_curve, red_curve, green_curve and blue_curve. -Allow for specifying the percentage of a sub batch each thread should iterate through per kernel call when running with OpenCL. This gives a roughly 1% performance increase due to having to make less kernel calls while iterating. --This field is present for interactive editing (where it's not very useful) and in the final render dialog. --On the command line, this is specified as --sbpctth for EmberRender and EmberAnimate. -Allow double clicking to toggle the supersample field in the flame tab between 1 and 2 for easily checking the effect of the field. -When showing affine values as polar coordinates, show angles normalized to 360 to match Chaotica. -Fuse Count spinner now toggles between 15 and 100 when double clicking for easily checking the effect of the field. -Added field for limiting the range in the x and y direction that the initial points are chosen from. -Added a field called K2 which is an alternative way to set brightness, ignored when zero. --This has no effect for many variations, but hs a noticeable effect for some. -Added new variations: arcsech arcsech2 arcsinh arctanh asteria block bwraps_rand circlecrop2 coth_spiral crackle2 depth_blur depth_blur2 depth_gaussian depth_gaussian2 depth_ngon depth_ngon2 depth_sine depth_sine2 dragonfire dspherical dust excinis exp2 flipx flowerdb foci_p gaussian glynnia2 glynnsim4 glynnsim5 henon henon hex_rand hex_truchet hypershift lazyjess lens lozi lozi modulusx modulusy oscilloscope2 point_symmetry pointsymmetry projective pulse rotate scry2 shift smartshape spher squares starblur2 swirl3 swirl3r tanh_spiral target0 target2 tile_hlp truchet_glyph truchet_inv truchet_knot unicorngaloshen vibration vibration2 --hex_truchet, hex_rand should always use double. They are extremely sensitive. --Bug fixes: -Bounds sign was flipped for x coordinate of world space when center was not zero. -Right clicking and dragging spinner showed menu on mouse up, even if it was very far away. -Text boxes for size in final render dialog were hard to type in. Same bug as xform weight used to be so fix the same way. -Fix spelling to be plural in toggle color speed box. -Stop using the blank user palette to generate flames. Either put colored palettes in it, or exclude it from randoms. -Clicking the random palette button for a palette file with only one palette in it would freeze the program. -Clicking none scale in final render did not re-render the preview. -Use less precision on random xaos. No need for 12 decimal places. -The term sub batch is overloaded in the options dialog. Change the naming and tooltip of those settings for cpu and opencl. --Also made clear in the tooltip for the default opencl quality setting that the value is per device. -The arrows spinner in palette editor appears like a read-only label. Made it look like a spinner. -Fix border colors for various spin boxes and table headers in the style sheet. Requires reload. -Fix a bug in the bwraps variation which would produce different results than Chaotica and Apophysis. -Synth was allowed to be selected for random flame generation when using an Nvidia card but it shouldn't have been because Nvidia has a hard time compiling synth. -A casting bug in the OpenCL kernels for log scaling and density filtering was preventing successful compilations on Intel iGPUs. Fixed even though we don't support anything other than AMD and Nvidia. -Palette rotation (click and drag) position was not being reset when loading a new flame. -When the xform circles were hidden, opening and closing the options dialog would improperly reshow them. -Double click toggle was broken on integer spin boxes. -Fixed tab order of some controls. -Creating a palette from a jpg in the palette editor only produced a single color. --Needed to package imageformats/qjpeg.dll with the Windows installer. -The basic memory benchmark test flame was not really testing memory. Make it more spread out. -Remove the temporal samples field from the flame tab, it was never used because it's only an animation parameter which is specified in the final render dialog or on the command line with EmberAnimate. --Code changes: -Add IsEmpty() to Palette to determine if a palette is all black. -Attempt to avoid selecting a blank palette in PaletteList::GetRandomPalette(). -Add function ScanForChaosNodes() and some associated helper functions in XmlToEmber. -Make variation param name correction be case insensitive in XmlToEmber. -Report error when assigning a variation param value in XmlToEmber. -Add SubBatchPercentPerThread() method to RendererCL. -Override enterEvent() and leaveEvent() in DoubleSpinBox and SpinBox to prevent the context menu from showing up on right mouse up after already leaving the spinner. -Filtering the mouse wheel event in TableWidget no longer appears to be needed. It was probably an old Qt bug that has been fixed. -Gui/ember syncing code in the final render dialog needed to be reworked to accommodate absolute sizes.
This commit is contained in:
@ -58,7 +58,7 @@
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.14</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a></p></body></html></string>
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.15</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
@ -104,7 +104,7 @@
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt; font-weight:400; font-style:normal;">
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.1pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Developers:</span></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Lead: </span><a href="http://www.fractorium.com"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Matt Feemster</span></a><span style=" font-size:10pt;"><br />Contributors: </span><a href="http://blog.highlyillogical.org/"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Simon Detheridge</span></a><span style=" font-size:10pt;">, </span><a href="https://www.deviantart.com/triptychaos"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Michel Mastriani.</span></a></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p>
|
||||
@ -114,8 +114,8 @@ p, li { white-space: pre-wrap; }
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Code and theory questions: </span><a href="https://github.com/scottdraves/flam3"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Erik Reckase</span></a><span style=" font-size:10pt;">, </span><a href="http://fractron9000.sourceforge.net/"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Mike Thiesen</span></a><span style=" font-size:10pt;">, </span><a href="https://github.com/scottdraves/flam3"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Scott Draves</span></a><span style=" font-size:10pt;">, </span><a href="https://github.com/stevenrobertson/cuburn"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Steve Robertson</span></a><span style=" font-size:10pt;">, </span><a href="http://www.chaoticafractals.com/"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Thomas Ludwig</span></a><span style=" font-size:10pt;">.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; font-weight:600;"><br /></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Code Copied:</span></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="https://github.com/scottdraves/flam3"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">flam3</span></a><span style=" font-size:10pt;">: Scott Draves, Erik Reckase (GPL v2)<br /></span><a href="http://github.com/stevenrobertson/cuburn"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">cuburn</span></a><span style=" font-size:10pt;">: Steven Robertson, Michael Semeniuk, Matthew Znoj, Nicolas Mejia (GPL v3)<br /></span><a href="http://fractron9000.sourceforge.net"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Fractron 9000</span></a><span style=" font-size:10pt;">: Mike Thiesen (GPL)<br /></span><a href="http://sourceforge.net/projects/apophysis7x"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Apophysis</span></a><span style=" font-size:10pt;">: Mark Townsend, Ronald Hordijk, Peter Sdobnov, Piotr Borys, Georg Kiehne (GPL)<br /></span><a href="http://jwildfire.org/"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">JWildfire</span></a><span style=" font-size:10pt;">: Andreas Maschke (LGPL)<br />gradLib: Stian Broen<br />ColorPickerWidget: Etienne Moutot<br />Numerous Apophysis plugin developers (GPL)</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="https://github.com/scottdraves/flam3"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">flam3</span></a><span style=" font-size:10pt;">: Scott Draves, Erik Reckase (GPL v2)<br /></span><a href="http://github.com/stevenrobertson/cuburn"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">cuburn</span></a><span style=" font-size:10pt;">: Steven Robertson, Michael Semeniuk, Matthew Znoj, Nicolas Mejia (GPL v3)<br /></span><a href="http://fractron9000.sourceforge.net"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Fractron 9000</span></a><span style=" font-size:10pt;">: Mike Thiesen (GPL)<br /></span><a href="http://sourceforge.net/projects/apophysis7x"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Apophysis</span></a><span style=" font-size:10pt;">: Mark Townsend, Ronald Hordijk, Peter Sdobnov, Piotr Borys, Georg Kiehne (GPL)<br /></span><a href="http://jwildfire.org/"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">JWildfire</span></a><span style=" font-size:10pt;">: Andreas Maschke (LGPL)<br />gradLib: Stian Broen<br />ColorPickerWidget: Etienne Moutot<br />Numerous Apophysis plugin developers (GPL)<br />Chaotica variations</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Libraries Linked:</span></p>
|
||||
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.qt.io/developers/"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Qt</span></a><span style=" font-size:10pt;">: Digia Plc (GPL v3, LGPL v2)<br /></span><a href="http://g-truc.net"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">glm</span></a><span style=" font-size:10pt;">: Christophe Riccio (MIT License)<br /></span><a href="http://threadingbuildingblocks.org"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Threading Building Blocks</span></a><span style=" font-size:10pt;">: Intel Corporation (GPLv2)<br /></span><a href="http://libjpeg.sourceforge.net"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">libjpeg</span></a><span style=" font-size:10pt;">: Independent JPEG Group (Free Software License)<br /></span><a href="http://libpng.org"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">libpng</span></a><span style=" font-size:10pt;">: Glenn Randers-Pehrson et al (Libpng License)<br /></span><a href="http://xmlsoft.org"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">libxml2</span></a><span style=" font-size:10pt;">: Daniel Veillard (MIT License)<br /></span><a href="http://zlib.net"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">zlib</span></a><span style=" font-size:10pt;">: Jean-loup Gailly, Mark Adler (Zlib License)<br /></span><a href="http://burtleburtle.net/bob/cplus/isaac.hpp"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">QTIsaac</span></a><span style=" font-size:10pt;">: Robert J. Jenkins, Quinn Tyler Jackson (Public Domain)<br /></span><a href="http://cas.ee.ic.ac.uk/people/dt10/research/rngs-gpu-mwc64x.html"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">MWC64X Random Number Generator</span></a><span style=" font-size:10pt;">: David Thomas (Public Domain)<br /></span><a href="https://github.com/brofield/simpleopt"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">SimpleOpt</span></a><span style=" font-size:10pt;">: Brodie Thiesfield (MIT License)</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p>
|
||||
|
@ -10,60 +10,21 @@ CurvesGraphicsView::CurvesGraphicsView(QWidget* parent)
|
||||
: QGraphicsView(parent)
|
||||
{
|
||||
m_Scene.setSceneRect(0, 0, 245, 245);
|
||||
|
||||
m_AllP1 = new EllipseItem(QRectF(-5, -5, 10, 10), 0, 1, this);
|
||||
m_AllP1->setBrush(QBrush(Qt::GlobalColor::black));
|
||||
m_AllP2 = new EllipseItem(QRectF(-5, -5, 10, 10), 0, 2, this);
|
||||
m_AllP2->setBrush(QBrush(Qt::GlobalColor::black));
|
||||
|
||||
m_RedP1 = new EllipseItem(QRectF(-5, -5, 10, 10), 1, 1, this);
|
||||
m_RedP1->setBrush(QBrush(Qt::GlobalColor::red));
|
||||
m_RedP2 = new EllipseItem(QRectF(-5, -5, 10, 10), 1, 2, this);
|
||||
m_RedP2->setBrush(QBrush(Qt::GlobalColor::red));
|
||||
|
||||
m_GrnP1 = new EllipseItem(QRectF(-5, -5, 10, 10), 2, 1, this);
|
||||
m_GrnP1->setBrush(QBrush(Qt::GlobalColor::green));
|
||||
m_GrnP2 = new EllipseItem(QRectF(-5, -5, 10, 10), 2, 2, this);
|
||||
m_GrnP2->setBrush(QBrush(Qt::GlobalColor::green));
|
||||
|
||||
m_BluP1 = new EllipseItem(QRectF(-5, -5, 10, 10), 3, 1, this);
|
||||
m_BluP1->setBrush(QBrush(Qt::GlobalColor::blue));
|
||||
m_BluP2 = new EllipseItem(QRectF(-5, -5, 10, 10), 3, 2, this);
|
||||
m_BluP2->setBrush(QBrush(Qt::GlobalColor::blue));
|
||||
|
||||
m_AxisPen = QPen(Qt::GlobalColor::white);
|
||||
m_XLine = new QGraphicsLineItem();
|
||||
m_XLine->setPen(m_AxisPen);
|
||||
m_XLine->setZValue(0);
|
||||
m_YLine = new QGraphicsLineItem();
|
||||
m_YLine->setPen(m_AxisPen);
|
||||
m_YLine->setZValue(0);
|
||||
|
||||
m_Scene.addItem(m_AllP1); m_Points[0].first = m_AllP1; m_AllP1->setZValue(2);
|
||||
m_Scene.addItem(m_AllP2); m_Points[0].second = m_AllP2; m_AllP2->setZValue(2);
|
||||
m_Scene.addItem(m_RedP1); m_Points[1].first = m_RedP1;
|
||||
m_Scene.addItem(m_RedP2); m_Points[1].second = m_RedP2;
|
||||
m_Scene.addItem(m_GrnP1); m_Points[2].first = m_GrnP1;
|
||||
m_Scene.addItem(m_GrnP2); m_Points[2].second = m_GrnP2;
|
||||
m_Scene.addItem(m_BluP1); m_Points[3].first = m_BluP1;
|
||||
m_Scene.addItem(m_BluP2); m_Points[3].second = m_BluP2;
|
||||
m_Scene.addItem(m_XLine);
|
||||
m_Scene.addItem(m_YLine);
|
||||
|
||||
m_APen = QPen(Qt::GlobalColor::black); m_Pens[0] = &m_APen;
|
||||
m_RPen = QPen(Qt::GlobalColor::red); m_Pens[1] = &m_RPen;
|
||||
m_GPen = QPen(Qt::GlobalColor::green); m_Pens[2] = &m_GPen;
|
||||
m_BPen = QPen(Qt::GlobalColor::blue); m_Pens[3] = &m_BPen;
|
||||
|
||||
m_APen.setWidth(2);
|
||||
m_RPen.setWidth(2);
|
||||
m_GPen.setWidth(2);
|
||||
m_BPen.setWidth(2);
|
||||
|
||||
setScene(&m_Scene);
|
||||
SetTop(CurveIndex::ALL);
|
||||
//qDebug() << "Original scene rect before setting anything is: " << sceneRect();
|
||||
m_OriginalRect = sceneRect();
|
||||
Curves<float> curves(true);
|
||||
Set(curves);
|
||||
show();
|
||||
//qDebug() << "Original scene rect is: " << m_OriginalRect;
|
||||
}
|
||||
@ -78,7 +39,6 @@ void CurvesGraphicsView::PointChanged(int curveIndex, int pointIndex, const QPoi
|
||||
{
|
||||
double x = point.x() / width();
|
||||
double y = (height() - point.y()) / height();
|
||||
|
||||
emit PointChangedSignal(curveIndex, pointIndex, QPointF(x, y));
|
||||
}
|
||||
|
||||
@ -86,14 +46,13 @@ void CurvesGraphicsView::PointChanged(int curveIndex, int pointIndex, const QPoi
|
||||
/// Get the position of a given point within a given curve.
|
||||
/// </summary>
|
||||
/// <param name="curveIndex">The curve whose point value will be retrieved, 0-3.</param>
|
||||
/// <param name="pointIndex">The point within the curve whose value will be retrieved, 1-2.</param>
|
||||
/// <param name="pointIndex">The point within the curve whose value will be retrieved, 0-3.</param>
|
||||
/// <returns>The position of the point. X,Y will each be within 0-1.</returns>
|
||||
QPointF CurvesGraphicsView::Get(int curveIndex, int pointIndex)
|
||||
{
|
||||
if (curveIndex < 4)
|
||||
if (curveIndex < 4 && pointIndex < m_Points[curveIndex].size())
|
||||
{
|
||||
EllipseItem* item = (pointIndex == 1) ? m_Points[curveIndex].first : m_Points[curveIndex].second;
|
||||
|
||||
EllipseItem* item = m_Points[curveIndex][pointIndex];
|
||||
return QPointF(item->pos().x() / width(), (height() - item->pos().y()) / height());
|
||||
}
|
||||
|
||||
@ -104,19 +63,50 @@ QPointF CurvesGraphicsView::Get(int curveIndex, int pointIndex)
|
||||
/// Set the position of a given point within a given curve.
|
||||
/// </summary>
|
||||
/// <param name="curveIndex">The curve whose point will be set, 0-3.</param>
|
||||
/// <param name="pointIndex">The point within the curve which will be set, 1-2</param>
|
||||
/// <param name="pointIndex">The point within the curve which will be set, 0-3</param>
|
||||
/// <param name="point">The position to set the point to. X,Y will each be within 0-1.</param>
|
||||
void CurvesGraphicsView::Set(int curveIndex, int pointIndex, const QPointF& point)
|
||||
{
|
||||
if (curveIndex < 4)
|
||||
if (curveIndex < 4 && pointIndex < m_Points[curveIndex].size())
|
||||
{
|
||||
if (pointIndex == 1)
|
||||
m_Points[curveIndex].first->setPos(point.x() * width(), (1.0 - point.y()) * height());//Scale to scene dimensions, Y axis is flipped.
|
||||
else
|
||||
m_Points[curveIndex].second->setPos(point.x() * width(), (1.0 - point.y()) * height());
|
||||
m_Points[curveIndex][pointIndex]->setPos(point.x() * width(), (1.0 - point.y()) * height());//Scale to scene dimensions, Y axis is flipped.
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesGraphicsView::Set(Curves<float>& curves)
|
||||
{
|
||||
m_Scene.clear();
|
||||
m_XLine = new QGraphicsLineItem();
|
||||
m_XLine->setPen(m_AxisPen);
|
||||
m_XLine->setZValue(0);
|
||||
m_YLine = new QGraphicsLineItem();
|
||||
m_YLine->setPen(m_AxisPen);
|
||||
m_YLine->setZValue(0);
|
||||
m_Scene.addItem(m_XLine);
|
||||
m_Scene.addItem(m_YLine);
|
||||
auto createpoints = [&](int index, vector<EllipseItem*>& items, Qt::GlobalColor col, int zval)
|
||||
{
|
||||
items.clear();
|
||||
m_Points[index].clear();
|
||||
|
||||
for (int i = 0; i < curves.m_Points[index].size(); i++)
|
||||
{
|
||||
auto item = new EllipseItem(QRectF(-5, -5, 10, 10), index, i, this);
|
||||
items.push_back(item);
|
||||
item->setBrush(QBrush(col));
|
||||
m_Scene.addItem(item);
|
||||
m_Points[index].push_back(item);
|
||||
item->setZValue(zval);
|
||||
QPointF point(curves.m_Points[index][i].x, curves.m_Points[index][i].y);
|
||||
Set(index, i, point);
|
||||
}
|
||||
};
|
||||
createpoints(0, m_AllP, Qt::GlobalColor::black, 2);
|
||||
createpoints(1, m_RedP, Qt::GlobalColor::red, 1);
|
||||
createpoints(2, m_GrnP, Qt::GlobalColor::green, 1);
|
||||
createpoints(3, m_BluP, Qt::GlobalColor::blue, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the topmost curve but setting its Z value.
|
||||
/// All other curves will get a value one less.
|
||||
@ -124,35 +114,36 @@ void CurvesGraphicsView::Set(int curveIndex, int pointIndex, const QPointF& poin
|
||||
/// <param name="curveIndex">The curve to set</param>
|
||||
void CurvesGraphicsView::SetTop(CurveIndex curveIndex)
|
||||
{
|
||||
size_t index;
|
||||
|
||||
switch (curveIndex)
|
||||
{
|
||||
case CurveIndex::ALL:
|
||||
index = 0;
|
||||
break;
|
||||
case CurveIndex::RED:
|
||||
index = 1;
|
||||
break;
|
||||
case CurveIndex::GREEN:
|
||||
index = 2;
|
||||
break;
|
||||
case CurveIndex::BLUE:
|
||||
default:
|
||||
index = 3;
|
||||
case CurveIndex::ALL:
|
||||
m_Index = 0;
|
||||
break;
|
||||
|
||||
case CurveIndex::RED:
|
||||
m_Index = 1;
|
||||
break;
|
||||
|
||||
case CurveIndex::GREEN:
|
||||
m_Index = 2;
|
||||
break;
|
||||
|
||||
case CurveIndex::BLUE:
|
||||
default:
|
||||
m_Index = 3;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
if (i == index)
|
||||
if (i == m_Index)
|
||||
{
|
||||
m_Points[i].first->setZValue(2);
|
||||
m_Points[i].second->setZValue(2);
|
||||
for (auto& p : m_Points[i])
|
||||
p->setZValue(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Points[i].first->setZValue(1);
|
||||
m_Points[i].second->setZValue(1);
|
||||
for (auto& p : m_Points[i])
|
||||
p->setZValue(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -164,50 +155,124 @@ void CurvesGraphicsView::SetTop(CurveIndex curveIndex)
|
||||
void CurvesGraphicsView::paintEvent(QPaintEvent* e)
|
||||
{
|
||||
QGraphicsView::paintEvent(e);
|
||||
|
||||
int i;
|
||||
QRectF rect = scene()->sceneRect();
|
||||
double w2 = width() / 2;
|
||||
double h2 = height() / 2;
|
||||
|
||||
//Draw axis lines.
|
||||
m_XLine->setLine(QLineF(0, h2, width(), h2));
|
||||
m_YLine->setLine(QLineF(w2, 0, w2, height()));
|
||||
|
||||
//This must be constructed every time and cannot be a member.
|
||||
QPainter painter(viewport());
|
||||
painter.setClipRect(rect);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
auto points = m_Points;
|
||||
|
||||
for (auto& p : points)
|
||||
{
|
||||
if (p.size() < 2)
|
||||
return;
|
||||
|
||||
std::sort(p.begin(), p.end(), [&](auto & lhs, auto & rhs) { return lhs->pos().x() < rhs->pos().x(); });
|
||||
}
|
||||
|
||||
//Create 4 new paths. These must be constructed every time and cannot be members.
|
||||
//Need to sort the points here first based on their x coordinate.
|
||||
QPainterPath paths[4] =
|
||||
{
|
||||
QPainterPath(mapFromScene(rect.bottomLeft())),
|
||||
QPainterPath(mapFromScene(rect.bottomLeft())),
|
||||
QPainterPath(mapFromScene(rect.bottomLeft())),
|
||||
QPainterPath(mapFromScene(rect.bottomLeft()))
|
||||
QPainterPath(points[0][0]->pos()),
|
||||
QPainterPath(points[1][0]->pos()),
|
||||
QPainterPath(points[2][0]->pos()),
|
||||
QPainterPath(points[3][0]->pos())
|
||||
};
|
||||
int topmost = 0;
|
||||
|
||||
//Draw paths for all but the topmost curve.
|
||||
//Construct paths or all curves, and draw them for all but the topmost curve.
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
paths[i].cubicTo(m_Points[i].first->pos(), m_Points[i].second->pos(), mapFromScene(rect.topRight()));
|
||||
vector<v2F> vals;
|
||||
vals.reserve(points[i].size());
|
||||
|
||||
if (m_Points[i].first->zValue() == 1)
|
||||
for (auto& p : points[i])
|
||||
vals.push_back({ p->pos().x(), p->pos().y() });
|
||||
Spline<float> spline(vals);
|
||||
|
||||
for (int j = 0; j < rect.width(); j++)
|
||||
{
|
||||
auto x = j;
|
||||
auto y = spline.Interpolate(x);
|
||||
paths[i].lineTo(QPointF(x, y));
|
||||
}
|
||||
|
||||
if (points[i][0]->zValue() == 1)
|
||||
{
|
||||
painter.setPen(*m_Pens[i]);
|
||||
painter.drawPath(paths[i]);
|
||||
}
|
||||
else
|
||||
topmost = i;
|
||||
}
|
||||
|
||||
//Draw the topmost curve.
|
||||
for (i = 0; i < 4; i++)
|
||||
painter.setPen(*m_Pens[topmost]);
|
||||
painter.drawPath(paths[topmost]);
|
||||
}
|
||||
|
||||
void CurvesGraphicsView::mousePressEvent(QMouseEvent* e)
|
||||
{
|
||||
QGraphicsView::mousePressEvent(e);
|
||||
auto thresh = devicePixelRatioF() * 2;
|
||||
auto findpoint = [&](int x, int y) -> int
|
||||
{
|
||||
if (m_Points[i].first->zValue() == 2)
|
||||
for (int i = 0; i < m_Points[m_Index].size(); i++)
|
||||
{
|
||||
painter.setPen(*m_Pens[i]);
|
||||
painter.drawPath(paths[i]);
|
||||
break;
|
||||
auto item = m_Points[m_Index][i];
|
||||
auto xdist = std::abs(item->pos().x() - x);
|
||||
auto ydist = std::abs(item->pos().y() - y);
|
||||
|
||||
if (xdist < thresh && ydist < thresh)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
if (e->button() == Qt::RightButton)//Right button does whole image rotation and scaling.
|
||||
{
|
||||
int i = findpoint(e->pos().x(), e->pos().y());
|
||||
|
||||
if (i != -1)
|
||||
emit PointRemovedSignal(m_Index, i);
|
||||
}
|
||||
else if (findpoint(e->pos().x(), e->pos().y()) == -1)
|
||||
{
|
||||
QRectF rect = scene()->sceneRect();
|
||||
auto points = m_Points[m_Index];
|
||||
|
||||
if (points.size() < 2)
|
||||
return;
|
||||
|
||||
std::sort(points.begin(), points.end(), [&](auto & lhs, auto & rhs) { return lhs->pos().x() < rhs->pos().x(); });
|
||||
vector<v2F> vals;
|
||||
vals.reserve(points.size());
|
||||
|
||||
for (auto& p : points)
|
||||
vals.push_back({ p->pos().x(), p->pos().y() });
|
||||
Spline<float> spline(vals);
|
||||
|
||||
for (int j = 0; j < rect.width(); j++)
|
||||
{
|
||||
auto y = spline.Interpolate(j);
|
||||
auto xdist = std::abs(j - e->pos().x());
|
||||
auto ydist = std::abs(y - e->pos().y());
|
||||
|
||||
if (xdist < thresh && ydist < thresh)
|
||||
{
|
||||
double x = e->pos().x() / (double)width();
|
||||
double y = (height() - e->pos().y()) / (double)height();
|
||||
emit PointAddedSignal(m_Index, QPointF(x, y));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -37,35 +37,37 @@ public:
|
||||
void PointChanged(int curveIndex, int pointIndex, const QPointF& point);
|
||||
QPointF Get(int curveIndex, int pointIndex);
|
||||
void Set(int curveIndex, int pointIndex, const QPointF& point);
|
||||
void Set(Curves<float>& curves);
|
||||
void SetTop(CurveIndex curveIndex);
|
||||
|
||||
Q_SIGNALS:
|
||||
void PointChangedSignal(int curveIndex, int pointIndex, const QPointF& point);
|
||||
void PointAddedSignal(size_t curveIndex, const QPointF& point);
|
||||
void PointRemovedSignal(size_t curveIndex, int pointIndex);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
virtual void mousePressEvent(QMouseEvent* e) override;
|
||||
|
||||
size_t m_Index = 0;
|
||||
QPen m_APen;
|
||||
QPen m_RPen;
|
||||
QPen m_GPen;
|
||||
QPen m_BPen;
|
||||
QPen m_AxisPen;
|
||||
EllipseItem* m_AllP1;
|
||||
EllipseItem* m_AllP2;
|
||||
EllipseItem* m_RedP1;
|
||||
EllipseItem* m_RedP2;
|
||||
EllipseItem* m_GrnP1;
|
||||
EllipseItem* m_GrnP2;
|
||||
EllipseItem* m_BluP1;
|
||||
EllipseItem* m_BluP2;
|
||||
std::vector<EllipseItem*> m_AllP;
|
||||
std::vector<EllipseItem*> m_RedP;
|
||||
std::vector<EllipseItem*> m_GrnP;
|
||||
std::vector<EllipseItem*> m_BluP;
|
||||
QGraphicsLineItem* m_XLine;
|
||||
QGraphicsLineItem* m_YLine;
|
||||
QPen* m_Pens[4];
|
||||
std::array<QPen*, 4> m_Pens;
|
||||
QGraphicsScene m_Scene;
|
||||
QRectF m_OriginalRect;
|
||||
std::pair<EllipseItem*, EllipseItem*> m_Points[4];
|
||||
std::array<std::vector<EllipseItem*>, 4> m_Points;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Derivation for draggable points needed to trigger an event whenever the item is changed.
|
||||
/// Custom drawing is also done to omit drawing a selection rectangle.
|
||||
@ -116,7 +118,7 @@ protected:
|
||||
|
||||
/// <summary>
|
||||
/// Overridden itemChange event to notify the parent control that it has moved.
|
||||
/// Movement is also restriced to the scene rect.
|
||||
/// Movement is also restricted to the scene rect.
|
||||
/// </summary>
|
||||
/// <param name="change">Action is only taken if this value equals ItemPositionChange</param>
|
||||
/// <param name="value">The new position. This will be clamped to the scene rect.</param>
|
||||
|
@ -184,6 +184,8 @@ bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
m_MouseDownPoint = m_MouseMovePoint = me->pos();
|
||||
StartTimer();
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
else if (!m_Settings->ToggleType() &&
|
||||
me->type() == QMouseEvent::MouseButtonRelease &&
|
||||
@ -191,12 +193,16 @@ bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
StopTimer();
|
||||
m_MouseDownPoint = m_MouseMovePoint = me->pos();
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
else if (!m_Settings->ToggleType() &&
|
||||
me->type() == QMouseEvent::MouseMove &&
|
||||
QGuiApplication::mouseButtons() & Qt::RightButton)
|
||||
{
|
||||
m_MouseMovePoint = me->pos();
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
else if (m_DoubleClick &&
|
||||
((!m_Settings->ToggleType() && e->type() == QMouseEvent::MouseButtonDblClick && me->button() == Qt::LeftButton) ||
|
||||
@ -207,6 +213,7 @@ bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
else
|
||||
setValue(m_DoubleClickNonZero);
|
||||
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -246,11 +253,13 @@ bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
}
|
||||
}
|
||||
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<QKeyEvent*>(e))
|
||||
{
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -378,6 +387,31 @@ SpecialDoubleSpinBox::SpecialDoubleSpinBox(QWidget* p, int h, double step)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when focus enters the spinner.
|
||||
/// When leaving the spinner, the context menu was disabled so it doesn't pop up on
|
||||
/// distant loctions on the screen when dragging with the right mouse button then releasing.
|
||||
/// So re-enable it here just to ensure whenever they focus this control, the menu works.
|
||||
/// </summary>
|
||||
/// <param name="e">The event</param>
|
||||
void SpecialDoubleSpinBox::enterEvent(QEvent* e)
|
||||
{
|
||||
this->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
DoubleSpinBox::enterEvent(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when focus leaves the spinner.
|
||||
/// When leaving the spinner, disable the context menu so it doesn't pop up on distant loctions on the screen
|
||||
/// when dragging with the right mouse button then releasing.
|
||||
/// </summary>
|
||||
/// <param name="e">The event</param>
|
||||
void SpecialDoubleSpinBox::leaveEvent(QEvent* e)
|
||||
{
|
||||
this->setContextMenuPolicy(Qt::PreventContextMenu);
|
||||
DoubleSpinBox::leaveEvent(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event filter for taking special action on right click events.
|
||||
/// </summary>
|
||||
|
@ -75,6 +75,8 @@ public:
|
||||
virtual ~SpecialDoubleSpinBox() { }
|
||||
|
||||
protected:
|
||||
virtual void enterEvent(QEvent* e) override;
|
||||
virtual void leaveEvent(QEvent* e) override;
|
||||
virtual bool eventFilter(QObject* o, QEvent* e) override;
|
||||
};
|
||||
|
||||
|
@ -35,14 +35,32 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
connect(ui.FinalRenderScaleWidthRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderScaleHeightRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderDeviceTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnDeviceTableCellChanged(int, int)), Qt::QueuedConnection);
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.FinalRenderSizeTable, this, row, 1, m_WidthScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnWidthScaleChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.FinalRenderSizeTable, this, row, 1, m_HeightScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHeightScaleChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
m_WidthScaleSpin->setDecimals(3);
|
||||
m_HeightScaleSpin->setDecimals(3);
|
||||
m_WidthScaleSpin->setSuffix(" ( )");
|
||||
m_HeightScaleSpin->setSuffix(" ( )");
|
||||
m_WidthScaleSpin->SmallStep(0.001);
|
||||
m_HeightScaleSpin->SmallStep(0.001);
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.FinalRenderSizeTable, this, row, -1, m_WidthScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnWidthScaleChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
SetupSpinner<SpinBox, int>(ui.FinalRenderSizeTable, this, row, -1, m_WidthSpin, spinHeight, 10, std::numeric_limits<int>::max(), 10, SIGNAL(valueChanged(int)), SLOT(OnWidthChanged(int)), true, 1920, 1920, 1920);
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.FinalRenderSizeTable, this, row, -1, m_HeightScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHeightScaleChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
SetupSpinner<SpinBox, int>(ui.FinalRenderSizeTable, this, row, -1, m_HeightSpin, spinHeight, 10, std::numeric_limits<int>::max(), 10, SIGNAL(valueChanged(int)), SLOT(OnHeightChanged(int)), true, 1080, 1080, 1080);
|
||||
int spinsize = 120;
|
||||
m_WidthScaleSpin->setDecimals(4);
|
||||
m_HeightScaleSpin->setDecimals(4);
|
||||
m_WidthScaleSpin->setFixedWidth(spinsize);
|
||||
m_HeightScaleSpin->setFixedWidth(spinsize);
|
||||
m_WidthScaleSpin->SmallStep(0.0001);
|
||||
m_HeightScaleSpin->SmallStep(0.0001);
|
||||
m_WidthSpin->setFixedWidth(spinsize);
|
||||
m_HeightSpin->setFixedWidth(spinsize);
|
||||
m_WidthSpinnerWidget = new DoubleIntSpinnerWidget(m_WidthScaleSpin, m_WidthSpin, ui.FinalRenderSizeTable);
|
||||
m_WidthSpinnerWidget->m_DoubleSpinBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
m_WidthSpinnerWidget->m_SpinBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
m_WidthSpinnerWidget->setMinimumWidth(spinsize);
|
||||
m_WidthSpinnerWidget->setMaximumWidth(spinsize);
|
||||
ui.FinalRenderSizeTable->setCellWidget(0, 1, m_WidthSpinnerWidget);
|
||||
//
|
||||
m_HeightSpinnerWidget = new DoubleIntSpinnerWidget(m_HeightScaleSpin, m_HeightSpin, ui.FinalRenderSizeTable);
|
||||
m_HeightSpinnerWidget->m_DoubleSpinBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
m_HeightSpinnerWidget->m_SpinBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
m_HeightSpinnerWidget->setMinimumWidth(spinsize);
|
||||
m_HeightSpinnerWidget->setMaximumWidth(spinsize);
|
||||
ui.FinalRenderSizeTable->setCellWidget(1, 1, m_HeightSpinnerWidget);
|
||||
row = 0;
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, 1000, 1000, 1000);
|
||||
SetupSpinner<SpinBox, int> (table, this, row, 1, m_TemporalSamplesSpin, spinHeight, 1, 5000, 50, SIGNAL(valueChanged(int)), SLOT(OnTemporalSamplesChanged(int)), true, 1000, 1000, 1000);
|
||||
@ -139,6 +157,7 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
ui.FinalRenderThreadPriorityComboBox->setCurrentIndex(Clamp<int>(m_Settings->FinalThreadPriority() / 25, 0, tpc));
|
||||
|
||||
#endif
|
||||
ui.FinalRenderOpenCLSubBatchPctSpin->setValue(m_Settings->FinalOpenCLSubBatchPct());
|
||||
m_QualitySpin->setValue(m_Settings->FinalQuality());
|
||||
m_TemporalSamplesSpin->setValue(m_Settings->FinalTemporalSamples());
|
||||
m_SupersampleSpin->setValue(m_Settings->FinalSupersample());
|
||||
@ -188,6 +207,7 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
w = SetTabOrder(this, w, ui.FinalRenderApplyToAllCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderThreadCountSpin);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderThreadPriorityComboBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderOpenCLSubBatchPctSpin);
|
||||
w = SetTabOrder(this, w, m_WidthScaleSpin);
|
||||
w = SetTabOrder(this, w, m_HeightScaleSpin);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderScaleNoneRadioButton);
|
||||
@ -260,6 +280,7 @@ int FractoriumFinalRenderDialog::ThreadPriority()
|
||||
return ui.FinalRenderThreadPriorityComboBox->currentIndex() * 25;
|
||||
}
|
||||
#endif
|
||||
double FractoriumFinalRenderDialog::OpenCLSubBatchPct() { return ui.FinalRenderOpenCLSubBatchPctSpin->value(); }
|
||||
double FractoriumFinalRenderDialog::WidthScale() { return m_WidthScaleSpin->value(); }
|
||||
double FractoriumFinalRenderDialog::HeightScale() { return m_HeightScaleSpin->value(); }
|
||||
double FractoriumFinalRenderDialog::Quality() { return m_QualitySpin->value(); }
|
||||
@ -294,6 +315,7 @@ FinalRenderGuiState FractoriumFinalRenderDialog::State()
|
||||
state.m_Devices = Devices();
|
||||
state.m_ThreadCount = ThreadCount();
|
||||
state.m_ThreadPriority = ThreadPriority();
|
||||
state.m_SubBatchPct = OpenCLSubBatchPct();
|
||||
state.m_WidthScale = WidthScale();
|
||||
state.m_HeightScale = HeightScale();
|
||||
state.m_Quality = Quality();
|
||||
@ -384,6 +406,7 @@ void FractoriumFinalRenderDialog::OnOpenCLCheckBoxStateChanged(int state)
|
||||
{
|
||||
bool checked = state == Qt::Checked;
|
||||
ui.FinalRenderDeviceTable->setEnabled(checked);
|
||||
ui.FinalRenderOpenCLSubBatchPctSpin->setEnabled(checked);
|
||||
ui.FinalRenderThreadCountSpin->setEnabled(!checked);
|
||||
ui.FinalRenderThreadPriorityLabel->setEnabled(!checked);
|
||||
ui.FinalRenderThreadPriorityComboBox->setEnabled(!checked);
|
||||
@ -462,11 +485,38 @@ void FractoriumFinalRenderDialog::OnApplyAllCheckBoxStateChanged(int state)
|
||||
/// <param name="d">Ignored</param>
|
||||
void FractoriumFinalRenderDialog::OnWidthScaleChanged(double d)
|
||||
{
|
||||
if (ui.FinalRenderKeepAspectCheckBox->isChecked() && m_Controller.get())
|
||||
m_HeightScaleSpin->SetValueStealth(m_WidthScaleSpin->value());
|
||||
if (m_Controller.get())
|
||||
{
|
||||
if (ui.FinalRenderKeepAspectCheckBox->isChecked())
|
||||
m_HeightScaleSpin->SetValueStealth(m_WidthScaleSpin->value());
|
||||
|
||||
if (SetMemory())
|
||||
m_Controller->SyncCurrentToSizeSpinners(false, true);
|
||||
if (SetMemory())
|
||||
m_Controller->SyncCurrentToSizeSpinners(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The width spinner was changed, recompute required memory.
|
||||
/// If the aspect ratio checkbox is checked, set the value of
|
||||
/// the height spinner as well to be in proportion.
|
||||
/// </summary>
|
||||
/// <param name="d">Ignored</param>
|
||||
void FractoriumFinalRenderDialog::OnWidthChanged(int d)
|
||||
{
|
||||
if (m_Controller.get())
|
||||
{
|
||||
m_Controller->SyncGuiToEmbers(m_WidthSpin->value(), m_HeightSpin->value());//Copy changed width value from gui to ember (height will be copied even though it hasn't changed).
|
||||
m_Controller->SyncCurrentToSizeSpinners(true, false, true, false);//Compute how much the original width had to be scaled by to equal the new width and put the value in the width scale spinner.
|
||||
|
||||
if (ui.FinalRenderKeepAspectCheckBox->isChecked())
|
||||
{
|
||||
m_HeightScaleSpin->SetValueStealth(m_WidthScaleSpin->value());//Make the height scale spinner match the newly computed width scale spinner.
|
||||
m_Controller->SyncGuiToEmbers(0, 0, false, true);//Scale height by the amount in the height scale spinner and assign the value to the ember height.
|
||||
m_Controller->SyncCurrentToSizeSpinners(false, true, false, true);//Copy new height value from the ember to the height spinner.
|
||||
}
|
||||
}
|
||||
|
||||
if (SetMemory()) {}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -477,11 +527,38 @@ void FractoriumFinalRenderDialog::OnWidthScaleChanged(double d)
|
||||
/// <param name="d">Ignored</param>
|
||||
void FractoriumFinalRenderDialog::OnHeightScaleChanged(double d)
|
||||
{
|
||||
if (ui.FinalRenderKeepAspectCheckBox->isChecked() && m_Controller.get())
|
||||
m_WidthScaleSpin->SetValueStealth(m_HeightScaleSpin->value());
|
||||
if (m_Controller.get())
|
||||
{
|
||||
if (ui.FinalRenderKeepAspectCheckBox->isChecked())
|
||||
m_WidthScaleSpin->SetValueStealth(m_HeightScaleSpin->value());
|
||||
|
||||
if (SetMemory())
|
||||
m_Controller->SyncCurrentToSizeSpinners(false, true);
|
||||
if (SetMemory())
|
||||
m_Controller->SyncCurrentToSizeSpinners(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The height spinner was changed, recompute required memory.
|
||||
/// If the aspect ratio checkbox is checked, set the value of
|
||||
/// the width spinner as well to be in proportion.
|
||||
/// </summary>
|
||||
/// <param name="d">Ignored</param>
|
||||
void FractoriumFinalRenderDialog::OnHeightChanged(int d)
|
||||
{
|
||||
if (m_Controller.get())
|
||||
{
|
||||
m_Controller->SyncGuiToEmbers(m_WidthSpin->value(), m_HeightSpin->value());//Copy changed height value from gui to ember (width will be copied even though it hasn't changed).
|
||||
m_Controller->SyncCurrentToSizeSpinners(true, false, false, true);//Compute how much the original height had to be scaled by to equal the new height and put the value in the height scale spinner.
|
||||
|
||||
if (ui.FinalRenderKeepAspectCheckBox->isChecked())
|
||||
{
|
||||
m_WidthScaleSpin->SetValueStealth(m_HeightScaleSpin->value());//Make the width scale spinner match the newly computed height scale spinner.
|
||||
m_Controller->SyncGuiToEmbers(0, 0, true, false);//Scale width by the amount in the width scale spinner and assign the value to the ember width.
|
||||
m_Controller->SyncCurrentToSizeSpinners(false, true, true, false);//Copy new width value from the ember to the width spinner.
|
||||
}
|
||||
}
|
||||
|
||||
if (SetMemory()) {}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -492,8 +569,9 @@ void FractoriumFinalRenderDialog::OnHeightScaleChanged(double d)
|
||||
void FractoriumFinalRenderDialog::OnKeepAspectCheckBoxStateChanged(int state)
|
||||
{
|
||||
if (state && m_Controller.get())
|
||||
m_HeightScaleSpin->SetValueStealth(m_WidthScaleSpin->value());
|
||||
m_HeightScaleSpin->setValue(m_WidthScaleSpin->value());
|
||||
|
||||
//m_HeightScaleSpin->SetValueStealth(m_WidthScaleSpin->value());
|
||||
SetMemory();
|
||||
}
|
||||
|
||||
@ -501,7 +579,7 @@ void FractoriumFinalRenderDialog::OnKeepAspectCheckBoxStateChanged(int state)
|
||||
/// The scaling method radio button selection was changed.
|
||||
/// </summary>
|
||||
/// <param name="checked">The state of the radio button</param>
|
||||
void FractoriumFinalRenderDialog::OnScaleRadioButtonChanged(bool checked)
|
||||
void FractoriumFinalRenderDialog::OnScaleRadioButtonChanged(bool checked)//This is wrong. Does not react when scale is switched back to zero. Fix!//TODO
|
||||
{
|
||||
if (checked)
|
||||
SetMemory();
|
||||
@ -714,6 +792,8 @@ void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
if (m_Controller.get() && m_Controller->m_Run)//On Linux, this event will be called when the main window minimized/maximized while rendering, so filter it out.
|
||||
return;
|
||||
|
||||
QString firstfile;
|
||||
|
||||
if (CreateControllerFromGUI(true))//Create controller if it does not exist, or if it does and the renderer is not running.
|
||||
{
|
||||
int index = int(m_Fractorium->m_Controller->Index()) + 1;
|
||||
@ -727,6 +807,7 @@ void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
ember.m_Supersample = m_Settings->FinalSupersample();
|
||||
ember.m_TemporalSamples = m_Settings->FinalTemporalSamples();
|
||||
});//Copy the whole file, will take about 0.2ms per ember in the file.
|
||||
firstfile = efi.m_Filename;
|
||||
#else
|
||||
Ember<float> ed;
|
||||
EmberFile<float> efi;
|
||||
@ -737,6 +818,7 @@ void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
ember.m_Supersample = m_Settings->FinalSupersample();
|
||||
ember.m_TemporalSamples = m_Settings->FinalTemporalSamples();
|
||||
});//Copy the whole file, will take about 0.2ms per ember in the file.
|
||||
firstfile = efi.m_Filename;
|
||||
#endif
|
||||
m_Controller->SetEmberFile(efi, true);//Move the temp file into the final render controller.
|
||||
ui.FinalRenderCurrentSpin->setMaximum(int(efi.Size()));
|
||||
@ -758,6 +840,7 @@ void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
ui.FinalRenderDoAllCheckBox->setChecked(true);
|
||||
ui.FinalRenderDoSequenceCheckBox->setChecked(true);
|
||||
ui.FinalRenderApplyToAllCheckBox->setChecked(true);
|
||||
m_PrefixEdit->setText(firstfile + "_");
|
||||
}
|
||||
|
||||
ui.FinalRenderTextOutput->clear();
|
||||
|
@ -73,6 +73,7 @@ public:
|
||||
uint Current();
|
||||
uint ThreadCount();
|
||||
int ThreadPriority();
|
||||
double OpenCLSubBatchPct();
|
||||
double WidthScale();
|
||||
double HeightScale();
|
||||
double Quality();
|
||||
@ -94,7 +95,9 @@ public slots:
|
||||
void OnCurrentSpinChanged(int d);
|
||||
void OnApplyAllCheckBoxStateChanged(int state);
|
||||
void OnWidthScaleChanged(double d);
|
||||
void OnWidthChanged(int d);
|
||||
void OnHeightScaleChanged(double d);
|
||||
void OnHeightChanged(int d);
|
||||
void OnKeepAspectCheckBoxStateChanged(int state);
|
||||
void OnScaleRadioButtonChanged(bool checked);
|
||||
void OnDeviceTableCellChanged(int row, int col);
|
||||
@ -127,7 +130,11 @@ private:
|
||||
int m_PathCellIndex;
|
||||
Timing m_RenderTimer;
|
||||
DoubleSpinBox* m_WidthScaleSpin;
|
||||
SpinBox* m_WidthSpin;
|
||||
DoubleSpinBox* m_HeightScaleSpin;
|
||||
SpinBox* m_HeightSpin;
|
||||
DoubleIntSpinnerWidget* m_WidthSpinnerWidget;
|
||||
DoubleIntSpinnerWidget* m_HeightSpinnerWidget;
|
||||
DoubleSpinBox* m_QualitySpin;
|
||||
SpinBox* m_TemporalSamplesSpin;
|
||||
SpinBox* m_SupersampleSpin;
|
||||
|
@ -418,11 +418,57 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="FinalRenderOpenCLSubBatchPctSpin">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>220</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The percentage of a sub batch to execute on each thread per kernel call when using OpenCL. Default: 0.025 (256 iters).</p><p>Increase this number for slightly faster render times.</p><p>Note that this can cause a crash and subsequent restart of the graphics driver if each kernel call takes too long. So reduce the value if you encounter such a problem.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Sub Batch Percent Per Thread </string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.250000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
@ -692,7 +738,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="TableWidget" name="FinalRenderParamsTable">
|
||||
<widget class="QTableWidget" name="FinalRenderParamsTable">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -890,6 +936,9 @@
|
||||
<property name="text">
|
||||
<string>Strips</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of sections to split rendering into. The first number is the value desired, and the second number in parentheses is the value actually used because it must divide evenly into the final image height.</p><p>Use this if you do not have enough memory to render a given size and supersample. You will know you are memory limited when you see a warning in the text box below.</p><p>Use this sparingly since the number of iterations required are scaled by the value in this field.</p></body></html></string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<property name="text">
|
||||
@ -913,6 +962,9 @@
|
||||
<property name="text">
|
||||
<string>Iterations</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The total number of iterations that will be done to complete a single image</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<property name="text">
|
||||
@ -1203,13 +1255,6 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TableWidget</class>
|
||||
<extends>QTableWidget</extends>
|
||||
<header>TableWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>FinalRenderEarlyClipCheckBox</tabstop>
|
||||
<tabstop>FinalRenderDoublePrecisionCheckBox</tabstop>
|
||||
@ -1221,13 +1266,18 @@
|
||||
<tabstop>FinalRenderDoSequenceCheckBox</tabstop>
|
||||
<tabstop>FinalRenderPng16BitCheckBox</tabstop>
|
||||
<tabstop>FinalRenderCurrentSpin</tabstop>
|
||||
<tabstop>FinalRenderStopButton</tabstop>
|
||||
<tabstop>FinalRenderStartButton</tabstop>
|
||||
<tabstop>FinalRenderThreadCountSpin</tabstop>
|
||||
<tabstop>FinalRenderThreadPriorityComboBox</tabstop>
|
||||
<tabstop>FinalRenderOpenCLSubBatchPctSpin</tabstop>
|
||||
<tabstop>FinalRenderApplyToAllCheckBox</tabstop>
|
||||
<tabstop>FinalRenderKeepAspectCheckBox</tabstop>
|
||||
<tabstop>FinalRenderScaleNoneRadioButton</tabstop>
|
||||
<tabstop>FinalRenderScaleWidthRadioButton</tabstop>
|
||||
<tabstop>FinalRenderScaleHeightRadioButton</tabstop>
|
||||
<tabstop>FinalRenderScaleNoneRadioButton</tabstop>
|
||||
<tabstop>FinalRenderKeepAspectCheckBox</tabstop>
|
||||
<tabstop>FinalRenderTextOutput</tabstop>
|
||||
<tabstop>FinalRenderStartButton</tabstop>
|
||||
<tabstop>FinalRenderPauseButton</tabstop>
|
||||
<tabstop>FinalRenderStopButton</tabstop>
|
||||
<tabstop>FinalRenderCloseButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
|
@ -368,6 +368,7 @@ template <typename T> void FinalRenderEmberController<T>::CopyEmberFile(EmberFil
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="index">The index in the file from which to retrieve the ember</param>
|
||||
/// <param name="verbatim">Unused</param>
|
||||
template <typename T>
|
||||
void FinalRenderEmberController<T>::SetEmber(size_t index, bool verbatim)
|
||||
{
|
||||
@ -420,6 +421,7 @@ bool FinalRenderEmberController<T>::Render()
|
||||
/// </summary>
|
||||
/// <param name="renderType">The type of render to create</param>
|
||||
/// <param name="devices">The platform,device index pairs of the devices to use</param>
|
||||
/// <param name="updatePreviews">Unused</param>
|
||||
/// <param name="shared">True if shared with OpenGL, else false. Always false in this case.</param>
|
||||
/// <returns>True if nothing went wrong, else false.</returns>
|
||||
template <typename T>
|
||||
@ -477,7 +479,7 @@ bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, con
|
||||
/// Note this is only called on the primary renderer.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember currently being rendered</param>
|
||||
/// <param name="foo">An extra dummy parameter</param>
|
||||
/// <param name="foo">An extra dummy parameter, unused.</param>
|
||||
/// <param name="fraction">The progress fraction from 0-100</param>
|
||||
/// <param name="stage">The stage of iteration. 1 is iterating, 2 is density filtering, 2 is final accumulation.</param>
|
||||
/// <param name="etaMs">The estimated milliseconds to completion of the current stage</param>
|
||||
@ -527,17 +529,19 @@ void FinalRenderEmberController<T>::SyncCurrentToGui()
|
||||
/// </summary>
|
||||
/// <param name="widthOverride">Width override to use instead of scaling the original width</param>
|
||||
/// <param name="heightOverride">Height override to use instead of scaling the original height</param>
|
||||
/// <param name="dowidth">Whether to apply width adjustment to the ember</param>
|
||||
/// <param name="doheight">Whether to apply height adjustment to the ember</param>
|
||||
template <typename T>
|
||||
void FinalRenderEmberController<T>::SyncGuiToEmbers(size_t widthOverride, size_t heightOverride)
|
||||
void FinalRenderEmberController<T>::SyncGuiToEmbers(size_t widthOverride, size_t heightOverride, bool dowidth, bool doheight)
|
||||
{
|
||||
if (m_FinalRenderDialog->ApplyToAll())
|
||||
{
|
||||
for (auto& ember : m_EmberFile.m_Embers)
|
||||
SyncGuiToEmber(ember, widthOverride, heightOverride);
|
||||
SyncGuiToEmber(ember, widthOverride, heightOverride, dowidth, doheight);
|
||||
}
|
||||
else
|
||||
{
|
||||
SyncGuiToEmber(*m_Ember, widthOverride, heightOverride);
|
||||
SyncGuiToEmber(*m_Ember, widthOverride, heightOverride, dowidth, doheight);
|
||||
}
|
||||
}
|
||||
|
||||
@ -556,6 +560,9 @@ bool FinalRenderEmberController<T>::SyncGuiToRenderer()
|
||||
m_Renderer->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_Renderer->ThreadCount(m_FinalRenderDialog->ThreadCount());
|
||||
m_Renderer->Priority((eThreadPriority)m_FinalRenderDialog->ThreadPriority());
|
||||
|
||||
if (auto rendererCL = dynamic_cast<RendererCL<T, float>*>(m_Renderer.get()))
|
||||
rendererCL->SubBatchPercentPerThread(m_FinalRenderDialog->OpenCLSubBatchPct());
|
||||
}
|
||||
else if (!m_Renderers.empty())
|
||||
{
|
||||
@ -566,6 +573,9 @@ bool FinalRenderEmberController<T>::SyncGuiToRenderer()
|
||||
m_Renderers[i]->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_Renderers[i]->ThreadCount(m_FinalRenderDialog->ThreadCount());
|
||||
m_Renderers[i]->Priority((eThreadPriority)m_FinalRenderDialog->ThreadPriority());
|
||||
|
||||
if (auto rendererCL = dynamic_cast<RendererCL<T, float>*>(m_Renderers[i].get()))
|
||||
rendererCL->SubBatchPercentPerThread(m_FinalRenderDialog->OpenCLSubBatchPct());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -583,19 +593,27 @@ bool FinalRenderEmberController<T>::SyncGuiToRenderer()
|
||||
/// </summary>
|
||||
/// <param name="scale">Whether to update the scale values</param>
|
||||
/// <param name="size">Whether to update the size suffix text</param>
|
||||
/// <param name="dowidth">Whether to apply width value to the width scale spinner</param>
|
||||
/// <param name="doheight">Whether to apply height value to the height scale spinner</param>
|
||||
template <typename T>
|
||||
void FinalRenderEmberController<T>::SyncCurrentToSizeSpinners(bool scale, bool size)
|
||||
void FinalRenderEmberController<T>::SyncCurrentToSizeSpinners(bool scale, bool size, bool doWidth, bool doHeight)
|
||||
{
|
||||
if (scale)
|
||||
{
|
||||
m_FinalRenderDialog->m_WidthScaleSpin->SetValueStealth(double(m_Ember->m_FinalRasW) / m_Ember->m_OrigFinalRasW);//Work backward to determine the scale.
|
||||
m_FinalRenderDialog->m_HeightScaleSpin->SetValueStealth(double(m_Ember->m_FinalRasH) / m_Ember->m_OrigFinalRasH);
|
||||
if (doWidth)
|
||||
m_FinalRenderDialog->m_WidthScaleSpin->SetValueStealth(double(m_Ember->m_FinalRasW) / m_Ember->m_OrigFinalRasW);//Work backward to determine the scale.
|
||||
|
||||
if (doHeight)
|
||||
m_FinalRenderDialog->m_HeightScaleSpin->SetValueStealth(double(m_Ember->m_FinalRasH) / m_Ember->m_OrigFinalRasH);
|
||||
}
|
||||
|
||||
if (size)
|
||||
{
|
||||
m_FinalRenderDialog->m_WidthScaleSpin->setSuffix(" (" + ToString<qulonglong>(m_Ember->m_FinalRasW) + ")");
|
||||
m_FinalRenderDialog->m_HeightScaleSpin->setSuffix(" (" + ToString<qulonglong>(m_Ember->m_FinalRasH) + ")");
|
||||
if (doWidth)
|
||||
m_FinalRenderDialog->m_WidthSpinnerWidget->m_SpinBox->SetValueStealth(m_Ember->m_FinalRasW);
|
||||
|
||||
if (doHeight)
|
||||
m_FinalRenderDialog->m_HeightSpinnerWidget->m_SpinBox->SetValueStealth(m_Ember->m_FinalRasH);
|
||||
}
|
||||
}
|
||||
|
||||
@ -800,7 +818,7 @@ void FinalRenderEmberController<T>::HandleFinishedProgress()
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember currently being rendered</param>
|
||||
/// <param name="stats">The renderer stats</param>
|
||||
/// <param name="pixels">The timer which was started at the beginning of the render</param>
|
||||
/// <param name="renderTimer">The timer which was started at the beginning of the render</param>
|
||||
template<typename T>
|
||||
void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberStats& stats, Timing& renderTimer)
|
||||
{
|
||||
@ -845,6 +863,7 @@ void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberS
|
||||
m_Settings->FinalExt(m_GuiState.m_Ext);
|
||||
m_Settings->FinalThreadCount(m_GuiState.m_ThreadCount);
|
||||
m_Settings->FinalThreadPriority(m_GuiState.m_ThreadPriority);
|
||||
m_Settings->FinalOpenCLSubBatchPct(m_GuiState.m_SubBatchPct);
|
||||
m_Settings->FinalQuality(m_GuiState.m_Quality);
|
||||
m_Settings->FinalTemporalSamples(m_GuiState.m_TemporalSamples);
|
||||
m_Settings->FinalSupersample(m_GuiState.m_Supersample);
|
||||
@ -860,8 +879,10 @@ void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberS
|
||||
/// <param name="ember">The ember whose values will be modified</param>
|
||||
/// <param name="widthOverride">Width override to use instead of scaling the original width</param>
|
||||
/// <param name="heightOverride">Height override to use instead of scaling the original height</param>
|
||||
/// <param name="dowidth">Whether to use the computed/overridden width value, or use the existing value in the ember</param>
|
||||
/// <param name="doheight">Whether to use the computed/overridden height value, or use the existing value in the ember</param>
|
||||
template <typename T>
|
||||
void FinalRenderEmberController<T>::SyncGuiToEmber(Ember<T>& ember, size_t widthOverride, size_t heightOverride)
|
||||
void FinalRenderEmberController<T>::SyncGuiToEmber(Ember<T>& ember, size_t widthOverride, size_t heightOverride, bool dowidth, bool doheight)
|
||||
{
|
||||
size_t w;
|
||||
size_t h;
|
||||
@ -879,8 +900,8 @@ void FinalRenderEmberController<T>::SyncGuiToEmber(Ember<T>& ember, size_t width
|
||||
h = ember.m_OrigFinalRasH * hScale;
|
||||
}
|
||||
|
||||
w = std::max<size_t>(w, 10);
|
||||
h = std::max<size_t>(h, 10);
|
||||
w = dowidth ? std::max<size_t>(w, 10) : ember.m_FinalRasW;
|
||||
h = doheight ? std::max<size_t>(h, 10) : ember.m_FinalRasH;
|
||||
ember.SetSizeAndAdjustScale(w, h, false, m_FinalRenderDialog->Scale());
|
||||
ember.m_Quality = m_FinalRenderDialog->m_QualitySpin->value();
|
||||
ember.m_Supersample = m_FinalRenderDialog->m_SupersampleSpin->value();
|
||||
@ -973,7 +994,7 @@ QString FinalRenderEmberController<T>::CheckMemory(const tuple<size_t, size_t, s
|
||||
}
|
||||
|
||||
if (!s.isEmpty())
|
||||
s += "Rendering will most likely fail.";
|
||||
s += "Rendering will most likely fail.\n\nMake strips > 1 to fix this. Strips must divide into the height evenly, and will also scale the number of iterations performed.";
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ struct FinalRenderGuiState
|
||||
QList<QVariant> m_Devices;
|
||||
uint m_ThreadCount;
|
||||
int m_ThreadPriority;
|
||||
double m_SubBatchPct;
|
||||
double m_WidthScale;
|
||||
double m_HeightScale;
|
||||
double m_Quality;
|
||||
@ -62,8 +63,8 @@ public:
|
||||
virtual ~FinalRenderEmberControllerBase() { }
|
||||
|
||||
virtual void SyncCurrentToGui() { }
|
||||
virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0) { }
|
||||
virtual void SyncCurrentToSizeSpinners(bool scale, bool size) { }
|
||||
virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true) { }
|
||||
virtual void SyncCurrentToSizeSpinners(bool scale, bool size, bool doWidth = true, bool doHeight = true) { }
|
||||
virtual void ResetProgress(bool total = true) { }
|
||||
virtual tuple<size_t, size_t, size_t> SyncAndComputeMemory() { return tuple<size_t, size_t, size_t>(0, 0, 0); }
|
||||
virtual double OriginalAspect() { return 1; }
|
||||
@ -120,8 +121,8 @@ public:
|
||||
|
||||
//Virtual functions overridden from FinalRenderEmberControllerBase.
|
||||
virtual void SyncCurrentToGui() override;
|
||||
virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0) override;
|
||||
virtual void SyncCurrentToSizeSpinners(bool scale, bool size) override;
|
||||
virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true) override;
|
||||
virtual void SyncCurrentToSizeSpinners(bool scale, bool size, bool doWidth = true, bool doHeight = true) override;
|
||||
virtual void ResetProgress(bool total = true) override;
|
||||
virtual tuple<size_t, size_t, size_t> SyncAndComputeMemory() override;
|
||||
virtual double OriginalAspect() override { return double(m_Ember->m_OrigFinalRasW) / m_Ember->m_OrigFinalRasH; }
|
||||
@ -141,7 +142,7 @@ protected:
|
||||
void SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<v4F>& pixels, size_t width, size_t height, bool png16Bit, bool transparency);
|
||||
void RenderComplete(Ember<T>& ember);
|
||||
void RenderComplete(Ember<T>& ember, const EmberStats& stats, Timing& renderTimer);
|
||||
void SyncGuiToEmber(Ember<T>& ember, size_t widthOverride = 0, size_t heightOverride = 0);
|
||||
void SyncGuiToEmber(Ember<T>& ember, size_t widthOverride = 0, size_t heightOverride = 0, bool dowidth = true, bool doheight = true);
|
||||
bool SyncGuiToRenderer();
|
||||
void SetProgressComplete(int val);
|
||||
|
||||
|
@ -53,6 +53,12 @@ Fractorium::Fractorium(QWidget* p)
|
||||
);
|
||||
}
|
||||
|
||||
m_Urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::DesktopLocation).first())
|
||||
<< QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::DownloadLocation).first())
|
||||
<< QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first())
|
||||
<< QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).first())
|
||||
<< QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).first())
|
||||
;
|
||||
m_FontSize = 9;
|
||||
m_VarSortMode = 1;//Sort by weight by default.
|
||||
m_PaletteSortMode = 0;//Sort by palette ascending by default.
|
||||
@ -238,6 +244,14 @@ Fractorium::~Fractorium()
|
||||
m_Controller->SaveCurrentFileOnShutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the URLs used to determine the icons that show up in the location bar in all file/folder dialogs.
|
||||
/// </summary>
|
||||
QList<QUrl> Fractorium::Urls()
|
||||
{
|
||||
return m_Urls;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the coordinate text in the status bar.
|
||||
/// </summary>
|
||||
@ -502,7 +516,7 @@ void Fractorium::dragEnterEvent(QDragEnterEvent* e)
|
||||
QFileInfo fileInfo(localFile);
|
||||
QString suf = fileInfo.suffix();
|
||||
|
||||
if (suf == "flam3" || suf == "flame" || suf == "xml")
|
||||
if (suf == "flam3" || suf == "flame" || suf == "xml" || suf == "chaos")
|
||||
{
|
||||
e->accept();
|
||||
break;
|
||||
@ -541,7 +555,7 @@ void Fractorium::dropEvent(QDropEvent* e)
|
||||
QFileInfo fileInfo(localFile);
|
||||
QString suf = fileInfo.suffix();
|
||||
|
||||
if (suf == "flam3" || suf == "flame" || suf == "xml")
|
||||
if (suf == "flam3" || suf == "flame" || suf == "xml" || suf == "chaos")
|
||||
filenames << localFile;
|
||||
}
|
||||
}
|
||||
@ -603,8 +617,9 @@ QStringList Fractorium::SetupOpenXmlDialog()
|
||||
connect(m_OpenFileDialog, &QFileDialog::filterSelected, [&](const QString & filter) { m_Settings->OpenXmlExt(filter); });
|
||||
m_OpenFileDialog->setFileMode(QFileDialog::ExistingFiles);
|
||||
m_OpenFileDialog->setAcceptMode(QFileDialog::AcceptOpen);
|
||||
m_OpenFileDialog->setNameFilter("flam3 (*.flam3);;flame (*.flame);;xml (*.xml)");
|
||||
m_OpenFileDialog->setNameFilter("flam3 (*.flam3);;flame (*.flame);;xml (*.xml);;chaos (*.chaos)");
|
||||
m_OpenFileDialog->setWindowTitle("Open Flame");
|
||||
m_OpenFileDialog->setSidebarUrls(m_Urls);
|
||||
}
|
||||
|
||||
QStringList filenames;
|
||||
@ -621,7 +636,7 @@ QStringList Fractorium::SetupOpenXmlDialog()
|
||||
|
||||
#else
|
||||
auto defaultFilter(m_Settings->OpenXmlExt());
|
||||
auto filenames = QFileDialog::getOpenFileNames(this, tr("Open Flame"), m_Settings->OpenFolder(), tr("flam3(*.flam3);; flame(*.flame);; fml(*.xml)"), &defaultFilter);
|
||||
auto filenames = QFileDialog::getOpenFileNames(this, tr("Open Flame"), m_Settings->OpenFolder(), tr("flam3(*.flam3);; flame(*.flame);; xml(*.xml);; chaos (*.chaos)"), &defaultFilter);
|
||||
m_Settings->OpenXmlExt(defaultFilter);
|
||||
|
||||
if (!filenames.empty())
|
||||
@ -659,6 +674,7 @@ QString Fractorium::SetupSaveXmlDialog(const QString& defaultFilename)
|
||||
});
|
||||
m_SaveFileDialog->setNameFilter("flam3 (*.flam3);;flame (*.flame);;xml (*.xml)");
|
||||
m_SaveFileDialog->setWindowTitle("Save flame as xml");
|
||||
m_SaveFileDialog->setSidebarUrls(m_Urls);
|
||||
}
|
||||
|
||||
QString filename;
|
||||
@ -714,6 +730,7 @@ QString Fractorium::SetupSaveImageDialog(const QString& defaultFilename)
|
||||
m_SaveImageDialog->setNameFilter(".jpg;;.png;;.exr");
|
||||
#endif
|
||||
m_SaveImageDialog->setWindowTitle("Save image");
|
||||
m_SaveImageDialog->setSidebarUrls(m_Urls);
|
||||
}
|
||||
|
||||
QString filename;
|
||||
@ -754,6 +771,7 @@ QString Fractorium::SetupSaveFolderDialog()
|
||||
m_FolderDialog->setFileMode(QFileDialog::Directory);
|
||||
m_FolderDialog->setOption(QFileDialog::ShowDirsOnly, true);
|
||||
m_FolderDialog->setWindowTitle("Save to folder");
|
||||
m_FolderDialog->setSidebarUrls(m_Urls);
|
||||
}
|
||||
|
||||
QString filename;
|
||||
@ -825,11 +843,11 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, m_DECurveSpin);
|
||||
w = SetTabOrder(this, w, m_SbsSpin);//Flame iteration.
|
||||
w = SetTabOrder(this, w, m_FuseSpin);
|
||||
w = SetTabOrder(this, w, m_RandRangeSpin);
|
||||
w = SetTabOrder(this, w, m_QualitySpin);
|
||||
w = SetTabOrder(this, w, m_SupersampleSpin);
|
||||
w = SetTabOrder(this, w, m_InterpTypeCombo);//Flame animation.
|
||||
w = SetTabOrder(this, w, m_AffineInterpTypeCombo);
|
||||
w = SetTabOrder(this, w, m_TemporalSamplesSpin);
|
||||
w = SetTabOrder(this, w, m_TemporalFilterWidthSpin);
|
||||
w = SetTabOrder(this, w, m_TemporalFilterTypeCombo);
|
||||
w = SetTabOrder(this, ui.LibraryTree, ui.SequenceStartCountSpinBox);//Library.
|
||||
@ -881,11 +899,11 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, m_PreY2Spin);
|
||||
w = SetTabOrder(this, w, m_PreO1Spin);
|
||||
w = SetTabOrder(this, w, m_PreO2Spin);
|
||||
w = SetTabOrder(this, w, ui.PreFlipVerticalButton);
|
||||
w = SetTabOrder(this, w, ui.PreCopyButton);
|
||||
w = SetTabOrder(this, w, ui.PreFlipVerticalButton);
|
||||
w = SetTabOrder(this, w, ui.PreResetButton);
|
||||
w = SetTabOrder(this, w, ui.PrePasteButton);
|
||||
w = SetTabOrder(this, w, ui.PreFlipHorizontalButton);
|
||||
w = SetTabOrder(this, w, ui.PrePasteButton);
|
||||
w = SetTabOrder(this, w, ui.PreRotate90CcButton);
|
||||
w = SetTabOrder(this, w, ui.PreRotateCcButton);
|
||||
w = SetTabOrder(this, w, ui.PreRotateCombo);
|
||||
@ -901,6 +919,7 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, ui.PreScaleUpButton);
|
||||
w = SetTabOrder(this, w, ui.PreRandomButton);
|
||||
w = SetTabOrder(this, w, ui.ShowPreAffineCurrentRadio);
|
||||
w = SetTabOrder(this, w, ui.ShowPreAffineSelectedRadio);
|
||||
w = SetTabOrder(this, w, ui.ShowPreAffineAllRadio);
|
||||
w = SetTabOrder(this, w, ui.SwapAffinesButton);
|
||||
w = SetTabOrder(this, w, ui.PostAffineGroupBox);
|
||||
@ -910,11 +929,11 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, m_PostY2Spin);
|
||||
w = SetTabOrder(this, w, m_PostO1Spin);
|
||||
w = SetTabOrder(this, w, m_PostO2Spin);
|
||||
w = SetTabOrder(this, w, ui.PostFlipVerticalButton);
|
||||
w = SetTabOrder(this, w, ui.PostCopyButton);
|
||||
w = SetTabOrder(this, w, ui.PostFlipVerticalButton);
|
||||
w = SetTabOrder(this, w, ui.PostResetButton);
|
||||
w = SetTabOrder(this, w, ui.PostPasteButton);
|
||||
w = SetTabOrder(this, w, ui.PostFlipHorizontalButton);
|
||||
w = SetTabOrder(this, w, ui.PostPasteButton);
|
||||
w = SetTabOrder(this, w, ui.PostRotate90CcButton);
|
||||
w = SetTabOrder(this, w, ui.PostRotateCcButton);
|
||||
w = SetTabOrder(this, w, ui.PostRotateCombo);
|
||||
@ -930,6 +949,7 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, ui.PostScaleUpButton);
|
||||
w = SetTabOrder(this, w, ui.PostRandomButton);
|
||||
w = SetTabOrder(this, w, ui.ShowPostAffineCurrentRadio);
|
||||
w = SetTabOrder(this, w, ui.ShowPostAffineSelectedRadio);
|
||||
w = SetTabOrder(this, w, ui.ShowPostAffineAllRadio);
|
||||
w = SetTabOrder(this, w, ui.PolarAffineCheckBox);
|
||||
w = SetTabOrder(this, w, ui.LocalPivotRadio);
|
||||
@ -940,6 +960,7 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, ui.RandomXaosButton);
|
||||
w = SetTabOrder(this, w, ui.AddLayerButton);
|
||||
w = SetTabOrder(this, w, ui.AddLayerSpinBox);
|
||||
w = SetTabOrder(this, w, ui.TransposeXaosButton);
|
||||
//Xforms xaos is done dynamically every time.
|
||||
w = SetTabOrder(this, ui.PaletteFilenameCombo, m_PaletteHueSpin);//Palette.
|
||||
w = SetTabOrder(this, w, m_PaletteContrastSpin);
|
||||
|
@ -99,6 +99,7 @@ public:
|
||||
bool DrawXforms();
|
||||
bool DrawImage();
|
||||
bool DrawGrid();
|
||||
QList<QUrl> Urls();
|
||||
|
||||
//Library.
|
||||
void SyncFileCountToSequenceCount();
|
||||
@ -214,6 +215,7 @@ public slots:
|
||||
void OnGammaThresholdChanged(double d);
|
||||
void OnVibrancyChanged(double d);
|
||||
void OnHighlightPowerChanged(double d);
|
||||
void OnK2Changed(double d);
|
||||
void OnBackgroundColorButtonClicked(bool checked);
|
||||
void OnColorSelected(const QColor& color);
|
||||
void OnPaletteModeComboCurrentIndexChanged(int index);
|
||||
@ -238,9 +240,9 @@ public slots:
|
||||
void OnDEFilterCurveWidthChanged(double d);
|
||||
void OnSbsChanged(int d);//Iteration.
|
||||
void OnFuseChanged(int d);
|
||||
void OnRandRangeChanged(double d);
|
||||
void OnQualityChanged(double d);
|
||||
void OnSupersampleChanged(int d);
|
||||
void OnTemporalSamplesChanged(int d);
|
||||
void OnAffineInterpTypeComboCurrentIndexChanged(int index);
|
||||
void OnInterpTypeComboCurrentIndexChanged(int index);
|
||||
|
||||
@ -299,7 +301,7 @@ public slots:
|
||||
void OnRandomColorIndicesButtonClicked(bool b);
|
||||
void OnToggleColorIndicesButtonClicked(bool b);
|
||||
void OnRandomColorSpeedButtonClicked(bool b);
|
||||
void OnToggleColorSpeedButtonClicked(bool b);
|
||||
void OnToggleColorSpeedsButtonClicked(bool b);
|
||||
|
||||
void OnXformColorSpeedChanged(double d);
|
||||
void OnXformOpacityChanged(double d);
|
||||
@ -308,6 +310,8 @@ public slots:
|
||||
void OnXformRefPaletteResized(int logicalIndex, int oldSize, int newSize);
|
||||
void OnResetCurvesButtonClicked(bool checked);
|
||||
void OnCurvesPointChanged(int curveIndex, int pointIndex, const QPointF& point);
|
||||
void OnCurvesPointAdded(size_t curveIndex, const QPointF& point);
|
||||
void OnCurvesPointRemoved(size_t curveIndex, int pointIndex);
|
||||
void OnCurvesAllRadioButtonToggled(bool checked);
|
||||
void OnCurvesRedRadioButtonToggled(bool checked);
|
||||
void OnCurvesGreenRadioButtonToggled(bool checked);
|
||||
@ -330,8 +334,11 @@ public slots:
|
||||
void OnClearXaosButtonClicked(bool checked);
|
||||
void OnRandomXaosButtonClicked(bool checked);
|
||||
void OnAddLayerButtonClicked(bool checked);
|
||||
void OnTransposeXaosButtonClicked(bool checked);
|
||||
void OnXaosRowDoubleClicked(int logicalIndex);
|
||||
void OnXaosColDoubleClicked(int logicalIndex);
|
||||
void OnXaosHScrollValueChanged(int value);
|
||||
void OnXaosVScrollValueChanged(int value);
|
||||
void OnXaosTableModelDataChanged(const QModelIndex& indexA, const QModelIndex& indexB);
|
||||
|
||||
//Palette.
|
||||
@ -464,6 +471,7 @@ private:
|
||||
DoubleSpinBox* m_GammaThresholdSpin;
|
||||
DoubleSpinBox* m_VibrancySpin;
|
||||
DoubleSpinBox* m_HighlightSpin;
|
||||
DoubleSpinBox* m_K2Spin;
|
||||
QPushButton* m_BackgroundColorButton;
|
||||
StealthComboBox* m_PaletteModeCombo;
|
||||
SpinBox* m_WidthSpin;//Geometry.
|
||||
@ -487,9 +495,9 @@ private:
|
||||
DoubleSpinBox* m_DECurveSpin;
|
||||
SpinBox* m_SbsSpin;//Iteration.
|
||||
SpinBox* m_FuseSpin;
|
||||
DoubleSpinBox* m_RandRangeSpin;
|
||||
DoubleSpinBox* m_QualitySpin;
|
||||
SpinBox* m_SupersampleSpin;
|
||||
SpinBox* m_TemporalSamplesSpin;
|
||||
StealthComboBox* m_AffineInterpTypeCombo;
|
||||
StealthComboBox* m_InterpTypeCombo;
|
||||
|
||||
@ -528,6 +536,7 @@ private:
|
||||
//Xaos.
|
||||
DoubleSpinBox* m_XaosSpinBox;
|
||||
QStandardItemModel* m_XaosTableModel;
|
||||
QStandardItemModel* m_AppliedXaosTableModel;
|
||||
DoubleSpinBoxTableItemDelegate* m_XaosTableItemDelegate;
|
||||
|
||||
//Palette.
|
||||
@ -553,6 +562,7 @@ private:
|
||||
QTableWidgetItem* m_InfoFinalXformItem;
|
||||
|
||||
//Files.
|
||||
QList<QUrl> m_Urls;
|
||||
#ifndef __APPLE__
|
||||
QFileDialog* m_SaveFileDialog = nullptr;
|
||||
QFileDialog* m_SaveImageDialog = nullptr;
|
||||
@ -582,6 +592,7 @@ private:
|
||||
int m_VarSortMode;
|
||||
int m_PaletteSortMode;
|
||||
int m_PreviousPaletteRow;
|
||||
int m_BgRow;
|
||||
vector<byte> m_PreviewVec;
|
||||
shared_ptr<OpenCLInfo> m_Info;
|
||||
unique_ptr<FractoriumEmberControllerBase> m_Controller;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -528,7 +528,7 @@ static QString BaseStyle()
|
||||
"{\n"
|
||||
"\tcolor: black;\n"
|
||||
"\tbackground-color: lightgray;\n"
|
||||
"\tborder: 0px solid darkgray;\n"
|
||||
"\tborder: 1px solid darkgray;\n"
|
||||
"\tborder-right: 1px solid gray;\n"
|
||||
"\tpadding-top: 0px;\n"
|
||||
"\tpadding-bottom: 0px;\n"
|
||||
|
@ -146,6 +146,7 @@ public:
|
||||
virtual void GammaThresholdChanged(double d) { }
|
||||
virtual void VibrancyChanged(double d) { }
|
||||
virtual void HighlightPowerChanged(double d) { }
|
||||
virtual void K2Changed(double d) { }
|
||||
virtual void PaletteModeChanged(uint i) { }
|
||||
virtual void WidthChanged(uint i) { }
|
||||
virtual void HeightChanged(uint i) { }
|
||||
@ -169,14 +170,16 @@ public:
|
||||
virtual void DEFilterCurveWidthChanged(double d) { }
|
||||
virtual void SbsChanged(int d) { }
|
||||
virtual void FuseChanged(int d) { }
|
||||
virtual void RandRangeChanged(double d) { }
|
||||
virtual void QualityChanged(double d) { }
|
||||
virtual void SupersampleChanged(int d) { }
|
||||
virtual void TemporalSamplesChanged(int d) { }
|
||||
virtual void AffineInterpTypeChanged(int i) { }
|
||||
virtual void InterpTypeChanged(int i) { }
|
||||
virtual void BackgroundChanged(const QColor& color) { }
|
||||
virtual void ClearColorCurves(int i) { }
|
||||
virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) { }
|
||||
virtual void ColorCurvesPointAdded(size_t curveIndex, const QPointF& point) { }
|
||||
virtual void ColorCurvesPointRemoved(size_t curveIndex, int pointIndex) { }
|
||||
|
||||
//Xforms.
|
||||
virtual void CurrentXformComboChanged(int index) { }
|
||||
@ -210,7 +213,7 @@ public:
|
||||
virtual void RandomColorIndicesButtonClicked() { }
|
||||
virtual void ToggleColorIndicesButtonClicked() { }
|
||||
virtual void RandomColorSpeedButtonClicked() { }
|
||||
virtual void ToggleColorSpeedButtonClicked() { }
|
||||
virtual void ToggleColorSpeedsButtonClicked() { }
|
||||
virtual void XformColorSpeedChanged(double d) { }
|
||||
virtual void XformOpacityChanged(double d) { }
|
||||
virtual void XformDirectColorChanged(double d) { }
|
||||
@ -230,10 +233,12 @@ public:
|
||||
|
||||
//Xaos.
|
||||
virtual void FillXaos() { }
|
||||
virtual void FillAppliedXaos() { }
|
||||
virtual void XaosChanged(int x, int y, double val) { }
|
||||
virtual void ClearXaos() { }
|
||||
virtual void RandomXaos() { }
|
||||
virtual void AddLayer(int xforms) { }
|
||||
virtual void TransposeXaos() { }
|
||||
|
||||
//Palette.
|
||||
virtual size_t InitPaletteList(const QString& s) { return 0; }
|
||||
@ -421,6 +426,7 @@ public:
|
||||
virtual void GammaThresholdChanged(double d) override;
|
||||
virtual void VibrancyChanged(double d) override;
|
||||
virtual void HighlightPowerChanged(double d) override;
|
||||
virtual void K2Changed(double d) override;
|
||||
virtual void PaletteModeChanged(uint i) override;
|
||||
virtual void WidthChanged(uint i) override;
|
||||
virtual void HeightChanged(uint i) override;
|
||||
@ -444,14 +450,16 @@ public:
|
||||
virtual void DEFilterCurveWidthChanged(double d) override;
|
||||
virtual void SbsChanged(int d) override;
|
||||
virtual void FuseChanged(int d) override;
|
||||
virtual void RandRangeChanged(double d) override;
|
||||
virtual void QualityChanged(double d) override;
|
||||
virtual void SupersampleChanged(int d) override;
|
||||
virtual void TemporalSamplesChanged(int d) override;
|
||||
virtual void AffineInterpTypeChanged(int index) override;
|
||||
virtual void InterpTypeChanged(int index) override;
|
||||
virtual void BackgroundChanged(const QColor& col) override;
|
||||
virtual void ClearColorCurves(int i) override;
|
||||
virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) override;
|
||||
virtual void ColorCurvesPointAdded(size_t curveIndex, const QPointF& point) override;
|
||||
virtual void ColorCurvesPointRemoved(size_t curveIndex, int pointIndex) override;
|
||||
|
||||
//Xforms.
|
||||
virtual void CurrentXformComboChanged(int index) override;
|
||||
@ -488,7 +496,7 @@ public:
|
||||
virtual void RandomColorIndicesButtonClicked() override;
|
||||
virtual void ToggleColorIndicesButtonClicked() override;
|
||||
virtual void RandomColorSpeedButtonClicked() override;
|
||||
virtual void ToggleColorSpeedButtonClicked() override;
|
||||
virtual void ToggleColorSpeedsButtonClicked() override;
|
||||
virtual void XformColorSpeedChanged(double d) override;
|
||||
virtual void XformOpacityChanged(double d) override;
|
||||
virtual void XformDirectColorChanged(double d) override;
|
||||
@ -507,10 +515,12 @@ public:
|
||||
|
||||
//Xforms Xaos.
|
||||
virtual void FillXaos() override;
|
||||
virtual void FillAppliedXaos() override;
|
||||
virtual void XaosChanged(int x, int y, double val) override;
|
||||
virtual void ClearXaos() override;
|
||||
virtual void RandomXaos() override;
|
||||
virtual void AddLayer(int xforms) override;
|
||||
virtual void TransposeXaos() override;
|
||||
|
||||
//Xforms Selection.
|
||||
virtual QString MakeXformCaption(size_t i) override;
|
||||
@ -612,9 +622,7 @@ public:
|
||||
m_PreviewRun = false;
|
||||
m_PreviewRenderer.Abort();
|
||||
m_PreviewResult.cancel();
|
||||
|
||||
while (m_PreviewResult.isRunning())
|
||||
QApplication::processEvents();
|
||||
m_PreviewResult.waitForFinished();
|
||||
}
|
||||
|
||||
bool EarlyClip()
|
||||
|
@ -189,8 +189,8 @@ void Fractorium::UpdateHistogramBounds()
|
||||
if (auto r = m_Controller->Renderer())
|
||||
{
|
||||
ul.sprintf("UL: %3.3f, %3.3f", r->LowerLeftX(), r->UpperRightY());//These bounds include gutter padding.
|
||||
ur.sprintf("UR: %3.3f, %3.3f", -r->LowerLeftX(), r->UpperRightY());
|
||||
lr.sprintf("LR: %3.3f, %3.3f", -r->LowerLeftX(), r->LowerLeftY());
|
||||
ur.sprintf("UR: %3.3f, %3.3f", r->UpperRightX(), r->UpperRightY());
|
||||
lr.sprintf("LR: %3.3f, %3.3f", r->UpperRightX(), r->LowerLeftY());
|
||||
ll.sprintf("LL: %3.3f, %3.3f", r->LowerLeftX(), r->LowerLeftY());
|
||||
wh.sprintf("W x H: %4u x %4u", r->SuperRasW(), r->SuperRasH());
|
||||
g.sprintf("%u", (uint)r->GutterWidth());
|
||||
|
@ -60,7 +60,7 @@ void FractoriumEmberController<T>::NewFlock(size_t count)
|
||||
m_EmberFile.Clear();
|
||||
m_EmberFile.m_Filename = EmberFile<T>::DefaultFilename();
|
||||
vector<eVariationId> filteredVariations;
|
||||
vector<eVariationId>& filteredVariationsRef = m_FilteredVariations;
|
||||
vector<eVariationId>* filteredVariationsRef = &m_FilteredVariations;
|
||||
auto& deviceNames = OpenCLInfo::Instance()->AllDeviceNames();
|
||||
|
||||
for (auto& dev : deviceNames)
|
||||
@ -70,15 +70,18 @@ void FractoriumEmberController<T>::NewFlock(size_t count)
|
||||
if (nv)//Nvidia cannot handle synth. It takes over a minute to compile and uses about 4GB of memory.
|
||||
{
|
||||
filteredVariations = m_FilteredVariations;
|
||||
filteredVariationsRef = filteredVariations;
|
||||
std::remove(filteredVariations.begin(), filteredVariations.end(), eVariationId::VAR_SYNTH);
|
||||
std::remove(filteredVariations.begin(), filteredVariations.end(), eVariationId::VAR_PRE_SYNTH);
|
||||
std::remove(filteredVariations.begin(), filteredVariations.end(), eVariationId::VAR_POST_SYNTH);
|
||||
filteredVariations.erase(std::remove_if(filteredVariations.begin(), filteredVariations.end(),
|
||||
[&](const eVariationId & id) -> bool
|
||||
{
|
||||
return id == eVariationId::VAR_SYNTH || id == eVariationId::VAR_PRE_SYNTH || id == eVariationId::VAR_POST_SYNTH;
|
||||
}
|
||||
), filteredVariations.end());
|
||||
filteredVariationsRef = &filteredVariations;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
m_SheepTools->Random(ember, filteredVariationsRef, static_cast<intmax_t>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, 8);
|
||||
m_SheepTools->Random(ember, *filteredVariationsRef, static_cast<intmax_t>(QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedFrand<T>(-2, 2)), 0, 8);
|
||||
ParamsToEmber(ember);
|
||||
ember.m_Index = i;
|
||||
ember.m_Name = m_EmberFile.m_Filename.toStdString() + "_" + ToString(i + 1ULL).toStdString();
|
||||
@ -892,7 +895,9 @@ void FractoriumEmberController<T>::ClearFlame()
|
||||
}
|
||||
}
|
||||
|
||||
m_Ember.m_Curves.Init();
|
||||
FillXforms();
|
||||
FillCurvesControl();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,8 @@ void Fractorium::InitPaletteUI()
|
||||
connect(paletteTable->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(OnPaletteHeaderSectionClicked(int)), Qt::QueuedConnection);
|
||||
connect(ui.ResetCurvesButton, SIGNAL(clicked(bool)), this, SLOT(OnResetCurvesButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.CurvesView, SIGNAL(PointChangedSignal(int, int, const QPointF&)), this, SLOT(OnCurvesPointChanged(int, int, const QPointF&)), Qt::QueuedConnection);
|
||||
connect(ui.CurvesView, SIGNAL(PointAddedSignal(size_t, const QPointF&)), this, SLOT(OnCurvesPointAdded(size_t, const QPointF&)), Qt::QueuedConnection);
|
||||
connect(ui.CurvesView, SIGNAL(PointRemovedSignal(size_t, int)), this, SLOT(OnCurvesPointRemoved(size_t, int)), Qt::QueuedConnection);
|
||||
connect(ui.CurvesAllRadio, SIGNAL(toggled(bool)), this, SLOT(OnCurvesAllRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.CurvesRedRadio, SIGNAL(toggled(bool)), this, SLOT(OnCurvesRedRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.CurvesGreenRadio, SIGNAL(toggled(bool)), this, SLOT(OnCurvesGreenRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
@ -208,6 +210,8 @@ void Fractorium::OnPaletteAdjust(int d) { m_Controller->PaletteAdjust(); }
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SetBasePaletteAndAdjust(const Palette<float>& palette)
|
||||
{
|
||||
//The temp palette is assigned the palette read when the file was parsed/saved. The user can apply adjustments on the GUI later.
|
||||
//These adjustments will be applied to the temp palette, then assigned back to m_Ember.m_Palette.
|
||||
m_TempPalette = palette;//Deep copy.
|
||||
ApplyPaletteToEmber();//Copy temp palette to ember palette and apply adjustments.
|
||||
UpdateAdjustedPaletteGUI(m_Ember.m_Palette);//Show the adjusted palette.
|
||||
@ -288,7 +292,7 @@ void Fractorium::OnPreviewPaletteMouseReleased()
|
||||
/// <param name="col">Ignored</param>
|
||||
void Fractorium::OnPreviewPaletteCellDoubleClicked(int row, int col)
|
||||
{
|
||||
m_PreviewPaletteRotation = 0;
|
||||
m_PreviewPaletteRotation = m_PreviewPaletteMouseDownRotation = 0;
|
||||
m_PreviewPaletteMouseDown = false;
|
||||
m_Controller->PaletteAdjust();
|
||||
}
|
||||
@ -335,7 +339,8 @@ void Fractorium::OnPaletteRandomSelectButtonClicked(bool checked)
|
||||
uint i = 0;
|
||||
int rowCount = ui.PaletteListTable->rowCount();
|
||||
|
||||
while (((i = QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedRand(rowCount)) == uint(m_PreviousPaletteRow)) || i >= uint(rowCount));
|
||||
if (rowCount > 1)//If only one palette in the current palette file, just use it.
|
||||
while (((i = QTIsaac<ISAAC_SIZE, ISAAC_INT>::LockedRand(rowCount)) == uint(m_PreviousPaletteRow)) || i >= uint(rowCount));
|
||||
|
||||
if (checked)
|
||||
OnPaletteCellDoubleClicked(i, 1);//Will clear the adjustments.
|
||||
@ -539,6 +544,7 @@ void Fractorium::OnPaletteHeaderSectionClicked(int col)
|
||||
/// </summary>
|
||||
void Fractorium::ResetPaletteControls()
|
||||
{
|
||||
m_PreviewPaletteRotation = m_PreviewPaletteMouseDownRotation = 0;
|
||||
m_PaletteHueSpin->SetValueStealth(0);
|
||||
m_PaletteSaturationSpin->SetValueStealth(0);
|
||||
m_PaletteBrightnessSpin->SetValueStealth(0);
|
||||
@ -599,7 +605,7 @@ void Fractorium::OnResetCurvesButtonClicked(bool checked)
|
||||
/// Called when the position of any of the points in the curves editor is is changed.
|
||||
/// Resets the rendering process at either ACCUM_ONLY by default, or FILTER_AND_ACCUM when using early clip.
|
||||
/// </summary>
|
||||
/// <param name="curveIndex">The curve index, 0-1/</param>
|
||||
/// <param name="curveIndex">The curve index, 0-3/</param>
|
||||
/// <param name="pointIndex">The point index within the selected curve, 1-2.</param>
|
||||
/// <param name="point">The new coordinate of the point in terms of the curves control rect.</param>
|
||||
template <typename T>
|
||||
@ -614,6 +620,49 @@ void FractoriumEmberController<T>::ColorCurveChanged(int curveIndex, int pointIn
|
||||
|
||||
void Fractorium::OnCurvesPointChanged(int curveIndex, int pointIndex, const QPointF& point) { m_Controller->ColorCurveChanged(curveIndex, pointIndex, point); }
|
||||
|
||||
/// <summary>
|
||||
/// Remove curve point.
|
||||
/// Called when right clicking on a color curve point.
|
||||
/// Resets the rendering process at either ACCUM_ONLY by default, or FILTER_AND_ACCUM when using early clip.
|
||||
/// </summary>
|
||||
/// <param name="curveIndex">The curve index./</param>
|
||||
/// <param name="pointIndex">The point index within the selected curve.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ColorCurvesPointRemoved(size_t curveIndex, int pointIndex)
|
||||
{
|
||||
Update([&]
|
||||
{
|
||||
if (m_Ember.m_Curves.m_Points[curveIndex].size() > 2)
|
||||
{
|
||||
m_Ember.m_Curves.m_Points[curveIndex].erase(m_Ember.m_Curves.m_Points[curveIndex].begin() + pointIndex);
|
||||
std::sort(m_Ember.m_Curves.m_Points[curveIndex].begin(), m_Ember.m_Curves.m_Points[curveIndex].end(), [&](auto & lhs, auto & rhs) { return lhs.x < rhs.x; });
|
||||
}
|
||||
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
|
||||
FillCurvesControl();
|
||||
}
|
||||
|
||||
void Fractorium::OnCurvesPointRemoved(size_t curveIndex, int pointIndex) { m_Controller->ColorCurvesPointRemoved(curveIndex, pointIndex); }
|
||||
|
||||
/// <summary>
|
||||
/// Add a curve point.
|
||||
/// Called when clicking in between points on a color curve.
|
||||
/// Resets the rendering process at either ACCUM_ONLY by default, or FILTER_AND_ACCUM when using early clip.
|
||||
/// </summary>
|
||||
/// <param name="curveIndex">The curve index./</param>
|
||||
/// <param name="pointIndex">The point to add to the selected curve.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ColorCurvesPointAdded(size_t curveIndex, const QPointF& point)
|
||||
{
|
||||
Update([&]
|
||||
{
|
||||
m_Ember.m_Curves.m_Points[curveIndex].push_back({ point.x(), point.y() });
|
||||
std::sort(m_Ember.m_Curves.m_Points[curveIndex].begin(), m_Ember.m_Curves.m_Points[curveIndex].end(), [&](auto & lhs, auto & rhs) { return lhs.x < rhs.x; });
|
||||
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
|
||||
FillCurvesControl();
|
||||
}
|
||||
|
||||
void Fractorium::OnCurvesPointAdded(size_t curveIndex, const QPointF& point) { m_Controller->ColorCurvesPointAdded(curveIndex, point); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the top most points in the curves control, which makes it easier to
|
||||
/// select a point by putting it on top of all the others.
|
||||
@ -632,16 +681,7 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::FillCurvesControl()
|
||||
{
|
||||
m_Fractorium->ui.CurvesView->blockSignals(true);
|
||||
|
||||
for (auto i = 0; i < 4; i++)
|
||||
{
|
||||
for (auto j = 1; j < 3; j++)//Only do middle points.
|
||||
{
|
||||
QPointF point(m_Ember.m_Curves.m_Points[i][j].x, m_Ember.m_Curves.m_Points[i][j].y);
|
||||
m_Fractorium->ui.CurvesView->Set(i, j, point);
|
||||
}
|
||||
}
|
||||
|
||||
m_Fractorium->ui.CurvesView->Set(m_Ember.m_Curves);
|
||||
m_Fractorium->ui.CurvesView->blockSignals(false);
|
||||
m_Fractorium->ui.CurvesView->update();
|
||||
}
|
||||
|
@ -22,13 +22,21 @@ void Fractorium::InitParamsUI()
|
||||
SetFixedTableHeader(ui.IterationTableHeader->horizontalHeader());
|
||||
SetFixedTableHeader(ui.AnimationTableHeader->horizontalHeader());
|
||||
//Color.
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_BrightnessSpin, spinHeight, 0.05, 1000, 1, SIGNAL(valueChanged(double)), SLOT(OnBrightnessChanged(double)), true, 4.0, 4.0, 4.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaSpin, spinHeight, 1, 9999, 0.5, SIGNAL(valueChanged(double)), SLOT(OnGammaChanged(double)), true, 4.0, 4.0, 4.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, 10, 0.01, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_VibrancySpin, spinHeight, 0, 30, 0.01, SIGNAL(valueChanged(double)), SLOT(OnVibrancyChanged(double)), true, 1.0, 1.0, 0.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, 1.0, 1.0, -1.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_BrightnessSpin, spinHeight, 0.05, 1000, 1, SIGNAL(valueChanged(double)), SLOT(OnBrightnessChanged(double)), true, 4.0, 4.0, 4.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaSpin, spinHeight, 1, 9999, 0.5, SIGNAL(valueChanged(double)), SLOT(OnGammaChanged(double)), true, 4.0, 4.0, 4.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, 10, 0.01, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_VibrancySpin, spinHeight, 0, 30, 0.01, SIGNAL(valueChanged(double)), SLOT(OnVibrancyChanged(double)), true, 1.0, 1.0, 0.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, 1.0, 1.0, -1.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_K2Spin, spinHeight, 0, 10.0, 0.0001, SIGNAL(valueChanged(double)), SLOT(OnK2Changed(double)), true, 0, 0.0001, 0);
|
||||
m_HighlightSpin->DoubleClickLowVal(-1.0);
|
||||
m_GammaThresholdSpin->setDecimals(4);
|
||||
int dec = 6;
|
||||
m_BrightnessSpin->setDecimals(dec);
|
||||
m_GammaSpin->setDecimals(dec);
|
||||
m_GammaThresholdSpin->setDecimals(dec);
|
||||
m_VibrancySpin->setDecimals(dec);
|
||||
m_HighlightSpin->setDecimals(dec);
|
||||
m_K2Spin->setDecimals(dec);
|
||||
m_BgRow = row;
|
||||
m_BackgroundColorButton = new QPushButton("...", table);
|
||||
m_BackgroundColorButton->setMinimumWidth(21);
|
||||
m_BackgroundColorButton->setMaximumWidth(21);
|
||||
@ -48,7 +56,7 @@ void Fractorium::InitParamsUI()
|
||||
SetupSpinner<SpinBox, int> (table, this, row, 1, m_HeightSpin, spinHeight, 10, 2048, 50, SIGNAL(valueChanged(int)), SLOT(OnHeightChanged(int)), true, height(), height(), height());
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterXSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterXChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterYSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterYChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ScaleSpin, spinHeight, 10, dmax, 20, SIGNAL(valueChanged(double)), SLOT(OnScaleChanged(double)), true, 240, 240, 240);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ScaleSpin, spinHeight, 10, dmax, 20, SIGNAL(valueChanged(double)), SLOT(OnScaleChanged(double)), true, 240, 240, 240);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZoomSpin, spinHeight, 0, 25, 0.2, SIGNAL(valueChanged(double)), SLOT(OnZoomChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_RotateSpin, spinHeight, -180, 180, 10, SIGNAL(valueChanged(double)), SLOT(OnRotateChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZPosSpin, spinHeight, -1000, 1000, 1, SIGNAL(valueChanged(double)), SLOT(OnZPosChanged(double)), true, 0, 1, 0);
|
||||
@ -66,20 +74,20 @@ void Fractorium::InitParamsUI()
|
||||
m_Controller->ResizeAndScale(m_WidthSpin->DoubleClickNonZero(), val, eScaleType::SCALE_HEIGHT);
|
||||
m_WidthSpin->SetValueStealth(m_WidthSpin->DoubleClickNonZero());
|
||||
};
|
||||
//Set w/h max values.
|
||||
m_CenterXSpin->setDecimals(3);
|
||||
m_CenterYSpin->setDecimals(3);
|
||||
m_ZPosSpin->setDecimals(3);
|
||||
m_PerspectiveSpin->setDecimals(4);
|
||||
m_DepthBlurSpin->setDecimals(3);
|
||||
dec = 4;
|
||||
m_CenterXSpin->setDecimals(dec);
|
||||
m_CenterYSpin->setDecimals(dec);
|
||||
m_ZPosSpin->setDecimals(dec);
|
||||
m_PerspectiveSpin->setDecimals(dec);
|
||||
m_DepthBlurSpin->setDecimals(dec);
|
||||
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
||||
//Filter.
|
||||
row = 0;
|
||||
table = ui.FilterTable;
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_SpatialFilterWidthSpin, spinHeight, 0, 2, 0.1, SIGNAL(valueChanged(double)), SLOT(OnSpatialFilterWidthChanged(double)), true, 1.0, 1.0, 0);
|
||||
m_SpatialFilterWidthSpin->DoubleClickLowVal(0.1);
|
||||
comboVals = SpatialFilterCreator<float>::FilterTypes();
|
||||
SetupCombo(table, this, row, 1, m_SpatialFilterTypeCombo, comboVals, SIGNAL(currentIndexChanged(const QString&)), SLOT(OnSpatialFilterTypeComboCurrentIndexChanged(const QString&)));
|
||||
m_SpatialFilterTypeCombo->SetCurrentIndexStealth(0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DEFilterMinRadiusSpin, spinHeight, 0, 25, 1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterMinRadiusWidthChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DEFilterMaxRadiusSpin, spinHeight, 0, 25, 1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterMaxRadiusWidthChanged(double)), true, 0.0, 9.0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DECurveSpin, spinHeight, 0.15, 5, 0.1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterCurveWidthChanged(double)), true, 0.4, 0.4, 0.4);
|
||||
@ -88,10 +96,15 @@ void Fractorium::InitParamsUI()
|
||||
row = 0;
|
||||
table = ui.IterationTable;
|
||||
auto quality = m_Settings->OpenCL() ? m_Settings->OpenClQuality() : m_Settings->CpuQuality();
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SbsSpin, spinHeight, 1000, 100000, 100, SIGNAL(valueChanged(int)), SLOT(OnSbsChanged(int)), true, DEFAULT_SBS, DEFAULT_SBS, DEFAULT_SBS);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_FuseSpin, spinHeight, 1, 1000, 5, SIGNAL(valueChanged(int)), SLOT(OnFuseChanged(int)), true, 15, 15, 15);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, quality, 10, 10);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 1, 1, 1);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SbsSpin, spinHeight, 1000, 100000, 100, SIGNAL(valueChanged(int)), SLOT(OnSbsChanged(int)), true, DEFAULT_SBS, DEFAULT_SBS, DEFAULT_SBS);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_FuseSpin, spinHeight, 1, 1000, 5, SIGNAL(valueChanged(int)), SLOT(OnFuseChanged(int)), true, 15, 100, 15);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_RandRangeSpin, spinHeight, 0.01, 1000, 0.1, SIGNAL(valueChanged(double)), SLOT(OnRandRangeChanged(double)), true, 1, 10, 1);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, quality, 10, 10);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 1, 2, 1);
|
||||
m_RandRangeSpin->DoubleClickLowVal(1);
|
||||
m_RandRangeSpin->setDecimals(4);
|
||||
m_FuseSpin->DoubleClickLowVal(15);
|
||||
m_SupersampleSpin->DoubleClickLowVal(1);
|
||||
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
||||
//Animation.
|
||||
row = 0;
|
||||
@ -106,10 +119,10 @@ void Fractorium::InitParamsUI()
|
||||
comboVals.push_back("Log");
|
||||
SetupCombo( table, this, row, 1, m_AffineInterpTypeCombo, comboVals, SIGNAL(currentIndexChanged(int)), SLOT(OnAffineInterpTypeComboCurrentIndexChanged(int)));
|
||||
m_AffineInterpTypeCombo->SetCurrentIndexStealth(int(eAffineInterp::AFFINE_INTERP_LOG));
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_TemporalSamplesSpin, spinHeight, 1, 5000, 1, SIGNAL(valueChanged(int)), SLOT(OnTemporalSamplesChanged(int)), true, 1000);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_TemporalFilterWidthSpin, spinHeight, 1, 10, 1, SIGNAL(valueChanged(double)), SLOT(OnTemporalFilterWidthChanged(double)), true, 1);
|
||||
comboVals = TemporalFilterCreator<float>::FilterTypes();
|
||||
SetupCombo( table, this, row, 1, m_TemporalFilterTypeCombo, comboVals, SIGNAL(currentIndexChanged(const QString&)), SLOT(OnTemporalFilterTypeComboCurrentIndexChanged(const QString&)));
|
||||
m_TemporalFilterTypeCombo->SetCurrentIndexStealth(int(eTemporalFilterType::GAUSSIAN_TEMPORAL_FILTER));
|
||||
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
||||
}
|
||||
|
||||
@ -140,6 +153,7 @@ void FractoriumEmberController<T>::BrightnessChanged(double d)
|
||||
ember.m_Brightness = d;
|
||||
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
|
||||
}
|
||||
|
||||
void Fractorium::OnBrightnessChanged(double d) { m_Controller->BrightnessChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
@ -203,6 +217,22 @@ template <typename T> void FractoriumEmberController<T>::HighlightPowerChanged(d
|
||||
}
|
||||
void Fractorium::OnHighlightPowerChanged(double d) { m_Controller->HighlightPowerChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the k2 brightness value to be used for final accum.
|
||||
/// Called when k2 is changed.
|
||||
/// Resets the rendering process to the final accumulation stage.
|
||||
/// </summary>
|
||||
/// <param name="d">The k2 value</param>
|
||||
template <typename T> void FractoriumEmberController<T>::K2Changed(double d)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
ember.m_K2 = d;
|
||||
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY, m_Fractorium->ApplyAll());
|
||||
}
|
||||
|
||||
void Fractorium::OnK2Changed(double d) { m_Controller->K2Changed(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Show the color selection dialog.
|
||||
/// Called when background color button is clicked.
|
||||
@ -223,7 +253,7 @@ void Fractorium::OnBackgroundColorButtonClicked(bool checked)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::BackgroundChanged(const QColor& color)
|
||||
{
|
||||
int itemRow = 5;
|
||||
auto itemRow = m_Fractorium->m_BgRow;
|
||||
auto colorTable = m_Fractorium->ui.ColorTable;
|
||||
colorTable->item(itemRow, 1)->setBackgroundColor(color);
|
||||
auto r = ToString(color.red());
|
||||
@ -553,6 +583,22 @@ template <typename T> void FractoriumEmberController<T>::SbsChanged(int d)
|
||||
}
|
||||
void Fractorium::OnSbsChanged(int d) { m_Controller->SbsChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the range from which to chose the starting random points, as well as point resets due to bad points.
|
||||
/// Called when the rand range spinner is changed.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="d">The sub batch size value to set</param>
|
||||
template <typename T> void FractoriumEmberController<T>::RandRangeChanged(double d)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
ember.m_RandPointRange = d;
|
||||
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
||||
}
|
||||
|
||||
void Fractorium::OnRandRangeChanged(double d) { m_Controller->RandRangeChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the number of samples to disregard for each sub batch.
|
||||
/// Called when the fuse count spinner is changed.
|
||||
@ -662,26 +708,6 @@ void FractoriumEmberController<T>::InterpTypeChanged(int i)
|
||||
|
||||
void Fractorium::OnInterpTypeComboCurrentIndexChanged(int index) { m_Controller->InterpTypeChanged(index); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the temporal samples to be used with animation.
|
||||
/// Called when the temporal samples spinner is changed.
|
||||
/// Does not reset anything because this is only used for animation.
|
||||
/// </summary>
|
||||
/// <param name="d">The temporal samples value</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::TemporalSamplesChanged(int i)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
ember.m_TemporalSamples = i;//This will be reset on every render to trick the renderer into not thinking it's doing an animation. So setting this has no real effect. Users should set it in the final render dialog when animating.
|
||||
|
||||
if (!m_Fractorium->ApplyAll())
|
||||
if (m_EmberFilePointer)
|
||||
m_EmberFilePointer->m_TemporalSamples = i;
|
||||
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
|
||||
}
|
||||
void Fractorium::OnTemporalSamplesChanged(int d) { m_Controller->TemporalSamplesChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the temporal filter width to be used with animation.
|
||||
/// Called when the temporal filter width spinner is changed.
|
||||
@ -754,8 +780,9 @@ void FractoriumEmberController<T>::FillParamTablesAndPalette()
|
||||
m_Fractorium->m_GammaThresholdSpin->SetValueStealth(m_Ember.m_GammaThresh);
|
||||
m_Fractorium->m_VibrancySpin->SetValueStealth(m_Ember.m_Vibrancy);
|
||||
m_Fractorium->m_HighlightSpin->SetValueStealth(m_Ember.m_HighlightPower);
|
||||
m_Fractorium->m_K2Spin->SetValueStealth(m_Ember.m_K2);
|
||||
m_Fractorium->m_ColorDialog->setCurrentColor(QColor(m_Ember.m_Background.r * 255, m_Ember.m_Background.g * 255, m_Ember.m_Background.b * 255));
|
||||
m_Fractorium->ui.ColorTable->item(5, 1)->setBackgroundColor(m_Fractorium->m_ColorDialog->currentColor());
|
||||
m_Fractorium->ui.ColorTable->item(m_Fractorium->m_BgRow, 1)->setBackgroundColor(m_Fractorium->m_ColorDialog->currentColor());
|
||||
BackgroundChanged(m_Fractorium->m_ColorDialog->currentColor());
|
||||
m_Fractorium->m_PaletteModeCombo->SetCurrentIndexStealth(int(m_Ember.m_PaletteMode));
|
||||
m_Fractorium->m_WidthSpin->SetValueStealth(m_Ember.m_FinalRasW);//Geometry.
|
||||
@ -779,31 +806,21 @@ void FractoriumEmberController<T>::FillParamTablesAndPalette()
|
||||
m_Fractorium->m_DECurveSpin->SetValueStealth(m_Ember.m_CurveDE);
|
||||
m_Fractorium->m_SbsSpin->SetValueStealth(m_Ember.m_SubBatchSize);//Iteration.
|
||||
m_Fractorium->m_FuseSpin->SetValueStealth(m_Ember.m_FuseCount);
|
||||
m_Fractorium->m_RandRangeSpin->SetValueStealth(m_Ember.m_RandPointRange);
|
||||
m_Fractorium->m_QualitySpin->SetValueStealth(m_Ember.m_Quality);
|
||||
m_Fractorium->m_SupersampleSpin->SetValueStealth(m_Ember.m_Supersample);
|
||||
m_Fractorium->m_TemporalSamplesSpin->SetValueStealth(m_Ember.m_TemporalSamples);
|
||||
m_Fractorium->m_AffineInterpTypeCombo->SetCurrentIndexStealth(int(m_Ember.m_AffineInterp));
|
||||
m_Fractorium->m_InterpTypeCombo->SetCurrentIndexStealth(int(m_Ember.m_Interp));
|
||||
//Palette related items:
|
||||
//The temp palette is assigned the palette read when the file was parsed/saved. The user can apply adjustments on the GUI later.
|
||||
//These adjustments will be applied to the temp palette, then assigned back to m_Ember.m_Palette.
|
||||
//Normally, the temp palette is assigned whenever the user clicks on a palette cell. But since this is not
|
||||
//called in response to that event, it is skipped here so must do it manually.
|
||||
m_TempPalette = m_Ember.m_Palette;
|
||||
//Palette controls are reset on each ember load. This means that if the palette was adjusted, saved, the selected ember
|
||||
//changed to another, then back, the previously adjusted palette will now be considered the base, and all adjustments set to 0.
|
||||
//To fix this, the caller must preserve the temp palette and the adjustment values and reassign. See Fractorium::CreateControllerFromOptions()
|
||||
//for an example.
|
||||
m_Fractorium->ResetPaletteControls();
|
||||
auto temp = m_Ember.m_Palette.m_Filename;
|
||||
|
||||
if (temp.get())
|
||||
m_Fractorium->SetPaletteFileComboIndex(*temp.get());
|
||||
|
||||
//Update the palette preview widget.
|
||||
m_Fractorium->ResetPaletteControls();
|
||||
//Since the controls were cleared above, the adjusted palette will be identical to the base palette.
|
||||
//Callers can set, apply and display palette adjustments after this function exits if needed.
|
||||
UpdateAdjustedPaletteGUI(m_Ember.m_Palette);//Updating the palette GUI will trigger a full render.
|
||||
SetBasePaletteAndAdjust(m_Ember.m_Palette);//Updating the palette GUI will trigger a full render.
|
||||
InitLockedScale();
|
||||
}
|
||||
|
||||
@ -820,6 +837,7 @@ void FractoriumEmberController<T>::ParamsToEmber(Ember<T>& ember)
|
||||
ember.m_GammaThresh = m_Fractorium->m_GammaThresholdSpin->value();
|
||||
ember.m_Vibrancy = m_Fractorium->m_VibrancySpin->value();
|
||||
ember.m_HighlightPower = m_Fractorium->m_HighlightSpin->value();
|
||||
ember.m_K2 = m_Fractorium->m_K2Spin->value();
|
||||
ember.m_Background.r = color.red() / 255.0;
|
||||
ember.m_Background.g = color.green() / 255.0;
|
||||
ember.m_Background.b = color.blue() / 255.0;
|
||||
@ -845,9 +863,9 @@ void FractoriumEmberController<T>::ParamsToEmber(Ember<T>& ember)
|
||||
ember.m_CurveDE = m_Fractorium->m_DECurveSpin->value();
|
||||
ember.m_SubBatchSize = m_Fractorium->m_SbsSpin->value();
|
||||
ember.m_FuseCount = m_Fractorium->m_FuseSpin->value();
|
||||
ember.m_RandPointRange = m_Fractorium->m_RandRangeSpin->value();
|
||||
ember.m_Quality = m_Fractorium->m_QualitySpin->value();
|
||||
ember.m_Supersample = m_Fractorium->m_SupersampleSpin->value();
|
||||
ember.m_TemporalSamples = m_Fractorium->m_TemporalSamplesSpin->value();
|
||||
ember.m_AffineInterp = eAffineInterp(m_Fractorium->m_AffineInterpTypeCombo->currentIndex());
|
||||
ember.m_Interp = eInterp(m_Fractorium->m_InterpTypeCombo->currentIndex());
|
||||
ember.SyncSize();
|
||||
|
@ -587,6 +587,9 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
|
||||
if (m_Fractorium->m_QualitySpin->value() < val)
|
||||
m_Fractorium->m_QualitySpin->setValue(val);
|
||||
|
||||
if (auto rendererCL = dynamic_cast<RendererCL<T, float>*>(m_Renderer.get()))
|
||||
rendererCL->SubBatchPercentPerThread(float(s->OpenCLSubBatchPct()));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -55,6 +55,16 @@ void FractoriumSettings::EnsureDefaults()
|
||||
FinalThreadPriority(Clamp<int>(FinalThreadPriority(), (int)eThreadPriority::LOWEST, (int)eThreadPriority::HIGHEST));
|
||||
CpuSubBatch(std::max(1u, CpuSubBatch()));
|
||||
OpenCLSubBatch(std::max(1u, OpenCLSubBatch()));
|
||||
|
||||
if (OpenCLSubBatchPct() == 0)
|
||||
OpenCLSubBatchPct(0.025);//Default to 256 iters per thread when using the default sub batch size of 10,240.
|
||||
|
||||
OpenCLSubBatchPct(Clamp(OpenCLSubBatchPct(), 0.01, 1.0));
|
||||
|
||||
if (FinalOpenCLSubBatchPct() == 0)
|
||||
FinalOpenCLSubBatchPct(0.025);//Default to 256 iters per thread when using the default sub batch size of 10,240.
|
||||
|
||||
FinalOpenCLSubBatchPct(Clamp(FinalOpenCLSubBatchPct(), 0.01, 1.0));
|
||||
RandomCount(std::max(1u, RandomCount()));
|
||||
|
||||
if (CpuQuality() == 0)
|
||||
@ -118,74 +128,77 @@ void FractoriumSettings::EnsureDefaults()
|
||||
/// Interactive renderer settings.
|
||||
/// </summary>
|
||||
|
||||
bool FractoriumSettings::EarlyClip() { return value(EARLYCLIP).toBool(); }
|
||||
void FractoriumSettings::EarlyClip(bool b) { setValue(EARLYCLIP, b); }
|
||||
bool FractoriumSettings::EarlyClip() { return value(EARLYCLIP).toBool(); }
|
||||
void FractoriumSettings::EarlyClip(bool b) { setValue(EARLYCLIP, b); }
|
||||
|
||||
bool FractoriumSettings::YAxisUp() { return value(YAXISUP).toBool(); }
|
||||
void FractoriumSettings::YAxisUp(bool b) { setValue(YAXISUP, b); }
|
||||
bool FractoriumSettings::YAxisUp() { return value(YAXISUP).toBool(); }
|
||||
void FractoriumSettings::YAxisUp(bool b) { setValue(YAXISUP, b); }
|
||||
|
||||
bool FractoriumSettings::Transparency() { return value(TRANSPARENCY).toBool(); }
|
||||
void FractoriumSettings::Transparency(bool b) { setValue(TRANSPARENCY, b); }
|
||||
bool FractoriumSettings::Transparency() { return value(TRANSPARENCY).toBool(); }
|
||||
void FractoriumSettings::Transparency(bool b) { setValue(TRANSPARENCY, b); }
|
||||
|
||||
bool FractoriumSettings::OpenCL() { return value(OPENCL).toBool(); }
|
||||
void FractoriumSettings::OpenCL(bool b) { setValue(OPENCL, b); }
|
||||
bool FractoriumSettings::OpenCL() { return value(OPENCL).toBool(); }
|
||||
void FractoriumSettings::OpenCL(bool b) { setValue(OPENCL, b); }
|
||||
|
||||
bool FractoriumSettings::SharedTexture() { return value(SHAREDTEXTURE).toBool(); }
|
||||
void FractoriumSettings::SharedTexture(bool b) { setValue(SHAREDTEXTURE, b); }
|
||||
bool FractoriumSettings::SharedTexture() { return value(SHAREDTEXTURE).toBool(); }
|
||||
void FractoriumSettings::SharedTexture(bool b) { setValue(SHAREDTEXTURE, b); }
|
||||
|
||||
bool FractoriumSettings::Double() { return value(DOUBLEPRECISION).toBool(); }
|
||||
void FractoriumSettings::Double(bool b) { setValue(DOUBLEPRECISION, b); }
|
||||
bool FractoriumSettings::Double() { return value(DOUBLEPRECISION).toBool(); }
|
||||
void FractoriumSettings::Double(bool b) { setValue(DOUBLEPRECISION, b); }
|
||||
|
||||
bool FractoriumSettings::ShowAllXforms() { return value(SHOWALLXFORMS).toBool(); }
|
||||
void FractoriumSettings::ShowAllXforms(bool b) { setValue(SHOWALLXFORMS, b); }
|
||||
bool FractoriumSettings::ShowAllXforms() { return value(SHOWALLXFORMS).toBool(); }
|
||||
void FractoriumSettings::ShowAllXforms(bool b) { setValue(SHOWALLXFORMS, b); }
|
||||
|
||||
bool FractoriumSettings::ShowXforms() { return value(SHOWXFORMS, QVariant::fromValue(true)).toBool(); }
|
||||
void FractoriumSettings::ShowXforms(bool b) { setValue(SHOWXFORMS, b); }
|
||||
bool FractoriumSettings::ShowXforms() { return value(SHOWXFORMS, QVariant::fromValue(true)).toBool(); }
|
||||
void FractoriumSettings::ShowXforms(bool b) { setValue(SHOWXFORMS, b); }
|
||||
|
||||
bool FractoriumSettings::ShowGrid() { return value(SHOWGRID, QVariant::fromValue(true)).toBool(); }
|
||||
void FractoriumSettings::ShowGrid(bool b) { setValue(SHOWGRID, b); }
|
||||
bool FractoriumSettings::ShowGrid() { return value(SHOWGRID, QVariant::fromValue(true)).toBool(); }
|
||||
void FractoriumSettings::ShowGrid(bool b) { setValue(SHOWGRID, b); }
|
||||
|
||||
bool FractoriumSettings::ToggleType() { return value(TOGGLETYPE).toBool(); }
|
||||
void FractoriumSettings::ToggleType(bool b) { setValue(TOGGLETYPE, b); }
|
||||
bool FractoriumSettings::ToggleType() { return value(TOGGLETYPE).toBool(); }
|
||||
void FractoriumSettings::ToggleType(bool b) { setValue(TOGGLETYPE, b); }
|
||||
|
||||
bool FractoriumSettings::Png16Bit() { return value(PNG16BIT).toBool(); }
|
||||
void FractoriumSettings::Png16Bit(bool b) { setValue(PNG16BIT, b); }
|
||||
bool FractoriumSettings::Png16Bit() { return value(PNG16BIT).toBool(); }
|
||||
void FractoriumSettings::Png16Bit(bool b) { setValue(PNG16BIT, b); }
|
||||
|
||||
bool FractoriumSettings::ContinuousUpdate() { return value(CONTUPDATE).toBool(); }
|
||||
void FractoriumSettings::ContinuousUpdate(bool b) { setValue(CONTUPDATE, b); }
|
||||
bool FractoriumSettings::ContinuousUpdate() { return value(CONTUPDATE).toBool(); }
|
||||
void FractoriumSettings::ContinuousUpdate(bool b) { setValue(CONTUPDATE, b); }
|
||||
|
||||
QList<QVariant> FractoriumSettings::Devices() { return value(DEVICES).toList(); }
|
||||
void FractoriumSettings::Devices(const QList<QVariant>& devices) { setValue(DEVICES, devices); }
|
||||
QList<QVariant> FractoriumSettings::Devices() { return value(DEVICES).toList(); }
|
||||
void FractoriumSettings::Devices(const QList<QVariant>& devices) { setValue(DEVICES, devices); }
|
||||
|
||||
uint FractoriumSettings::ThreadCount() { return value(THREADCOUNT).toUInt(); }
|
||||
void FractoriumSettings::ThreadCount(uint i) { setValue(THREADCOUNT, i); }
|
||||
uint FractoriumSettings::ThreadCount() { return value(THREADCOUNT).toUInt(); }
|
||||
void FractoriumSettings::ThreadCount(uint i) { setValue(THREADCOUNT, i); }
|
||||
|
||||
bool FractoriumSettings::CpuDEFilter() { return value(CPUDEFILTER).toBool(); }
|
||||
void FractoriumSettings::CpuDEFilter(bool b) { setValue(CPUDEFILTER, b); }
|
||||
bool FractoriumSettings::CpuDEFilter() { return value(CPUDEFILTER).toBool(); }
|
||||
void FractoriumSettings::CpuDEFilter(bool b) { setValue(CPUDEFILTER, b); }
|
||||
|
||||
bool FractoriumSettings::OpenCLDEFilter() { return value(OPENCLDEFILTER).toBool(); }
|
||||
void FractoriumSettings::OpenCLDEFilter(bool b) { setValue(OPENCLDEFILTER, b); }
|
||||
bool FractoriumSettings::OpenCLDEFilter() { return value(OPENCLDEFILTER).toBool(); }
|
||||
void FractoriumSettings::OpenCLDEFilter(bool b) { setValue(OPENCLDEFILTER, b); }
|
||||
|
||||
uint FractoriumSettings::CpuSubBatch() { return value(CPUSUBBATCH).toUInt(); }
|
||||
void FractoriumSettings::CpuSubBatch(uint i) { setValue(CPUSUBBATCH, i); }
|
||||
uint FractoriumSettings::CpuSubBatch() { return value(CPUSUBBATCH).toUInt(); }
|
||||
void FractoriumSettings::CpuSubBatch(uint i) { setValue(CPUSUBBATCH, i); }
|
||||
|
||||
uint FractoriumSettings::OpenCLSubBatch() { return value(OPENCLSUBBATCH).toUInt(); }
|
||||
void FractoriumSettings::OpenCLSubBatch(uint i) { setValue(OPENCLSUBBATCH, i); }
|
||||
double FractoriumSettings::OpenCLSubBatchPct() { return value(OPENCLSUBBATCHPCT).toDouble(); }
|
||||
void FractoriumSettings::OpenCLSubBatchPct(double d) { setValue(OPENCLSUBBATCHPCT, d); }
|
||||
|
||||
uint FractoriumSettings::RandomCount() { return value(RANDOMCOUNT).toUInt(); }
|
||||
void FractoriumSettings::RandomCount(uint i) { setValue(RANDOMCOUNT, i); }
|
||||
uint FractoriumSettings::OpenCLSubBatch() { return value(OPENCLSUBBATCH).toUInt(); }
|
||||
void FractoriumSettings::OpenCLSubBatch(uint i) { setValue(OPENCLSUBBATCH, i); }
|
||||
|
||||
uint FractoriumSettings::CpuQuality() { return value(CPUQUALITY).toUInt(); }
|
||||
void FractoriumSettings::CpuQuality(uint i) { setValue(CPUQUALITY, i); }
|
||||
uint FractoriumSettings::RandomCount() { return value(RANDOMCOUNT).toUInt(); }
|
||||
void FractoriumSettings::RandomCount(uint i) { setValue(RANDOMCOUNT, i); }
|
||||
|
||||
uint FractoriumSettings::OpenClQuality() { return value(OPENCLQUALITY).toUInt(); }
|
||||
void FractoriumSettings::OpenClQuality(uint i) { setValue(OPENCLQUALITY, i); }
|
||||
uint FractoriumSettings::CpuQuality() { return value(CPUQUALITY).toUInt(); }
|
||||
void FractoriumSettings::CpuQuality(uint i) { setValue(CPUQUALITY, i); }
|
||||
|
||||
bool FractoriumSettings::LoadLast() { return value(LOADLAST).toBool(); }
|
||||
void FractoriumSettings::LoadLast(bool b) { setValue(LOADLAST, b); }
|
||||
uint FractoriumSettings::OpenClQuality() { return value(OPENCLQUALITY).toUInt(); }
|
||||
void FractoriumSettings::OpenClQuality(uint i) { setValue(OPENCLQUALITY, i); }
|
||||
|
||||
bool FractoriumSettings::RotateAndScale() { return value(ROTSCALE).toBool(); }
|
||||
void FractoriumSettings::RotateAndScale(bool b) { setValue(ROTSCALE, b); }
|
||||
bool FractoriumSettings::LoadLast() { return value(LOADLAST).toBool(); }
|
||||
void FractoriumSettings::LoadLast(bool b) { setValue(LOADLAST, b); }
|
||||
|
||||
bool FractoriumSettings::RotateAndScale() { return value(ROTSCALE).toBool(); }
|
||||
void FractoriumSettings::RotateAndScale(bool b) { setValue(ROTSCALE, b); }
|
||||
|
||||
/// <summary>
|
||||
/// Sequence generation settings.
|
||||
@ -253,62 +266,65 @@ void FractoriumSettings::VarFilterNonparam(int i) { setValue(VARFILTERNONPARAM,
|
||||
/// Final render settings.
|
||||
/// </summary>
|
||||
|
||||
bool FractoriumSettings::FinalEarlyClip() { return value(FINALEARLYCLIP).toBool(); }
|
||||
void FractoriumSettings::FinalEarlyClip(bool b) { setValue(FINALEARLYCLIP, b); }
|
||||
bool FractoriumSettings::FinalEarlyClip() { return value(FINALEARLYCLIP).toBool(); }
|
||||
void FractoriumSettings::FinalEarlyClip(bool b) { setValue(FINALEARLYCLIP, b); }
|
||||
|
||||
bool FractoriumSettings::FinalYAxisUp() { return value(FINALYAXISUP).toBool(); }
|
||||
void FractoriumSettings::FinalYAxisUp(bool b) { setValue(FINALYAXISUP, b); }
|
||||
bool FractoriumSettings::FinalYAxisUp() { return value(FINALYAXISUP).toBool(); }
|
||||
void FractoriumSettings::FinalYAxisUp(bool b) { setValue(FINALYAXISUP, b); }
|
||||
|
||||
bool FractoriumSettings::FinalTransparency() { return value(FINALTRANSPARENCY).toBool(); }
|
||||
void FractoriumSettings::FinalTransparency(bool b) { setValue(FINALTRANSPARENCY, b); }
|
||||
bool FractoriumSettings::FinalTransparency() { return value(FINALTRANSPARENCY).toBool(); }
|
||||
void FractoriumSettings::FinalTransparency(bool b) { setValue(FINALTRANSPARENCY, b); }
|
||||
|
||||
bool FractoriumSettings::FinalOpenCL() { return value(FINALOPENCL).toBool(); }
|
||||
void FractoriumSettings::FinalOpenCL(bool b) { setValue(FINALOPENCL, b); }
|
||||
bool FractoriumSettings::FinalOpenCL() { return value(FINALOPENCL).toBool(); }
|
||||
void FractoriumSettings::FinalOpenCL(bool b) { setValue(FINALOPENCL, b); }
|
||||
|
||||
bool FractoriumSettings::FinalDouble() { return value(FINALDOUBLEPRECISION).toBool(); }
|
||||
void FractoriumSettings::FinalDouble(bool b) { setValue(FINALDOUBLEPRECISION, b); }
|
||||
bool FractoriumSettings::FinalDouble() { return value(FINALDOUBLEPRECISION).toBool(); }
|
||||
void FractoriumSettings::FinalDouble(bool b) { setValue(FINALDOUBLEPRECISION, b); }
|
||||
|
||||
bool FractoriumSettings::FinalSaveXml() { return value(FINALSAVEXML).toBool(); }
|
||||
void FractoriumSettings::FinalSaveXml(bool b) { setValue(FINALSAVEXML, b); }
|
||||
bool FractoriumSettings::FinalSaveXml() { return value(FINALSAVEXML).toBool(); }
|
||||
void FractoriumSettings::FinalSaveXml(bool b) { setValue(FINALSAVEXML, b); }
|
||||
|
||||
bool FractoriumSettings::FinalDoAll() { return value(FINALDOALL).toBool(); }
|
||||
void FractoriumSettings::FinalDoAll(bool b) { setValue(FINALDOALL, b); }
|
||||
bool FractoriumSettings::FinalDoAll() { return value(FINALDOALL).toBool(); }
|
||||
void FractoriumSettings::FinalDoAll(bool b) { setValue(FINALDOALL, b); }
|
||||
|
||||
bool FractoriumSettings::FinalDoSequence() { return value(FINALDOSEQUENCE).toBool(); }
|
||||
void FractoriumSettings::FinalDoSequence(bool b) { setValue(FINALDOSEQUENCE, b); }
|
||||
bool FractoriumSettings::FinalDoSequence() { return value(FINALDOSEQUENCE).toBool(); }
|
||||
void FractoriumSettings::FinalDoSequence(bool b) { setValue(FINALDOSEQUENCE, b); }
|
||||
|
||||
bool FractoriumSettings::FinalPng16Bit() { return value(FINALPNG16BIT).toBool(); }
|
||||
void FractoriumSettings::FinalPng16Bit(bool b) { setValue(FINALPNG16BIT, b); }
|
||||
bool FractoriumSettings::FinalPng16Bit() { return value(FINALPNG16BIT).toBool(); }
|
||||
void FractoriumSettings::FinalPng16Bit(bool b) { setValue(FINALPNG16BIT, b); }
|
||||
|
||||
bool FractoriumSettings::FinalKeepAspect() { return value(FINALKEEPASPECT).toBool(); }
|
||||
void FractoriumSettings::FinalKeepAspect(bool b) { setValue(FINALKEEPASPECT, b); }
|
||||
bool FractoriumSettings::FinalKeepAspect() { return value(FINALKEEPASPECT).toBool(); }
|
||||
void FractoriumSettings::FinalKeepAspect(bool b) { setValue(FINALKEEPASPECT, b); }
|
||||
|
||||
uint FractoriumSettings::FinalScale() { return value(FINALSCALE).toUInt(); }
|
||||
void FractoriumSettings::FinalScale(uint i) { setValue(FINALSCALE, i); }
|
||||
uint FractoriumSettings::FinalScale() { return value(FINALSCALE).toUInt(); }
|
||||
void FractoriumSettings::FinalScale(uint i) { setValue(FINALSCALE, i); }
|
||||
|
||||
QString FractoriumSettings::FinalExt() { return value(FINALEXT).toString(); }
|
||||
void FractoriumSettings::FinalExt(const QString& s) { setValue(FINALEXT, s); }
|
||||
QString FractoriumSettings::FinalExt() { return value(FINALEXT).toString(); }
|
||||
void FractoriumSettings::FinalExt(const QString& s) { setValue(FINALEXT, s); }
|
||||
|
||||
QList<QVariant> FractoriumSettings::FinalDevices() { return value(FINALDEVICES).toList(); }
|
||||
void FractoriumSettings::FinalDevices(const QList<QVariant>& devices) { setValue(FINALDEVICES, devices); }
|
||||
QList<QVariant> FractoriumSettings::FinalDevices() { return value(FINALDEVICES).toList(); }
|
||||
void FractoriumSettings::FinalDevices(const QList<QVariant>& devices) { setValue(FINALDEVICES, devices); }
|
||||
|
||||
uint FractoriumSettings::FinalThreadCount() { return value(FINALTHREADCOUNT).toUInt(); }
|
||||
void FractoriumSettings::FinalThreadCount(uint i) { setValue(FINALTHREADCOUNT, i); }
|
||||
uint FractoriumSettings::FinalThreadCount() { return value(FINALTHREADCOUNT).toUInt(); }
|
||||
void FractoriumSettings::FinalThreadCount(uint i) { setValue(FINALTHREADCOUNT, i); }
|
||||
|
||||
int FractoriumSettings::FinalThreadPriority() { return value(FINALTHREADPRIORITY).toInt(); }
|
||||
void FractoriumSettings::FinalThreadPriority(int i) { setValue(FINALTHREADPRIORITY, i); }
|
||||
int FractoriumSettings::FinalThreadPriority() { return value(FINALTHREADPRIORITY).toInt(); }
|
||||
void FractoriumSettings::FinalThreadPriority(int i) { setValue(FINALTHREADPRIORITY, i); }
|
||||
|
||||
uint FractoriumSettings::FinalQuality() { return value(FINALQUALITY).toUInt(); }
|
||||
void FractoriumSettings::FinalQuality(uint i) { setValue(FINALQUALITY, i); }
|
||||
double FractoriumSettings::FinalOpenCLSubBatchPct() { return value(FINALOPENCLSUBBATCHPCT).toDouble(); }
|
||||
void FractoriumSettings::FinalOpenCLSubBatchPct(double d) { setValue(FINALOPENCLSUBBATCHPCT, d); }
|
||||
|
||||
uint FractoriumSettings::FinalTemporalSamples() { return value(FINALTEMPORALSAMPLES).toUInt(); }
|
||||
void FractoriumSettings::FinalTemporalSamples(uint i) { setValue(FINALTEMPORALSAMPLES, i); }
|
||||
uint FractoriumSettings::FinalQuality() { return value(FINALQUALITY).toUInt(); }
|
||||
void FractoriumSettings::FinalQuality(uint i) { setValue(FINALQUALITY, i); }
|
||||
|
||||
uint FractoriumSettings::FinalSupersample() { return value(FINALSUPERSAMPLE).toUInt(); }
|
||||
void FractoriumSettings::FinalSupersample(uint i) { setValue(FINALSUPERSAMPLE, i); }
|
||||
uint FractoriumSettings::FinalTemporalSamples() { return value(FINALTEMPORALSAMPLES).toUInt(); }
|
||||
void FractoriumSettings::FinalTemporalSamples(uint i) { setValue(FINALTEMPORALSAMPLES, i); }
|
||||
|
||||
size_t FractoriumSettings::FinalStrips() { return value(FINALSTRIPS).toULongLong(); }
|
||||
void FractoriumSettings::FinalStrips(size_t i) { setValue(FINALSTRIPS, uint(i)); }
|
||||
uint FractoriumSettings::FinalSupersample() { return value(FINALSUPERSAMPLE).toUInt(); }
|
||||
void FractoriumSettings::FinalSupersample(uint i) { setValue(FINALSUPERSAMPLE, i); }
|
||||
|
||||
size_t FractoriumSettings::FinalStrips() { return value(FINALSTRIPS).toULongLong(); }
|
||||
void FractoriumSettings::FinalStrips(size_t i) { setValue(FINALSTRIPS, uint(i)); }
|
||||
|
||||
/// <summary>
|
||||
/// Xml file saving settings.
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define OPENCLDEFILTER "render/opencldefilter"
|
||||
#define CPUSUBBATCH "render/cpusubbatch"
|
||||
#define OPENCLSUBBATCH "render/openclsubbatch"
|
||||
#define OPENCLSUBBATCHPCT "render/openclsubbatchpct"
|
||||
#define RANDOMCOUNT "render/randomcount"
|
||||
#define CPUQUALITY "render/cpuquality"
|
||||
#define OPENCLQUALITY "render/openclquality"
|
||||
@ -50,25 +51,26 @@
|
||||
#define VARFILTERPARAM "varfilter/paramcheckbox"
|
||||
#define VARFILTERNONPARAM "varfilter/nonparamcheckbox"
|
||||
|
||||
#define FINALEARLYCLIP "finalrender/earlyclip"
|
||||
#define FINALYAXISUP "finalrender/finalyaxisup"
|
||||
#define FINALTRANSPARENCY "finalrender/transparency"
|
||||
#define FINALOPENCL "finalrender/opencl"
|
||||
#define FINALDOUBLEPRECISION "finalrender/dp64"
|
||||
#define FINALSAVEXML "finalrender/savexml"
|
||||
#define FINALDOALL "finalrender/doall"
|
||||
#define FINALDOSEQUENCE "finalrender/dosequence"
|
||||
#define FINALPNG16BIT "finalrender/png16bit"
|
||||
#define FINALKEEPASPECT "finalrender/keepaspect"
|
||||
#define FINALSCALE "finalrender/scale"
|
||||
#define FINALEXT "finalrender/ext"
|
||||
#define FINALDEVICES "finalrender/devices"
|
||||
#define FINALTHREADCOUNT "finalrender/threadcount"
|
||||
#define FINALTHREADPRIORITY "finalrender/threadpriority"
|
||||
#define FINALQUALITY "finalrender/quality"
|
||||
#define FINALTEMPORALSAMPLES "finalrender/temporalsamples"
|
||||
#define FINALSUPERSAMPLE "finalrender/supersample"
|
||||
#define FINALSTRIPS "finalrender/strips"
|
||||
#define FINALEARLYCLIP "finalrender/earlyclip"
|
||||
#define FINALYAXISUP "finalrender/finalyaxisup"
|
||||
#define FINALTRANSPARENCY "finalrender/transparency"
|
||||
#define FINALOPENCL "finalrender/opencl"
|
||||
#define FINALDOUBLEPRECISION "finalrender/dp64"
|
||||
#define FINALSAVEXML "finalrender/savexml"
|
||||
#define FINALDOALL "finalrender/doall"
|
||||
#define FINALDOSEQUENCE "finalrender/dosequence"
|
||||
#define FINALPNG16BIT "finalrender/png16bit"
|
||||
#define FINALKEEPASPECT "finalrender/keepaspect"
|
||||
#define FINALSCALE "finalrender/scale"
|
||||
#define FINALEXT "finalrender/ext"
|
||||
#define FINALDEVICES "finalrender/devices"
|
||||
#define FINALTHREADCOUNT "finalrender/threadcount"
|
||||
#define FINALTHREADPRIORITY "finalrender/threadpriority"
|
||||
#define FINALOPENCLSUBBATCHPCT "finalrender/openclsubbatchpct"
|
||||
#define FINALQUALITY "finalrender/quality"
|
||||
#define FINALTEMPORALSAMPLES "finalrender/temporalsamples"
|
||||
#define FINALSUPERSAMPLE "finalrender/supersample"
|
||||
#define FINALSTRIPS "finalrender/strips"
|
||||
|
||||
#define XMLWIDTH "xml/width"
|
||||
#define XMLHEIGHT "xml/height"
|
||||
@ -157,6 +159,9 @@ public:
|
||||
uint CpuSubBatch();
|
||||
void CpuSubBatch(uint i);
|
||||
|
||||
double OpenCLSubBatchPct();
|
||||
void OpenCLSubBatchPct(double d);
|
||||
|
||||
uint OpenCLSubBatch();
|
||||
void OpenCLSubBatch(uint i);
|
||||
|
||||
@ -274,6 +279,9 @@ public:
|
||||
int FinalThreadPriority();
|
||||
void FinalThreadPriority(int b);
|
||||
|
||||
double FinalOpenCLSubBatchPct();
|
||||
void FinalOpenCLSubBatchPct(double d);
|
||||
|
||||
uint FinalQuality();
|
||||
void FinalQuality(uint i);
|
||||
|
||||
|
@ -128,6 +128,8 @@ void Fractorium::OnActionStartStopRenderer(bool checked)
|
||||
/// <param name="checked">Check state, show editor if true, else hide.</param>
|
||||
void Fractorium::OnActionDrawXforms(bool checked)
|
||||
{
|
||||
m_Settings->ShowXforms(checked);
|
||||
|
||||
if (!ui.ActionDrawImage->isChecked() && !ui.ActionDrawXforms->isChecked())
|
||||
ui.ActionDrawImage->setChecked(true);
|
||||
|
||||
|
@ -18,13 +18,17 @@ void Fractorium::InitXaosUI()
|
||||
m_XaosSpinBox->setDecimals(XAOS_PREC);
|
||||
m_XaosSpinBox->setObjectName("XaosSpinBox");
|
||||
m_XaosTableModel = nullptr;
|
||||
m_AppliedXaosTableModel = nullptr;
|
||||
m_XaosTableItemDelegate = new DoubleSpinBoxTableItemDelegate(m_XaosSpinBox, this);
|
||||
connect(m_XaosSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnXaosChanged(double)), Qt::QueuedConnection);
|
||||
connect(ui.ClearXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnClearXaosButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.RandomXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnRandomXaosButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.TransposeXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnTransposeXaosButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.AddLayerButton, SIGNAL(clicked(bool)), this, SLOT(OnAddLayerButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.XaosTableView->verticalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnXaosRowDoubleClicked(int)), Qt::QueuedConnection);
|
||||
connect(ui.XaosTableView->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnXaosColDoubleClicked(int)), Qt::QueuedConnection);
|
||||
connect(ui.XaosTableView->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(OnXaosHScrollValueChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.XaosTableView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(OnXaosVScrollValueChanged(int)), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -49,6 +53,62 @@ void FractoriumEmberController<T>::FillXaos()
|
||||
m_Fractorium->ui.XaosTableView->resizeColumnsToContents();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill the xaos table with the xaos values applied to the xform weights from the ember.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillAppliedXaos()
|
||||
{
|
||||
m_Ember.CalcNormalizedWeights(m_NormalizedWeights);
|
||||
|
||||
for (int i = 0, count = int(XformCount()); i < count; i++)//Column.
|
||||
{
|
||||
if (auto xform = m_Ember.GetXform(i))
|
||||
{
|
||||
T norm = 0;
|
||||
double start = 0, offset = 0;
|
||||
auto tempweights = m_NormalizedWeights;
|
||||
|
||||
for (int j = 0; j < count; j++)//Row.
|
||||
{
|
||||
tempweights[j] *= xform->Xaos(j);
|
||||
QModelIndex index = m_Fractorium->m_AppliedXaosTableModel->index(j, i, QModelIndex());//j and i are intentionally swapped here.
|
||||
m_Fractorium->m_AppliedXaosTableModel->setData(index, TruncPrecision(xform->Xaos(j) * xform->m_Weight, 4));//Applied xaos is just a read only table for display purposes.
|
||||
}
|
||||
|
||||
QPixmap pixmap(m_Fractorium->ui.XaosAppliedTableView->columnWidth(i) - 8, m_Fractorium->ui.XaosTableView->rowHeight(0) * count);
|
||||
QPainter painter(&pixmap);
|
||||
auto twi = new QTableWidgetItem();
|
||||
|
||||
for (auto& w : tempweights) norm += w;
|
||||
|
||||
for (auto& w : tempweights) w = norm == T(0) ? T(0) : w / norm;
|
||||
|
||||
if (norm)
|
||||
{
|
||||
for (size_t i = 0; i < tempweights.size() && offset <= pixmap.height(); i++)
|
||||
{
|
||||
offset = std::min<T>(offset + tempweights[i] * pixmap.height(), pixmap.height());
|
||||
painter.fillRect(0, start, pixmap.width(), offset, m_Fractorium->m_XformComboColors[i % XFORM_COLOR_COUNT]);
|
||||
start = offset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.fillRect(0, 0, pixmap.width(), pixmap.height(), m_Fractorium->m_XformComboColors[0]);
|
||||
}
|
||||
|
||||
twi->setData(Qt::DecorationRole, pixmap);
|
||||
m_Fractorium->ui.XaosDistVizTableWidget->setItem(0, i, twi);
|
||||
}
|
||||
}
|
||||
|
||||
m_Fractorium->ui.XaosDistVizTableWidget->resizeRowsToContents();
|
||||
m_Fractorium->ui.XaosDistVizTableWidget->resizeColumnsToContents();
|
||||
m_Fractorium->ui.XaosAppliedTableView->resizeRowsToContents();
|
||||
m_Fractorium->ui.XaosAppliedTableView->resizeColumnsToContents();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the xaos value.
|
||||
/// Called when any xaos spinner is changed.
|
||||
@ -68,7 +128,10 @@ void FractoriumEmberController<T>::XaosChanged(int x, int y, double val)
|
||||
|
||||
if (auto xform = m_Ember.GetXform(x))
|
||||
if (!IsClose<T>(newVal, xform->Xaos(y), T(1e-7)))
|
||||
{
|
||||
Update([&] { xform->SetXaos(y, newVal); });
|
||||
FillAppliedXaos();
|
||||
}
|
||||
}
|
||||
|
||||
void Fractorium::OnXaosChanged(double d)
|
||||
@ -91,13 +154,14 @@ void Fractorium::OnXaosTableModelDataChanged(const QModelIndex& indexA, const QM
|
||||
void Fractorium::FillXaosTable()
|
||||
{
|
||||
int count = int(m_Controller->XformCount());
|
||||
QStringList hl, vl;
|
||||
QStringList hl, vl, blanks;
|
||||
auto oldModel = std::make_unique<QStandardItemModel>(m_XaosTableModel);
|
||||
hl.reserve(count);
|
||||
vl.reserve(count);
|
||||
blanks.push_back("");
|
||||
m_XaosTableModel = new QStandardItemModel(count, count, this);
|
||||
m_AppliedXaosTableModel = new QStandardItemModel(count, count, this);
|
||||
connect(m_XaosTableModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), SLOT(OnXaosTableModelDataChanged(QModelIndex, QModelIndex)));
|
||||
ui.XaosTableView->blockSignals(true);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
@ -108,14 +172,30 @@ void Fractorium::FillXaosTable()
|
||||
|
||||
m_XaosTableModel->setHorizontalHeaderLabels(hl);
|
||||
m_XaosTableModel->setVerticalHeaderLabels(vl);
|
||||
m_AppliedXaosTableModel->setHorizontalHeaderLabels(hl);
|
||||
m_AppliedXaosTableModel->setVerticalHeaderLabels(vl);
|
||||
ui.XaosDistVizTableWidget->setRowCount(1);
|
||||
ui.XaosDistVizTableWidget->setColumnCount(count);
|
||||
ui.XaosDistVizTableWidget->setHorizontalHeaderLabels(hl);
|
||||
ui.XaosDistVizTableWidget->setVerticalHeaderLabels(blanks);
|
||||
ui.XaosDistVizTableWidget->verticalHeader()->setSectionsClickable(false);
|
||||
ui.XaosDistVizTableWidget->horizontalHeader()->setSectionsClickable(false);
|
||||
ui.XaosTableView->setModel(m_XaosTableModel);
|
||||
ui.XaosTableView->setItemDelegate(m_XaosTableItemDelegate);
|
||||
ui.XaosAppliedTableView->setModel(m_AppliedXaosTableModel);
|
||||
ui.XaosTableView->setItemDelegate(m_XaosTableItemDelegate);//No need for a delegate on the applied table because it's read-only.
|
||||
ui.XaosDistVizTableWidget->verticalHeader()->setFixedWidth(ui.XaosTableView->verticalHeader()->width());
|
||||
SetTabOrder(this, ui.ClearXaosButton, ui.RandomXaosButton);
|
||||
ui.XaosDistVizTableWidget->setRowHeight(0, ui.XaosTableView->rowHeight(0) * count);
|
||||
m_Controller->FillXaos();
|
||||
ui.XaosTableView->blockSignals(false);
|
||||
m_Controller->FillAppliedXaos();
|
||||
//Needed to get the dark stylesheet to correctly color the top left corner button.
|
||||
auto widgetList = ui.XaosTableView->findChildren<QAbstractButton*>();
|
||||
|
||||
for (auto& it : widgetList)
|
||||
it->setEnabled(true);
|
||||
|
||||
widgetList = ui.XaosAppliedTableView->findChildren<QAbstractButton*>();
|
||||
|
||||
for (auto& it : widgetList)
|
||||
it->setEnabled(true);
|
||||
}
|
||||
@ -128,6 +208,7 @@ void FractoriumEmberController<T>::ClearXaos()
|
||||
{
|
||||
Update([&] { m_Ember.ClearXaos(); });
|
||||
FillXaos();
|
||||
FillAppliedXaos();
|
||||
}
|
||||
|
||||
void Fractorium::OnClearXaosButtonClicked(bool checked) { m_Controller->ClearXaos(); }
|
||||
@ -143,21 +224,21 @@ void FractoriumEmberController<T>::RandomXaos()
|
||||
{
|
||||
Update([&]
|
||||
{
|
||||
for (size_t i = 0; i < m_Ember.XformCount(); i++)
|
||||
size_t i = 0;
|
||||
|
||||
while (auto xform = m_Ember.GetXform(i++))
|
||||
{
|
||||
if (auto xform = m_Ember.GetXform(i))
|
||||
for (size_t j = 0; j < m_Ember.XformCount(); j++)
|
||||
{
|
||||
for (size_t j = 0; j < m_Ember.XformCount(); j++)
|
||||
{
|
||||
if (m_Rand.RandBit())
|
||||
xform->SetXaos(j, T(m_Rand.RandBit()));
|
||||
else
|
||||
xform->SetXaos(j, m_Rand.Frand<T>(0, 3));
|
||||
}
|
||||
if (m_Rand.RandBit())
|
||||
xform->SetXaos(j, T(m_Rand.RandBit()));
|
||||
else
|
||||
xform->SetXaos(j, TruncPrecision(m_Rand.Frand<T>(0, 3), 3));
|
||||
}
|
||||
}
|
||||
});
|
||||
FillXaos();
|
||||
FillAppliedXaos();
|
||||
}
|
||||
|
||||
void Fractorium::OnRandomXaosButtonClicked(bool checked) { m_Controller->RandomXaos(); }
|
||||
@ -169,6 +250,7 @@ void Fractorium::OnRandomXaosButtonClicked(bool checked) { m_Controller->RandomX
|
||||
/// From existing to new: 0.
|
||||
/// From new to existing: 0.
|
||||
/// From new to new: 1.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="xforms">The number of new xforms to add to create the layer</param>
|
||||
template <typename T>
|
||||
@ -186,6 +268,41 @@ void FractoriumEmberController<T>::AddLayer(int xforms)
|
||||
|
||||
void Fractorium::OnAddLayerButtonClicked(bool checked) { m_Controller->AddLayer(ui.AddLayerSpinBox->value()); }
|
||||
|
||||
/// <summary>
|
||||
/// Flip the row and column values of the xaos table.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::TransposeXaos()
|
||||
{
|
||||
Update([&]
|
||||
{
|
||||
size_t i = 0, j = 0;
|
||||
vector<vector<double>> tempxaos;
|
||||
tempxaos.reserve(m_Ember.XformCount());
|
||||
|
||||
while (auto xform = m_Ember.GetXform(i++))
|
||||
{
|
||||
vector<double> tempvec;
|
||||
tempvec.reserve(m_Ember.XformCount());
|
||||
|
||||
for (j = 0; j < m_Ember.XformCount(); j++)
|
||||
tempvec.push_back(xform->Xaos(j));
|
||||
|
||||
tempxaos.push_back(std::move(tempvec));
|
||||
}
|
||||
|
||||
for (j = 0; j < tempxaos.size(); j++)
|
||||
for (i = 0; i < tempxaos[j].size(); i++)
|
||||
if (auto xform = m_Ember.GetXform(i))
|
||||
xform->SetXaos(j, T(tempxaos[j][i]));
|
||||
});
|
||||
FillXaos();
|
||||
FillAppliedXaos();
|
||||
}
|
||||
|
||||
void Fractorium::OnTransposeXaosButtonClicked(bool checked) { m_Controller->TransposeXaos(); }
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all xaos values in one row on left mouse button double click and resize all cells to fit their data.
|
||||
/// Skip toggling and only refit on right mouse button double click.
|
||||
@ -201,6 +318,7 @@ void Fractorium::OnXaosRowDoubleClicked(int logicalIndex)
|
||||
|
||||
ui.XaosTableView->resizeRowsToContents();
|
||||
ui.XaosTableView->resizeColumnsToContents();
|
||||
m_Controller->FillAppliedXaos();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -218,6 +336,33 @@ void Fractorium::OnXaosColDoubleClicked(int logicalIndex)
|
||||
|
||||
ui.XaosTableView->resizeRowsToContents();
|
||||
ui.XaosTableView->resizeColumnsToContents();
|
||||
m_Controller->FillAppliedXaos();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Take the value of the horizontal scrollbar on the xaos table and set the same
|
||||
/// horizontal scroll bar position on XaosDistVizTableWidget and XaosAppliedTableView.
|
||||
/// This allows them to easily see the same part of all three tables at the same time
|
||||
/// when there are more xforms than can fit on the screen at once.
|
||||
/// </summary>
|
||||
/// <param name="value">The value of the xaos table horizontal scroll bar</param>
|
||||
void Fractorium::OnXaosHScrollValueChanged(int value)
|
||||
{
|
||||
ui.XaosDistVizTableWidget->horizontalScrollBar()->setValue(value);
|
||||
ui.XaosAppliedTableView->horizontalScrollBar()->setValue(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Take the value of the vertical scrollbar on the xaos table and set the same
|
||||
/// vertical scroll bar position on XaosDistVizTableWidget and XaosAppliedTableView.
|
||||
/// This allows them to easily see the same part of all three tables at the same time
|
||||
/// when there are more xforms than can fit on the screen at once.
|
||||
/// </summary>
|
||||
/// <param name="value">The value of the xaos table vertical scroll bar</param>
|
||||
void Fractorium::OnXaosVScrollValueChanged(int value)
|
||||
{
|
||||
ui.XaosDistVizTableWidget->verticalScrollBar()->setValue(value);
|
||||
ui.XaosAppliedTableView->verticalScrollBar()->setValue(value);
|
||||
}
|
||||
|
||||
template class FractoriumEmberController<float>;
|
||||
|
@ -24,7 +24,6 @@ void Fractorium::InitXformsUI()
|
||||
m_XformWeightSpinnerButtonWidget = new SpinnerLabelButtonWidget(m_XformWeightSpin, "=", 20, 19, ui.XformWeightNameTable);
|
||||
m_XformWeightSpinnerButtonWidget->m_SpinBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
m_XformWeightSpinnerButtonWidget->m_Label->setStyleSheet("border: 0px;");
|
||||
m_XformWeightSpinnerButtonWidget->m_Label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
m_XformWeightSpinnerButtonWidget->m_Label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
m_XformWeightSpinnerButtonWidget->m_Button->setToolTip("Equalize weights");
|
||||
m_XformWeightSpinnerButtonWidget->m_Button->setStyleSheet("text-align: center center");
|
||||
@ -380,8 +379,11 @@ void FractoriumEmberController<T>::XformWeightChanged(double d)
|
||||
xform->m_Weight = d;
|
||||
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL);
|
||||
SetNormalizedWeightText(CurrentXform());
|
||||
FillAppliedXaos();
|
||||
}
|
||||
|
||||
void Fractorium::OnXformWeightChanged(double d) { m_Controller->XformWeightChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Equalize the weights of all xforms in the ember.
|
||||
/// </summary>
|
||||
@ -393,8 +395,11 @@ void FractoriumEmberController<T>::EqualizeWeights()
|
||||
m_Ember.EqualizeWeights();
|
||||
m_Fractorium->m_XformWeightSpin->setValue(xform->m_Weight);//Will trigger an update, so pass false to updateRender below.
|
||||
}, eXformUpdate::UPDATE_CURRENT, false);
|
||||
FillAppliedXaos();
|
||||
}
|
||||
|
||||
void Fractorium::OnEqualWeightButtonClicked(bool checked) { m_Controller->EqualizeWeights(); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the current xform.
|
||||
/// Update the corresponding xform checkbox text with the name.
|
||||
|
@ -667,9 +667,9 @@ void FractoriumEmberController<T>::FillAffineWithXform(Xform<T>* xform, bool pre
|
||||
|
||||
if (m_Fractorium->ui.PolarAffineCheckBox->isChecked())
|
||||
{
|
||||
spinners[0]->SetValueStealth(RAD_2_DEG * std::atan2(affine.D(), affine.A()));
|
||||
spinners[1]->SetValueStealth(RAD_2_DEG * std::atan2(affine.E(), affine.B()));
|
||||
spinners[2]->SetValueStealth(RAD_2_DEG * std::atan2(affine.F(), affine.C()));
|
||||
spinners[0]->SetValueStealth(NormalizeDeg360(RAD_2_DEG * std::atan2(affine.D(), affine.A())));
|
||||
spinners[1]->SetValueStealth(NormalizeDeg360(RAD_2_DEG * std::atan2(affine.E(), affine.B())));
|
||||
spinners[2]->SetValueStealth(NormalizeDeg360(RAD_2_DEG * std::atan2(affine.F(), affine.C())));
|
||||
spinners[3]->SetValueStealth(VarFuncs<T>::Hypot(affine.D(), affine.A()));
|
||||
spinners[4]->SetValueStealth(VarFuncs<T>::Hypot(affine.E(), affine.B()));
|
||||
spinners[5]->SetValueStealth(VarFuncs<T>::Hypot(affine.F(), affine.C()));
|
||||
|
@ -16,10 +16,10 @@ void Fractorium::InitXformsColorUI()
|
||||
ui.XformPaletteRefTable->setItem(0, 0, m_PaletteRefItem);
|
||||
ui.XformPaletteRefTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
connect(ui.XformPaletteRefTable->horizontalHeader(), SIGNAL(sectionResized(int, int, int)), this, SLOT(OnXformRefPaletteResized(int, int, int)), Qt::QueuedConnection);
|
||||
connect(ui.RandomColorIndicesButton, SIGNAL(clicked(bool)), this, SLOT(OnRandomColorIndicesButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ToggleColorIndicesButton, SIGNAL(clicked(bool)), this, SLOT(OnToggleColorIndicesButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.RandomColorSpeedButton, SIGNAL(clicked(bool)), this, SLOT(OnRandomColorSpeedButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ToggleColorSpeedButton, SIGNAL(clicked(bool)), this, SLOT(OnToggleColorSpeedButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.RandomColorIndicesButton, SIGNAL(clicked(bool)), this, SLOT(OnRandomColorIndicesButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ToggleColorIndicesButton, SIGNAL(clicked(bool)), this, SLOT(OnToggleColorIndicesButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.RandomColorSpeedButton, SIGNAL(clicked(bool)), this, SLOT(OnRandomColorSpeedButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ToggleColorSpeedsButton, SIGNAL(clicked(bool)), this, SLOT(OnToggleColorSpeedsButtonClicked(bool)), Qt::QueuedConnection);
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.XformColorIndexTable, this, row, 1, m_XformColorIndexSpin, spinHeight, 0, 1, 0.01, SIGNAL(valueChanged(double)), SLOT(OnXformColorIndexChanged(double)), false, 0, 1, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.XformColorValuesTable, this, row, 1, m_XformColorSpeedSpin, spinHeight, -1, 1, 0.1, SIGNAL(valueChanged(double)), SLOT(OnXformColorSpeedChanged(double)), true, 0.5, 0.5, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.XformColorValuesTable, this, row, 1, m_XformOpacitySpin, spinHeight, 0, 1, 0.1, SIGNAL(valueChanged(double)), SLOT(OnXformOpacityChanged(double)), true, 1, 1, 0);
|
||||
@ -137,13 +137,13 @@ void Fractorium::OnRandomColorSpeedButtonClicked(bool b) { m_Controller->RandomC
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ToggleColorSpeedButtonClicked()
|
||||
void FractoriumEmberController<T>::ToggleColorSpeedsButtonClicked()
|
||||
{
|
||||
char ch = 1;
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex) { xform->m_ColorSpeed = (T(ch ^= 1) ? 0.5 : 0.0); }, eXformUpdate::UPDATE_ALL);
|
||||
m_Fractorium->m_XformColorSpeedSpin->SetValueStealth(CurrentXform()->m_ColorSpeed);
|
||||
}
|
||||
void Fractorium::OnToggleColorSpeedButtonClicked(bool b) { m_Controller->ToggleColorSpeedButtonClicked(); }
|
||||
void Fractorium::OnToggleColorSpeedsButtonClicked(bool b) { m_Controller->ToggleColorSpeedsButtonClicked(); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the color speed of the selected xforms.
|
||||
|
@ -49,6 +49,7 @@ FractoriumOptionsDialog::FractoriumOptionsDialog(QWidget* p, Qt::WindowFlags f)
|
||||
ui.OpenCLCheckBox->setEnabled(false);
|
||||
ui.SharedTextureCheckBox->setChecked(false);
|
||||
ui.SharedTextureCheckBox->setEnabled(false);
|
||||
ui.OpenCLSubBatchPctSpin->setEnabled(false);
|
||||
ui.OpenCLSubBatchSpin->setEnabled(false);
|
||||
ui.OpenCLQualitySpin->setEnabled(false);
|
||||
ui.OpenCLFilteringDERadioButton->setEnabled(false);
|
||||
@ -132,6 +133,7 @@ void FractoriumOptionsDialog::OnOpenCLCheckBoxStateChanged(int state)
|
||||
ui.ThreadCountSpin->setEnabled(!checked);
|
||||
ui.CpuSubBatchSpin->setEnabled(!checked);
|
||||
ui.SharedTextureCheckBox->setEnabled(checked);
|
||||
ui.OpenCLSubBatchPctSpin->setEnabled(checked);
|
||||
ui.OpenCLSubBatchSpin->setEnabled(checked);
|
||||
ui.OpenCLQualitySpin->setEnabled(checked);
|
||||
ui.CpuQualitySpin->setEnabled(!checked);
|
||||
@ -197,6 +199,7 @@ void FractoriumOptionsDialog::GuiToData()
|
||||
m_Settings->CpuQuality(CpuQuality());
|
||||
m_Settings->OpenClQuality(OpenClQuality());
|
||||
m_Settings->CpuSubBatch(ui.CpuSubBatchSpin->value());
|
||||
m_Settings->OpenCLSubBatchPct(ui.OpenCLSubBatchPctSpin->value());
|
||||
m_Settings->OpenCLSubBatch(ui.OpenCLSubBatchSpin->value());
|
||||
m_Settings->CpuDEFilter(ui.CpuFilteringDERadioButton->isChecked());
|
||||
m_Settings->OpenCLDEFilter(ui.OpenCLFilteringDERadioButton->isChecked());
|
||||
@ -236,6 +239,7 @@ void FractoriumOptionsDialog::DataToGui()
|
||||
ui.CpuQualitySpin->setValue(m_Settings->CpuQuality());
|
||||
ui.OpenCLQualitySpin->setValue(m_Settings->OpenClQuality());
|
||||
ui.CpuSubBatchSpin->setValue(m_Settings->CpuSubBatch());
|
||||
ui.OpenCLSubBatchPctSpin->setValue(m_Settings->OpenCLSubBatchPct());
|
||||
ui.OpenCLSubBatchSpin->setValue(m_Settings->OpenCLSubBatch());
|
||||
SettingsToDeviceTable(ui.DeviceTable, devices);
|
||||
|
||||
|
@ -248,7 +248,7 @@
|
||||
</item>
|
||||
<item row="16" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="InteractiveRenderingTabGridLayout">
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QGroupBox" name="InteraciveGpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>OpenCL Filtering</string>
|
||||
@ -292,7 +292,42 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="OpenCLQualitySpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default quality per device to use for the interactive renderer when using OpenCL.</p><p>30 is a good number for this, but you can use a larger value if you have a faster GPU.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Quality </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QSpinBox" name="OpenCLSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of ~8M iteration chunks ran using OpenCL in interactive mode for each mouse movement.</p><p>Increase this number for a higher quality image on each mouse movement, at the expense of responsiveness.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Chunks per Mouse Movement </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QGroupBox" name="InteraciveCpuFilteringGroupBox">
|
||||
<property name="title">
|
||||
<string>CPU Filtering</string>
|
||||
@ -339,69 +374,13 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QSpinBox" name="OpenCLSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of ~8M iteration chunks ran using OpenCL
|
||||
in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Sub Batch </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="OpenCLQualitySpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default quality to use for the interactive renderer when using OpenCL.</p><p>30 is a good number for this, but you can use a larger value if you have a faster GPU.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>OpenCL Quality </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>30</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="CpuQualitySpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default quality to use for the interactive renderer when using the CPU.</p><p>10 is a good number for this, but you can use a larger value if you have a faster system.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Quality </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="CpuSubBatchSpin">
|
||||
<property name="toolTip">
|
||||
<string>The number of 10,000 iteration chunks ran per thread on the CPU
|
||||
in interactive mode for each mouse movement</string>
|
||||
<string><html><head/><body><p>The number of ~10,000 iteration chunks ran per thread on the CPU in interactive mode for each mouse movement.</p><p>Increase this number for a higher quality image on each mouse movement, at the expense of responsiveness.</p><p>The number of iterations done in each chunk is controlled by the Sub Batch Size field in the Flame tab.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Sub Batch </string>
|
||||
<string>CPU Chunks per Mouse Movement </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
@ -411,6 +390,22 @@ in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QSpinBox" name="ThreadCountSpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of threads to use with CPU rendering.</p><p>Decrease for more responsive editing, increase for better performance.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Threads </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>64</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QSpinBox" name="RandomCountSpin">
|
||||
<property name="toolTip">
|
||||
@ -427,19 +422,47 @@ in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QSpinBox" name="ThreadCountSpin">
|
||||
<item row="2" column="0">
|
||||
<widget class="QDoubleSpinBox" name="OpenCLSubBatchPctSpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of threads to use with CPU rendering.</p><p>Decrease for more responsive editing, increase for better performance.</p></body></html></string>
|
||||
<string><html><head/><body><p>The percentage of a sub batch to execute on each thread per kernel call when using OpenCL in interactive mode. Default: 0.025 (256 iters).</p><p>Increase this number for a higher quality image on each mouse movement, at the expense of responsiveness.</p><p>Note that this can cause a crash and subsequent restart of the graphics driver if each kernel call takes too long. So reduce the value if you encounter such a problem.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>Threads </string>
|
||||
<string>OpenCL Sub Batch Percent Per Thread </string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.025000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="CpuQualitySpin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default quality to use for the interactive renderer when using the CPU.</p><p>10 is a good number for this, but you can use a larger value if you have a faster system.</p></body></html></string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>CPU Quality </string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>64</number>
|
||||
<number>99999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -538,7 +561,7 @@ in interactive mode for each mouse movement</string>
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="TableWidget" name="OptionsXmlSavingTable">
|
||||
<widget class="QTableWidget" name="OptionsXmlSavingTable">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -731,7 +754,7 @@ in interactive mode for each mouse movement</string>
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="TableWidget" name="OptionsIdentityTable">
|
||||
<widget class="QTableWidget" name="OptionsIdentityTable">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@ -922,13 +945,6 @@ in interactive mode for each mouse movement</string>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TableWidget</class>
|
||||
<extends>QTableWidget</extends>
|
||||
<header>TableWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>EarlyClipCheckBox</tabstop>
|
||||
<tabstop>OpenCLCheckBox</tabstop>
|
||||
@ -946,8 +962,9 @@ in interactive mode for each mouse movement</string>
|
||||
<tabstop>CpuSubBatchSpin</tabstop>
|
||||
<tabstop>RandomCountSpin</tabstop>
|
||||
<tabstop>OpenCLQualitySpin</tabstop>
|
||||
<tabstop>OpenCLSubBatchSpin</tabstop>
|
||||
<tabstop>OpenCLSubBatchPctSpin</tabstop>
|
||||
<tabstop>CpuQualitySpin</tabstop>
|
||||
<tabstop>OpenCLSubBatchSpin</tabstop>
|
||||
<tabstop>CpuFilteringLogRadioButton</tabstop>
|
||||
<tabstop>CpuFilteringDERadioButton</tabstop>
|
||||
<tabstop>OpenCLFilteringLogRadioButton</tabstop>
|
||||
|
@ -231,8 +231,11 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
|
@ -1,13 +1,11 @@
|
||||
#include "FractoriumPch.h"
|
||||
#include "PaletteEditor.h"
|
||||
#include "Fractorium.h"
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which passes parent widget to the base and sets up slots and other ui
|
||||
/// elements.
|
||||
/// This takes a reference to a palette list, which it then searches for user created palettes
|
||||
/// and only populates the combo box with those.
|
||||
/// </summary>
|
||||
/// <param name="paletteList">A reference to an existing palette list, gotten from the main window.</param>
|
||||
/// <param name="p">The parent widget</param>
|
||||
PaletteEditor::PaletteEditor(QWidget* p) :
|
||||
QDialog(p),
|
||||
@ -519,6 +517,7 @@ QStringList PaletteEditor::SetupOpenImagesDialog()
|
||||
m_FileDialog->setWindowTitle("Open Image");
|
||||
m_FileDialog->setDirectory(settings->OpenPaletteImageFolder());
|
||||
m_FileDialog->selectNameFilter("*.jpg");
|
||||
m_FileDialog->setSidebarUrls(dynamic_cast<Fractorium*>(parent())->Urls());
|
||||
}
|
||||
|
||||
if (m_FileDialog->exec() == QDialog::Accepted)
|
||||
|
@ -639,6 +639,7 @@ void QssDialog::SetupFileDialog()
|
||||
m_FileDialog->setViewMode(QFileDialog::List);
|
||||
m_FileDialog->setDirectory(m_Parent->m_SettingsPath);
|
||||
m_FileDialog->setOption(QFileDialog::DontUseNativeDialog, true);
|
||||
m_FileDialog->setSidebarUrls(dynamic_cast<Fractorium*>(parent())->Urls());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -176,6 +176,8 @@ bool SpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
m_MouseDownPoint = m_MouseMovePoint = me->pos();
|
||||
StartTimer();
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
else if (!m_Settings->ToggleType() &&
|
||||
me->type() == QMouseEvent::MouseButtonRelease &&
|
||||
@ -183,18 +185,22 @@ bool SpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
StopTimer();
|
||||
m_MouseDownPoint = m_MouseMovePoint = me->pos();
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
else if (!m_Settings->ToggleType() &&
|
||||
me->type() == QMouseEvent::MouseMove &&
|
||||
QGuiApplication::mouseButtons() & Qt::RightButton)
|
||||
{
|
||||
m_MouseMovePoint = me->pos();
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
else if (m_DoubleClick &&
|
||||
((!m_Settings->ToggleType() && e->type() == QMouseEvent::MouseButtonDblClick && me->button() == Qt::LeftButton) ||
|
||||
(m_Settings->ToggleType() && me->type() == QMouseEvent::MouseButtonRelease && me->button() == Qt::RightButton)))
|
||||
{
|
||||
if (IsClose(m_DoubleClickLowVal, value()))
|
||||
if (m_DoubleClickLowVal == value())
|
||||
{
|
||||
m_DoubleClickZeroEvent(this, m_DoubleClickZero);
|
||||
setValue(m_DoubleClickZero);
|
||||
@ -204,6 +210,9 @@ bool SpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
m_DoubleClickNonZeroEvent(this, m_DoubleClickNonZero);
|
||||
setValue(m_DoubleClickNonZero);
|
||||
}
|
||||
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -241,12 +250,16 @@ bool SpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
setValue(value() - (ctrl ? m_Step * 10 : m_Step));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<QKeyEvent*>(e))
|
||||
{
|
||||
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (dynamic_cast<QKeyEvent*>(e))
|
||||
{
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return QSpinBox::eventFilter(o, e);
|
||||
|
@ -7,20 +7,8 @@
|
||||
/// </summary>
|
||||
|
||||
/// <summary>
|
||||
/// The entire purpose for this subclass is to overcome a glaring flaw
|
||||
/// in the way Qt handles table drawing.
|
||||
/// For most of the tables Fractorium uses, it draw the grid lines. Qt draws them
|
||||
/// in a very naive manner, whereby it draws lines above the first row and below
|
||||
/// the last row. It also draws to the left of the first column and to the right
|
||||
/// of the last column. This has the effect of putting an additional border inside
|
||||
/// of the specified border. This extra border becomes very noticeable when changing
|
||||
/// the background color of a cell.
|
||||
/// The workaround is to scrunch the size of the table up by one pixel. However,
|
||||
/// since the viewable area is then smaller than the size of the table, it will scroll
|
||||
/// by one pixel if the mouse is hovered over the table and the user moves the mouse wheel.
|
||||
/// This subclass is done solely to filter out the mouse wheel event.
|
||||
/// Note that this filtering only applies to the table as a whole, which means
|
||||
/// mouse wheel events still get properly routed to spinners.
|
||||
/// The purpose of this subclass is to allow for dragging the contents of a table cell.
|
||||
/// It's used in the palette preview table.
|
||||
/// </summary>
|
||||
class TableWidget : public QTableWidget
|
||||
{
|
||||
@ -45,20 +33,15 @@ signals:
|
||||
protected:
|
||||
|
||||
/// <summary>
|
||||
/// Event filter to ignore mouse wheel events and also handle others such as mouse move and mouse button release.
|
||||
/// Event filter to handle dragging and releasing the mouse.
|
||||
/// Sadly, QTableWidget makes these hard to get to, so we must handle them here.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object sending the event</param>
|
||||
/// <param name="e">The event</param>
|
||||
/// <returns>True if mouse wheel, else return the result of calling the base fucntion.</returns>
|
||||
/// <returns>The result of calling the base fucntion.</returns>
|
||||
bool eventFilter(QObject* obj, QEvent* e)
|
||||
{
|
||||
if (e->type() == QEvent::Wheel)
|
||||
{
|
||||
e->ignore();
|
||||
return true;
|
||||
}
|
||||
else if (e->type() == QEvent::MouseMove)
|
||||
if (e->type() == QEvent::MouseMove)
|
||||
{
|
||||
if (auto me = dynamic_cast<QMouseEvent*>(e))
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "FractoriumPch.h"
|
||||
#include "SpinBox.h"
|
||||
#include "DoubleSpinBox.h"
|
||||
|
||||
/// <summary>
|
||||
@ -114,7 +115,42 @@ public:
|
||||
QPushButton* m_Button;
|
||||
};
|
||||
|
||||
class SpinnerLabelButtonWidget : public QWidget
|
||||
class SpinnerLabelWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor that passes the parent to the base, then creates a QLabel,
|
||||
/// then creates a QPushButton and sets up its caption and dimensions, then
|
||||
/// assigns the DoubleSpinBox.
|
||||
/// </summary>
|
||||
/// <param name="spinBox">The pre-created DoubleSpinBox</param>
|
||||
/// <param name="h">The height of the label</param>
|
||||
/// <param name="p">The parent widget</param>
|
||||
SpinnerLabelWidget(DoubleSpinBox* spinBox, int h, QWidget* p)
|
||||
: QWidget(p)
|
||||
{
|
||||
m_L = new QHBoxLayout(this);
|
||||
m_SpinBox = spinBox;
|
||||
m_Label = new QLabel(p);
|
||||
m_Label->setMinimumHeight(h);
|
||||
m_Label->setMaximumHeight(h);
|
||||
m_L->addWidget(spinBox);
|
||||
m_L->addWidget(m_Label);
|
||||
m_L->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
m_L->setMargin(0);
|
||||
m_L->setSpacing(0);
|
||||
setLayout(m_L);
|
||||
}
|
||||
DoubleSpinBox* m_SpinBox;
|
||||
QLabel* m_Label;
|
||||
|
||||
protected:
|
||||
QHBoxLayout* m_L;
|
||||
};
|
||||
|
||||
class SpinnerLabelButtonWidget : public SpinnerLabelWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -130,14 +166,9 @@ public:
|
||||
/// <param name="h">The height of the button</param>
|
||||
/// <param name="p">The parent widget</param>
|
||||
SpinnerLabelButtonWidget(DoubleSpinBox* spinBox, QString buttonCaption, int w, int h, QWidget* p)
|
||||
: QWidget(p)
|
||||
: SpinnerLabelWidget(spinBox, h, p)
|
||||
{
|
||||
QHBoxLayout* l = new QHBoxLayout(this);
|
||||
m_Button = new QPushButton(buttonCaption, p);
|
||||
m_SpinBox = spinBox;
|
||||
m_Label = new QLabel(p);
|
||||
m_Label->setMinimumHeight(h);
|
||||
m_Label->setMaximumHeight(h);
|
||||
|
||||
if (w != -1)
|
||||
{
|
||||
@ -147,16 +178,41 @@ public:
|
||||
|
||||
m_Button->setMinimumHeight(h);
|
||||
m_Button->setMaximumHeight(h);
|
||||
l->addWidget(spinBox);
|
||||
l->addWidget(m_Label);
|
||||
l->addWidget(m_Button);
|
||||
l->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
l->setMargin(0);
|
||||
l->setSpacing(0);
|
||||
setLayout(l);
|
||||
m_L->addWidget(m_Button);
|
||||
}
|
||||
|
||||
DoubleSpinBox* m_SpinBox;
|
||||
QPushButton* m_Button;
|
||||
QLabel* m_Label;
|
||||
};
|
||||
|
||||
|
||||
class DoubleIntSpinnerWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor that passes the parent to the base, then creates a QHBoxLayout,
|
||||
/// and adds the passed in DoubleSpinBox and SpinBox to the layout.
|
||||
/// </summary>
|
||||
/// <param name="doubleSpinBox">The pre-created DoubleSpinBox</param>
|
||||
/// <param name="spinBox">The pre-created SpinBox</param>
|
||||
/// <param name="p">The parent widget</param>
|
||||
DoubleIntSpinnerWidget(DoubleSpinBox* doubleSpinBox, SpinBox* spinBox, QWidget* p)
|
||||
: QWidget(p)
|
||||
{
|
||||
m_L = new QHBoxLayout(this);
|
||||
m_DoubleSpinBox = doubleSpinBox;
|
||||
m_SpinBox = spinBox;
|
||||
m_L->addWidget(doubleSpinBox);
|
||||
m_L->addWidget(spinBox);
|
||||
m_L->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
m_L->setMargin(0);
|
||||
m_L->setSpacing(0);
|
||||
setLayout(m_L);
|
||||
}
|
||||
DoubleSpinBox* m_DoubleSpinBox;
|
||||
SpinBox* m_SpinBox;
|
||||
|
||||
protected:
|
||||
QHBoxLayout* m_L;
|
||||
};
|
||||
|
Reference in New Issue
Block a user