--User changes

-Add variations changes to the list of functionality that can be applied to all xforms using the Select tab.
 -Allow for graphical affine adjustments to apply to multiple selected xforms.
 -Slight optimization of the pie variation.
 -Undo state is only saved when the render completes and the mouse buttons are released. This helps avoid intermediate steps for quickly completing renders while dragging.
 -Add some keyboard shortcuts for toolbar and menu items.
 -Make info tab tree always expanded.

--Bug fixes
 -Make precalcs for all hypertile variations safer by using Zeps() for denominators.
 -Changing the current xform with more than one selected would set all xform's color index value that of the current one.
 -Use hard found palette path information for randoms as well.
 -OpenCL build and assignment errors for Z value in epispiral variation.
 -Unitialized local variables in hexaplay3D, crob, pRose3D.

--Code changes
 -Change static member variables from m_ to s_.
 -Get rid of excessive endl and replace with "\n".
 -Remove old IMAGEGL2D define from before Nvidia supported OpenCL 1.2.
 -Remove old CriticalSection code and use std::recursive_mutex.
 -Make Affine2D Rotate() and RotateTrans() take radians instead of angles.
 -More C++11 work.
 -General cleanup.
This commit is contained in:
mfeemster
2016-02-11 21:38:21 -08:00
parent a345e2d5e1
commit a800b08b67
69 changed files with 981 additions and 1094 deletions

View File

@ -1,7 +1,7 @@
#include "FractoriumPch.h"
#include "DoubleSpinBox.h"
QTimer DoubleSpinBox::m_Timer;
QTimer DoubleSpinBox::s_Timer;
/// <summary>
/// Constructor that passes parent to the base and sets up height and step.
@ -144,17 +144,16 @@ void DoubleSpinBox::OnTimeout()
//qDebug() << "Shift pressed";
scale = 0.0001;
}
/*else if (ctrl)
{
/* else if (ctrl)
{
qDebug() << "Control pressed";
scale = 0.01;
}*/
}*/
else
scale = 0.001;
val = d + (distance * amount * scale);
setValue(val);
//qDebug() << "Timer on, orig val: " << d << ", new val: " << val << ", distance " << distance;
}
@ -169,47 +168,47 @@ bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
if (isEnabled() &&
me &&
me->type() == QMouseEvent::MouseButtonPress &&
me->button() == Qt::RightButton)
me &&
me->type() == QMouseEvent::MouseButtonPress &&
me->button() == Qt::RightButton)
{
m_MouseDownPoint = m_MouseMovePoint = me->pos();
StartTimer();
//qDebug() << "Right mouse down";
// QPoint pt;
//
// if (QMouseEvent* me = (QMouseEvent*)e)
// pt = me->localPos().toPoint();
//
// int pos = lineEdit()->cursorPositionAt(pt);
//
// if (lineEdit()->selectedText() != "")
// {
// lineEdit()->deselect();
// lineEdit()->setCursorPosition(pos);
// return true;
// }
// else if (m_Select)
// {
// lineEdit()->setCursorPosition(pos);
// selectAll();
// m_Select = false;
// return true;
// }
// QPoint pt;
//
// if (QMouseEvent* me = (QMouseEvent*)e)
// pt = me->localPos().toPoint();
//
// int pos = lineEdit()->cursorPositionAt(pt);
//
// if (lineEdit()->selectedText() != "")
// {
// lineEdit()->deselect();
// lineEdit()->setCursorPosition(pos);
// return true;
// }
// else if (m_Select)
// {
// lineEdit()->setCursorPosition(pos);
// selectAll();
// m_Select = false;
// return true;
// }
}
else if (isEnabled() &&
me &&
me->type() == QMouseEvent::MouseButtonRelease &&
me->button() == Qt::RightButton)
me &&
me->type() == QMouseEvent::MouseButtonRelease &&
me->button() == Qt::RightButton)
{
StopTimer();
m_MouseDownPoint = m_MouseMovePoint = me->pos();
//qDebug() << "Right mouse up";
}
else if (isEnabled() &&
me &&
me->type() == QMouseEvent::MouseMove &&
QGuiApplication::mouseButtons() & Qt::RightButton)
me &&
me->type() == QMouseEvent::MouseMove &&
QGuiApplication::mouseButtons() & Qt::RightButton)
{
m_MouseMovePoint = me->pos();
qDebug() << "Mouse move while right down. Pt = " << me->pos() << ", global: " << mapToGlobal(me->pos());
@ -262,8 +261,8 @@ void DoubleSpinBox::focusInEvent(QFocusEvent* e)
/// <param name="e">The event</param>
void DoubleSpinBox::focusOutEvent(QFocusEvent* e)
{
//lineEdit()->deselect();//Clear selection when leaving.
//lineEdit()->setReadOnly(true);//Clever hack to clear the cursor when leaving.
//lineEdit()->deselect();//Clear selection when leaving.
//lineEdit()->setReadOnly(true);//Clever hack to clear the cursor when leaving.
StopTimer();
QDoubleSpinBox::focusOutEvent(e);
}
@ -299,9 +298,9 @@ void DoubleSpinBox::leaveEvent(QEvent* e)
/// </summary>
void DoubleSpinBox::StartTimer()
{
m_Timer.stop();
connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
m_Timer.start(300);
s_Timer.stop();
connect(&s_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
s_Timer.start(300);
}
/// <summary>
@ -309,6 +308,6 @@ void DoubleSpinBox::StartTimer()
/// </summary>
void DoubleSpinBox::StopTimer()
{
m_Timer.stop();
disconnect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
s_Timer.stop();
disconnect(&s_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
}

View File

@ -51,7 +51,7 @@ private:
double m_SmallStep;
QPoint m_MouseDownPoint;
QPoint m_MouseMovePoint;
static QTimer m_Timer;
static QTimer s_Timer;
};
/// <summary>

View File

@ -15,7 +15,6 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
{
ui.setupUi(this);
int row = 0, spinHeight = 20;
uint i;
double dmax = numeric_limits<double>::max();
QTableWidget* table = ui.FinalRenderParamsTable;
QTableWidgetItem* item = nullptr;

View File

@ -110,7 +110,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
m_FinalPreviewRenderer->NumChannels(4);
m_FinalPreviewRenderFunc = [&]()
{
m_PreviewCs.Enter();//Thread prep.
rlg l(m_PreviewCs);//Thread prep.
m_PreviewRun = true;
m_FinalPreviewRenderer->Abort();
T scalePercentage;
@ -144,11 +144,10 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
{
QImage image(finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, QImage::Format_RGBA8888);//The label wants RGBA.
memcpy(image.scanLine(0), m_PreviewFinalImage.data(), finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);//Memcpy the data in.
QPixmap pixmap = QPixmap::fromImage(image);
QPixmap pixmap(QPixmap::fromImage(image));
QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap));
});
m_PreviewRun = false;
m_PreviewCs.Leave();
};
//The main rendering function which will be called in a Qt thread.
//A backup Xml is made before the rendering process starts just in case it crashes before finishing.
@ -837,7 +836,7 @@ void FinalRenderEmberController<T>::HandleFinishedProgress()
template<typename T>
void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberStats& stats, Timing& renderTimer)
{
m_ProgressCs.Enter();
rlg l(m_ProgressCs);
string renderTimeString = renderTimer.Format(renderTimer.Toc()), totalTimeString;
QString status, filename = ComposePath(QString::fromStdString(ember.m_Name));
QString itersString = ToString<qulonglong>(stats.m_Iters);
@ -885,7 +884,6 @@ void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberS
}
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "update", Qt::QueuedConnection);
m_ProgressCs.Leave();
}
/// <summary>

View File

@ -82,11 +82,11 @@ protected:
QFuture<void> m_FinalPreviewResult;
std::function<void (void)> m_FinalRenderFunc;
std::function<void (void)> m_FinalPreviewRenderFunc;
FractoriumSettings* m_Settings;
FractoriumFinalRenderDialog* m_FinalRenderDialog;
FinalRenderGuiState m_GuiState;
CriticalSection m_PreviewCs, m_ProgressCs;
std::recursive_mutex m_PreviewCs, m_ProgressCs;
Timing m_RenderTimer;
Timing m_TotalTimer;
};

View File

@ -2780,7 +2780,7 @@
<enum>QTabWidget::Triangular</enum>
</property>
<property name="currentIndex">
<number>1</number>
<number>2</number>
</property>
<widget class="QWidget" name="XformColorTab">
<property name="sizePolicy">
@ -3470,8 +3470,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>263</width>
<height>700</height>
<width>118</width>
<height>618</height>
</rect>
</property>
<property name="autoFillBackground">
@ -5485,8 +5485,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>259</width>
<height>652</height>
<width>133</width>
<height>52</height>
</rect>
</property>
<property name="sizePolicy">
@ -6768,6 +6768,9 @@
<property name="toolTip">
<string>Clear any existing flames and create a new file with 10 random flames in it</string>
</property>
<property name="shortcut">
<string>Ctrl+N</string>
</property>
</action>
<action name="ActionOpen">
<property name="icon">
@ -6777,6 +6780,9 @@
<property name="text">
<string>&amp;Open</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="ActionExit">
<property name="icon">
@ -6798,6 +6804,9 @@
<property name="toolTip">
<string>&lt;html&gt;&lt;body&gt;&lt;p&gt;Save the currently displayed flame back to the opened file in memory.&lt;/p&gt;&lt;p&gt;This overwrites the original flame but does not store the file back to disk.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="shortcut">
<string>Ctrl+B</string>
</property>
</action>
<action name="ActionSaveCurrentAsXml">
<property name="icon">
@ -6810,6 +6819,9 @@
<property name="toolTip">
<string>Save the current flame as an xml file</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="ActionAbout">
<property name="icon">
@ -6861,6 +6873,9 @@
<property name="toolTip">
<string>Add a new random flame to the end of the current file</string>
</property>
<property name="shortcut">
<string>Ctrl+R</string>
</property>
</action>
<action name="ActionSaveEntireFileAsXml">
<property name="icon">
@ -6876,6 +6891,9 @@
<property name="toolTip">
<string>Save all flames as a single xml file</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
</property>
</action>
<action name="ActionAddReflectiveSymmetry">
<property name="icon">
@ -6920,6 +6938,9 @@
<property name="toolTip">
<string>Add a new empty flame to the end of the current file</string>
</property>
<property name="shortcut">
<string>Ctrl+E</string>
</property>
</action>
<action name="ActionCopyFlameInCurrentFile">
<property name="icon">
@ -6927,7 +6948,7 @@
<normaloff>:/Fractorium/Icons/layers.png</normaloff>:/Fractorium/Icons/layers.png</iconset>
</property>
<property name="text">
<string>Co&amp;py Flame</string>
<string>Add Co&amp;py of Flame</string>
</property>
<property name="toolTip">
<string>Add a copy of the current flame to the end of the current file</string>
@ -7069,11 +7090,6 @@
<string>Remove the flatten variation from each xform</string>
</property>
</action>
<action name="ActionFlip">
<property name="text">
<string>Fl&amp;ip</string>
</property>
</action>
<action name="ActionCopySelectedXforms">
<property name="text">
<string>Copy Selected &amp;Xforms</string>
@ -7082,7 +7098,7 @@
<string>Copy selected xforms to the clipboard</string>
</property>
<property name="shortcut">
<string>Ctrl+D</string>
<string>Ctrl+C, X</string>
</property>
</action>
<action name="ActionPasteSelectedXforms">
@ -7093,7 +7109,7 @@
<string>Paste copied xforms into the current flame</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
<string>Ctrl+V, X</string>
</property>
</action>
<action name="ActionResetWorkspace">
@ -7192,7 +7208,7 @@
<string>Stop Renderer</string>
</property>
<property name="shortcut">
<string>Ctrl+R</string>
<string>Ctrl+P</string>
</property>
</action>
</widget>

View File

@ -20,15 +20,13 @@ FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractor
m_OutputTexID = 0;
m_SubBatchCount = 1;//Will be ovewritten by the options on first render.
m_Fractorium = fractorium;
m_RenderTimer = nullptr;
m_RenderRestartTimer = nullptr;
m_Info = OpenCLInfo::Instance();
m_Rand = QTIsaac<ISAAC_SIZE, ISAAC_INT>(ISAAC_INT(t.Tic()), ISAAC_INT(t.Tic() * 2), ISAAC_INT(t.Tic() * 3));//Ensure a different rand seed on each instance.
m_RenderTimer = new QTimer(m_Fractorium);
m_RenderTimer = std::unique_ptr<QTimer>(new QTimer(m_Fractorium));
m_RenderTimer->setInterval(0);
m_Fractorium->connect(m_RenderTimer, SIGNAL(timeout()), SLOT(IdleTimer()));
m_RenderRestartTimer = new QTimer(m_Fractorium);
m_Fractorium->connect(m_RenderRestartTimer, SIGNAL(timeout()), SLOT(StartRenderTimer()));
m_Fractorium->connect(m_RenderTimer.get(), SIGNAL(timeout()), SLOT(IdleTimer()));
m_RenderRestartTimer = std::unique_ptr<QTimer>(new QTimer(m_Fractorium));
m_Fractorium->connect(m_RenderRestartTimer.get(), SIGNAL(timeout()), SLOT(StartRenderTimer()));
}
/// <summary>
@ -38,20 +36,8 @@ FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractor
FractoriumEmberControllerBase::~FractoriumEmberControllerBase()
{
StopRenderTimer(true);
if (m_RenderTimer)
{
m_RenderTimer->stop();
delete m_RenderTimer;
m_RenderTimer = nullptr;
}
if (m_RenderRestartTimer)
{
m_RenderRestartTimer->stop();
delete m_RenderRestartTimer;
m_RenderRestartTimer = nullptr;
}
m_RenderTimer->stop();
m_RenderRestartTimer->stop();
}
/// <summary>
@ -64,26 +50,35 @@ template <typename T>
FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
: FractoriumEmberControllerBase(fractorium)
{
bool b = false;
m_PreviewRun = false;
m_PreviewRunning = false;
m_SheepTools = unique_ptr<SheepTools<T, float>>(new SheepTools<T, float>(
QString(QApplication::applicationDirPath() + "flam3-palettes.xml").toLocal8Bit().data(),
new EmberNs::Renderer<T, float>()));
m_GLController = unique_ptr<GLEmberController<T>>(new GLEmberController<T>(fractorium, fractorium->ui.GLDisplay, this));
m_PreviewRenderer = unique_ptr<EmberNs::Renderer<T, float>>(new EmberNs::Renderer<T, float>());
//Initial combo change event to fill the palette table will be called automatically later.
//Look hard for a palette.
if (!(InitPaletteList(QDir::currentPath().toLocal8Bit().data()) ||
InitPaletteList(QDir::homePath().toLocal8Bit().data()) ||
InitPaletteList(QCoreApplication::applicationDirPath().toLocal8Bit().data()) ||
InitPaletteList(QString("/usr/local/share/fractorium").toLocal8Bit().data()) ||
InitPaletteList(QString("/usr/share/fractorium").toLocal8Bit().data())) )
static vector<string> paths =
{
throw "No palettes found, exiting.";
QDir::currentPath().toLocal8Bit().data(),
QDir::homePath().toLocal8Bit().data(),
QCoreApplication::applicationDirPath().toLocal8Bit().data(),
QString("/usr/local/share/fractorium").toLocal8Bit().data(),
QString("/usr/share/fractorium").toLocal8Bit().data()
};
for (auto& path : paths)
{
if (b = InitPaletteList(path))
{
m_SheepTools = unique_ptr<SheepTools<T, float>>(new SheepTools<T, float>(
m_PaletteList.Name(0), new EmberNs::Renderer<T, float>()));
break;
}
}
if (!b)
throw "No palettes found, exiting.";
BackgroundChanged(QColor(0, 0, 0));//Default to black.
ClearUndo();
m_PreviewRenderer->Callback(nullptr);
@ -101,9 +96,9 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
m_PreviewRun = true;
m_PreviewRunning = true;
m_PreviewRenderer->ThreadCount(std::max(1u, Timing::ProcessorCount() - 1));//Leave one processor free so the GUI can breathe.
QTreeWidget* tree = m_Fractorium->ui.LibraryTree;
auto tree = m_Fractorium->ui.LibraryTree;
if (QTreeWidgetItem* top = tree->topLevelItem(0))
if (auto top = tree->topLevelItem(0))
{
for (size_t i = start; m_PreviewRun && i < end && i < m_EmberFile.Size(); i++)
{
@ -117,7 +112,7 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
if (m_PreviewRenderer->Run(m_PreviewFinalImage) == eRenderStatus::RENDER_OK)
{
if (EmberTreeWidgetItem<T>* treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
if (auto treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
{
//It is critical that Qt::BlockingQueuedConnection is passed because this is running on a different thread than the UI.
//This ensures the events are processed in order as each preview is updated, and that control does not return here
@ -193,11 +188,11 @@ void FractoriumEmberController<T>::SetEmber(size_t index)
{
if (index < m_EmberFile.Size())
{
if (QTreeWidgetItem* top = m_Fractorium->ui.LibraryTree->topLevelItem(0))
if (auto top = m_Fractorium->ui.LibraryTree->topLevelItem(0))
{
for (uint i = 0; i < top->childCount(); i++)
{
if (EmberTreeWidgetItem<T>* emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
emberItem->setSelected(i == index);
}
}

View File

@ -194,7 +194,6 @@ public:
//Xaos.
virtual void FillXaos() { }
virtual QString MakeXaosNameString(uint i) { return ""; }
virtual void XaosChanged(int x, int y, double val) { }
virtual void ClearXaos() { }
virtual void RandomXaos() { }
@ -254,7 +253,7 @@ protected:
QString m_LastSaveAll;
QString m_LastSaveCurrent;
string m_CurrentPaletteFilePath;
CriticalSection m_Cs;
std::recursive_mutex m_Cs;
std::thread m_WriteThread;
vector<byte> m_FinalImage;
vector<byte> m_PreviewFinalImage;
@ -263,8 +262,8 @@ protected:
unique_ptr<EmberNs::RendererBase> m_Renderer;
QTIsaac<ISAAC_SIZE, ISAAC_INT> m_Rand;
Fractorium* m_Fractorium;
QTimer* m_RenderTimer;
QTimer* m_RenderRestartTimer;
std::unique_ptr<QTimer> m_RenderTimer;
std::unique_ptr<QTimer> m_RenderRestartTimer;
shared_ptr<OpenCLInfo> m_Info;
};
@ -439,7 +438,6 @@ public:
//Xforms Xaos.
virtual void FillXaos() override;
virtual QString MakeXaosNameString(uint i) override;
virtual void XaosChanged(int x, int y, double val) override;
virtual void ClearXaos() override;
virtual void RandomXaos() override;
@ -475,7 +473,6 @@ private:
bool IsFinal(Xform<T>* xform);
//Xforms Color.
void SetCurrentXformColorIndex(double d, bool updateRender);
void FillCurvesControl();
//Xforms Selection.

View File

@ -32,7 +32,7 @@ void Fractorium::InitInfoUI()
/// <param name="newSize">Ignored</param>
void Fractorium::OnSummaryTableHeaderResized(int logicalIndex, int oldSize, int newSize)
{
QPixmap pixmap = QPixmap::fromImage(m_Controller->FinalPaletteImage());//Create a QPixmap out of the QImage, will be empty on startup.
QPixmap pixmap(QPixmap::fromImage(m_Controller->FinalPaletteImage()));//Create a QPixmap out of the QImage, will be empty on startup.
SetPaletteTableItem(&pixmap, ui.SummaryTable, m_InfoPaletteItem, 1, 0);
}
@ -57,7 +57,7 @@ void Fractorium::OnSummaryTreeHeaderSectionClicked(int logicalIndex)
/// values from the ember.
/// It's also meant to be used in a fire-and-forget way. Once the tree is filled
/// individual nodes are never referenced again.
/// The entire tree is cleared and refilled for every field change.
/// The entire tree is cleared and refilled whenever a render is completed.
/// This would seem inefficient, but it appears to update with no flicker.
/// If this ever presents a problem in the future, revisit with a more
/// intelligent design.
@ -74,17 +74,6 @@ void FractoriumEmberController<T>::FillSummary()
QColor color;
auto table = m_Fractorium->ui.SummaryTable;
auto tree = m_Fractorium->ui.SummaryTree;
QVariantList states;
QTreeWidgetItemIterator it(tree);
while (*it)
{
if (!(*it)->parent())//Top level only.
states += (*it)->isExpanded();
++it;
}
tree->blockSignals(true);
tree->clear();
m_Fractorium->m_InfoNameItem->setText(m_Ember.m_Name.c_str());
@ -92,7 +81,7 @@ void FractoriumEmberController<T>::FillSummary()
m_Fractorium->m_InfoXaosItem->setText(m_Ember.XaosPresent() ? "Yes" : "No");
m_Fractorium->m_InfoXformCountItem->setText(QString::number(m_Ember.XformCount()));
m_Fractorium->m_InfoFinalXformItem->setText(m_Ember.UseFinalXform() ? "Yes" : "No");
QPixmap pixmap = QPixmap::fromImage(m_FinalPaletteImage);//Create a QPixmap out of the QImage.
QPixmap pixmap(QPixmap::fromImage(m_FinalPaletteImage));//Create a QPixmap out of the QImage.
QSize size(table->columnWidth(0), table->rowHeight(1) + 1);
m_Fractorium->m_InfoPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
@ -178,26 +167,7 @@ void FractoriumEmberController<T>::FillSummary()
auto item2 = new QTreeWidgetItem(tree);//Empty item in between xforms.
}
QTreeWidgetItemIterator it2(tree);
if (!states.isEmpty())
{
while (*it2)
{
if (!(*it2)->parent())//Top level only.
{
if (!states.isEmpty())
(*it2)->setExpanded(states.takeFirst().toBool());
else
(*it2)->setExpanded(true);//Expand any remainder when going from lesser to greater number of xforms.
}
++it2;
}
}
else
tree->expandAll();
tree->expandAll();
tree->blockSignals(false);
}

View File

@ -20,9 +20,9 @@ pair<size_t, QTreeWidgetItem*> Fractorium::GetCurrentEmberIndex()
{
size_t index = 0;
QTreeWidgetItem* item = nullptr;
QTreeWidget* tree = ui.LibraryTree;
auto tree = ui.LibraryTree;
if (QTreeWidgetItem* top = tree->topLevelItem(0))
if (auto top = tree->topLevelItem(0))
{
for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers.
{
@ -35,7 +35,7 @@ pair<size_t, QTreeWidgetItem*> Fractorium::GetCurrentEmberIndex()
}
}
return pair<size_t, QTreeWidgetItem*>(index, item);
return make_pair(index, item);
}
/// <summary>
@ -57,11 +57,10 @@ template <typename T>
void FractoriumEmberController<T>::SyncNames()
{
EmberTreeWidgetItem<T>* item;
QTreeWidget* tree = m_Fractorium->ui.LibraryTree;
auto tree = m_Fractorium->ui.LibraryTree;
tree->blockSignals(true);
if (QTreeWidgetItem* top = tree->topLevelItem(0))
if (auto top = tree->topLevelItem(0))
{
for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers.
{
@ -80,11 +79,10 @@ template <typename T>
void FractoriumEmberController<T>::SyncPointers()
{
EmberTreeWidgetItem<T>* item;
QTreeWidget* tree = m_Fractorium->ui.LibraryTree;
auto tree = m_Fractorium->ui.LibraryTree;
tree->blockSignals(true);
if (QTreeWidgetItem* top = tree->topLevelItem(0))
if (auto top = tree->topLevelItem(0))
{
size_t childCount = top->childCount();
@ -107,28 +105,23 @@ void FractoriumEmberController<T>::SyncPointers()
template <typename T>
void FractoriumEmberController<T>::FillLibraryTree(int selectIndex)
{
uint i, j, size = 64;
QTreeWidget* tree = m_Fractorium->ui.LibraryTree;
uint j, size = 64;
auto tree = m_Fractorium->ui.LibraryTree;
vector<byte> v(size * size * 4);
StopPreviewRender();
tree->clear();
QCoreApplication::flush();
tree->blockSignals(true);
QTreeWidgetItem* fileItem = new QTreeWidgetItem(tree);
auto fileItem = new QTreeWidgetItem(tree);
QFileInfo info(m_EmberFile.m_Filename);
fileItem->setText(0, info.fileName());
fileItem->setToolTip(0, m_EmberFile.m_Filename);
fileItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
for (j = 0; j < m_EmberFile.Size(); j++)
{
Ember<T>* ember = &m_EmberFile.m_Embers[j];
EmberTreeWidgetItem<T>* emberItem = new EmberTreeWidgetItem<T>(ember, fileItem);
auto ember = &m_EmberFile.m_Embers[j];
auto emberItem = new EmberTreeWidgetItem<T>(ember, fileItem);
emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
if (ember->m_Name.empty())
@ -143,13 +136,13 @@ void FractoriumEmberController<T>::FillLibraryTree(int selectIndex)
tree->blockSignals(false);
if (selectIndex != -1)
if (QTreeWidgetItem* top = tree->topLevelItem(0))
if (EmberTreeWidgetItem<T>* emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(selectIndex)))
if (auto top = tree->topLevelItem(0))
if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(selectIndex)))
emberItem->setSelected(true);
QCoreApplication::flush();
RenderPreviews(0, m_EmberFile.Size());
tree->expandAll();
tree->expandAll();
}
/// <summary>
@ -160,20 +153,18 @@ template <typename T>
void FractoriumEmberController<T>::UpdateLibraryTree()
{
uint i, size = 64;
QTreeWidget* tree = m_Fractorium->ui.LibraryTree;
auto tree = m_Fractorium->ui.LibraryTree;
vector<byte> v(size * size * 4);
if (QTreeWidgetItem* top = tree->topLevelItem(0))
if (auto top = tree->topLevelItem(0))
{
int childCount = top->childCount();
tree->blockSignals(true);
for (i = childCount; i < m_EmberFile.Size(); i++)
{
Ember<T>* ember = &m_EmberFile.m_Embers[i];
EmberTreeWidgetItem<T>* emberItem = new EmberTreeWidgetItem<T>(ember, top);
auto emberItem = new EmberTreeWidgetItem<T>(ember, top);
emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
if (ember->m_Name.empty())
@ -208,9 +199,9 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
{
try
{
QTreeWidget* tree = m_Fractorium->ui.LibraryTree;
EmberTreeWidgetItem<T>* emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item);
auto tree = m_Fractorium->ui.LibraryTree;
auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item);
if (emberItem)
{
if (emberItem->text(0).isEmpty())//Prevent empty string.
@ -220,7 +211,6 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
}
string oldName = emberItem->GetEmber()->m_Name;//First preserve the previous name.
tree->blockSignals(true);
emberItem->UpdateEmberName();//Copy edit text to the ember's name variable.
m_EmberFile.MakeNamesUnique();//Ensure all names remain unique.
@ -246,7 +236,7 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
}
}
}
catch(const std::exception& e)
catch (const std::exception& e)
{
qDebug() << "FractoriumEmberController<T>::EmberTreeItemChanged() : Exception thrown: " << e.what();
}
@ -267,7 +257,7 @@ void Fractorium::OnEmberTreeItemChanged(QTreeWidgetItem* item, int col) { m_Cont
template <typename T>
void FractoriumEmberController<T>::EmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col)
{
if (EmberTreeWidgetItem<T>* emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item))
if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item))
{
ClearUndo();
SetEmber(*emberItem->GetEmber());
@ -285,8 +275,7 @@ void Fractorium::OnEmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) {
template <typename T>
void FractoriumEmberController<T>::Delete(const pair<size_t, QTreeWidgetItem*>& p)
{
QTreeWidget* tree = m_Fractorium->ui.LibraryTree;
auto tree = m_Fractorium->ui.LibraryTree;
tree->blockSignals(true);
if (m_EmberFile.Delete(p.first))
@ -298,7 +287,7 @@ void FractoriumEmberController<T>::Delete(const pair<size_t, QTreeWidgetItem*>&
tree->blockSignals(false);
//If there is now only one item left and it wasn't selected, select it.
if (QTreeWidgetItem* top = tree->topLevelItem(0))
if (auto top = tree->topLevelItem(0))
{
if (top->childCount() == 1)
if (auto item = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(0)))
@ -331,17 +320,16 @@ void FractoriumEmberController<T>::RenderPreviews(uint start, uint end)
if (start == UINT_MAX && end == UINT_MAX)
{
QTreeWidget* tree = m_Fractorium->ui.LibraryTree;
auto tree = m_Fractorium->ui.LibraryTree;
tree->blockSignals(true);
if (QTreeWidgetItem* top = tree->topLevelItem(0))
if (auto top = tree->topLevelItem(0))
{
int childCount = top->childCount();
vector<byte> emptyPreview(PREVIEW_SIZE * PREVIEW_SIZE * 3);
for (int i = 0; i < childCount; i++)
if (EmberTreeWidgetItem<T>* treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
if (auto treeItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))
treeItem->SetImage(emptyPreview, PREVIEW_SIZE, PREVIEW_SIZE);
}
@ -359,10 +347,11 @@ template <typename T>
void FractoriumEmberController<T>::StopPreviewRender()
{
m_PreviewRun = false;
m_PreviewRenderer->Abort();
while (m_PreviewRunning)
QApplication::processEvents();
m_PreviewResult.cancel();
while (m_PreviewResult.isRunning())
@ -375,5 +364,5 @@ void FractoriumEmberController<T>::StopPreviewRender()
template class FractoriumEmberController<float>;
#ifdef DO_DOUBLE
template class FractoriumEmberController<double>;
template class FractoriumEmberController<double>;
#endif

View File

@ -139,7 +139,7 @@ void Fractorium::OnActionNewRandomFlameInCurrentFile(bool checked) { m_Controlle
template <typename T>
void FractoriumEmberController<T>::CopyFlameInCurrentFile()
{
Ember<T> ember = m_Ember;
auto ember = m_Ember;
StopPreviewRender();
ember.m_Name = EmberFile<T>::DefaultEmberName(m_EmberFile.Size() + 1).toStdString();
ember.m_Index = m_EmberFile.Size();
@ -199,7 +199,7 @@ void FractoriumEmberController<T>::OpenAndPrepFiles(const QStringList& filenames
}
else
{
vector<string> errors = parser.ErrorReport();
auto errors = parser.ErrorReport();
m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit);
m_Fractorium->ShowCritical("Open Failed", "Could not open file, see info tab for details.");
}
@ -246,7 +246,7 @@ template <typename T>
void FractoriumEmberController<T>::SaveCurrentAsXml()
{
QString filename;
FractoriumSettings* s = m_Fractorium->m_Settings;
auto s = m_Fractorium->m_Settings;
if (s->SaveAutoUnique() && m_LastSaveCurrent != "")
{
@ -266,10 +266,10 @@ void FractoriumEmberController<T>::SaveCurrentAsXml()
if (filename != "")
{
Ember<T> ember = m_Ember;
auto ember = m_Ember;
EmberToXml<T> writer;
QFileInfo fileInfo(filename);
xmlDocPtr tempEdit = ember.m_Edits;
auto tempEdit = ember.m_Edits;
SaveCurrentToOpenedFile();//Save the current ember back to the opened file before writing to disk.
ApplyXmlSavingTemplate(ember);
ember.m_Edits = writer.CreateNewEditdoc(&ember, nullptr, "edit", s->Nick().toStdString(), s->Url().toStdString(), s->Id().toStdString(), "", 0, 0);
@ -300,7 +300,7 @@ template <typename T>
void FractoriumEmberController<T>::SaveEntireFileAsXml()
{
QString filename;
FractoriumSettings* s = m_Fractorium->m_Settings;
auto s = m_Fractorium->m_Settings;
if (s->SaveAutoUnique() && m_LastSaveAll != "")
filename = EmberFile<T>::UniqueFilename(m_LastSaveAll);
@ -340,12 +340,12 @@ void Fractorium::OnActionSaveEntireFileAsXml(bool checked) { m_Controller->SaveE
/// <param name="checked">Ignored</param>
void Fractorium::OnActionSaveCurrentScreen(bool checked)
{
QString filename = SetupSaveImageDialog(m_Controller->Name());
auto filename = SetupSaveImageDialog(m_Controller->Name());
auto renderer = m_Controller->Renderer();
auto& pixels = *m_Controller->FinalImage();
RendererCLBase* rendererCL = dynamic_cast<RendererCLBase*>(m_Controller->Renderer());
auto rendererCL = dynamic_cast<RendererCLBase*>(m_Controller->Renderer());
auto stats = m_Controller->Stats();
EmberImageComments comments = renderer->ImageComments(stats, 0, false, true);
auto comments = renderer->ImageComments(stats, 0, false, true);
if (rendererCL && renderer->PrepFinalAccumVector(pixels))
{
@ -460,9 +460,9 @@ void Fractorium::OnActionRedo(bool checked) { m_Controller->Redo(); }
template <typename T>
void FractoriumEmberController<T>::CopyXml()
{
Ember<T> ember = m_Ember;
auto ember = m_Ember;
EmberToXml<T> emberToXml;
FractoriumSettings* settings = m_Fractorium->m_Settings;
auto settings = m_Fractorium->m_Settings;
ember.m_Quality = settings->XmlQuality();
ember.m_Supersample = settings->XmlSupersample();
ember.m_TemporalSamples = settings->XmlTemporalSamples();
@ -480,7 +480,7 @@ void FractoriumEmberController<T>::CopyAllXml()
{
ostringstream os;
EmberToXml<T> emberToXml;
FractoriumSettings* settings = m_Fractorium->m_Settings;
auto settings = m_Fractorium->m_Settings;
os << "<flames>\n";
for (auto& e : m_EmberFile.m_Embers)
@ -510,8 +510,8 @@ void FractoriumEmberController<T>::PasteXmlAppend()
string s, errors;
XmlToEmber<T> parser;
vector<Ember<T>> embers;
QTextCodec* codec = QTextCodec::codecForName("UTF-8");
QByteArray b = codec->fromUnicode(QApplication::clipboard()->text());
auto codec = QTextCodec::codecForName("UTF-8");
auto b = codec->fromUnicode(QApplication::clipboard()->text());
s.reserve(b.size());
for (i = 0; i < b.size(); i++)
@ -563,9 +563,9 @@ void FractoriumEmberController<T>::PasteXmlOver()
uint i;
string s, errors;
XmlToEmber<T> parser;
Ember<T> backupEmber = m_EmberFile.m_Embers[0];
QTextCodec* codec = QTextCodec::codecForName("UTF-8");
QByteArray b = codec->fromUnicode(QApplication::clipboard()->text());
auto backupEmber = m_EmberFile.m_Embers[0];
auto codec = QTextCodec::codecForName("UTF-8");
auto b = codec->fromUnicode(QApplication::clipboard()->text());
s.reserve(b.size());
for (i = 0; i < b.size(); i++)
@ -810,6 +810,7 @@ void Fractorium::OnActionFinalRender(bool checked)
{
//First completely stop what the current rendering process is doing.
m_Controller->DeleteRenderer();//Delete the renderer, but not the controller.
m_Controller->StopPreviewRender();
OnActionSaveCurrentToOpenedFile(true);//Save whatever was edited back to the current open file.
m_RenderStatusLabel->setText("Renderer stopped.");
m_FinalRenderDialog->show();

View File

@ -139,7 +139,7 @@ void Fractorium::OnPaletteFilenameComboChanged(const QString& text)
template <typename T>
void FractoriumEmberController<T>::ApplyPaletteToEmber()
{
int i, rot = 0;
int rot = 0;
uint blur = m_Fractorium->m_PaletteBlurSpin->value();
uint freq = m_Fractorium->m_PaletteFrequencySpin->value();
double sat = double(m_Fractorium->m_PaletteSaturationSpin->value() / 100.0);
@ -170,7 +170,7 @@ void FractoriumEmberController<T>::UpdateAdjustedPaletteGUI(Palette<T>& palette)
vector<byte> v = palette.MakeRgbPaletteBlock(PALETTE_CELL_HEIGHT);//Make the palette repeat for PALETTE_CELL_HEIGHT rows.
m_FinalPaletteImage = QImage(palette.Size(), PALETTE_CELL_HEIGHT, QImage::Format_RGB888);//Create a QImage out of it.
memcpy(m_FinalPaletteImage.scanLine(0), v.data(), v.size() * sizeof(v[0]));//Memcpy the data in.
auto pixmap = QPixmap::fromImage(m_FinalPaletteImage);//Create a QPixmap out of the QImage.
QPixmap pixmap(QPixmap::fromImage(m_FinalPaletteImage));//Create a QPixmap out of the QImage.
previewPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(QSize(pixmap.width(), palettePreviewTable->rowHeight(0) + 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));//Set the pixmap on the palette tab.
m_Fractorium->SetPaletteTableItem(&pixmap, m_Fractorium->ui.XformPaletteRefTable, m_Fractorium->m_PaletteRefItem, 0, 0);//Set the palette ref table on the xforms | color tab.
auto previewNameItem = palettePreviewTable->item(0, 0);
@ -287,7 +287,7 @@ void Fractorium::OnPaletteRandomSelectButtonClicked(bool checked)
/// </summary>
void Fractorium::OnPaletteRandomAdjustButtonClicked(bool checked)
{
QTIsaac<ISAAC_SIZE, ISAAC_INT>* gRand = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand.get();
auto 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));

View File

@ -565,7 +565,7 @@ void FractoriumEmberController<T>::FillParamTablesAndPalette()
template <typename T>
void FractoriumEmberController<T>::ParamsToEmber(Ember<T>& ember)
{
QColor color = m_Fractorium->ui.ColorTable->item(5, 1)->backgroundColor();
auto color = m_Fractorium->ui.ColorTable->item(5, 1)->backgroundColor();
ember.m_Brightness = m_Fractorium->m_BrightnessSpin->value();//Color.
ember.m_Gamma = m_Fractorium->m_GammaSpin->value();
ember.m_GammaThresh = m_Fractorium->m_GammaThresholdSpin->value();

View File

@ -7,7 +7,7 @@
/// <returns>True if running, else false.</returns>
bool FractoriumEmberControllerBase::RenderTimerRunning()
{
return m_RenderTimer && m_RenderTimer->isActive();
return m_RenderTimer->isActive();
}
/// <summary>
@ -16,12 +16,9 @@ bool FractoriumEmberControllerBase::RenderTimerRunning()
/// </summary>
void FractoriumEmberControllerBase::StartRenderTimer()
{
if (m_RenderTimer)
{
UpdateRender();
m_RenderTimer->start();
m_RenderElapsedTimer.Tic();
}
UpdateRender();
m_RenderTimer->start();
m_RenderElapsedTimer.Tic();
}
/// <summary>
@ -33,12 +30,8 @@ void FractoriumEmberControllerBase::StartRenderTimer()
void FractoriumEmberControllerBase::DelayedStartRenderTimer()
{
DeleteRenderer();
if (m_RenderRestartTimer)
{
m_RenderRestartTimer->setSingleShot(true);
m_RenderRestartTimer->start(300);//Will stop the timer if it's already running, and start again.
}
m_RenderRestartTimer->setSingleShot(true);
m_RenderRestartTimer->start(300);//Will stop the timer if it's already running, and start again.
}
/// <summary>
@ -48,8 +41,7 @@ void FractoriumEmberControllerBase::DelayedStartRenderTimer()
/// <param name="wait">True to block, else false.</param>
void FractoriumEmberControllerBase::StopRenderTimer(bool wait)
{
if (m_RenderTimer)
m_RenderTimer->stop();
m_RenderTimer->stop();
if (m_Renderer.get())
m_Renderer->Abort();
@ -130,12 +122,11 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, c
if (filename != "")
{
bool b = false;
uint i, j;
byte* data = nullptr;
vector<byte> vecRgb;
QFileInfo fileInfo(filename);
QString suffix = fileInfo.suffix();
FractoriumSettings* settings = m_Fractorium->m_Settings;
auto settings = m_Fractorium->m_Settings;
//Ensure dimensions are valid.
if (pixels.size() < (width * height * channels * bpc))
@ -183,13 +174,11 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, c
/// <param name="action">The action for the renderer to take</param>
void FractoriumEmberControllerBase::AddProcessAction(eProcessAction action)
{
m_Cs.Enter();
rlg l(m_Cs);
m_ProcessActions.push_back(action);
if (m_Renderer.get())
m_Renderer->Abort();
m_Cs.Leave();
}
/// <summary>
@ -200,7 +189,7 @@ void FractoriumEmberControllerBase::AddProcessAction(eProcessAction action)
/// <returns>The most significant processing action desired</returns>
eProcessAction FractoriumEmberControllerBase::CondenseAndClearProcessActions()
{
m_Cs.Enter();
rlg l(m_Cs);
auto action = eProcessAction::NOTHING;
for (auto a : m_ProcessActions)
@ -208,7 +197,6 @@ eProcessAction FractoriumEmberControllerBase::CondenseAndClearProcessActions()
action = a;
m_ProcessActions.clear();
m_Cs.Leave();
return action;
}
@ -266,7 +254,7 @@ template <typename T>
bool FractoriumEmberController<T>::SyncSizes()
{
bool changed = false;
GLWidget* gl = m_Fractorium->ui.GLDisplay;
auto gl = m_Fractorium->ui.GLDisplay;
RendererCL<T, float>* rendererCL = nullptr;
if (!m_GLController->SizesMatch())
@ -296,7 +284,7 @@ bool FractoriumEmberController<T>::Render()
{
m_Rendering = true;
bool success = true;
GLWidget* gl = m_Fractorium->ui.GLDisplay;
auto gl = m_Fractorium->ui.GLDisplay;
RendererCL<T, float>* rendererCL = nullptr;
eProcessAction qualityAction, action;
//Quality is the only parameter we update inside the timer.
@ -403,10 +391,10 @@ bool FractoriumEmberController<T>::Render()
//Rendering has finished, update final stats.
if (ProcessState() == eProcessState::ACCUM_DONE)
{
EmberStats stats = m_Renderer->Stats();
QString iters = ToString<qulonglong>(stats.m_Iters);
QString scaledQuality = ToString(uint(m_Renderer->ScaledQuality()));
string renderTime = m_RenderElapsedTimer.Format(m_RenderElapsedTimer.Toc());
auto stats = m_Renderer->Stats();
auto iters = ToString<qulonglong>(stats.m_Iters);
auto scaledQuality = ToString(uint(m_Renderer->ScaledQuality()));
auto renderTime = m_RenderElapsedTimer.Format(m_RenderElapsedTimer.Toc());
m_Fractorium->m_ProgressBar->setValue(100);
//Only certain stats can be reported with OpenCL.
@ -417,8 +405,8 @@ bool FractoriumEmberController<T>::Render()
else
{
double percent = double(stats.m_Badvals) / double(stats.m_Iters);
QString badVals = ToString<qulonglong>(stats.m_Badvals);
QString badPercent = QLocale::system().toString(percent * 100, 'f', 2);
auto badVals = ToString<qulonglong>(stats.m_Badvals);
auto badPercent = QLocale::system().toString(percent * 100, 'f', 2);
m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Bad values: " + badVals + " (" + badPercent + "%). Total time: " + QString::fromStdString(renderTime) + ".");
}
@ -428,13 +416,18 @@ bool FractoriumEmberController<T>::Render()
}
else if (m_EditState == eEditUndoState::REGULAR_EDIT)//Regular edit, just add to the end of the undo list.
{
m_UndoList.push_back(m_Ember);
m_UndoIndex = m_UndoList.size() - 1;
m_Fractorium->ui.ActionUndo->setEnabled(m_UndoList.size() > 1);
m_Fractorium->ui.ActionRedo->setEnabled(false);
auto btn = QApplication::mouseButtons();
if (m_UndoList.size() >= UNDO_SIZE)
m_UndoList.pop_front();
if (!btn.testFlag(Qt::LeftButton) && !btn.testFlag(Qt::RightButton) && !btn.testFlag(Qt::MiddleButton))
{
m_UndoList.push_back(m_Ember);
m_UndoIndex = m_UndoList.size() - 1;
m_Fractorium->ui.ActionUndo->setEnabled(m_UndoList.size() > 1);
m_Fractorium->ui.ActionRedo->setEnabled(false);
if (m_UndoList.size() >= UNDO_SIZE)
m_UndoList.pop_front();
}
}
else if (!m_LastEditWasUndoRedo && m_UndoIndex < m_UndoList.size() - 1)//They were anywhere but the end of the undo list, then did a manual edit, so clear the undo list.
{
@ -459,9 +452,6 @@ bool FractoriumEmberController<T>::Render()
if (m_FinalImage.size() == m_Renderer->FinalBufferSize())//Make absolutely sure the correct amount of data is passed.
gl->update();
//gl->repaint();
//m_Fractorium->update();
//m_Fractorium->ui.GLParentScrollArea->update();
//Uncomment for debugging kernel build and execution errors.
//m_Fractorium->ui.InfoRenderingTextEdit->setText(QString::fromStdString(m_Fractorium->m_Wrapper.DumpInfo()));
//if (rendererCL)
@ -474,7 +464,7 @@ bool FractoriumEmberController<T>::Render()
}
else//Something went very wrong, show error report.
{
vector<string> errors = m_Renderer->ErrorReport();
auto errors = m_Renderer->ErrorReport();
success = false;
m_FailedRenders++;
m_Fractorium->m_RenderStatusLabel->setText("Rendering failed, see info tab. Try changing parameters.");
@ -503,7 +493,6 @@ bool FractoriumEmberController<T>::Render()
if (ProcessState() == eProcessState::ACCUM_DONE)
QThread::msleep(1);
//QApplication::processEvents();
m_Rendering = false;
return success;
}
@ -520,8 +509,8 @@ template <typename T>
bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared)
{
bool ok = true;
FractoriumSettings* s = m_Fractorium->m_Settings;
GLWidget* gl = m_Fractorium->ui.GLDisplay;
auto s = m_Fractorium->m_Settings;
auto gl = m_Fractorium->ui.GLDisplay;
if (!m_Renderer.get() || (m_Renderer->RendererType() != renderType) || !Equal(m_Devices, devices))
{
@ -691,6 +680,7 @@ bool Fractorium::CreateControllerFromOptions()
//First check if a controller has already been created, and if so, save its embers and gracefully shut it down.
if (m_Controller.get())
{
m_Controller->StopPreviewRender();//Must stop any previews first, else changing controllers will crash the program.
m_Controller->CopyTempPalette(tempPalette);//Convert float to double or save double verbatim;
//Replace below with this once LLVM fixes a crash in their compiler with default lambda parameters.//TODO
//m_Controller->CopyEmber(ed);

View File

@ -48,35 +48,6 @@ void FractoriumEmberController<T>::FillXaos()
m_Fractorium->ui.XaosTableView->resizeColumnsToContents();
}
/// <summary>
/// Create and return a xaos name string.
/// </summary>
/// <param name="i">The index of the xform whose xaos will be used</param>
/// <returns>The xaos name string</returns>
template <typename T>
QString FractoriumEmberController<T>::MakeXaosNameString(uint i)
{
auto xform = m_Ember.GetXform(i);
QString name;
//if (xform)
//{
// int indexPlus1 = m_Ember.GetXformIndex(xform) + 1;//GUI is 1 indexed to avoid confusing the user.
// int curr = m_Fractorium->ui.CurrentXformCombo->currentIndex() + 1;
//
// if (indexPlus1 != -1)
// {
// if (m_Fractorium->ui.XaosToRadio->isChecked())
// name = QString("From ") + ToString(curr) + QString(" To ") + ToString(indexPlus1);
// else
// name = QString("From ") + ToString(indexPlus1) + QString(" To ") + ToString(curr);
//
// //if (xform->m_Name != "")
// // name = name + " (" + QString::fromStdString(xform->m_Name) + ")";
// }
//}
return name;
}
/// <summary>
/// Set the xaos value.
/// Called when any xaos spinner is changed.
@ -93,13 +64,13 @@ void FractoriumEmberController<T>::XaosChanged(int x, int y, double val)
auto newVal = TruncPrecision(val, XAOS_PREC);//Sometimes 0 comes in as a very small number, so round.
if (auto xform = m_Ember.GetXform(x))
if (!IsClose<T>(newVal, xform->Xaos(y), 1e-7))
if (!IsClose<T>(newVal, xform->Xaos(y), T(1e-7)))
Update([&] { xform->SetXaos(y, newVal); });
}
void Fractorium::OnXaosChanged(double d)
{
if (auto* senderSpinBox = qobject_cast<DoubleSpinBox*>(this->sender()))
if (auto senderSpinBox = qobject_cast<DoubleSpinBox*>(this->sender()))
{
auto p = senderSpinBox->property("tableindex").toPoint();
m_Controller->XaosChanged(p.x(), p.y(), d);

View File

@ -364,7 +364,7 @@ void FractoriumEmberController<T>::RotateXformsByAngle(double angle, bool pre)
UpdateXform([&] (Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
affine->Rotate(angle);
affine->Rotate(angle * DEG_2_RAD_T);
}, eXformUpdate::UPDATE_SELECTED);
FillAffineWithXform(CurrentXform(), pre);
}
@ -595,7 +595,7 @@ template <typename T>
void FractoriumEmberController<T>::FillAffineWithXform(Xform<T>* xform, bool pre)
{
DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
const Affine2D<T>& affine = pre ? xform->m_Affine : xform->m_Post;
auto& affine = pre ? xform->m_Affine : xform->m_Post;
if (m_Fractorium->ui.PolarAffineCheckBox->isChecked())
{

View File

@ -47,7 +47,15 @@ void FractoriumEmberController<T>::XformColorIndexChanged(double d, bool updateR
scroll->blockSignals(true);
scroll->setValue(scrollVal);
scroll->blockSignals(false);
SetCurrentXformColorIndex(d, updateRender);
m_Fractorium->ui.XformColorIndexTable->item(0, 0)->setBackgroundColor(ColorIndexToQColor(d));//Grab the current color from the index and assign it to the first cell of the first table.
if (updateRender)//False when just updating GUI, true when in response to a GUI change so update values and reset renderer.
{
UpdateXform([&](Xform<T>* xform)
{
xform->m_ColorX = Clamp<T>(d, 0, 1);
}, eXformUpdate::UPDATE_SELECTED, updateRender);
}
}
void Fractorium::OnXformColorIndexChanged(double d) { OnXformColorIndexChanged(d, true); }
@ -135,7 +143,7 @@ void Fractorium::OnSoloXformCheckBoxStateChanged(int state)
/// <param name="newSize">Ignored</param>
void Fractorium::OnXformRefPaletteResized(int logicalIndex, int oldSize, int newSize)
{
QPixmap pixmap = QPixmap::fromImage(m_Controller->FinalPaletteImage());
QPixmap pixmap(QPixmap::fromImage(m_Controller->FinalPaletteImage()));
SetPaletteTableItem(&pixmap, ui.XformPaletteRefTable, m_PaletteRefItem, 0, 0);
}
@ -204,22 +212,6 @@ QColor FractoriumEmberController<T>::ColorIndexToQColor(double d)
return QColor::fromRgb(rgb);
}
/// <summary>
/// Set the selected xforms color index to the passed in value.
/// Set the color cell in the palette ref table.
/// </summary>
/// <param name="d">The index value to set, 0-1.</param>
template <typename T>
void FractoriumEmberController<T>::SetCurrentXformColorIndex(double d, bool updateRender)
{
UpdateXform([&] (Xform<T>* xform)
{
xform->m_ColorX = Clamp<T>(d, 0, 1);
//Grab the current color from the index and assign it to the first cell of the first table.
m_Fractorium->ui.XformColorIndexTable->item(0, 0)->setBackgroundColor(ColorIndexToQColor(xform->m_ColorX)/*QColor::fromRgb(rgb)*/);
}, eXformUpdate::UPDATE_SELECTED, updateRender);
}
/// <summary>
/// Set the points in the curves control to the values of the curve points in the current ember.
/// </summary>

View File

@ -9,7 +9,6 @@ void Fractorium::InitXformsSelectUI()
m_XformsSelectionLayout = (QFormLayout*)ui.XformsSelectGroupBoxScrollAreaWidget->layout();
connect(ui.XformsSelectAllButton, SIGNAL(clicked(bool)), this, SLOT(OnXformsSelectAllButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.XformsSelectNoneButton, SIGNAL(clicked(bool)), this, SLOT(OnXformsSelectNoneButtonClicked(bool)), Qt::QueuedConnection);
ClearXformsSelections();
}
@ -17,13 +16,13 @@ void Fractorium::InitXformsSelectUI()
/// Check all of the xform selection checkboxes.
/// </summary>
/// <param name="checked">Ignored</param>
void Fractorium::OnXformsSelectAllButtonClicked(bool checked) { ForEachXformCheckbox([&](int i, QCheckBox* w) { w->setChecked(true); }); }
void Fractorium::OnXformsSelectAllButtonClicked(bool checked) { ForEachXformCheckbox([&](int i, QCheckBox * w) { w->setChecked(true); }); }
/// <summary>
/// Uncheck all of the xform selection checkboxes.
/// </summary>
/// <param name="checked">Ignored</param>
void Fractorium::OnXformsSelectNoneButtonClicked(bool checked) { ForEachXformCheckbox([&](int i, QCheckBox* w) { w->setChecked(false); }); }
void Fractorium::OnXformsSelectNoneButtonClicked(bool checked) { ForEachXformCheckbox([&](int i, QCheckBox * w) { w->setChecked(false); }); }
/// <summary>
/// Clear all of the dynamically created xform checkboxes.
@ -31,7 +30,6 @@ void Fractorium::OnXformsSelectNoneButtonClicked(bool checked) { ForEachXformChe
void Fractorium::ClearXformsSelections()
{
QLayoutItem* child = nullptr;
m_XformSelections.clear();
m_XformsSelectionLayout->blockSignals(true);
@ -95,9 +93,9 @@ void Fractorium::ForEachXformCheckbox(std::function<void(int, QCheckBox*)> func)
template <typename T>
bool FractoriumEmberController<T>::XformCheckboxAt(int i, std::function<void(QCheckBox*)> func)
{
if (QLayoutItem* child = m_Fractorium->m_XformsSelectionLayout->itemAt(i))
if (auto child = m_Fractorium->m_XformsSelectionLayout->itemAt(i))
{
if (auto* w = qobject_cast<QCheckBox*>(child->widget()))
if (auto w = qobject_cast<QCheckBox*>(child->widget()))
{
func(w);
return true;

View File

@ -171,11 +171,11 @@ void FractoriumEmberController<T>::SetupVariationTree()
template <typename T>
void FractoriumEmberController<T>::ClearVariationsTree()
{
QTreeWidget* tree = m_Fractorium->ui.VariationsTree;
auto tree = m_Fractorium->ui.VariationsTree;
for (int i = 0; i < tree->topLevelItemCount(); i++)
{
QTreeWidgetItem* item = tree->topLevelItem(i);
auto item = tree->topLevelItem(i);
auto* spinBox = dynamic_cast<VariationTreeDoubleSpinBox*>(tree->itemWidget(item, 1));
spinBox->SetValueStealth(0);
@ -189,7 +189,7 @@ void FractoriumEmberController<T>::ClearVariationsTree()
/// <summary>
/// Copy the value of a variation or param spinner to its corresponding value
/// in the currently selected xform.
/// in the selected xforms.
/// Called when any spinner in the variations tree is changed.
/// Resets the rendering process.
/// </summary>
@ -197,79 +197,82 @@ void FractoriumEmberController<T>::ClearVariationsTree()
template <typename T>
void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would be awesome to make this work for all.//TODO
{
bool update = false;
auto objSender = m_Fractorium->sender();
auto tree = m_Fractorium->ui.VariationsTree;
auto sender = dynamic_cast<VariationTreeDoubleSpinBox*>(objSender);
auto xform = m_Ember.GetTotalXform(m_Fractorium->ui.CurrentXformCombo->currentIndex());//Will retrieve normal xform or final if needed.
if (sender && xform)
if (sender)
{
auto var = m_VariationList.GetVariation(sender->GetVariationId());//The variation attached to the sender, for reference only.
auto parVar = dynamic_cast<const ParametricVariation<T>*>(var);//The parametric cast of that variation.
auto xformVar = xform->GetVariationById(var->VariationId());//The corresponding variation in the currently selected xform.
auto widgetItem = sender->WidgetItem();
bool isParam = parVar && sender->IsParam();
if (isParam)
UpdateXform([&](Xform<T>* xform)
{
//Do not take action if the xform doesn't contain the variation which this param is part of.
if (ParametricVariation<T>* xformParVar = dynamic_cast<ParametricVariation<T>*>(xformVar))//The parametric cast of the xform's variation.
{
if (xformParVar->SetParamVal(sender->ParamName().c_str(), d))
{
UpdateRender();
}
}
}
else
{
//If they spun down to zero, and it wasn't a parameter item,
//and the current xform contained the variation, then remove the variation.
if (IsNearZero(d))
{
if (xformVar)
xform->DeleteVariationById(var->VariationId());
auto var = m_VariationList.GetVariation(sender->GetVariationId());//The variation attached to the sender, for reference only.
auto parVar = dynamic_cast<const ParametricVariation<T>*>(var);//The parametric cast of that variation.
auto xformVar = xform->GetVariationById(var->VariationId());//The corresponding variation in the currently selected xform.
auto widgetItem = sender->WidgetItem();
bool isParam = parVar && sender->IsParam();
widgetItem->setBackgroundColor(0, QColor(255, 255, 255));//Ensure background is always white if weight goes to zero.
if (isParam)
{
//Do not take action if the xform doesn't contain the variation which this param is part of.
if (ParametricVariation<T>* xformParVar = dynamic_cast<ParametricVariation<T>*>(xformVar))//The parametric cast of the xform's variation.
if (xformParVar->SetParamVal(sender->ParamName().c_str(), d))
update = true;
}
else
{
if (xformVar)//The xform already contained this variation, which means they just went from a non-zero weight to another non-zero weight (the simple case).
//If they spun down to zero, and it wasn't a parameter item,
//and the current xform contained the variation, then remove the variation.
if (IsNearZero(d))
{
xformVar->m_Weight = d;
if (xformVar)
xform->DeleteVariationById(var->VariationId());
widgetItem->setBackgroundColor(0, QColor(255, 255, 255));//Ensure background is always white if weight goes to zero.
}
else
{
//If the item wasn't a param and the xform did not contain this variation,
//it means they went from zero to a non-zero weight, so add a new copy of this xform.
auto newVar = var->Copy();//Create a new one with default values.
newVar->m_Weight = d;
xform->AddVariation(newVar);
widgetItem->setBackgroundColor(0, QColor(200, 200, 200));//Set background to gray when a variation has non-zero weight in this xform.
//If they've added a new parametric variation, then grab the values currently in the spinners
//for the child parameters and assign them to the newly added variation.
if (parVar)
if (xformVar)//The xform already contained this variation, which means they just went from a non-zero weight to another non-zero weight (the simple case).
{
auto newParVar = dynamic_cast<ParametricVariation<T>*>(newVar);
xformVar->m_Weight = d;
}
else
{
//If the item wasn't a param and the xform did not contain this variation,
//it means they went from zero to a non-zero weight, so add a new copy of this xform.
auto newVar = var->Copy();//Create a new one with default values.
newVar->m_Weight = d;
xform->AddVariation(newVar);
widgetItem->setBackgroundColor(0, QColor(200, 200, 200));//Set background to gray when a variation has non-zero weight in this xform.
for (int i = 0; i < widgetItem->childCount(); i++)//Iterate through all of the children, which will be the params.
//If they've added a new parametric variation, then grab the values currently in the spinners
//for the child parameters and assign them to the newly added variation.
if (parVar)
{
auto childItem = widgetItem->child(i);//Get the child.
auto itemWidget = tree->itemWidget(childItem, 1);//Get the widget for the child.
auto newParVar = dynamic_cast<ParametricVariation<T>*>(newVar);
if (auto spinBox = dynamic_cast<VariationTreeDoubleSpinBox*>(itemWidget))//Cast the widget to the VariationTreeDoubleSpinBox type.
for (int i = 0; i < widgetItem->childCount(); i++)//Iterate through all of the children, which will be the params.
{
string s = childItem->text(0).toStdString();//Use the name of the child, and the value of the spinner widget to assign the param.
newParVar->SetParamVal(s.c_str(), spinBox->value());
auto childItem = widgetItem->child(i);//Get the child.
auto itemWidget = tree->itemWidget(childItem, 1);//Get the widget for the child.
if (auto spinBox = dynamic_cast<VariationTreeDoubleSpinBox*>(itemWidget))//Cast the widget to the VariationTreeDoubleSpinBox type.
{
string s = childItem->text(0).toStdString();//Use the name of the child, and the value of the spinner widget to assign the param.
newParVar->SetParamVal(s.c_str(), spinBox->value());
}
}
}
}
}
}
update = true;
}
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);
if (update)
UpdateRender();
}
}
}

View File

@ -103,6 +103,20 @@ T GLEmberController<T>::CalcRotation()
return rotStart - rot;
}
/// <summary>
/// Snap the passed in world cartesian coordinate to the grid for rotation, scale or translation.
/// </summary>
/// <param name="vec">The world cartesian coordinate to be snapped</param>
/// <returns>The snapped world cartesian coordinate</returns>
template <typename T>
typename v2T GLEmberController<T>::SnapToGrid(v2T& vec)
{
v2T ret;
ret.x = glm::round(vec.x / GridStep) * GridStep;
ret.y = glm::round(vec.y / GridStep) * GridStep;
return ret;
}
/// <summary>
/// Snap the passed in world cartesian coordinate to the grid for rotation, scale or translation.
/// </summary>
@ -135,8 +149,8 @@ typename v3T GLEmberController<T>::SnapToNormalizedAngle(v3T& vec, uint division
for (uint i = 0; i < divisions; i++)
{
theta = 2.0 * M_PI * T(i) / T(divisions);
c.x = cos(theta);
c.y = sin(theta);
c.x = std::cos(theta);
c.y = std::sin(theta);
rsq = glm::distance(vec, c);
if (rsq < bestRsq)
@ -220,7 +234,7 @@ void GLEmberController<double>::MultMatrix(tmat4x4<double, glm::defaultp>& mat)
template <typename T>
void GLEmberController<T>::QueryMatrices(bool print)
{
RendererBase* renderer = m_FractoriumEmberController->Renderer();
auto renderer = m_FractoriumEmberController->Renderer();
if (renderer)
{
@ -242,13 +256,13 @@ void GLEmberController<T>::QueryMatrices(bool print)
if (print)
{
for (size_t i = 0; i < 4; i++)
qDebug() << "Viewport[" << i << "] = " << m_Viewport[i] << endl;
qDebug() << "Viewport[" << i << "] = " << m_Viewport[i] << "\n";
for (size_t i = 0; i < 16; i++)
qDebug() << "Modelview[" << i << "] = " << glm::value_ptr(m_Modelview)[i] << endl;
qDebug() << "Modelview[" << i << "] = " << glm::value_ptr(m_Modelview)[i] << "\n";
for (size_t i = 0; i < 16; i++)
qDebug() << "Projection[" << i << "] = " << glm::value_ptr(m_Projection)[i] << endl;
qDebug() << "Projection[" << i << "] = " << glm::value_ptr(m_Projection)[i] << "\n";
}
}
}

View File

@ -109,9 +109,9 @@ public:
T CalcScale();
T CalcRotation();
Affine2D<T> CalcDragXAxis();
Affine2D<T> CalcDragYAxis();
Affine2D<T> CalcDragTranslation();
void CalcDragXAxis();
void CalcDragYAxis();
void CalcDragTranslation();
void SetEmber(Ember<T>* ember);
void SetSelectedXform(Xform<T>* xform);
@ -120,6 +120,7 @@ public:
bool CheckXformHover(Xform<T>* xform, v3T& glCoords, T& bestDist, bool pre, bool post);
private:
v2T SnapToGrid(v2T& vec);
v3T SnapToGrid(v3T& vec);
v3T SnapToNormalizedAngle(v3T& vec, uint divisions);
v3T WindowToWorld(v3T& v, bool flip);

View File

@ -63,8 +63,8 @@ void GLWidget::DrawQuad()
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
RendererBase* renderer = m_Fractorium->m_Controller->Renderer();
vector<byte>* finalImage = m_Fractorium->m_Controller->FinalImage();
auto renderer = m_Fractorium->m_Controller->Renderer();
auto finalImage = m_Fractorium->m_Controller->FinalImage();
//Ensure all allocation has taken place first.
if (m_OutputTexID != 0 && finalImage && !finalImage->empty())
@ -123,14 +123,14 @@ bool GLEmberControllerBase::Allocate(bool force) { return m_GL->Allocate(force);
/// Helpers to set/get/clear which keys are pressed while dragging.
/// </summary>
/// <returns>bool</returns>
bool GLEmberControllerBase::GetAlt() { return (m_DragModifier & et(eDragModifier::DragModAlt)) == et(eDragModifier::DragModAlt); }
bool GLEmberControllerBase::GetShift() { return (m_DragModifier & et(eDragModifier::DragModShift)) == et(eDragModifier::DragModShift); }
bool GLEmberControllerBase::GetControl() { return (m_DragModifier & et(eDragModifier::DragModControl)) == et(eDragModifier::DragModControl); }
void GLEmberControllerBase::SetAlt() { m_DragModifier |= et(eDragModifier::DragModAlt); }
void GLEmberControllerBase::SetShift() { m_DragModifier |= et(eDragModifier::DragModShift); }
void GLEmberControllerBase::SetControl() { m_DragModifier |= et(eDragModifier::DragModControl); }
void GLEmberControllerBase::ClearAlt() { m_DragModifier &= ~et(eDragModifier::DragModAlt); }
void GLEmberControllerBase::ClearShift() { m_DragModifier &= ~et(eDragModifier::DragModShift); }
bool GLEmberControllerBase::GetAlt() { return (m_DragModifier & et(eDragModifier::DragModAlt)) == et(eDragModifier::DragModAlt); }
bool GLEmberControllerBase::GetShift() { return (m_DragModifier & et(eDragModifier::DragModShift)) == et(eDragModifier::DragModShift); }
bool GLEmberControllerBase::GetControl() { return (m_DragModifier & et(eDragModifier::DragModControl)) == et(eDragModifier::DragModControl); }
void GLEmberControllerBase::SetAlt() { m_DragModifier |= et(eDragModifier::DragModAlt); }
void GLEmberControllerBase::SetShift() { m_DragModifier |= et(eDragModifier::DragModShift); }
void GLEmberControllerBase::SetControl() { m_DragModifier |= et(eDragModifier::DragModControl); }
void GLEmberControllerBase::ClearAlt() { m_DragModifier &= ~et(eDragModifier::DragModAlt); }
void GLEmberControllerBase::ClearShift() { m_DragModifier &= ~et(eDragModifier::DragModShift); }
void GLEmberControllerBase::ClearControl() { m_DragModifier &= ~et(eDragModifier::DragModControl); }
/// <summary>
@ -214,9 +214,9 @@ void GLWidget::paintGL()
//Ensure there is a renderer and that it's supposed to be drawing, signified by the running timer.
if (controller && controller->Renderer())
{
RendererBase* renderer = controller->Renderer();
auto renderer = controller->Renderer();
m_Drawing = true;
controller->GLController()->DrawImage();
GLController()->DrawImage();
//Affine drawing.
bool pre = m_Fractorium->ui.PreAffineGroupBox->isChecked();
bool post = m_Fractorium->ui.PostAffineGroupBox->isChecked();
@ -431,7 +431,7 @@ void GLEmberController<T>::MousePress(QMouseEvent* e)
m_BoundsDown.x = renderer->LowerLeftY(false);
m_BoundsDown.y = renderer->UpperRightX(false);
m_BoundsDown.z = renderer->UpperRightY(false);
Qt::KeyboardModifiers mod = e->modifiers();
auto mod = e->modifiers();
if (mod.testFlag(Qt::ShiftModifier))
SetShift();
@ -455,11 +455,11 @@ void GLEmberController<T>::MousePress(QMouseEvent* e)
m_DragSrcTransform = Affine2D<T>(m_AffineType == eAffineType::AffinePre ? m_SelectedXform->m_Affine : m_SelectedXform->m_Post);//Copy the affine of the xform that was selected.
//The user has selected an xform by clicking on it, so update the main GUI by selecting this xform in the combo box.
m_Fractorium->CurrentXform(xformIndex);//Must do this first so UpdateXform() below properly grabs the current plus any selected.
//m_DragSrcTransforms.clear();
//m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
//{
// m_DragSrcTransforms.push_back(m_AffineType == eAffineType::AffinePre ? xform->m_Affine : xform->m_Post);
//}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Don't update renderer here.
m_DragSrcTransforms.clear();
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
m_DragSrcTransforms.push_back(m_AffineType == eAffineType::AffinePre ? xform->m_Affine : xform->m_Post);
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Don't update renderer here.
m_DragHandlePos = m_HoverHandlePos;//The location in local coordinates of the point selected on the spinner, x, y or center.
m_DragHandleOffset = m_DragHandlePos - m_MouseWorldPos;//The distance in world coordinates from the point selected to the center of the spinner.
m_DragState = eDragState::DragDragging;
@ -505,7 +505,7 @@ void GLWidget::mousePressEvent(QMouseEvent* e)
{
setFocus();//Must do this so that this window gets keyboard events.
if (GLEmberControllerBase* controller = GLController())
if (auto controller = GLController())
controller->MousePress(e);
QOpenGLWidget::mousePressEvent(e);
@ -538,7 +538,7 @@ void GLWidget::mouseReleaseEvent(QMouseEvent* e)
{
setFocus();//Must do this so that this window gets keyboard events.
if (GLEmberControllerBase* controller = GLController())
if (auto controller = GLController())
controller->MouseRelease(e);
QOpenGLWidget::mouseReleaseEvent(e);
@ -571,22 +571,13 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
if (m_SelectedXform && m_DragState == eDragState::DragDragging)//Dragging and affine.
{
bool pre = m_AffineType == eAffineType::AffinePre;
Affine2D<T>* affine = pre ? &m_SelectedXform->m_Affine : &m_SelectedXform->m_Post;//Determine pre or post affine.
if (m_HoverType == eHoverType::HoverTranslation)
{
//m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
//{
// affine = pre ? &xform->m_Affine : &xform->m_Post;//Determine pre or post affine.
// *affine = CalcDragTranslation();
//}, eXformUpdate::UPDATE_ALL, false);//Don't need to update render for every xform, just do it once below.
*affine = CalcDragTranslation();
//CalcDragTranslation();
}
CalcDragTranslation();
else if (m_HoverType == eHoverType::HoverXAxis)
*affine = CalcDragXAxis();
CalcDragXAxis();
else if (m_HoverType == eHoverType::HoverYAxis)
*affine = CalcDragYAxis();
CalcDragYAxis();
m_FractoriumEmberController->FillAffineWithXform(m_SelectedXform, pre);//Update the spinners in the affine tab of the main window.
m_FractoriumEmberController->UpdateRender();//Restart the rendering process.
@ -598,7 +589,7 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
Affine2D<T> rotMat;
rotMat.C(m_CenterDownX);
rotMat.F(m_CenterDownY);
rotMat.Rotate(ember->m_Rotate);
rotMat.Rotate(ember->m_Rotate * DEG_2_RAD_T);
v2T v1(x, y);
v2T v2 = rotMat.TransformVector(v1);
ember->m_CenterX = v2.x;
@ -611,8 +602,7 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
T scale = CalcScale();
ember->m_Rotate = NormalizeDeg180<T>(m_RotationDown + rot);
m_Fractorium->SetRotation(ember->m_Rotate, true);
ember->m_PixelsPerUnit = m_ScaleDown + scale;
m_Fractorium->SetScale(ember->m_PixelsPerUnit);//Will restart the rendering process.
m_Fractorium->SetScale(m_ScaleDown + scale);//Will restart the rendering process.
}
else
{
@ -625,22 +615,12 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
//In that case, nothing needs to be done.
if (UpdateHover(mouseFlipped) == -1)
draw = false;
//auto previousHover = m_HoverXform;
//
//if (UpdateHover(mouseFlipped) == -1)
// m_HoverXform = m_SelectedXform;
//
//if (m_HoverXform == previousHover)
// draw = false;
}
//Only update if the user was dragging or hovered over a point.
//Use repaint() to update immediately for a more responsive feel.
if ((m_DragState != eDragState::DragNone) || draw)
m_GL->update();
//m_GL->repaint();
}
/// <summary>
@ -651,7 +631,7 @@ void GLWidget::mouseMoveEvent(QMouseEvent* e)
{
setFocus();//Must do this so that this window gets keyboard events.
if (GLEmberControllerBase* controller = GLController())
if (auto controller = GLController())
controller->MouseMove(e);
QOpenGLWidget::mouseMoveEvent(e);
@ -679,28 +659,12 @@ void GLEmberController<T>::Wheel(QWheelEvent* e)
/// <param name="e">The event</param>
void GLWidget::wheelEvent(QWheelEvent* e)
{
if (GLEmberControllerBase* controller = GLController())
if (auto controller = GLController())
controller->Wheel(e);
//Do not call QOpenGLWidget::wheelEvent(e) because this should only affect the scale and not the position of the scroll bars.
}
/// <summary>
/// Respond to a resize event which will set the double click default value
/// in the width and height spinners.
/// Note, this does not change the size of the ember being rendered or
/// the OpenGL texture it's being drawn on.
/// </summary>
/// <param name="e">The event</param>
//void GLWidget::resizeEvent(QResizeEvent* e)
//{
// if (m_Fractorium)
// {
// }
//
// QOpenGLWidget::resizeEvent(e);
//}
/// <summary>
/// Set the dimensions of the drawing area.
/// This will be called from the main window's SyncSizes() function.
@ -710,8 +674,6 @@ void GLWidget::wheelEvent(QWheelEvent* e)
void GLWidget::SetDimensions(int w, int h)
{
setFixedSize(w, h);
//resize(w, h);
//m_Fractorium->ui.GLParentScrollAreaContents->setFixedSize(w, h);
}
/// <summary>
@ -817,7 +779,7 @@ bool GLEmberController<T>::SizesMatch()
/// <param name="scale">A value to scale by, used when locking the affine scale</param>
void GLWidget::DrawGrid(double scale)
{
RendererBase* renderer = m_Fractorium->m_Controller->Renderer();
auto renderer = m_Fractorium->m_Controller->Renderer();
float unitX = std::abs(renderer->UpperRightX(false) - renderer->LowerLeftX(false)) / 2.0f;
float unitY = std::abs(renderer->UpperRightY(false) - renderer->LowerLeftY(false)) / 2.0f;
float rad = std::max(unitX * scale, unitY * scale);
@ -916,10 +878,10 @@ template <typename T>
void GLEmberController<T>::DrawAffine(Xform<T>* xform, bool pre, bool selected)
{
auto ember = m_FractoriumEmberController->CurrentEmber();
bool final = ember->IsFinalXform(xform);
int index = ember->GetXformIndex(xform);
size_t size = ember->m_Palette.m_Entries.size();
v4T color = ember->m_Palette.m_Entries[Clamp<T>(xform->m_ColorX * size, 0, size - 1)];
auto final = ember->IsFinalXform(xform);
auto index = ember->GetXformIndex(xform);
auto size = ember->m_Palette.m_Entries.size();
auto color = ember->m_Palette.m_Entries[Clamp<T>(xform->m_ColorX * size, 0, size - 1)];
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
//For some incredibly strange reason, even though glm and OpenGL use matrices with a column-major
//data layout, nothing will work here unless they are flipped to row major order. This is how it was
@ -968,7 +930,7 @@ void GLWidget::DrawAffineHelper(int index, bool selected, bool pre, bool final,
{
float px = 1.0f;
float py = 0.0f;
QColor col = final ? m_Fractorium->m_FinalXformComboColor : m_Fractorium->m_XformComboColors[index % XFORM_COLOR_COUNT];
auto col = final ? m_Fractorium->m_FinalXformComboColor : m_Fractorium->m_XformComboColors[index % XFORM_COLOR_COUNT];
glBegin(GL_LINES);
//Circle part.
@ -986,8 +948,8 @@ void GLWidget::DrawAffineHelper(int index, bool selected, bool pre, bool final,
for (size_t i = 1; i <= 64; i++)//The circle.
{
float theta = float(M_PI) * 2.0f * float(i % 64) / 64.0f;
float fx = float(cos(theta));
float fy = float(sin(theta));
float fx = std::cos(theta);
float fy = std::sin(theta);
glVertex2f(px, py);
glVertex2f(fx, fy);
px = fx;
@ -1214,56 +1176,73 @@ bool GLEmberController<T>::CheckXformHover(Xform<T>* xform, v3T& glCoords, T& be
/// </summary>
/// <returns>The new affine transform to be assigned to the selected xform</returns>
template <typename T>
Affine2D<T> GLEmberController<T>::CalcDragXAxis()
void GLEmberController<T>::CalcDragXAxis()
{
v3T t3, newAxis, newPos;
size_t index = 0;
auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
auto result = m_DragSrcTransform;
auto scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
bool pre = m_AffineType == eAffineType::AffinePre;
bool worldPivotShiftAlt = !m_Fractorium->LocalPivot() && GetShift() && GetAlt();
if (worldPivotShiftAlt)
t3 = v3T(0, 0, 0);
else
t3 = v3T(m_DragSrcTransform.O(), 0);
if (GetShift())
{
v3T targetAxis = (m_MouseWorldPos * scale) - t3;
v3T norm = glm::normalize(targetAxis);
v3T snapped = GetControl() ? SnapToNormalizedAngle(m_MouseWorldPos + m_DragHandleOffset, 24) : m_MouseWorldPos + m_DragHandleOffset;
auto startDiff = (v2T(m_MouseDownWorldPos) * scale) - m_DragSrcTransform.O();
auto endDiff = (v2T(snapped) * scale) - m_DragSrcTransform.O();
T startAngle = std::atan2(startDiff.y, startDiff.x);
T endAngle = std::atan2(endDiff.y, endDiff.x);
T angle = startAngle - endAngle;
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto srcRotated = m_DragSrcTransforms[index++];
if (GetControl())
norm = SnapToNormalizedAngle(norm, 24);
if (worldPivotShiftAlt)
{
srcRotated.X(srcRotated.O() + srcRotated.X());
srcRotated.O(v2T(0));
srcRotated.Rotate(angle);
affine->X(srcRotated.X() - affine->O());
}
else if (GetAlt())
{
srcRotated.Rotate(angle);
affine->X(srcRotated.X());
}
else
{
srcRotated.Rotate(angle);
*affine = srcRotated;
}
if (worldPivotShiftAlt)
newAxis = norm * glm::length(m_DragSrcTransform.O() + m_DragSrcTransform.X());
else
newAxis = norm * glm::length(m_DragSrcTransform.X());
if (xform == m_FractoriumEmberController->CurrentXform())
m_DragHandlePos = v3T((affine->O() + affine->X()) * scaleBack, 0);
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Calling code will update renderer.
}
else
{
v3T diff;
if (GetControl())
newPos = SnapToGrid(m_MouseWorldPos);
diff = SnapToGrid(m_MouseWorldPos + m_DragHandleOffset) - m_MouseDownWorldPos;
else
newPos = m_MouseWorldPos + m_DragHandleOffset;
diff = (m_MouseWorldPos + m_DragHandleOffset) - m_MouseDownWorldPos;
newAxis = (newPos * scale) - t3;
}
auto origXPlusOff = v3T(m_DragSrcTransform.X(), 0) + (diff * scale);
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto axis = v3T(m_DragSrcTransforms[index++].X(), 0) + (diff * scale);
if (GetAlt())
{
if (worldPivotShiftAlt)
result.X(v2T(newAxis) - m_DragSrcTransform.O());
else
result.X(v2T(newAxis));
}
else
{
result.RotateScaleXTo(v2T(newAxis));
}
if (GetAlt())
affine->X(v2T(origXPlusOff));//Absolute, not ratio.
else
affine->RotateScaleXTo(v2T(axis));
T scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
m_DragHandlePos = v3T((result.O() + result.X()) * scaleBack, 0);
return result;
if (xform == m_FractoriumEmberController->CurrentXform())
m_DragHandlePos = v3T((affine->O() + affine->X()) * scaleBack, 0);
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);
}
}
/// <summary>
@ -1285,56 +1264,73 @@ Affine2D<T> GLEmberController<T>::CalcDragXAxis()
/// </summary>
/// <returns>The new affine transform to be assigned to the selected xform</returns>
template <typename T>
Affine2D<T> GLEmberController<T>::CalcDragYAxis()
void GLEmberController<T>::CalcDragYAxis()
{
v3T t3, newAxis, newPos;
size_t index = 0;
auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
auto result = m_DragSrcTransform;
auto scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
bool pre = m_AffineType == eAffineType::AffinePre;
bool worldPivotShiftAlt = !m_Fractorium->LocalPivot() && GetShift() && GetAlt();
if (worldPivotShiftAlt)
t3 = v3T(0, 0, 0);
else
t3 = v3T(m_DragSrcTransform.O(), 0);
if (GetShift())
{
v3T targetAxis = (m_MouseWorldPos * scale) - t3;
v3T norm = glm::normalize(targetAxis);
v3T snapped = GetControl() ? SnapToNormalizedAngle(m_MouseWorldPos + m_DragHandleOffset, 24) : m_MouseWorldPos + m_DragHandleOffset;
auto startDiff = (v2T(m_MouseDownWorldPos) * scale) - m_DragSrcTransform.O();
auto endDiff = (v2T(snapped) * scale) - m_DragSrcTransform.O();
T startAngle = std::atan2(startDiff.y, startDiff.x);
T endAngle = std::atan2(endDiff.y, endDiff.x);
T angle = startAngle - endAngle;
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto srcRotated = m_DragSrcTransforms[index++];
if (GetControl())
norm = SnapToNormalizedAngle(norm, 24);
if (worldPivotShiftAlt)
{
srcRotated.Y(srcRotated.O() + srcRotated.Y());
srcRotated.O(v2T(0));
srcRotated.Rotate(angle);
affine->Y(srcRotated.Y() - affine->O());
}
else if (GetAlt())
{
srcRotated.Rotate(angle);
affine->Y(srcRotated.Y());
}
else
{
srcRotated.Rotate(angle);
*affine = srcRotated;
}
if (worldPivotShiftAlt)
newAxis = norm * glm::length(m_DragSrcTransform.O() + m_DragSrcTransform.Y());
else
newAxis = norm * glm::length(m_DragSrcTransform.Y());
if (xform == m_FractoriumEmberController->CurrentXform())
m_DragHandlePos = v3T((affine->O() + affine->Y()) * scaleBack, 0);
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Calling code will update renderer.
}
else
{
v3T diff;
if (GetControl())
newPos = SnapToGrid(m_MouseWorldPos);
diff = SnapToGrid(m_MouseWorldPos + m_DragHandleOffset) - m_MouseDownWorldPos;
else
newPos = m_MouseWorldPos + m_DragHandleOffset;
diff = (m_MouseWorldPos + m_DragHandleOffset) - m_MouseDownWorldPos;
newAxis = (newPos * scale) - t3;
}
auto origXPlusOff = v3T(m_DragSrcTransform.Y(), 0) + (diff * scale);
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto axis = v3T(m_DragSrcTransforms[index++].Y(), 0) + (diff * scale);
if (GetAlt())
{
if (worldPivotShiftAlt)
result.Y(v2T(newAxis) - m_DragSrcTransform.O());
else
result.Y(v2T(newAxis));
}
else
{
result.RotateScaleYTo(v2T(newAxis));
}
if (GetAlt())
affine->Y(v2T(origXPlusOff));//Absolute, not ratio.
else
affine->RotateScaleYTo(v2T(axis));
T scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
m_DragHandlePos = v3T((result.O() + result.Y()) * scaleBack, 0);
return result;
if (xform == m_FractoriumEmberController->CurrentXform())
m_DragHandlePos = v3T((affine->O() + affine->Y()) * scaleBack, 0);
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);
}
}
/// <summary>
@ -1350,58 +1346,65 @@ Affine2D<T> GLEmberController<T>::CalcDragYAxis()
/// Control + Shift: Rotate about world center, rotating orientation, snapping to grid.
/// All others are the same as local pivot.
/// </summary>
/// <returns>The new affine transform to be assigned to the selected xform</returns>
template <typename T>
Affine2D<T> GLEmberController<T>::CalcDragTranslation()
void GLEmberController<T>::CalcDragTranslation()
{
v3T newPos;
size_t index = 0;
auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
auto result = m_DragSrcTransform;
auto scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
bool worldPivotShift = !m_Fractorium->LocalPivot() && GetShift();
bool pre = m_AffineType == eAffineType::AffinePre;
if (GetShift())
{
v3T norm = glm::normalize(m_MouseWorldPos);
if (GetControl())
norm = SnapToNormalizedAngle(norm, 12);
newPos = glm::length(m_DragSrcTransform.O()) * norm;
if (worldPivotShift)
v3T snapped = GetControl() ? SnapToNormalizedAngle(m_MouseWorldPos, 24) : m_MouseWorldPos;
T startAngle = std::atan2(m_DragSrcTransform.O().y, m_DragSrcTransform.O().x);
T endAngle = std::atan2(snapped.y, snapped.x);
T angle = startAngle - endAngle;
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
T startAngle = atan2(m_DragSrcTransform.O().y, m_DragSrcTransform.O().x);
T endAngle = atan2(newPos.y, newPos.x);
T angle = startAngle - endAngle;
result.Rotate(angle * RAD_2_DEG);
//RotateXformsByAngle
}
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto srcRotated = m_DragSrcTransforms[index++];
srcRotated.RotateTrans(angle);
if (worldPivotShift)
{
srcRotated.Rotate(angle);
affine->X(srcRotated.X());
affine->Y(srcRotated.Y());
}
affine->O(srcRotated.O());
if (xform == m_FractoriumEmberController->CurrentXform())
m_DragHandlePos = v3T(srcRotated.O(), 0) * scaleBack;
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Calling code will update renderer.
}
else
{
auto diff = m_MouseWorldPos - m_MouseDownWorldPos;
if (GetControl())
{
newPos = SnapToGrid(m_MouseWorldPos);
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
auto offset = m_DragSrcTransforms[index++].O() + (scale * v2T(diff));
auto snapped = SnapToGrid(offset);
affine->O(v2T(snapped.x, snapped.y));
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);
m_DragHandlePos = SnapToGrid(m_MouseWorldPos);
}
else
{
newPos = m_MouseWorldPos + m_DragHandleOffset;
//bool pre = m_AffineType == eAffineType::AffinePre;
//size_t index = 0;
//newPos = m_MouseWorldPos;
//auto diff = m_MouseWorldPos - m_MouseDownWorldPos;
//m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
//{
// auto affine = pre ? &xform->m_Affine : &xform->m_Post;//Determine pre or post affine.
// affine->O(m_DragSrcTransforms[index++].O() + v2T(diff));
//}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Don't need to update render for every xform, just do it once below.
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
{
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
affine->O(m_DragSrcTransforms[index++].O() + (scale * v2T(diff)));
}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);
m_DragHandlePos = m_MouseWorldPos;
}
}
T scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
result.O(v2T(newPos * scale));
m_DragHandlePos = newPos;
return result;
}
/// <summary>

View File

@ -62,7 +62,6 @@ protected:
virtual void mouseReleaseEvent(QMouseEvent* e) override;
virtual void mouseMoveEvent(QMouseEvent* e) override;
virtual void wheelEvent(QWheelEvent* e) override;
//virtual void resizeEvent(QResizeEvent* e) override;
private:
void SetDimensions(int w, int h);

View File

@ -1,7 +1,7 @@
#include "FractoriumPch.h"
#include "SpinBox.h"
QTimer SpinBox::m_Timer;
QTimer SpinBox::s_Timer;
/// <summary>
/// Constructor that passes parent to the base and sets up height and step.
@ -118,17 +118,16 @@ void SpinBox::OnTimeout()
//qDebug() << "Shift pressed";
scale = 0.001;
}
/*else if (ctrl)
{
qDebug() << "Control pressed";
scale = 0.01;
}*/
/* else if (ctrl)
{
qDebug() << "Control pressed";
scale = 0.01;
}*/
else
scale = 0.01;
val = d + (distance * amount * scale);
setValue(int(val));
//qDebug() << "Timer on, orig val: " << d << ", new val: " << val << ", distance " << distance;
}
@ -143,9 +142,9 @@ bool SpinBox::eventFilter(QObject* o, QEvent* e)
QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
if (isEnabled() &&
me &&
me->type() == QMouseEvent::MouseButtonPress &&
me->button() == Qt::RightButton)
me &&
me->type() == QMouseEvent::MouseButtonPress &&
me->button() == Qt::RightButton)
{
m_MouseDownPoint = m_MouseMovePoint = me->pos();
StartTimer();
@ -172,18 +171,18 @@ bool SpinBox::eventFilter(QObject* o, QEvent* e)
// }
}
else if (isEnabled() &&
me &&
me->type() == QMouseEvent::MouseButtonRelease &&
me->button() == Qt::RightButton)
me &&
me->type() == QMouseEvent::MouseButtonRelease &&
me->button() == Qt::RightButton)
{
StopTimer();
m_MouseDownPoint = m_MouseMovePoint = me->pos();
//qDebug() << "Right mouse up";
}
else if (isEnabled() &&
me &&
me->type() == QMouseEvent::MouseMove &&
QGuiApplication::mouseButtons() & Qt::RightButton)
me &&
me->type() == QMouseEvent::MouseMove &&
QGuiApplication::mouseButtons() & Qt::RightButton)
{
m_MouseMovePoint = me->pos();
qDebug() << "Mouse move while right down. Pt = " << me->pos() << ", global: " << mapToGlobal(me->pos());
@ -236,8 +235,8 @@ void SpinBox::focusInEvent(QFocusEvent* e)
/// <param name="e">The event</param>
void SpinBox::focusOutEvent(QFocusEvent* e)
{
//lineEdit()->deselect();//Clear selection when leaving.
//lineEdit()->setReadOnly(true);//Clever hack to clear the cursor when leaving.
//lineEdit()->deselect();//Clear selection when leaving.
//lineEdit()->setReadOnly(true);//Clever hack to clear the cursor when leaving.
StopTimer();
QSpinBox::focusOutEvent(e);
}
@ -273,9 +272,9 @@ void SpinBox::leaveEvent(QEvent* e)
/// </summary>
void SpinBox::StartTimer()
{
m_Timer.stop();
connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
m_Timer.start(300);
s_Timer.stop();
connect(&s_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
s_Timer.start(300);
}
/// <summary>
@ -283,6 +282,6 @@ void SpinBox::StartTimer()
/// </summary>
void SpinBox::StopTimer()
{
m_Timer.stop();
disconnect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
s_Timer.stop();
disconnect(&s_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
}

View File

@ -48,5 +48,5 @@ private:
int m_SmallStep;
QPoint m_MouseDownPoint;
QPoint m_MouseMovePoint;
static QTimer m_Timer;
static QTimer s_Timer;
};

View File

@ -53,25 +53,21 @@ private:
bool operator < (const QTreeWidgetItem& other) const
{
int column = treeWidget()->sortColumn();
eVariationId index1, index2;
double weight1 = 0, weight2 = 0;
VariationTreeWidgetItem* varItemWidget;
VariationTreeDoubleSpinBox* spinBox1, *spinBox2;
auto itemWidget1 = treeWidget()->itemWidget(const_cast<VariationTreeWidgetItem*>(this), 1);//Get the widget for the second column.
if ((spinBox1 = dynamic_cast<VariationTreeDoubleSpinBox*>(itemWidget1)))//Cast the widget to the VariationTreeDoubleSpinBox type.
if (auto spinBox1 = dynamic_cast<VariationTreeDoubleSpinBox*>(itemWidget1))//Cast the widget to the VariationTreeDoubleSpinBox type.
{
auto itemWidget2 = treeWidget()->itemWidget(const_cast<QTreeWidgetItem*>(&other), 1);//Get the widget for the second column of the widget item passed in.
if ((spinBox2 = dynamic_cast<VariationTreeDoubleSpinBox*>(itemWidget2)))//Cast the widget to the VariationTreeDoubleSpinBox type.
if (auto spinBox2 = dynamic_cast<VariationTreeDoubleSpinBox*>(itemWidget2))//Cast the widget to the VariationTreeDoubleSpinBox type.
{
if (spinBox1->IsParam() || spinBox2->IsParam())//Do not sort params, their order will always remain the same.
return false;
weight1 = spinBox1->value();
weight2 = spinBox2->value();
index1 = spinBox1->GetVariationId();
index2 = spinBox2->GetVariationId();
auto weight1 = spinBox1->value();
auto weight2 = spinBox2->value();
auto index1 = spinBox1->GetVariationId();
auto index2 = spinBox2->GetVariationId();
if (column == 0)//First column clicked, sort by variation index.
{