Fix bug when using rotation with strips by adding a new member to Ember named m_RotCenterY which is a copy of the original center value since the center value gets changed when using strips.

Change PaletteList Count() member to Size() to be consistent with other code.

Remove PaletteImage option, it's unused. Improve documentation for some other options.

Make ComposePath() always return a unique string.

Add Random Palette and Random Adjustment buttons.

Another attempt at solving the locale bug with the affine adjustment combo boxes.
This commit is contained in:
mfeemster 2014-10-27 14:21:06 -07:00
parent 2a98e8c05b
commit 6b2b6ede7f
19 changed files with 440 additions and 375 deletions

View File

@ -108,6 +108,7 @@ public:
m_CamMat = ember.m_CamMat;
m_CenterX = T(ember.m_CenterX);
m_CenterY = T(ember.m_CenterY);
m_RotCenterY = T(ember.m_RotCenterY);
m_Rotate = T(ember.m_Rotate);
m_Hue = T(ember.m_Hue);
m_Brightness = T(ember.m_Brightness);
@ -201,6 +202,7 @@ public:
m_CamMat = m3T(0);
m_CenterX = 0;
m_CenterY = 0;
m_RotCenterY = 0;
m_Rotate = 0;
m_Hue = 0;
m_Brightness = 4;
@ -761,6 +763,7 @@ public:
InterpI<&Ember<T>::m_Supersample>(embers, coefs, size);
InterpT<&Ember<T>::m_CenterX>(embers, coefs, size);
InterpT<&Ember<T>::m_CenterY>(embers, coefs, size);
InterpT<&Ember<T>::m_RotCenterY>(embers, coefs, size);
InterpX<Color<T>, &Ember<T>::m_Background>(embers, coefs, size); m_Background.a = bgAlphaSave;//Don't interp alpha.
InterpT<&Ember<T>::m_PixelsPerUnit>(embers, coefs, size);
InterpT<&Ember<T>::m_SpatialFilterRadius>(embers, coefs, size);
@ -1269,6 +1272,7 @@ public:
m_Palette.m_Index = -1;
m_CenterX = 0;
m_CenterY = 0;
m_RotCenterY = 0;
m_Gamma = 4;
m_Vibrancy = 1;
m_Brightness = 4;
@ -1392,6 +1396,7 @@ public:
<< "Depth Blur: " << m_CamDepthBlur << endl
<< "CenterX: " << m_CenterX << endl
<< "CenterY: " << m_CenterY << endl
<< "RotCenterY: " << m_RotCenterY << endl
<< "Rotate: " << m_Rotate << endl
<< "Hue: " << m_Hue << endl
<< "Brightness: " << m_Brightness << endl
@ -1523,10 +1528,11 @@ public:
m3T m_CamMat;
//The camera offset from the center of the cartesian plane. Since this is the camera offset, the final output image will be moved in the opposite
//direction of the values specified.
//direction of the values specified. There is also a second copy of the Y coordinate needed because m_CenterY will be modified during strips rendering.
//Xml field: "center".
T m_CenterX;
T m_CenterY;
T m_RotCenterY;
//Rotate the camera by this many degrees. Since this is a camera rotation, the final output image will be rotated counter-clockwise.
//Xml field: "rotate".

View File

@ -100,9 +100,10 @@ public:
}
/// <summary>
/// Return the next random integer between 0 and the value passed in.
/// Return the next random integer between 0 and the value passed in minus 1.
/// </summary>
/// <returns>A value one greater than the maximum value that will be returned</returns>
/// <param name="upper">A value one greater than the maximum value that will be returned</param>
/// <returns>A value between 0 and the value passed in minus 1</returns>
inline T Rand(T upper)
{
return (upper == 0) ? Rand() : Rand() % upper;

View File

@ -80,7 +80,7 @@ public:
if (!m_Palettes.empty())
{
if (i == -1)
return &m_Palettes[QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Rand() % Count()];
return &m_Palettes[QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Rand() % Size()];
else if (i < (int)m_Palettes.size())
return &m_Palettes[i];
}
@ -95,7 +95,7 @@ public:
/// <returns>A pointer to the palette if found, else nullptr</returns>
Palette<T>* GetPaletteByName(const string&& name)
{
for (unsigned int i = 0; i < Count(); i++)
for (unsigned int i = 0; i < Size(); i++)
if (m_Palettes[i].m_Name == name)
return &m_Palettes[i];
@ -136,7 +136,7 @@ public:
/// Accessors.
/// </summary>
bool Init() { return m_Init; }
unsigned int Count() { return (unsigned int)m_Palettes.size(); }
size_t Size() { return m_Palettes.size(); }
private:
/// <summary>

View File

@ -459,6 +459,7 @@ eRenderStatus Renderer<T, bucketT>::Run(vector<unsigned char>& finalImage, doubl
//it.Tic();
if (m_Embers.size() > 1)
Interpolater<T>::Interpolate(m_Embers, temporalTime, 0, m_Ember);//This will perform all necessary precalcs via the ember/xform/variation assignment operators.
//it.Toc("Interp 3");
if (!resume && !AssignIterator())
@ -1478,10 +1479,10 @@ void Renderer<T, bucketT>::Accumulate(Point<T>* samples, size_t sampleCount, con
if (Rotate() != 0)
{
T p00 = samples[i].m_X - CenterX();
T p11 = samples[i].m_Y - CenterY();
T p11 = samples[i].m_Y - m_Ember.m_RotCenterY;
samples[i].m_X = (p00 * m_RotMat.A()) + (p11 * m_RotMat.B()) + CenterX();
samples[i].m_Y = (p00 * m_RotMat.D()) + (p11 * m_RotMat.E()) + CenterY();
samples[i].m_Y = (p00 * m_RotMat.D()) + (p11 * m_RotMat.E()) + m_Ember.m_RotCenterY;
}
//Checking this first before converting gives better performance than converting and checking a single value, which the original did.

View File

@ -655,7 +655,7 @@ private:
}
currentEmber.m_CenterX = T(vals[0]);
currentEmber.m_CenterY = T(vals[1]);
currentEmber.m_CenterY = currentEmber.m_RotCenterY = T(vals[1]);
}
else if (!Compare(curAtt->name, "filter_shape"))
{

View File

@ -1297,7 +1297,7 @@ EmberCL<T> RendererCL<T>::ConvertEmber(Ember<T>& ember)
emberCL.m_RotE = m_RotMat.E();
emberCL.m_CamMat = ember.m_CamMat;
emberCL.m_CenterX = CenterX();
emberCL.m_CenterY = CenterY();
emberCL.m_CenterY = ember.m_RotCenterY;
emberCL.m_CamZPos = ember.m_CamZPos;
emberCL.m_CamPerspective = ember.m_CamPerspective;
emberCL.m_CamYaw = ember.m_CamYaw;

View File

@ -7,11 +7,14 @@
#include "FinalAccumOpenCLKernelCreator.h"
/// <summary>
/// RendererCL class.
/// RendererCLBase and RendererCL classes.
/// </summary>
namespace EmberCLns
{
/// <summary>
/// Serves only as an interface for OpenCL specific rendering functions.
/// </summary>
class EMBERCL_API RendererCLBase
{
public:

View File

@ -313,7 +313,6 @@ static bool StripsRender(RendererBase* renderer, Ember<T>& ember, vector<unsigne
ember.m_CenterY -= (origHeight - ember.m_FinalRasH) * T(0.5) / (ember.m_PixelsPerUnit * zoomScale);
}
ember.m_CenterY;
perStripStart(strip);
if (strips > 1)

View File

@ -99,7 +99,7 @@ enum eOptionIDs
OPT_SUFFIX,
OPT_FORMAT,
OPT_PALETTE_FILE,
OPT_PALETTE_IMAGE,
//OPT_PALETTE_IMAGE,
OPT_ID,
OPT_URL,
OPT_NICK,
@ -292,7 +292,7 @@ public:
INITBOOLOPTION(Enclosed, Eob(OPT_USE_GENOME, OPT_ENCLOSED, _T("--enclosed"), true, SO_NONE, "\t--enclosed Use enclosing XML tags [default: false].\n"));
INITBOOLOPTION(NoEdits, Eob(OPT_USE_GENOME, OPT_NO_EDITS, _T("--noedits"), false, SO_NONE, "\t--noedits Exclude edit tags when writing Xml [default: false].\n"));
INITBOOLOPTION(UnsmoothEdge, Eob(OPT_USE_GENOME, OPT_UNSMOOTH_EDGE, _T("--unsmoother"), false, SO_NONE, "\t--unsmoother Do not use smooth blending for sheep edges [default: false].\n"));
INITBOOLOPTION(LockAccum, Eob(OPT_USE_ALL, OPT_LOCK_ACCUM, _T("--lock_accum"), false, SO_NONE, "\t--lock_accum Lock threads when accumulating to the histogram using the CPU (ignored for OpenCL). This will drop performance to that of single threading [default: false].\n"));
INITBOOLOPTION(LockAccum, Eob(OPT_USE_ALL, OPT_LOCK_ACCUM, _T("--lock_accum"), false, SO_NONE, "\t--lock_accum Lock threads when accumulating to the histogram using the CPU. This will drop performance to that of single threading [default: false].\n"));
INITBOOLOPTION(DumpKernel, Eob(OPT_USE_RENDER, OPT_DUMP_KERNEL, _T("--dump_kernel"), false, SO_NONE, "\t--dump_kernel Print the iteration kernel string when using OpenCL (ignored for CPU) [default: false].\n"));
//Int.
@ -348,10 +348,10 @@ public:
INITSTRINGOPTION(Suffix, Eos(OPT_RENDER_ANIM, OPT_SUFFIX, _T("--suffix"), "", SO_REQ_SEP, "\t--suffix=<val> Suffix to append to all output files.\n"));
INITSTRINGOPTION(Format, Eos(OPT_RENDER_ANIM, OPT_FORMAT, _T("--format"), "png", SO_REQ_SEP, "\t--format=<val> Format of the output file. Valid values are: bmp, jpg, png, ppm [default: jpg].\n"));
INITSTRINGOPTION(PalettePath, Eos(OPT_USE_ALL, OPT_PALETTE_FILE, _T("--flam3_palettes"), "flam3-palettes.xml", SO_REQ_SEP, "\t--flam3_palettes=<val> Path and name of the palette file [default: flam3-palettes.xml].\n"));
INITSTRINGOPTION(PaletteImage, Eos(OPT_USE_ALL, OPT_PALETTE_IMAGE, _T("--image"), "", SO_REQ_SEP, "\t--image=<val> Replace palette with png, jpg, or ppm image.\n"));
INITSTRINGOPTION(Id, Eos(OPT_USE_ALL, OPT_ID, _T("--id"), "", SO_REQ_SEP, "\t--id=<val> ID to use in <edit> tags.\n"));
INITSTRINGOPTION(Url, Eos(OPT_USE_ALL, OPT_URL, _T("--url"), "", SO_REQ_SEP, "\t--url=<val> URL to use in <edit> tags / img comments.\n"));
INITSTRINGOPTION(Nick, Eos(OPT_USE_ALL, OPT_NICK, _T("--nick"), "", SO_REQ_SEP, "\t--nick=<val> Nickname to use in <edit> tags / img comments.\n"));
//INITSTRINGOPTION(PaletteImage, Eos(OPT_USE_ALL, OPT_PALETTE_IMAGE, _T("--image"), "", SO_REQ_SEP, "\t--image=<val> Replace palette with png, jpg, or ppm image.\n"));
INITSTRINGOPTION(Id, Eos(OPT_USE_ALL, OPT_ID, _T("--id"), "", SO_REQ_SEP, "\t--id=<val> ID to use in <edit> tags / image comments.\n"));
INITSTRINGOPTION(Url, Eos(OPT_USE_ALL, OPT_URL, _T("--url"), "", SO_REQ_SEP, "\t--url=<val> URL to use in <edit> tags / image comments.\n"));
INITSTRINGOPTION(Nick, Eos(OPT_USE_ALL, OPT_NICK, _T("--nick"), "", SO_REQ_SEP, "\t--nick=<val> Nickname to use in <edit> tags / image comments.\n"));
INITSTRINGOPTION(Comment, Eos(OPT_USE_GENOME, OPT_COMMENT, _T("--comment"), "", SO_REQ_SEP, "\t--comment=<val> Comment to use in <edit> tags.\n"));
INITSTRINGOPTION(TemplateFile, Eos(OPT_USE_GENOME, OPT_TEMPLATE, _T("--template"), "", SO_REQ_SEP, "\t--template=<val> Apply defaults based on this flame.\n"));
@ -472,7 +472,7 @@ public:
PARSESTRINGOPTION(OPT_SUFFIX, Suffix);
PARSESTRINGOPTION(OPT_FORMAT, Format);
PARSESTRINGOPTION(OPT_PALETTE_FILE, PalettePath);
PARSESTRINGOPTION(OPT_PALETTE_IMAGE, PaletteImage);
//PARSESTRINGOPTION(OPT_PALETTE_IMAGE, PaletteImage);
PARSESTRINGOPTION(OPT_ID, Id);
PARSESTRINGOPTION(OPT_URL, Url);
PARSESTRINGOPTION(OPT_NICK, Nick);
@ -639,8 +639,8 @@ public:
EmberOptionEntry<bool> DumpKernel;
EmberOptionEntry<int> Symmetry;//Value int.
EmberOptionEntry<int> SheepGen;//Value int.
EmberOptionEntry<int> SheepId;//Value int.
EmberOptionEntry<int> SheepGen;
EmberOptionEntry<int> SheepId;
EmberOptionEntry<unsigned int> Platform;//Value unsigned int.
EmberOptionEntry<unsigned int> Device;
EmberOptionEntry<unsigned int> Seed;
@ -682,7 +682,7 @@ public:
EmberOptionEntry<string> Suffix;
EmberOptionEntry<string> Format;
EmberOptionEntry<string> PalettePath;
EmberOptionEntry<string> PaletteImage;
//EmberOptionEntry<string> PaletteImage;
EmberOptionEntry<string> Id;
EmberOptionEntry<string> Url;
EmberOptionEntry<string> Nick;

View File

@ -198,7 +198,7 @@ void MakeTestAllVarsRegPrePostComboFile(const string& filename)
ss << index << "_" << regVar->Name();
ember1.m_Name = ss.str();
ss.str("");
ember1.m_Palette = *paletteList.GetPalette(index % paletteList.Count());
ember1.m_Palette = *paletteList.GetPalette(index % paletteList.Size());
index++;
embers.push_back(ember1);
}

View File

@ -155,7 +155,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
m_GuiState = m_FinalRenderDialog->State();//Cache render settings from the GUI before running.
bool doAll = m_GuiState.m_DoAll && m_EmberFile.Size() > 1;
unsigned int currentStripForProgress = 0;//Sort of a hack to get the strip value to the progress function.
QString path = EmberFile<T>::UniqueFilename(doAll ? ComposePath(QString::fromStdString(m_EmberFile.m_Embers[0].m_Name)) : ComposePath(Name()));
QString path = doAll ? ComposePath(QString::fromStdString(m_EmberFile.m_Embers[0].m_Name)) : ComposePath(Name());
QString backup = path + "_backup.flame";
//Save backup Xml.
@ -219,7 +219,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
//Render each image, cancelling if m_Run ever gets set to false.
for (i = 0; i < m_EmberFile.Size() && m_Run; i++)
{
Output("Image " + ToString(m_FinishedImageCount) + ":\n" + EmberFile<T>::UniqueFilename(ComposePath(QString::fromStdString(m_EmberFile.m_Embers[i].m_Name))));
Output("Image " + ToString(m_FinishedImageCount) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[i].m_Name)));
m_Renderer->Reset();//Have to manually set this since the ember is not set each time through.
m_RenderTimer.Tic();//Toc() is called in RenderComplete().
@ -244,7 +244,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
//Render each image, cancelling if m_Run ever gets set to false.
for (i = 0; i < m_EmberFile.Size() && m_Run; i++)
{
Output("Image " + ToString(m_FinishedImageCount) + ":\n" + EmberFile<T>::UniqueFilename(ComposePath(QString::fromStdString(m_EmberFile.m_Embers[i].m_Name))));
Output("Image " + ToString(m_FinishedImageCount) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[i].m_Name)));
m_Renderer->SetEmber(m_EmberFile.m_Embers[i]);
m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
m_Stats.Clear();
@ -272,7 +272,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
m_Stats.Clear();
Memset(m_FinalImage);
Output(EmberFile<T>::UniqueFilename(ComposePath(QString::fromStdString(m_Ember->m_Name))));
Output(ComposePath(QString::fromStdString(m_Ember->m_Name)));
m_RenderTimer.Tic();//Toc() is called in RenderComplete().
StripsRender<T>(m_Renderer.get(), *m_Ember, m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp,
@ -496,7 +496,7 @@ void FinalRenderEmberController<T>::SyncCurrentToGui()
m_FinalRenderDialog->Scale(m_Ember->ScaleType());
m_FinalRenderDialog->m_QualitySpin->SetValueStealth(m_Ember->m_Quality);
m_FinalRenderDialog->m_SupersampleSpin->SetValueStealth(m_Ember->m_Supersample);
m_FinalRenderDialog->Path(EmberFile<T>::UniqueFilename(ComposePath(Name())));
m_FinalRenderDialog->Path(ComposePath(Name()));
}
/// <summary>
@ -606,7 +606,7 @@ QString FinalRenderEmberController<T>::ComposePath(const QString& name)
QString path = MakeEnd(m_Settings->SaveFolder(), '/');//Base path.
QString full = path + m_FinalRenderDialog->Prefix() + name + m_FinalRenderDialog->Suffix() + "." + m_FinalRenderDialog->Ext();
return full;
return EmberFile<T>::UniqueFilename(full);
}
/// <summary>
@ -635,7 +635,7 @@ template<typename T>
void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember)
{
string renderTimeString = m_RenderTimer.Format(m_RenderTimer.Toc()), totalTimeString;
QString status, filename = EmberFile<T>::UniqueFilename(ComposePath(QString::fromStdString(ember.m_Name)));
QString status, filename = ComposePath(QString::fromStdString(ember.m_Name));
QString itersString = ToString(m_Stats.m_Iters);
QString itersPerSecString = ToString(size_t(m_Stats.m_Iters / (m_Stats.m_IterMs / 1000.0)));

View File

@ -221,6 +221,8 @@ public slots:
void OnPaletteAdjust(int d);
void OnPaletteCellClicked(int row, int col);
void OnPaletteCellDoubleClicked(int row, int col);
void OnPaletteRandomSelectButtonClicked(bool checked);
void OnPaletteRandomAdjustButtonClicked(bool checked);
//Library.
void OnEmberTreeItemChanged(QTreeWidgetItem* item, int col);

View File

@ -2314,6 +2314,9 @@ SpinBox
<string>Color</string>
</attribute>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="leftMargin">
<number>6</number>
</property>
@ -2326,192 +2329,6 @@ SpinBox
<property name="bottomMargin">
<number>6</number>
</property>
<item row="3" column="0" colspan="2">
<widget class="TableWidget" name="XformColorValuesTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>45</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>68</height>
</size>
</property>
<property name="font">
<font>
<kerning>true</kerning>
</font>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="autoScroll">
<bool>false</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragDropOverwriteMode">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="showGrid">
<bool>true</bool>
</property>
<property name="gridStyle">
<enum>Qt::SolidLine</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<property name="columnCount">
<number>2</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>110</number>
</attribute>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>27</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>22</number>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize">
<number>22</number>
</attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<row>
<property name="text">
<string>Color Speed</string>
</property>
</row>
<row>
<property name="text">
<string>Opacity</string>
</property>
</row>
<row>
<property name="text">
<string>Direct Color</string>
</property>
</row>
<column>
<property name="text">
<string>Field</string>
</property>
</column>
<column>
<property name="text">
<string/>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>Color Speed</string>
</property>
</item>
<item row="0" column="1">
<property name="text">
<string>0</string>
</property>
<property name="font">
<font>
<kerning>true</kerning>
</font>
</property>
<property name="textAlignment">
<set>AlignLeft|AlignVCenter</set>
</property>
</item>
<item row="1" column="0">
<property name="text">
<string>Opacity</string>
</property>
</item>
<item row="1" column="1">
<property name="text">
<string>0</string>
</property>
</item>
<item row="2" column="0">
<property name="text">
<string>Direct Color</string>
</property>
</item>
<item row="2" column="1">
<property name="text">
<string>0</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="TableWidget" name="XformColorIndexTable">
<property name="sizePolicy">
@ -2731,6 +2548,58 @@ SpinBox
</item>
<item row="2" column="0" colspan="2">
<widget class="QScrollBar" name="XformColorScroll">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>162</width>
<height>18</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>18</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="pageStep">
<number>10</number>
</property>
<property name="value">
<number>128</number>
</property>
<property name="tracking">
<bool>true</bool>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
<property name="invertedControls">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="TableWidget" name="XformColorValuesTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
@ -2740,30 +2609,179 @@ SpinBox
<property name="minimumSize">
<size>
<width>0</width>
<height>16</height>
<height>45</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16</height>
<height>68</height>
</size>
</property>
<property name="font">
<font>
<kerning>true</kerning>
</font>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
<enum>Qt::NoFocus</enum>
</property>
<property name="maximum">
<number>255</number>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="value">
<number>128</number>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="invertedAppearance">
<property name="lineWidth">
<number>1</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="autoScroll">
<bool>false</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragDropOverwriteMode">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="showGrid">
<bool>true</bool>
</property>
<property name="gridStyle">
<enum>Qt::SolidLine</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<property name="columnCount">
<number>2</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>110</number>
</attribute>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>27</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>22</number>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize">
<number>22</number>
</attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<row>
<property name="text">
<string>Color Speed</string>
</property>
</row>
<row>
<property name="text">
<string>Opacity</string>
</property>
</row>
<row>
<property name="text">
<string>Direct Color</string>
</property>
</row>
<column>
<property name="text">
<string>Field</string>
</property>
</column>
<column>
<property name="text">
<string/>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>Color Speed</string>
</property>
</item>
<item row="0" column="1">
<property name="text">
<string>0</string>
</property>
<property name="font">
<font>
<kerning>true</kerning>
</font>
</property>
<property name="textAlignment">
<set>AlignLeft|AlignVCenter</set>
</property>
</item>
<item row="1" column="0">
<property name="text">
<string>Opacity</string>
</property>
</item>
<item row="1" column="1">
<property name="text">
<string>0</string>
</property>
</item>
<item row="2" column="0">
<property name="text">
<string>Direct Color</string>
</property>
</item>
<item row="2" column="1">
<property name="text">
<string>0</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
@ -3214,36 +3232,6 @@ SpinBox
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>0.5</string>
</property>
</item>
<item>
<property name="text">
<string>0.25</string>
</property>
</item>
<item>
<property name="text">
<string>0.1</string>
</property>
</item>
<item>
<property name="text">
<string>0.05</string>
</property>
</item>
<item>
<property name="text">
<string>0.025</string>
</property>
</item>
<item>
<property name="text">
<string>0.01</string>
</property>
</item>
</widget>
</item>
<item row="2" column="3">
@ -3818,36 +3806,6 @@ SpinBox
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>0.5</string>
</property>
</item>
<item>
<property name="text">
<string>0.25</string>
</property>
</item>
<item>
<property name="text">
<string>0.1</string>
</property>
</item>
<item>
<property name="text">
<string>0.05</string>
</property>
</item>
<item>
<property name="text">
<string>0.025</string>
</property>
</item>
<item>
<property name="text">
<string>0.01</string>
</property>
</item>
</widget>
</item>
<item row="2" column="3">
@ -4029,7 +3987,7 @@ SpinBox
<item>
<widget class="QGroupBox" name="PostAffineShowGroupBox">
<property name="enabled">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="title">
<string>Show</string>
@ -4050,7 +4008,7 @@ SpinBox
<item>
<widget class="QRadioButton" name="ShowPostAffineCurrentRadio">
<property name="enabled">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="text">
<string>Current</string>
@ -4619,7 +4577,7 @@ SpinBox
<attribute name="title">
<string>Palette</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_16" rowstretch="0,0,0" columnstretch="0">
<layout class="QGridLayout" name="gridLayout_16" rowstretch="0,0,0,0" columnstretch="0">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
@ -4638,6 +4596,88 @@ SpinBox
<property name="spacing">
<number>6</number>
</property>
<item row="2" column="0">
<widget class="TableWidget" name="PalettePreviewTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>19</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>19</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="autoScroll">
<bool>false</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<property name="rowCount">
<number>1</number>
</property>
<property name="columnCount">
<number>2</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>19</number>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize">
<number>19</number>
</attribute>
<row/>
<column/>
<column/>
</widget>
</item>
<item row="0" column="0">
<widget class="TableWidget" name="PaletteAdjustTable">
<property name="sizePolicy">
@ -4771,7 +4811,7 @@ SpinBox
</item>
</widget>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QTableWidget" name="PaletteListTable">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
@ -4846,86 +4886,37 @@ SpinBox
</widget>
</item>
<item row="1" column="0">
<widget class="TableWidget" name="PalettePreviewTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>4</number>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>19</height>
</size>
<property name="leftMargin">
<number>0</number>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>19</height>
</size>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="autoScroll">
<bool>false</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<property name="rowCount">
<number>1</number>
</property>
<property name="columnCount">
<number>2</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>19</number>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize">
<number>19</number>
</attribute>
<row/>
<column/>
<column/>
</widget>
<item>
<widget class="QPushButton" name="PaletteRandomSelect">
<property name="toolTip">
<string>Select a random palette from the list</string>
</property>
<property name="text">
<string>Random Palette</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="PaletteRandomAdjust">
<property name="text">
<string>Random Adjustment</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>

View File

@ -27,6 +27,9 @@ void Fractorium::InitPaletteUI()
SetupSpinner<SpinBox, int>(table, this, row, 3, m_PaletteContrastSpin, spinHeight, -100, 100, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
SetupSpinner<SpinBox, int>(table, this, row, 3, m_PaletteBlurSpin, spinHeight, 0, 127, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
SetupSpinner<SpinBox, int>(table, this, row, 3, m_PaletteFrequencySpin, spinHeight, 1, 10, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 1, 1, 1);
connect(ui.PaletteRandomSelect, SIGNAL(clicked(bool)), this, SLOT(OnPaletteRandomSelectButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.PaletteRandomAdjust, SIGNAL(clicked(bool)), this, SLOT(OnPaletteRandomAdjustButtonClicked(bool)), Qt::QueuedConnection);
}
/// <summary>
@ -55,7 +58,7 @@ bool FractoriumEmberController<T>::InitPaletteTable(const string& s)
palettePreviewTable->setItem(0, 1, previewPaletteItem);
//Palette list table.
paletteTable->setRowCount(m_PaletteList.Count());
paletteTable->setRowCount(m_PaletteList.Size());
paletteTable->setColumnWidth(1, 260);//256 plus small margin on each side.
paletteTable->horizontalHeader()->setSectionsClickable(false);
@ -70,7 +73,7 @@ bool FractoriumEmberController<T>::InitPaletteTable(const string& s)
paletteTable->setHorizontalHeaderItem(1, paletteHeader);
//Palette list table.
for (size_t i = 0; i < m_PaletteList.Count(); i++)
for (size_t i = 0; i < m_PaletteList.Size(); i++)
{
Palette<T>* p = m_PaletteList.GetPalette(i);
vector<unsigned char> v = p->MakeRgbPaletteBlock(PALETTE_CELL_HEIGHT);
@ -220,6 +223,52 @@ void Fractorium::OnPaletteCellDoubleClicked(int row, int col)
OnPaletteCellClicked(row, col);
}
/// <summary>
/// Set the selected palette to a randomly selected one,
/// applying any adjustments previously specified.
/// Called when the Random Palette button is clicked.
/// Resets the rendering process.
/// </summary>
/// <param name="row">The current row selected</param>
void Fractorium::OnPaletteRandomSelectButtonClicked(bool checked)
{
unsigned int i = 0;
int rowCount = ui.PaletteListTable->rowCount() - 1;
while ((i = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Rand(rowCount)) == m_PreviousPaletteRow);
OnPaletteCellClicked(i, 1);
}
/// <summary>
/// Apply random adjustments to the selected palette.
/// Called when the Random Adjustment button is clicked.
/// Resets the rendering process.
/// </summary>
void Fractorium::OnPaletteRandomAdjustButtonClicked(bool checked)
{
QTIsaac<ISAAC_SIZE, ISAAC_INT>* gRand = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand.get();
m_PaletteHueSpin->setValue(-180 + gRand->Rand(361));
m_PaletteSaturationSpin->setValue(-50 + gRand->Rand(101));//Full range of these leads to bad palettes, so clamp range.
m_PaletteBrightnessSpin->setValue(-50 + gRand->Rand(101));
m_PaletteContrastSpin->setValue(-50 + gRand->Rand(101));
//Doing frequency and blur together gives bad palettes that are just a solid color.
if (gRand->RandBit())
{
m_PaletteBlurSpin->setValue(gRand->Rand(21));
m_PaletteFrequencySpin->setValue(1);
}
else
{
m_PaletteBlurSpin->setValue(0);
m_PaletteFrequencySpin->setValue(1 + gRand->Rand(10));
}
OnPaletteAdjust(0);
}
/// <summary>
/// Reset the palette controls.
/// Usually in response to a palette cell double click.

View File

@ -242,7 +242,7 @@ void Fractorium::OnCenterXChanged(double d) { m_Controller->CenterXChanged(d); }
/// Resets the rendering process.
/// </summary>
/// <param name="d">The y offset value</param>
template <typename T> void FractoriumEmberController<T>::CenterYChanged(double d) { Update([&] { m_Ember.m_CenterY = d; }); }
template <typename T> void FractoriumEmberController<T>::CenterYChanged(double d) { Update([&] { m_Ember.m_CenterY = m_Ember.m_RotCenterY = d; }); }
void Fractorium::OnCenterYChanged(double d) { m_Controller->CenterYChanged(d); }
/// <summary>
@ -493,7 +493,7 @@ template <typename T>
void FractoriumEmberController<T>::SetCenter(double x, double y)
{
m_Ember.m_CenterX = x;
m_Ember.m_CenterY = y;
m_Ember.m_CenterY = m_Ember.m_RotCenterY = y;
m_Fractorium->m_CenterXSpin->SetValueStealth(x);//Don't trigger a redraw twice.
m_Fractorium->m_CenterYSpin->SetValueStealth(y);
@ -581,7 +581,7 @@ void FractoriumEmberController<T>::ParamsToEmber(Ember<T>& ember)
ember.m_FinalRasW = m_Fractorium->m_WidthSpin->value();//Geometry.
ember.m_FinalRasH = m_Fractorium->m_HeightSpin->value();
ember.m_CenterX = m_Fractorium->m_CenterXSpin->value();
ember.m_CenterY = m_Fractorium->m_CenterYSpin->value();
ember.m_CenterY = ember.m_RotCenterY = m_Fractorium->m_CenterYSpin->value();
ember.m_PixelsPerUnit = m_Fractorium->m_ScaleSpin->value();
ember.m_Zoom = m_Fractorium->m_ZoomSpin->value();
ember.m_Rotate = m_Fractorium->m_RotateSpin->value();

View File

@ -49,6 +49,18 @@ void Fractorium::InitXformsAffineUI()
ui.PostMoveCombo->setValidator(postMoveVal);
ui.PostScaleCombo->setValidator(postScaleVal);
QStringList moveList;
moveList.append(ToString(0.5));
moveList.append(ToString(0.25));
moveList.append(ToString(0.1));
moveList.append(ToString(0.05));
moveList.append(ToString(0.025));
moveList.append(ToString(0.01));
ui.PreMoveCombo->addItems(moveList);
ui.PostMoveCombo->addItems(moveList);
connect(ui.PreFlipHorizontalButton, SIGNAL(clicked(bool)), this, SLOT(OnFlipHorizontalButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.PreFlipVerticalButton, SIGNAL(clicked(bool)), this, SLOT(OnFlipVerticalButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.PreRotate90CButton, SIGNAL(clicked(bool)), this, SLOT(OnRotate90CButtonClicked(bool)), Qt::QueuedConnection);

View File

@ -15,12 +15,12 @@ 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);
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.5);
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);
SetupSpinner<DoubleSpinBox, double>(ui.XformColorValuesTable, this, row, 1, m_XformDirectColorSpin, spinHeight, 0, 1, 0.1, SIGNAL(valueChanged(double)), SLOT(OnXformDirectColorChanged(double)), true, 1, 1, 0);
m_XformColorIndexSpin->setDecimals(3);
m_XformColorSpeedSpin->setDecimals(3);
m_XformOpacitySpin->setDecimals(3);

View File

@ -189,6 +189,7 @@ void Fractorium::OnClearXaosButtonClicked(bool checked) { m_Controller->ClearXao
/// Set all xaos values to random numbers.
/// There is a 50% chance they're set to 0 or 1, and
/// 50% that they're 0-3.
/// Resets the rendering process.
/// </summary>
/// <param name="checked">Ignored</param>
template <typename T>

View File

@ -633,7 +633,7 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
v2T v2 = rotMat.TransformVector(v1);
ember->m_CenterX = v2.x;
ember->m_CenterY = v2.y;
ember->m_CenterY = ember->m_RotCenterY = v2.y;
m_FractoriumEmberController->SetCenter(ember->m_CenterX, ember->m_CenterY);//Will restart the rendering process.
}
else if (m_DragState == DragRotateScale)//Rotating and scaling the whole image.