mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-06-30 21:36:33 -04:00
--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:
@ -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()));
|
||||
}
|
@ -51,7 +51,7 @@ private:
|
||||
double m_SmallStep;
|
||||
QPoint m_MouseDownPoint;
|
||||
QPoint m_MouseMovePoint;
|
||||
static QTimer m_Timer;
|
||||
static QTimer s_Timer;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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>&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><html><body><p>Save the currently displayed flame back to the opened file in memory.</p><p>This overwrites the original flame but does not store the file back to disk.</p></body></html></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&py Flame</string>
|
||||
<string>Add Co&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&ip</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionCopySelectedXforms">
|
||||
<property name="text">
|
||||
<string>Copy Selected &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>
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -48,5 +48,5 @@ private:
|
||||
int m_SmallStep;
|
||||
QPoint m_MouseDownPoint;
|
||||
QPoint m_MouseMovePoint;
|
||||
static QTimer m_Timer;
|
||||
static QTimer s_Timer;
|
||||
};
|
||||
|
@ -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.
|
||||
{
|
||||
|
Reference in New Issue
Block a user