mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-10-07 13:40:53 -04:00
--User changes
-Add new variations: crackle, dc_perlin. -Make default palette interp mode be linear instead of step. -Make summary tab the selected one in the Info tab. -Allow for highlight power of up to 10. It was previously limited to 2. --Bug fixes -Direct color calculations were wrong. -Flattening was not applied to final xform. -Fix "pure virtual function call" error on shutdown. --Code changes -Allow for array precalc params in variations by adding a size member to the ParamWithName class. -In IterOpenCLKernelCreator, memcpy precalc params instead of a direct assign since they can now be of variable length. -Add new file VarFuncs to consolidate some functions that are common to multiple variations. This also contains texture data for crackle and dc_perlin. -Place OpenCL versions of these functions in the FunctionMapper class in the EmberCL project. -Add new Singleton class that uses CRTP, is thread safe, and deletes after the last reference goes away. This fixes the usual "delete after main()" problem with singletons that use the static local function variable pattern. -Began saving files with AStyle autoformatter turned on. This will eventually touch all files as they are worked on. -Add missing backslash to CUDA include and library paths for builds on Nvidia systems. -Add missing gl.h include for Windows. -Remove glew include paths from Fractorium, it's not used. -Remove any Nvidia specific #defines and build targets, they are no longer needed with OpenCL 1.2. -Fix bad paths on linux build. -General cleanup.
This commit is contained in:
@ -11,17 +11,15 @@
|
||||
/// <param name="p">The parent widget</param>
|
||||
/// <param name="f">The window flags. Default: 0.</param>
|
||||
FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* settings, QWidget* p, Qt::WindowFlags f)
|
||||
: QDialog(p, f),
|
||||
m_Info(OpenCLInfo::Instance())
|
||||
{
|
||||
: QDialog(p, f)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
|
||||
int row = 0, spinHeight = 20;
|
||||
uint i;
|
||||
double dmax = numeric_limits<double>::max();
|
||||
QTableWidget* table = ui.FinalRenderParamsTable;
|
||||
QTableWidgetItem* item = nullptr;
|
||||
|
||||
m_Info = OpenCLInfo::Instance();
|
||||
m_Fractorium = qobject_cast<Fractorium*>(p);
|
||||
m_Settings = settings;
|
||||
ui.FinalRenderThreadCountSpin->setRange(1, Timing::ProcessorCount());
|
||||
@ -39,7 +37,6 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
|
||||
connect(ui.FinalRenderScaleWidthRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderScaleHeightRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderDeviceTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnDeviceTableCellChanged(int, int)), Qt::QueuedConnection);
|
||||
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.FinalRenderSizeTable, this, row, 1, m_WidthScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnWidthScaleChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.FinalRenderSizeTable, this, row, 1, m_HeightScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHeightScaleChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
m_WidthScaleSpin->setDecimals(3);
|
||||
@ -48,46 +45,37 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
|
||||
m_HeightScaleSpin->setSuffix(" ( )");
|
||||
m_WidthScaleSpin->SmallStep(0.001);
|
||||
m_HeightScaleSpin->SmallStep(0.001);
|
||||
|
||||
row = 0;
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, 1000, 1000, 1000);
|
||||
SetupSpinner<SpinBox, int> (table, this, row, 1, m_TemporalSamplesSpin, spinHeight, 1, 5000, 50, SIGNAL(valueChanged(int)), SLOT(OnTemporalSamplesChanged(int)), true, 1000, 1000, 1000);
|
||||
SetupSpinner<SpinBox, int> (table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 2, 1, 1);
|
||||
SetupSpinner<SpinBox, int> (table, this, row, 1, m_StripsSpin, spinHeight, 1, 64, 1, SIGNAL(valueChanged(int)), SLOT(OnStripsChanged(int)), true, 1, 1, 1);
|
||||
|
||||
m_MemoryCellIndex = row++;//Memory usage.
|
||||
m_ItersCellIndex = row++;//Iters.
|
||||
m_PathCellIndex = row;
|
||||
|
||||
QStringList comboList;
|
||||
|
||||
comboList.append("jpg");
|
||||
comboList.append("png");
|
||||
|
||||
m_Tbcw = new TwoButtonComboWidget("...", "Open", comboList, 22, 40, 22, table);
|
||||
table->setCellWidget(row, 1, m_Tbcw);
|
||||
table->item(row++, 1)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
connect(m_Tbcw->m_Button1, SIGNAL(clicked(bool)), this, SLOT(OnFileButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(m_Tbcw->m_Button2, SIGNAL(clicked(bool)), this, SLOT(OnShowFolderButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(m_Tbcw->m_Combo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnExtIndexChanged(int)), Qt::QueuedConnection);
|
||||
|
||||
m_PrefixEdit = new QLineEdit(table);
|
||||
table->setCellWidget(row++, 1, m_PrefixEdit);
|
||||
|
||||
m_SuffixEdit = new QLineEdit(table);
|
||||
table->setCellWidget(row++, 1, m_SuffixEdit);
|
||||
connect(m_PrefixEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnPrefixChanged(const QString&)), Qt::QueuedConnection);
|
||||
connect(m_SuffixEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnSuffixChanged(const QString&)), Qt::QueuedConnection);
|
||||
|
||||
ui.FinalRenderStartButton->disconnect(SIGNAL(clicked(bool)));
|
||||
connect(ui.FinalRenderStartButton, SIGNAL(clicked(bool)), this, SLOT(OnRenderClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.FinalRenderStopButton, SIGNAL(clicked(bool)), this, SLOT(OnCancelRenderClicked(bool)), Qt::QueuedConnection);
|
||||
|
||||
table = ui.FinalRenderDeviceTable;
|
||||
table->clearContents();
|
||||
table->setRowCount(0);
|
||||
|
||||
if (m_Info.Ok() && !m_Info.Devices().empty())
|
||||
if (m_Info->Ok() && !m_Info->Devices().empty())
|
||||
{
|
||||
SetupDeviceTable(table, m_Settings->FinalDevices());
|
||||
|
||||
@ -124,28 +112,25 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
|
||||
ui.FinalRenderThreadPriorityComboBox->setCurrentIndex(tpc);
|
||||
else
|
||||
ui.FinalRenderThreadPriorityComboBox->setCurrentIndex(Clamp<int>(m_Settings->FinalThreadPriority() / 25, 0, tpc));
|
||||
#endif
|
||||
|
||||
#endif
|
||||
m_QualitySpin->setValue(m_Settings->FinalQuality());
|
||||
m_TemporalSamplesSpin->setValue(m_Settings->FinalTemporalSamples());
|
||||
m_SupersampleSpin->setValue(m_Settings->FinalSupersample());
|
||||
m_StripsSpin->setValue(m_Settings->FinalStrips());
|
||||
|
||||
Scale(eScaleType(m_Settings->FinalScale()));
|
||||
|
||||
if (m_Settings->FinalExt() == "jpg")
|
||||
m_Tbcw->m_Combo->setCurrentIndex(0);
|
||||
else
|
||||
m_Tbcw->m_Combo->setCurrentIndex(1);
|
||||
|
||||
|
||||
//Explicitly call these to enable/disable the appropriate controls.
|
||||
OnOpenCLCheckBoxStateChanged(ui.FinalRenderOpenCLCheckBox->isChecked());
|
||||
OnDoAllCheckBoxStateChanged(ui.FinalRenderDoAllCheckBox->isChecked());
|
||||
OnDoSequenceCheckBoxStateChanged(ui.FinalRenderDoSequenceCheckBox->isChecked());
|
||||
|
||||
QSize s = size();
|
||||
int desktopHeight = qApp->desktop()->availableGeometry().height();
|
||||
|
||||
s.setHeight(std::min(s.height(), int(double(desktopHeight * 0.90))));
|
||||
setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, s, qApp->desktop()->availableGeometry()));
|
||||
ui.FinalRenderThreadHorizontalLayout->setAlignment(Qt::AlignLeft);
|
||||
@ -153,7 +138,6 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set
|
||||
ui.FinalRenderThreadHorizontalLayout->setAlignment(ui.FinalRenderThreadPriorityLabel, Qt::AlignLeft);
|
||||
ui.FinalRenderThreadHorizontalLayout->setAlignment(ui.FinalRenderThreadPriorityComboBox, Qt::AlignLeft);
|
||||
QWidget* w = SetTabOrder(this, ui.FinalRenderEarlyClipCheckBox, ui.FinalRenderYAxisUpCheckBox);
|
||||
|
||||
//Update these with new controls.
|
||||
w = SetTabOrder(this, w, ui.FinalRenderTransparencyCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderOpenCLCheckBox);
|
||||
@ -238,7 +222,6 @@ QList<QVariant> FractoriumFinalRenderDialog::Devices() { return DeviceTableToSet
|
||||
FinalRenderGuiState FractoriumFinalRenderDialog::State()
|
||||
{
|
||||
FinalRenderGuiState state;
|
||||
|
||||
state.m_EarlyClip = EarlyClip();
|
||||
state.m_YAxisUp = YAxisUp();
|
||||
state.m_Transparency = Transparency();
|
||||
@ -262,7 +245,6 @@ FinalRenderGuiState FractoriumFinalRenderDialog::State()
|
||||
state.m_TemporalSamples = TemporalSamples();
|
||||
state.m_Supersample = Supersample();
|
||||
state.m_Strips = Strips();
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -346,7 +328,6 @@ void FractoriumFinalRenderDialog::OnTransparencyCheckBoxStateChanged(int state)
|
||||
void FractoriumFinalRenderDialog::OnOpenCLCheckBoxStateChanged(int state)
|
||||
{
|
||||
bool checked = state == Qt::Checked;
|
||||
|
||||
ui.FinalRenderDeviceTable->setEnabled(checked);
|
||||
ui.FinalRenderThreadCountSpin->setEnabled(!checked);
|
||||
ui.FinalRenderThreadPriorityLabel->setEnabled(!checked);
|
||||
@ -387,7 +368,6 @@ void FractoriumFinalRenderDialog::OnDoAllCheckBoxStateChanged(int state)
|
||||
void FractoriumFinalRenderDialog::OnDoSequenceCheckBoxStateChanged(int state)
|
||||
{
|
||||
bool checked = ui.FinalRenderDoSequenceCheckBox->isChecked();
|
||||
|
||||
m_TemporalSamplesSpin->setEnabled(checked);
|
||||
|
||||
if (checked)
|
||||
@ -428,7 +408,7 @@ void FractoriumFinalRenderDialog::OnApplyAllCheckBoxStateChanged(int state)
|
||||
void FractoriumFinalRenderDialog::OnWidthScaleChanged(double d)
|
||||
{
|
||||
if (ui.FinalRenderKeepAspectCheckBox->isChecked() && m_Controller.get())
|
||||
m_HeightScaleSpin->SetValueStealth(m_WidthScaleSpin->value());
|
||||
m_HeightScaleSpin->SetValueStealth(m_WidthScaleSpin->value());
|
||||
|
||||
if (SetMemory())
|
||||
m_Controller->SyncCurrentToSizeSpinners(false, true);
|
||||
@ -443,7 +423,7 @@ void FractoriumFinalRenderDialog::OnWidthScaleChanged(double d)
|
||||
void FractoriumFinalRenderDialog::OnHeightScaleChanged(double d)
|
||||
{
|
||||
if (ui.FinalRenderKeepAspectCheckBox->isChecked() && m_Controller.get())
|
||||
m_WidthScaleSpin->SetValueStealth(m_HeightScaleSpin->value());
|
||||
m_WidthScaleSpin->SetValueStealth(m_HeightScaleSpin->value());
|
||||
|
||||
if (SetMemory())
|
||||
m_Controller->SyncCurrentToSizeSpinners(false, true);
|
||||
@ -578,7 +558,7 @@ void FractoriumFinalRenderDialog::OnFileButtonClicked(bool checked)
|
||||
void FractoriumFinalRenderDialog::OnShowFolderButtonClicked(bool checked)
|
||||
{
|
||||
QString s = m_Settings->SaveFolder();
|
||||
|
||||
|
||||
if (Exists(s))
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(s));
|
||||
else
|
||||
@ -673,13 +653,12 @@ void FractoriumFinalRenderDialog::showEvent(QShowEvent* e)
|
||||
m_Controller->m_ImageCount = 0;
|
||||
SetMemory();
|
||||
m_Controller->ResetProgress();
|
||||
|
||||
QString s = m_Settings->SaveFolder();
|
||||
|
||||
if (Exists(s))
|
||||
Path(m_Controller->ComposePath(m_Controller->Name()));//Update the GUI.
|
||||
}
|
||||
|
||||
|
||||
ui.FinalRenderTextOutput->clear();
|
||||
QDialog::showEvent(e);
|
||||
}
|
||||
@ -708,13 +687,12 @@ bool FractoriumFinalRenderDialog::CreateControllerFromGUI(bool createRenderer)
|
||||
{
|
||||
bool ok = true;
|
||||
int index = Current() - 1;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
size_t elementSize = Double() ? sizeof(double) : sizeof(float);
|
||||
#else
|
||||
size_t elementSize = sizeof(float);
|
||||
#endif
|
||||
|
||||
|
||||
if (!m_Controller.get() || (m_Controller->SizeOfT() != elementSize))
|
||||
{
|
||||
#ifdef DO_DOUBLE
|
||||
@ -740,6 +718,7 @@ bool FractoriumFinalRenderDialog::CreateControllerFromGUI(bool createRenderer)
|
||||
|
||||
//Create a float or double controller based on the GUI.
|
||||
#ifdef DO_DOUBLE
|
||||
|
||||
if (Double())
|
||||
m_Controller = unique_ptr<FinalRenderEmberControllerBase>(new FinalRenderEmberController<double>(this));
|
||||
else
|
||||
@ -778,10 +757,9 @@ bool FractoriumFinalRenderDialog::SetMemory()
|
||||
bool error = false;
|
||||
tuple<size_t, size_t, size_t> p = m_Controller->SyncAndComputeMemory();
|
||||
QString s;
|
||||
|
||||
ui.FinalRenderParamsTable->item(m_MemoryCellIndex, 1)->setText(ToString<qulonglong>(get<1>(p)));
|
||||
ui.FinalRenderParamsTable->item(m_ItersCellIndex, 1)->setText(ToString<qulonglong>(get<2>(p)));
|
||||
|
||||
|
||||
if (OpenCL() && !m_Wrappers.empty())
|
||||
{
|
||||
auto devices = Devices();
|
||||
@ -799,13 +777,13 @@ bool FractoriumFinalRenderDialog::SetMemory()
|
||||
if (histSize > maxAlloc)
|
||||
{
|
||||
temp = "Histogram/Accumulator memory size of " + ToString<qulonglong>(histSize) +
|
||||
" is greater than the max OpenCL allocation size of " + ToString<qulonglong>(maxAlloc);
|
||||
" is greater than the max OpenCL allocation size of " + ToString<qulonglong>(maxAlloc);
|
||||
}
|
||||
|
||||
if (totalSize > totalAvail)
|
||||
{
|
||||
temp += "\n\nTotal required memory size of " + ToString<qulonglong>(totalSize) +
|
||||
" is greater than the max OpenCL available memory of " + ToString<qulonglong>(totalAvail);
|
||||
" is greater than the max OpenCL available memory of " + ToString<qulonglong>(totalAvail);
|
||||
}
|
||||
|
||||
if (!temp.isEmpty())
|
||||
|
@ -40,7 +40,7 @@ class FractoriumFinalRenderDialog : public QDialog
|
||||
friend Fractorium;
|
||||
friend FinalRenderEmberControllerBase;
|
||||
friend FinalRenderEmberController<float>;
|
||||
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
friend FinalRenderEmberController<double>;
|
||||
#endif
|
||||
@ -112,7 +112,7 @@ protected:
|
||||
private:
|
||||
bool CreateControllerFromGUI(bool createRenderer);
|
||||
bool SetMemory();
|
||||
|
||||
|
||||
int m_MemoryCellIndex;
|
||||
int m_ItersCellIndex;
|
||||
int m_PathCellIndex;
|
||||
@ -128,7 +128,7 @@ private:
|
||||
QLineEdit* m_SuffixEdit;
|
||||
FractoriumSettings* m_Settings;
|
||||
Fractorium* m_Fractorium;
|
||||
OpenCLInfo& m_Info;
|
||||
shared_ptr<OpenCLInfo> m_Info;
|
||||
vector<OpenCLWrapper> m_Wrappers;
|
||||
unique_ptr<FinalRenderEmberControllerBase> m_Controller;
|
||||
Ui::FinalRenderDialog ui;
|
||||
|
@ -32,7 +32,6 @@ void FinalRenderEmberController<T>::CancelRender()
|
||||
if (m_Result.isRunning())
|
||||
{
|
||||
tbb::task_group g;
|
||||
|
||||
g.run([&]
|
||||
{
|
||||
m_Run = false;
|
||||
@ -65,7 +64,6 @@ void FinalRenderEmberController<T>::CancelRender()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
g.wait();
|
||||
|
||||
while (m_Result.isRunning())
|
||||
@ -82,9 +80,8 @@ void FinalRenderEmberController<T>::CancelRender()
|
||||
/// <returns>True if a valid renderer is created or if no action is taken, else false.</returns>
|
||||
bool FinalRenderEmberControllerBase::CreateRendererFromGUI()
|
||||
{
|
||||
bool useOpenCL = m_Info.Ok() && m_FinalRenderDialog->OpenCL();
|
||||
bool useOpenCL = m_Info->Ok() && m_FinalRenderDialog->OpenCL();
|
||||
auto v = Devices(m_FinalRenderDialog->Devices());
|
||||
|
||||
return CreateRenderer((useOpenCL && !v.empty()) ? OPENCL_RENDERER : CPU_RENDERER,
|
||||
v,
|
||||
false);//Not shared.
|
||||
@ -111,13 +108,11 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
m_FinalPreviewRenderer = unique_ptr<EmberNs::Renderer<T, float>>(new EmberNs::Renderer<T, float>());
|
||||
m_FinalPreviewRenderer->Callback(nullptr);
|
||||
m_FinalPreviewRenderer->NumChannels(4);
|
||||
|
||||
m_FinalPreviewRenderFunc = [&]()
|
||||
{
|
||||
m_PreviewCs.Enter();//Thread prep.
|
||||
m_PreviewRun = true;
|
||||
m_FinalPreviewRenderer->Abort();
|
||||
|
||||
T scalePercentage;
|
||||
size_t maxDim = 100;
|
||||
QLabel* widget = m_FinalRenderDialog->ui.FinalRenderPreviewLabel;
|
||||
@ -134,32 +129,27 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
m_PreviewEmber.m_FinalRasW = std::max<size_t>(1, std::min<size_t>(maxDim, size_t(scalePercentage * m_Ember->m_FinalRasW)));//Ensure neither is zero.
|
||||
m_PreviewEmber.m_FinalRasH = std::max<size_t>(1, std::min<size_t>(maxDim, size_t(scalePercentage * m_Ember->m_FinalRasH)));
|
||||
m_PreviewEmber.m_PixelsPerUnit = scalePercentage * m_Ember->m_PixelsPerUnit;
|
||||
|
||||
m_FinalPreviewRenderer->EarlyClip(m_FinalRenderDialog->EarlyClip());
|
||||
m_FinalPreviewRenderer->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_FinalPreviewRenderer->Transparency(m_FinalRenderDialog->Transparency());
|
||||
m_FinalPreviewRenderer->SetEmber(m_PreviewEmber);
|
||||
m_FinalPreviewRenderer->PrepFinalAccumVector(m_PreviewFinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run().
|
||||
|
||||
auto strips = VerifyStrips(m_PreviewEmber.m_FinalRasH, m_FinalRenderDialog->Strips(),
|
||||
[&](const string& s) { }, [&](const string& s) { }, [&](const string& s) { });
|
||||
|
||||
[&](const string & s) { }, [&](const string & s) { }, [&](const string & s) { });
|
||||
StripsRender<T>(m_FinalPreviewRenderer.get(), m_PreviewEmber, m_PreviewFinalImage, 0, strips, m_FinalRenderDialog->YAxisUp(),
|
||||
[&](size_t strip) { },//Pre strip.
|
||||
[&](size_t strip) { },//Post strip.
|
||||
[&](size_t strip) { },//Error.
|
||||
[&](Ember<T>& finalEmber)//Final strip.
|
||||
{
|
||||
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);
|
||||
QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap));
|
||||
});
|
||||
|
||||
[&](size_t strip) { },//Pre strip.
|
||||
[&](size_t strip) { },//Post strip.
|
||||
[&](size_t strip) { },//Error.
|
||||
[&](Ember<T>& finalEmber)//Final strip.
|
||||
{
|
||||
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);
|
||||
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.
|
||||
//If it finishes successfully, delete the backup file.
|
||||
@ -168,7 +158,6 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
m_Run = true;
|
||||
m_TotalTimer.Tic();//Begin timing for progress of all operations.
|
||||
m_GuiState = m_FinalRenderDialog->State();//Cache render settings from the GUI before running.
|
||||
|
||||
size_t i;
|
||||
bool doAll = m_GuiState.m_DoAll && m_EmberFile.Size() > 1;
|
||||
size_t currentStripForProgress = 0;//Sort of a hack to get the strip value to the progress function.
|
||||
@ -184,11 +173,10 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
m_FinishedImageCount.store(0);
|
||||
SyncGuiToRenderer();
|
||||
FirstOrDefaultRenderer()->m_ProgressParameter = reinterpret_cast<void*>(¤tStripForProgress);//When animating, only the first (primary) device has a progress parameter.
|
||||
|
||||
m_GuiState.m_Strips = VerifyStrips(m_Ember->m_FinalRasH, m_GuiState.m_Strips,
|
||||
[&](const string& s) { Output(QString::fromStdString(s)); },//Greater than height.
|
||||
[&](const string& s) { Output(QString::fromStdString(s)); },//Mod height != 0.
|
||||
[&](const string& s) { Output(QString::fromStdString(s) + "\n"); });//Final strips value to be set.
|
||||
[&](const string & s) { Output(QString::fromStdString(s)); }, //Greater than height.
|
||||
[&](const string & s) { Output(QString::fromStdString(s)); }, //Mod height != 0.
|
||||
[&](const string & s) { Output(QString::fromStdString(s) + "\n"); }); //Final strips value to be set.
|
||||
ResetProgress();
|
||||
|
||||
//The rendering process is different between doing a single image, and doing multiple.
|
||||
@ -205,7 +193,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
for (i = 0; i < m_EmberFile.Size() && m_Run; i++)
|
||||
{
|
||||
SyncGuiToEmber(m_EmberFile.m_Embers[i], firstEmber->m_FinalRasW, firstEmber->m_FinalRasH);
|
||||
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
if (m_EmberFile.m_Embers[i].m_Time <= m_EmberFile.m_Embers[i - 1].m_Time)
|
||||
@ -221,13 +209,11 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
|
||||
std::atomic<size_t> atomfTime;
|
||||
vector<std::thread> threadVec;
|
||||
|
||||
//Not supporting strips with animation.
|
||||
//Shouldn't be a problem because animations will be at max 4k x 2k which will take about 1GB
|
||||
//even when using double precision, which most cards at the time of this writing already exceed.
|
||||
//even when using double precision, which most cards at the time of this writing already exceed.
|
||||
m_GuiState.m_Strips = 1;
|
||||
atomfTime.store(0);
|
||||
|
||||
std::function<void(size_t)> iterFunc = [&](size_t index)
|
||||
{
|
||||
size_t ftime;
|
||||
@ -244,7 +230,6 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
while (atomfTime.fetch_add(1), ((ftime = atomfTime.load() - 1) < m_EmberFile.Size()) && m_Run)//Needed to set 1 to claim this iter from other threads, so decrement it to be zero-indexed here.
|
||||
{
|
||||
T localTime = T(ftime);
|
||||
|
||||
Output("Image " + ToString(ftime + 1ULL) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[ftime].m_Name)));
|
||||
renderer->Reset();//Have to manually set this since the ember is not set each time through.
|
||||
renderTimer.Tic();//Toc() is called in RenderComplete().
|
||||
@ -264,18 +249,16 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
|
||||
stats = renderer->Stats();
|
||||
comments = renderer->ImageComments(stats, 0, false, true);
|
||||
|
||||
writeThread = std::thread([&](size_t tempTime, size_t threadFinalImageIndex)
|
||||
{
|
||||
SaveCurrentRender(m_EmberFile.m_Embers[tempTime],
|
||||
comments,//These all don't change during the renders, so it's ok to access them in the thread.
|
||||
finalImages[threadFinalImageIndex],
|
||||
renderer->FinalRasW(),
|
||||
renderer->FinalRasH(),
|
||||
renderer->NumChannels(),
|
||||
renderer->BytesPerChannel());
|
||||
comments,//These all don't change during the renders, so it's ok to access them in the thread.
|
||||
finalImages[threadFinalImageIndex],
|
||||
renderer->FinalRasW(),
|
||||
renderer->FinalRasH(),
|
||||
renderer->NumChannels(),
|
||||
renderer->BytesPerChannel());
|
||||
}, ftime, finalImageIndex);
|
||||
|
||||
m_FinishedImageCount.fetch_add(1);
|
||||
RenderComplete(m_EmberFile.m_Embers[ftime], stats, renderTimer);
|
||||
|
||||
@ -289,7 +272,6 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
if (writeThread.joinable())//One final check to make sure all writing is done before exiting this thread.
|
||||
writeThread.join();
|
||||
};
|
||||
|
||||
threadVec.reserve(m_Renderers.size());
|
||||
|
||||
for (size_t r = 0; r < m_Renderers.size(); r++)
|
||||
@ -318,7 +300,6 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
m_Stats.Clear();
|
||||
Memset(m_FinalImage);
|
||||
m_RenderTimer.Tic();//Toc() is called in RenderComplete().
|
||||
|
||||
StripsRender<T>(m_Renderer.get(), m_EmberFile.m_Embers[i], m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp,
|
||||
[&](size_t strip) { currentStripForProgress = strip; },//Pre strip.
|
||||
[&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip.
|
||||
@ -351,7 +332,6 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
Memset(m_FinalImage);
|
||||
Output(ComposePath(QString::fromStdString(m_Ember->m_Name)));
|
||||
m_RenderTimer.Tic();//Toc() is called in RenderComplete().
|
||||
|
||||
StripsRender<T>(m_Renderer.get(), *m_Ember, m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp,
|
||||
[&](size_t strip) { currentStripForProgress = strip; },//Pre strip.
|
||||
[&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip.
|
||||
@ -375,7 +355,6 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
|
||||
QString totalTimeString = "All renders completed in: " + QString::fromStdString(m_TotalTimer.Format(m_TotalTimer.Toc())) + ".";
|
||||
Output(totalTimeString);
|
||||
|
||||
QFile::remove(backup);
|
||||
m_Run = false;
|
||||
};
|
||||
@ -457,7 +436,6 @@ bool FinalRenderEmberController<T>::Render()
|
||||
if (CreateRendererFromGUI())
|
||||
{
|
||||
m_FinalRenderDialog->ui.FinalRenderTextOutput->setText("Preparing all parameters.\n");
|
||||
|
||||
//Note that a Qt thread must be used, rather than a tbb task.
|
||||
//This is because tbb does a very poor job of allocating thread resources
|
||||
//and dedicates an entire core just to this thread which does nothing waiting for the
|
||||
@ -486,18 +464,16 @@ bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, con
|
||||
bool deviceDiff = false;
|
||||
//uint channels = m_FinalRenderDialog->Ext().endsWith("png", Qt::CaseInsensitive) ? 4 : 3;
|
||||
bool renderTypeMismatch = (m_Renderer.get() && (m_Renderer->RendererType() != renderType)) ||
|
||||
(!m_Renderers.empty() && (m_Renderers[0]->RendererType() != renderType));
|
||||
|
||||
(!m_Renderers.empty() && (m_Renderers[0]->RendererType() != renderType));
|
||||
CancelRender();
|
||||
|
||||
if ((!m_FinalRenderDialog->DoSequence() && (!m_Renderer.get() || !m_Renderer->Ok())) ||
|
||||
(m_FinalRenderDialog->DoSequence() && m_Renderers.empty()) ||
|
||||
renderTypeMismatch ||
|
||||
!Equal(m_Devices, devices))
|
||||
(m_FinalRenderDialog->DoSequence() && m_Renderers.empty()) ||
|
||||
renderTypeMismatch ||
|
||||
!Equal(m_Devices, devices))
|
||||
{
|
||||
EmberReport emberReport;
|
||||
vector<string> errorReport;
|
||||
|
||||
m_Devices = devices;//Store values for re-creation later on.
|
||||
m_OutputTexID = 0;//Don't care about tex ID when doing final render.
|
||||
m_Shared = shared;//So shared is of course false.
|
||||
@ -555,7 +531,6 @@ int FinalRenderEmberController<T>::ProgressFunc(Ember<T>& ember, void* foo, doub
|
||||
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, ToString<qulonglong>(m_FinishedImageCount.load() + 1) + " / " + ToString<qulonglong>(m_ImageCount) + " Eta: " + QString::fromStdString(m_RenderTimer.Format(etaMs))));
|
||||
QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "update", Qt::QueuedConnection);
|
||||
|
||||
return m_Run ? 1 : 0;
|
||||
}
|
||||
|
||||
@ -698,14 +673,12 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
size_t strips;
|
||||
bool b = false;
|
||||
uint channels = m_FinalRenderDialog->Ext() == "png" ? 4 : 3;//4 channels for Png, else 3.
|
||||
|
||||
SyncGuiToEmbers();
|
||||
|
||||
|
||||
if (m_Renderer.get())
|
||||
{
|
||||
strips = VerifyStrips(m_Ember->m_FinalRasH, m_FinalRenderDialog->Strips(),
|
||||
[&](const string& s) {}, [&](const string& s) {}, [&](const string& s) {});
|
||||
|
||||
[&](const string & s) {}, [&](const string & s) {}, [&](const string & s) {});
|
||||
m_Renderer->SetEmber(*m_Ember);
|
||||
m_Renderer->CreateSpatialFilter(b);
|
||||
m_Renderer->CreateTemporalFilter(b);
|
||||
@ -715,7 +688,6 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
m_Renderer->ComputeCamera();
|
||||
CancelPreviewRender();
|
||||
m_FinalPreviewRenderFunc();
|
||||
|
||||
p = m_Renderer->MemoryRequired(strips, true, m_FinalRenderDialog->DoSequence());
|
||||
iterCount = m_Renderer->TotalIterCount(strips);
|
||||
}
|
||||
@ -734,14 +706,12 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
|
||||
CancelPreviewRender();
|
||||
m_FinalPreviewRenderFunc();
|
||||
|
||||
strips = 1;
|
||||
p = m_Renderers[0]->MemoryRequired(1, true, m_FinalRenderDialog->DoSequence());
|
||||
iterCount = m_Renderers[0]->TotalIterCount(strips);
|
||||
}
|
||||
|
||||
m_FinalRenderDialog->m_StripsSpin->setSuffix(" (" + ToString<qulonglong>(strips) +")");
|
||||
|
||||
m_FinalRenderDialog->m_StripsSpin->setSuffix(" (" + ToString<qulonglong>(strips) + ")");
|
||||
return tuple<size_t, size_t, size_t>(p.first, p.second, iterCount);
|
||||
}
|
||||
|
||||
@ -757,7 +727,6 @@ QString FinalRenderEmberController<T>::ComposePath(const QString& name)
|
||||
{
|
||||
QString path = MakeEnd(m_Settings->SaveFolder(), '/');//Base path.
|
||||
QString full = path + m_FinalRenderDialog->Prefix() + name + m_FinalRenderDialog->Suffix() + "." + m_FinalRenderDialog->Ext();
|
||||
|
||||
return EmberFile<T>::UniqueFilename(full);
|
||||
}
|
||||
|
||||
@ -794,7 +763,9 @@ void FinalRenderEmberController<T>::CancelPreviewRender()
|
||||
m_FinalPreviewRenderer->Abort();
|
||||
|
||||
while (m_FinalPreviewRenderer->InRender()) { QApplication::processEvents(); }
|
||||
|
||||
while (m_PreviewRun) { QApplication::processEvents(); }
|
||||
|
||||
while (m_FinalPreviewResult.isRunning()) { QApplication::processEvents(); }
|
||||
}
|
||||
|
||||
@ -871,13 +842,12 @@ void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberS
|
||||
QString status, filename = ComposePath(QString::fromStdString(ember.m_Name));
|
||||
QString itersString = ToString<qulonglong>(stats.m_Iters);
|
||||
QString itersPerSecString = ToString<qulonglong>(size_t(stats.m_Iters / (stats.m_IterMs / 1000.0)));
|
||||
|
||||
|
||||
if (m_GuiState.m_SaveXml)
|
||||
{
|
||||
QFileInfo xmlFileInfo(filename);//Create another one in case it was modified for batch rendering.
|
||||
QString newPath = xmlFileInfo.absolutePath() + '/' + xmlFileInfo.completeBaseName() + ".flame";
|
||||
xmlDocPtr tempEdit = ember.m_Edits;
|
||||
|
||||
ember.m_Edits = m_XmlWriter.CreateNewEditdoc(&ember, nullptr, "edit", m_Settings->Nick().toStdString(), m_Settings->Url().toStdString(), m_Settings->Id().toStdString(), "", 0, 0);
|
||||
m_XmlWriter.Save(newPath.toStdString().c_str(), ember, 0, true, false, true);//Note that the ember passed is used, rather than m_Ember because it's what was actually rendered.
|
||||
|
||||
@ -887,7 +857,6 @@ void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberS
|
||||
|
||||
status = "Pure render time: " + QString::fromStdString(renderTimeString);
|
||||
Output(status);
|
||||
|
||||
totalTimeString = renderTimer.Format(renderTimer.Toc());
|
||||
status = "Total time: " + QString::fromStdString(totalTimeString) + "\nTotal iters: " + itersString + "\nIters/second: " + itersPerSecString + "\n";
|
||||
Output(status);
|
||||
@ -940,14 +909,12 @@ void FinalRenderEmberController<T>::SyncGuiToEmber(Ember<T>& ember, size_t width
|
||||
{
|
||||
double wScale = m_FinalRenderDialog->m_WidthScaleSpin->value();
|
||||
double hScale = m_FinalRenderDialog->m_HeightScaleSpin->value();
|
||||
|
||||
w = ember.m_OrigFinalRasW * wScale;
|
||||
h = ember.m_OrigFinalRasH * hScale;
|
||||
}
|
||||
|
||||
w = std::max<size_t>(w, 10);
|
||||
h = std::max<size_t>(h, 10);
|
||||
|
||||
ember.SetSizeAndAdjustScale(w, h, false, m_FinalRenderDialog->Scale());
|
||||
ember.m_Quality = m_FinalRenderDialog->m_QualitySpin->value();
|
||||
ember.m_Supersample = m_FinalRenderDialog->m_SupersampleSpin->value();
|
||||
|
@ -14,20 +14,18 @@
|
||||
/// is present here, it's safe to assume it can't be done in the designer.
|
||||
/// </summary>
|
||||
/// <param name="p">The parent widget of this item</param>
|
||||
Fractorium::Fractorium(QWidget* p)
|
||||
: QMainWindow(p),
|
||||
m_Info(OpenCLInfo::Instance())
|
||||
Fractorium::Fractorium(QWidget* p)
|
||||
: QMainWindow(p)
|
||||
{
|
||||
int spinHeight = 20, iconSize_ = 9;
|
||||
size_t i = 0;
|
||||
string s;
|
||||
Timing t;
|
||||
ui.setupUi(this);
|
||||
|
||||
m_Info = OpenCLInfo::Instance();
|
||||
qRegisterMetaType<QVector<int>>("QVector<int>");//For previews.
|
||||
qRegisterMetaType<vector<byte>>("vector<byte>");
|
||||
qRegisterMetaType<EmberTreeWidgetItemBase*>("EmberTreeWidgetItemBase*");
|
||||
|
||||
setDockOptions(DockOption::AllowNestedDocks | DockOption::AllowTabbedDocks);
|
||||
setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::TabPosition::North);
|
||||
setTabShape(QTabWidget::TabShape::Triangular);
|
||||
@ -36,7 +34,6 @@ Fractorium::Fractorium(QWidget* p)
|
||||
tabifyDockWidget(ui.XformsDockWidget, ui.XaosDockWidget);
|
||||
tabifyDockWidget(ui.XaosDockWidget, ui.PaletteDockWidget);
|
||||
tabifyDockWidget(ui.PaletteDockWidget, ui.InfoDockWidget);
|
||||
|
||||
m_Docks.reserve(8);
|
||||
m_Docks.push_back(ui.LibraryDockWidget);
|
||||
m_Docks.push_back(ui.FlameDockWidget);
|
||||
@ -44,58 +41,48 @@ Fractorium::Fractorium(QWidget* p)
|
||||
m_Docks.push_back(ui.XaosDockWidget);
|
||||
m_Docks.push_back(ui.PaletteDockWidget);
|
||||
m_Docks.push_back(ui.InfoDockWidget);
|
||||
|
||||
m_FontSize = 9;
|
||||
m_VarSortMode = 1;//Sort by weight by default.
|
||||
m_PaletteSortMode = 0;//Sort by palette ascending by default.
|
||||
m_ColorDialog = new QColorDialog(this);
|
||||
m_Settings = new FractoriumSettings(this);
|
||||
m_QssDialog = new QssDialog(this);
|
||||
|
||||
m_FileDialog = nullptr;//Use lazy instantiation upon first use.
|
||||
m_FolderDialog = nullptr;
|
||||
m_FinalRenderDialog = new FractoriumFinalRenderDialog(m_Settings, this);
|
||||
m_OptionsDialog = new FractoriumOptionsDialog(m_Settings, this);
|
||||
m_VarDialog = new FractoriumVariationsDialog(m_Settings, this);
|
||||
m_AboutDialog = new FractoriumAboutDialog(this);
|
||||
|
||||
//Put the about dialog in the screen center.
|
||||
const QRect screen = QApplication::desktop()->screenGeometry();
|
||||
m_AboutDialog->move(screen.center() - m_AboutDialog->rect().center());
|
||||
|
||||
connect(m_ColorDialog, SIGNAL(colorSelected(const QColor&)), this, SLOT(OnColorSelected(const QColor&)), Qt::QueuedConnection);
|
||||
|
||||
m_XformComboColors[i++] = QColor(0XFF, 0X00, 0X00);
|
||||
m_XformComboColors[i++] = QColor(0XCC, 0XCC, 0X00);
|
||||
m_XformComboColors[i++] = QColor(0X00, 0XCC, 0X00);
|
||||
m_XformComboColors[i++] = QColor(0X00, 0XCC, 0XCC);
|
||||
m_XformComboColors[i++] = QColor(0X40, 0X40, 0XFF);
|
||||
|
||||
m_XformComboColors[i++] = QColor(0XCC, 0X00, 0XCC);
|
||||
m_XformComboColors[i++] = QColor(0XCC, 0X80, 0X00);
|
||||
m_XformComboColors[i++] = QColor(0X80, 0X00, 0X4F);
|
||||
m_XformComboColors[i++] = QColor(0X80, 0X80, 0X22);
|
||||
m_XformComboColors[i++] = QColor(0X60, 0X80, 0X60);
|
||||
|
||||
m_XformComboColors[i++] = QColor(0X50, 0X80, 0X80);
|
||||
m_XformComboColors[i++] = QColor(0X4F, 0X4F, 0X80);
|
||||
m_XformComboColors[i++] = QColor(0X80, 0X50, 0X80);
|
||||
m_XformComboColors[i++] = QColor(0X80, 0X60, 0X22);
|
||||
m_FinalXformComboColor = QColor(0x7F, 0x7F, 0x7F);
|
||||
|
||||
|
||||
for (i = 0; i < XFORM_COLOR_COUNT; i++)
|
||||
{
|
||||
QPixmap pixmap(iconSize_, iconSize_);
|
||||
|
||||
pixmap.fill(m_XformComboColors[i]);
|
||||
m_XformComboIcons[i] = QIcon(pixmap);
|
||||
}
|
||||
|
||||
QPixmap pixmap(iconSize_, iconSize_);
|
||||
|
||||
pixmap.fill(m_FinalXformComboColor);
|
||||
m_FinalXformComboIcon = QIcon(pixmap);
|
||||
|
||||
InitToolbarUI();
|
||||
InitParamsUI();
|
||||
InitXformsUI();
|
||||
@ -108,10 +95,10 @@ Fractorium::Fractorium(QWidget* p)
|
||||
InitLibraryUI();
|
||||
InitInfoUI();
|
||||
InitMenusUI();
|
||||
|
||||
//This will init the controller and fill in the variations and palette tables with template specific instances
|
||||
//of their respective objects.
|
||||
#ifdef DO_DOUBLE
|
||||
|
||||
if (m_Settings->Double())
|
||||
m_Controller = unique_ptr<FractoriumEmberControllerBase>(new FractoriumEmberController<double>(this));
|
||||
else
|
||||
@ -121,24 +108,21 @@ Fractorium::Fractorium(QWidget* p)
|
||||
m_Controller->SetupVariationTree();
|
||||
m_Controller->FilteredVariations();
|
||||
|
||||
if (m_Info.Ok() && m_Settings->OpenCL() && m_QualitySpin->value() < (30 * m_Settings->Devices().size()))
|
||||
if (m_Info->Ok() && m_Settings->OpenCL() && m_QualitySpin->value() < (30 * m_Settings->Devices().size()))
|
||||
m_QualitySpin->setValue(30 * m_Settings->Devices().size());
|
||||
|
||||
int statusBarHeight = 20 * devicePixelRatio();
|
||||
ui.StatusBar->setMinimumHeight(statusBarHeight);
|
||||
ui.StatusBar->setMaximumHeight(statusBarHeight);
|
||||
|
||||
m_RenderStatusLabel = new QLabel(this);
|
||||
m_RenderStatusLabel->setMinimumWidth(200);
|
||||
m_RenderStatusLabel->setAlignment(Qt::AlignRight);
|
||||
ui.StatusBar->addPermanentWidget(m_RenderStatusLabel);
|
||||
|
||||
m_CoordinateStatusLabel = new QLabel(this);
|
||||
m_CoordinateStatusLabel->setMinimumWidth(300);
|
||||
m_CoordinateStatusLabel->setMaximumWidth(300);
|
||||
m_CoordinateStatusLabel->setAlignment(Qt::AlignLeft);
|
||||
ui.StatusBar->addWidget(m_CoordinateStatusLabel);
|
||||
|
||||
int progressBarHeight = 15;
|
||||
int progressBarWidth = 300;
|
||||
m_ProgressBar = new QProgressBar(this);
|
||||
@ -149,15 +133,13 @@ Fractorium::Fractorium(QWidget* p)
|
||||
m_ProgressBar->setMinimumWidth(progressBarWidth);
|
||||
m_ProgressBar->setMaximumWidth(progressBarWidth);
|
||||
ui.StatusBar->addPermanentWidget(m_ProgressBar);
|
||||
|
||||
//Setup pointer in the GL window to point back to here.
|
||||
ui.GLDisplay->SetMainWindow(this);
|
||||
bool restored = restoreState(m_Settings->value("windowState").toByteArray());
|
||||
showMaximized();//This won't fully set things up and show them until after this constructor exits.
|
||||
|
||||
connect(ui.LibraryDockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(dockLocationChanged(Qt::DockWidgetArea)));
|
||||
connect(ui.LibraryDockWidget, SIGNAL(topLevelChanged(bool)), this, SLOT(OnDockTopLevelChanged(bool)));
|
||||
|
||||
|
||||
//Always ensure the library tab is selected, which will show preview renders.
|
||||
if (!restored)
|
||||
{
|
||||
@ -243,7 +225,6 @@ void Fractorium::CenterScrollbars()
|
||||
{
|
||||
QScrollBar* w = ui.GLParentScrollArea->horizontalScrollBar();
|
||||
QScrollBar* h = ui.GLParentScrollArea->verticalScrollBar();
|
||||
|
||||
w->setValue(w->maximum() / 2);
|
||||
h->setValue(h->maximum() / 2);
|
||||
}
|
||||
@ -267,7 +248,6 @@ void FractoriumEmberController<T>::ApplyXmlSavingTemplate(Ember<T>& ember)
|
||||
bool Fractorium::HaveFinal()
|
||||
{
|
||||
QComboBox* combo = ui.CurrentXformCombo;
|
||||
|
||||
return (combo->count() > 0 && combo->itemText(combo->count() - 1) == "Final");
|
||||
}
|
||||
|
||||
@ -375,7 +355,7 @@ void Fractorium::resizeEvent(QResizeEvent* e)
|
||||
/// but telling it that this window has become the focus window forces
|
||||
/// it to refresh this.
|
||||
/// <param name="e">The event</param>
|
||||
void Fractorium::showEvent(QShowEvent *e)
|
||||
void Fractorium::showEvent(QShowEvent* e)
|
||||
{
|
||||
//Tell Qt to refresh the native menubar from this widget.
|
||||
emit qGuiApp->focusWindowChanged(windowHandle());
|
||||
@ -476,7 +456,9 @@ void Fractorium::dropEvent(QDropEvent* e)
|
||||
void Fractorium::SetupCombo(QTableWidget* table, const QObject* receiver, int& row, int col, StealthComboBox*& comboBox, const vector<string>& vals, const char* signal, const char* slot, Qt::ConnectionType connectionType)
|
||||
{
|
||||
comboBox = new StealthComboBox(table);
|
||||
|
||||
for (auto& s : vals) comboBox->addItem(s.c_str());
|
||||
|
||||
table->setCellWidget(row, col, comboBox);
|
||||
connect(comboBox, signal, receiver, slot, connectionType);
|
||||
row++;
|
||||
@ -507,14 +489,13 @@ QStringList Fractorium::SetupOpenXmlDialog()
|
||||
m_FileDialog = new QFileDialog(this);
|
||||
m_FileDialog->setViewMode(QFileDialog::List);
|
||||
}
|
||||
|
||||
|
||||
if (!m_FileDialog)
|
||||
return QStringList("");
|
||||
|
||||
QStringList filenames;
|
||||
m_FileDialog->disconnect(SIGNAL(filterSelected(const QString&)));
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [=](const QString &filter) { m_Settings->OpenXmlExt(filter); });
|
||||
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [ = ](const QString & filter) { m_Settings->OpenXmlExt(filter); });
|
||||
m_FileDialog->setFileMode(QFileDialog::ExistingFiles);
|
||||
m_FileDialog->setAcceptMode(QFileDialog::AcceptOpen);
|
||||
m_FileDialog->setNameFilter("Flam3 (*.flam3);;Flame (*.flame);;Xml (*.xml)");
|
||||
@ -547,15 +528,13 @@ QString Fractorium::SetupSaveXmlDialog(const QString& defaultFilename)
|
||||
m_FileDialog = new QFileDialog(this);
|
||||
m_FileDialog->setViewMode(QFileDialog::List);
|
||||
}
|
||||
|
||||
|
||||
if (!m_FileDialog)
|
||||
return "";
|
||||
|
||||
QString filename;
|
||||
|
||||
m_FileDialog->disconnect(SIGNAL(filterSelected(const QString&)));
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [=](const QString &filter) { m_Settings->SaveXmlExt(filter); });
|
||||
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [ = ](const QString & filter) { m_Settings->SaveXmlExt(filter); });
|
||||
//This must come first because it clears various internal states which allow the file text to be properly set.
|
||||
//This is most likely a bug in QFileDialog.
|
||||
m_FileDialog->setAcceptMode(QFileDialog::AcceptSave);
|
||||
@ -585,15 +564,13 @@ QString Fractorium::SetupSaveImageDialog(const QString& defaultFilename)
|
||||
m_FileDialog = new QFileDialog(this);
|
||||
m_FileDialog->setViewMode(QFileDialog::List);
|
||||
}
|
||||
|
||||
|
||||
if (!m_FileDialog)
|
||||
return "";
|
||||
|
||||
|
||||
QString filename;
|
||||
|
||||
m_FileDialog->disconnect(SIGNAL(filterSelected(const QString&)));
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [=](const QString &filter) { m_Settings->SaveImageExt(filter); });
|
||||
|
||||
connect(m_FileDialog, &QFileDialog::filterSelected, [ = ](const QString & filter) { m_Settings->SaveImageExt(filter); });
|
||||
//This must come first because it clears various internal states which allow the file text to be properly set.
|
||||
//This is most likely a bug in QFileDialog.
|
||||
m_FileDialog->setAcceptMode(QFileDialog::AcceptSave);
|
||||
@ -625,12 +602,11 @@ QString Fractorium::SetupSaveFolderDialog()
|
||||
m_FolderDialog = new QFileDialog(this);
|
||||
m_FolderDialog->setViewMode(QFileDialog::List);
|
||||
}
|
||||
|
||||
|
||||
if (!m_FolderDialog)
|
||||
return "";
|
||||
|
||||
|
||||
QString filename;
|
||||
|
||||
//This must come first because it clears various internal states which allow the file text to be properly set.
|
||||
//This is most likely a bug in QFileDialog.
|
||||
m_FolderDialog->setAcceptMode(QFileDialog::AcceptSave);
|
||||
@ -672,14 +648,12 @@ void Fractorium::ShowCritical(const QString& title, const QString& text, bool in
|
||||
void Fractorium::SetTabOrders()
|
||||
{
|
||||
QWidget* w = SetTabOrder(this, ui.ColorTable, m_BrightnessSpin);//Flame.
|
||||
|
||||
w = SetTabOrder(this, w, m_GammaSpin);
|
||||
w = SetTabOrder(this, w, m_GammaThresholdSpin);
|
||||
w = SetTabOrder(this, w, m_VibrancySpin);
|
||||
w = SetTabOrder(this, w, m_HighlightSpin);
|
||||
w = SetTabOrder(this, w, m_BackgroundColorButton);
|
||||
w = SetTabOrder(this, w, m_PaletteModeCombo);
|
||||
|
||||
w = SetTabOrder(this, w, m_CenterXSpin);
|
||||
w = SetTabOrder(this, w, m_CenterYSpin);
|
||||
w = SetTabOrder(this, w, m_ScaleSpin);
|
||||
@ -690,20 +664,17 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, m_PitchSpin);
|
||||
w = SetTabOrder(this, w, m_YawSpin);
|
||||
w = SetTabOrder(this, w, m_DepthBlurSpin);
|
||||
|
||||
w = SetTabOrder(this, w, m_SpatialFilterWidthSpin);
|
||||
w = SetTabOrder(this, w, m_SpatialFilterTypeCombo);
|
||||
w = SetTabOrder(this, w, m_TemporalFilterTypeCombo);
|
||||
w = SetTabOrder(this, w, m_DEFilterMinRadiusSpin);
|
||||
w = SetTabOrder(this, w, m_DEFilterMaxRadiusSpin);
|
||||
w = SetTabOrder(this, w, m_DECurveSpin);
|
||||
|
||||
w = SetTabOrder(this, w, m_TemporalSamplesSpin);
|
||||
w = SetTabOrder(this, w, m_QualitySpin);
|
||||
w = SetTabOrder(this, w, m_SupersampleSpin);
|
||||
w = SetTabOrder(this, w, m_AffineInterpTypeCombo);
|
||||
w = SetTabOrder(this, w, m_InterpTypeCombo);
|
||||
|
||||
w = SetTabOrder(this, ui.CurrentXformCombo, ui.AddXformButton);//Xforms.
|
||||
w = SetTabOrder(this, w, ui.DuplicateXformButton);
|
||||
w = SetTabOrder(this, w, ui.ClearXformButton);
|
||||
@ -711,13 +682,11 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, ui.AddFinalXformButton);
|
||||
w = SetTabOrder(this, w, m_XformWeightSpin);
|
||||
w = SetTabOrder(this, w, m_XformWeightSpinnerButtonWidget->m_Button);
|
||||
|
||||
w = SetTabOrder(this, m_XformColorIndexSpin, ui.XformColorScroll);//Xforms color.
|
||||
w = SetTabOrder(this, w, m_XformColorSpeedSpin);
|
||||
w = SetTabOrder(this, w, m_XformOpacitySpin);
|
||||
w = SetTabOrder(this, w, m_XformDirectColorSpin);
|
||||
w = SetTabOrder(this, w, ui.SoloXformCheckBox);
|
||||
|
||||
w = SetTabOrder(this, ui.PreAffineGroupBox, m_PreX1Spin);//Xforms affine.
|
||||
w = SetTabOrder(this, w, m_PreX2Spin);
|
||||
w = SetTabOrder(this, w, m_PreY1Spin);
|
||||
@ -769,12 +738,9 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, ui.ShowPostAffineAllRadio);
|
||||
w = SetTabOrder(this, w, ui.LocalPivotRadio);
|
||||
w = SetTabOrder(this, w, ui.WorldPivotRadio);
|
||||
|
||||
w = SetTabOrder(this, ui.VariationsFilterLineEdit, ui.VariationsFilterClearButton);//Xforms variation.
|
||||
w = SetTabOrder(this, w, ui.VariationsTree);
|
||||
|
||||
//Xforms xaos is done dynamically every time.
|
||||
|
||||
w = SetTabOrder(this, m_PaletteHueSpin, m_PaletteContrastSpin);//Palette.
|
||||
w = SetTabOrder(this, w, m_PaletteSaturationSpin);
|
||||
w = SetTabOrder(this, w, m_PaletteBlurSpin);
|
||||
@ -783,12 +749,8 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, ui.PaletteFilterLineEdit);
|
||||
w = SetTabOrder(this, w, ui.PaletteFilterClearButton);
|
||||
w = SetTabOrder(this, w, ui.PaletteListTable);
|
||||
|
||||
|
||||
w = SetTabOrder(this, ui.SummaryTable, ui.SummaryTree);//Info summary.
|
||||
|
||||
w = SetTabOrder(this, ui.InfoBoundsGroupBox, ui.InfoBoundsFrame);//Info bounds.
|
||||
|
||||
w = SetTabOrder(this, w, ui.InfoBoundsTable);
|
||||
w = SetTabOrder(this, w, ui.InfoFileOpeningGroupBox);
|
||||
w = SetTabOrder(this, w, ui.InfoFileOpeningTextEdit);
|
||||
@ -872,7 +834,6 @@ void Fractorium::ToggleTableCol(QTableView* table, int logicalIndex)
|
||||
auto model = table->model();
|
||||
int rows = model->rowCount();
|
||||
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
|
||||
auto tableWidget = qobject_cast<QTableWidget*>(table);
|
||||
|
||||
if (tableWidget)
|
||||
|
@ -50,7 +50,7 @@ template <typename T> class FinalRenderEmberController;
|
||||
/// upon first use with lazy instantiation and then kept around for the remainder of the program.
|
||||
/// Additional dialogs are for the about box, options, and final rendering out to a file.
|
||||
/// While all class member variables and functions are declared in this .h file, the implementation
|
||||
/// for them is far too lengthy to put in a single .cpp file. So general functionality is placed in
|
||||
/// for them is far too lengthy to put in a single .cpp file. So general functionality is placed in
|
||||
/// Fractorium.cpp and the other functional areas are each broken out into their own files.
|
||||
/// The order of the functions in each .cpp file should roughly match the order they appear in the .h file.
|
||||
/// Future todo list:
|
||||
@ -74,13 +74,13 @@ class Fractorium : public QMainWindow
|
||||
friend FractoriumEmberController<float>;
|
||||
friend FinalRenderEmberControllerBase;
|
||||
friend FinalRenderEmberController<float>;
|
||||
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
friend GLEmberController<double>;
|
||||
friend FractoriumEmberController<double>;
|
||||
friend FinalRenderEmberController<double>;
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
Fractorium(QWidget* p = 0);
|
||||
~Fractorium();
|
||||
@ -99,7 +99,7 @@ public:
|
||||
bool DrawAllPre();
|
||||
bool DrawAllPost();
|
||||
bool LocalPivot();
|
||||
|
||||
|
||||
public slots:
|
||||
//Dock.
|
||||
void OnDockTopLevelChanged(bool topLevel);
|
||||
@ -306,7 +306,7 @@ protected:
|
||||
virtual void dragEnterEvent(QDragEnterEvent* e) override;
|
||||
virtual void dragMoveEvent(QDragMoveEvent* e) override;
|
||||
virtual void dropEvent(QDropEvent* e) override;
|
||||
virtual void showEvent(QShowEvent *e) override;
|
||||
virtual void showEvent(QShowEvent* e) override;
|
||||
|
||||
private:
|
||||
void InitMenusUI();
|
||||
@ -353,7 +353,7 @@ private:
|
||||
|
||||
//Xaos.
|
||||
void FillXaosTable();
|
||||
|
||||
|
||||
//Palette.
|
||||
void ResetPaletteControls();
|
||||
void SetPaletteFileComboIndex(const string& filename);
|
||||
@ -415,7 +415,7 @@ private:
|
||||
SpinBox* m_TemporalSamplesSpin;
|
||||
StealthComboBox* m_AffineInterpTypeCombo;
|
||||
StealthComboBox* m_InterpTypeCombo;
|
||||
|
||||
|
||||
//Xforms.
|
||||
DoubleSpinBox* m_XformWeightSpin;
|
||||
SpinnerButtonWidget* m_XformWeightSpinnerButtonWidget;
|
||||
@ -444,7 +444,7 @@ private:
|
||||
DoubleSpinBox* m_PostY2Spin;
|
||||
DoubleSpinBox* m_PostO1Spin;
|
||||
DoubleSpinBox* m_PostO2Spin;
|
||||
|
||||
|
||||
DoubleSpinBox* m_PreSpins[6];
|
||||
DoubleSpinBox* m_PostSpins[6];
|
||||
|
||||
@ -499,7 +499,7 @@ private:
|
||||
int m_VarSortMode;
|
||||
int m_PaletteSortMode;
|
||||
int m_PreviousPaletteRow;
|
||||
OpenCLInfo& m_Info;
|
||||
shared_ptr<OpenCLInfo> m_Info;
|
||||
unique_ptr<FractoriumEmberControllerBase> m_Controller;
|
||||
Ui::FractoriumClass ui;
|
||||
};
|
||||
|
@ -71,7 +71,7 @@ static QWidget* SetTabOrder(QWidget* p, QWidget* w1, QWidget* w2)
|
||||
/// <param name="s">The string to convert</param>
|
||||
/// <param name="ok">Pointer to boolean which stores the success value of the conversion</param>
|
||||
/// <returns>The converted value if successful, else 0.</returns>
|
||||
static double ToDouble(const QString &s, bool *ok)
|
||||
static double ToDouble(const QString& s, bool* ok)
|
||||
{
|
||||
return QLocale::system().toDouble(s, ok);
|
||||
}
|
||||
@ -109,7 +109,7 @@ static QString MakeEnd(const QString& s, T e)
|
||||
/// <returns>True if s was not empty and existed, else false.</returns>
|
||||
static bool Exists(const QString& s)
|
||||
{
|
||||
return s != "" && QDir(s).exists();
|
||||
return s != "" && QDir(s).exists();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -121,9 +121,8 @@ static QColor VisibleColor(const QColor& color)
|
||||
{
|
||||
int threshold = 105;
|
||||
int delta = (color.red() * 0.299) + //Magic numbers gotten from a Stack Overflow post.
|
||||
(color.green() * 0.587) +
|
||||
(color.blue() * 0.114);
|
||||
|
||||
(color.green() * 0.587) +
|
||||
(color.blue() * 0.114);
|
||||
QColor textColor = (255 - delta < threshold) ? QColor(0, 0, 0) : QColor(255, 255, 255);
|
||||
return textColor;
|
||||
}
|
||||
@ -196,9 +195,7 @@ static intmax_t IsXformLinked(Ember<T>& ember, Xform<T>* xform)
|
||||
static vector<pair<size_t, size_t>> Devices(const QList<QVariant>& selectedDevices)
|
||||
{
|
||||
vector<pair<size_t, size_t>> vec;
|
||||
OpenCLInfo& info = OpenCLInfo::Instance();
|
||||
auto& devices = info.DeviceIndices();
|
||||
|
||||
auto& devices = OpenCLInfo::Instance()->DeviceIndices();
|
||||
vec.reserve(selectedDevices.size());
|
||||
|
||||
for (size_t i = 0; i < selectedDevices.size(); i++)
|
||||
@ -223,8 +220,7 @@ static vector<pair<size_t, size_t>> Devices(const QList<QVariant>& selectedDevic
|
||||
static void SetupDeviceTable(QTableWidget* table, const QList<QVariant>& settingsDevices)
|
||||
{
|
||||
bool primary = false;
|
||||
auto& deviceNames = OpenCLInfo::Instance().AllDeviceNames();
|
||||
|
||||
auto& deviceNames = OpenCLInfo::Instance()->AllDeviceNames();
|
||||
table->clearContents();
|
||||
table->setRowCount(deviceNames.size());
|
||||
|
||||
@ -233,7 +229,6 @@ static void SetupDeviceTable(QTableWidget* table, const QList<QVariant>& setting
|
||||
auto checkItem = new QTableWidgetItem();
|
||||
auto radio = new QRadioButton();
|
||||
auto deviceItem = new QTableWidgetItem(QString::fromStdString(deviceNames[i]));
|
||||
|
||||
table->setItem(i, 0, checkItem);
|
||||
table->setCellWidget(i, 1, radio);
|
||||
table->setItem(i, 2, deviceItem);
|
||||
@ -365,17 +360,17 @@ static void HandleDeviceTableCheckChanged(QTableWidget* table, int row, int col)
|
||||
static QString BaseStyle()
|
||||
{
|
||||
return "/*---Base Style---\n"
|
||||
"This is needed to deal with the large tabs in the fusion theme which is the default on Linux, and optional on Windows.\n"
|
||||
"It's not needed for other themes."
|
||||
"You should keep this at the top of whatever custom style you make to ensure the tabs aren't unusually large.*/\n"
|
||||
"This is needed to deal with the large tabs in the fusion theme which is the default on Linux, and optional on Windows.\n"
|
||||
"It's not needed for other themes."
|
||||
"You should keep this at the top of whatever custom style you make to ensure the tabs aren't unusually large.*/\n"
|
||||
#ifndef WIN32
|
||||
"QTabBar::tab { height: 3ex; }\n\n"
|
||||
"QTabBar::tab { height: 3ex; }\n\n"
|
||||
#else
|
||||
"QTabBar::tab { height: 5ex; }\n\n"
|
||||
"QTabBar::tab { height: 5ex; }\n\n"
|
||||
#endif
|
||||
"/*This is needed to give the labels on the status bar some padding.*/\n"
|
||||
"QStatusBar QLabel { padding-left: 2px; padding-right: 2px; }\n\n"
|
||||
;
|
||||
"/*This is needed to give the labels on the status bar some padding.*/\n"
|
||||
"QStatusBar QLabel { padding-left: 2px; padding-right: 2px; }\n\n"
|
||||
;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -3,18 +3,14 @@
|
||||
#include "Fractorium.h"
|
||||
#include "GLEmberController.h"
|
||||
|
||||
#define SAVE_EACH 1
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which initializes the non-templated members contained in this class.
|
||||
/// The renderer, other templated members and GUI setup will be done in the templated derived controller class.
|
||||
/// </summary>
|
||||
/// <param name="fractorium">Pointer to the main window.</param>
|
||||
FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractorium)
|
||||
: m_Info(OpenCLInfo::Instance())
|
||||
{
|
||||
Timing t;
|
||||
|
||||
m_Rendering = false;
|
||||
m_Shared = true;
|
||||
m_FailedRenders = 0;
|
||||
@ -25,12 +21,11 @@ FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractor
|
||||
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->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()));
|
||||
}
|
||||
@ -71,42 +66,34 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
|
||||
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>()));
|
||||
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.
|
||||
|
||||
// TODO
|
||||
// QStandardPaths::AppConfigLocation -- errors out, not a member.
|
||||
// QStandardPaths::DataLocation -- how to parse this? It should include "/usr/share/fractorium" on Linux.
|
||||
|
||||
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())) )
|
||||
{
|
||||
// TODO better error dialog
|
||||
throw "No palettes found, exiting.";
|
||||
}
|
||||
//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())) )
|
||||
{
|
||||
throw "No palettes found, exiting.";
|
||||
}
|
||||
|
||||
BackgroundChanged(QColor(0, 0, 0));//Default to black.
|
||||
ClearUndo();
|
||||
|
||||
m_PreviewRenderer->Callback(nullptr);
|
||||
m_PreviewRenderer->NumChannels(4);
|
||||
m_PreviewRenderer->EarlyClip(m_Fractorium->m_Settings->EarlyClip());
|
||||
m_PreviewRenderer->YAxisUp(m_Fractorium->m_Settings->YAxisUp());
|
||||
m_PreviewRenderer->SetEmber(m_Ember);//Give it an initial ember, will be updated many times later.
|
||||
//m_PreviewRenderer->ThreadCount(1);//For debugging.
|
||||
|
||||
m_PreviewRenderFunc = [&](uint start, uint end)
|
||||
{
|
||||
while(m_PreviewRun || m_PreviewRunning)
|
||||
while (m_PreviewRun || m_PreviewRunning)
|
||||
{
|
||||
}
|
||||
|
||||
@ -120,7 +107,6 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
|
||||
for (size_t i = start; m_PreviewRun && i < end && i < m_EmberFile.Size(); i++)
|
||||
{
|
||||
Ember<T> ember = m_EmberFile.m_Embers[i];
|
||||
|
||||
ember.SyncSize();
|
||||
ember.SetSizeAndAdjustScale(PREVIEW_SIZE, PREVIEW_SIZE, false, SCALE_WIDTH);
|
||||
ember.m_TemporalSamples = 1;
|
||||
@ -136,11 +122,10 @@ FractoriumEmberController<T>::FractoriumEmberController(Fractorium* fractorium)
|
||||
//This ensures the events are processed in order as each preview is updated, and that control does not return here
|
||||
//until the update is complete.
|
||||
QMetaObject::invokeMethod(m_Fractorium, "SetLibraryTreeItemData", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(EmberTreeWidgetItemBase*, dynamic_cast<EmberTreeWidgetItemBase*>(treeItem)),
|
||||
Q_ARG(vector<byte>&, m_PreviewFinalImage),
|
||||
Q_ARG(uint, PREVIEW_SIZE),
|
||||
Q_ARG(uint, PREVIEW_SIZE));
|
||||
|
||||
Q_ARG(EmberTreeWidgetItemBase*, dynamic_cast<EmberTreeWidgetItemBase*>(treeItem)),
|
||||
Q_ARG(vector<byte>&, m_PreviewFinalImage),
|
||||
Q_ARG(uint, PREVIEW_SIZE),
|
||||
Q_ARG(uint, PREVIEW_SIZE));
|
||||
//treeItem->SetImage(m_PreviewFinalImage, PREVIEW_SIZE, PREVIEW_SIZE);
|
||||
}
|
||||
}
|
||||
@ -287,7 +272,6 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
if (Xform<T>* xform = CurrentXform())
|
||||
func(xform);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_ALL:
|
||||
@ -295,7 +279,6 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
while (Xform<T>* xform = m_Ember.GetTotalXform(i++))
|
||||
func(xform);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_ALL_EXCEPT_FINAL:
|
||||
@ -304,7 +287,6 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
while (Xform<T>* xform = m_Ember.GetXform(i++))
|
||||
func(xform);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -326,10 +308,9 @@ void FractoriumEmberController<T>::SetEmberPrivate(const Ember<U>& ember, bool v
|
||||
{
|
||||
if (ember.m_Name != m_Ember.m_Name)
|
||||
m_LastSaveCurrent = "";
|
||||
|
||||
|
||||
size_t w = m_Ember.m_FinalRasW;//Cache values for use below.
|
||||
size_t h = m_Ember.m_FinalRasH;
|
||||
|
||||
m_Ember = ember;
|
||||
|
||||
if (!verbatim)
|
||||
@ -340,20 +321,16 @@ void FractoriumEmberController<T>::SetEmberPrivate(const Ember<U>& ember, bool v
|
||||
m_Ember.m_Supersample = m_Fractorium->m_SupersampleSpin->value();
|
||||
}
|
||||
|
||||
#ifdef SAVE_EACH
|
||||
static EmberToXml<T> writer;
|
||||
static EmberToXml<T> writer;//Save parameters of last full render just in case there is a crash.
|
||||
string filename = "last.flame";
|
||||
|
||||
writer.Save(filename.c_str(), m_Ember, 0, true, false, true);
|
||||
#endif
|
||||
|
||||
m_GLController->ResetMouseState();
|
||||
FillXforms();//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo.
|
||||
FillParamTablesAndPalette();
|
||||
FillSummary();
|
||||
|
||||
//If a resize happened, this won't do anything because the new size is not reflected in the scroll area yet.
|
||||
//However, it will have been taken care of in SyncSizes() in that case, so it's ok.
|
||||
//However, it will have been taken care of in SyncSizes() in that case, so it's ok.
|
||||
//This is for when a new ember with the same size was loaded. If it was larger than the scroll area, and was scrolled, re-center it.
|
||||
if (m_Ember.m_FinalRasW == w && m_Ember.m_FinalRasH == h)
|
||||
m_Fractorium->CenterScrollbars();
|
||||
|
@ -206,7 +206,7 @@ public:
|
||||
|
||||
//Info.
|
||||
virtual void FillSummary() { }
|
||||
|
||||
|
||||
//Rendering/progress.
|
||||
virtual bool Render() { return false; }
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared = true) { return false; }
|
||||
@ -232,7 +232,7 @@ protected:
|
||||
void AddProcessAction(eProcessAction action);
|
||||
eProcessAction CondenseAndClearProcessActions();
|
||||
eProcessState ProcessState() { return m_Renderer.get() ? m_Renderer->ProcessState() : NONE; }
|
||||
|
||||
|
||||
//Non-templated members.
|
||||
bool m_Rendering;
|
||||
bool m_Shared;
|
||||
@ -261,7 +261,7 @@ protected:
|
||||
Fractorium* m_Fractorium;
|
||||
QTimer* m_RenderTimer;
|
||||
QTimer* m_RenderRestartTimer;
|
||||
OpenCLInfo& m_Info;
|
||||
shared_ptr<OpenCLInfo> m_Info;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@ -434,7 +434,7 @@ public:
|
||||
virtual void XaosChanged(int x, int y, double val) override;
|
||||
virtual void ClearXaos() override;
|
||||
virtual void RandomXaos() override;
|
||||
|
||||
|
||||
//Palette.
|
||||
virtual int InitPaletteList(const string& s) override;
|
||||
virtual bool FillPaletteTable(const string& s) override;
|
||||
|
@ -8,20 +8,19 @@ void Fractorium::InitInfoUI()
|
||||
{
|
||||
auto treeHeader = ui.SummaryTree->header();
|
||||
auto tableHeader = ui.SummaryTable->horizontalHeader();
|
||||
|
||||
treeHeader->setVisible(true);
|
||||
treeHeader->setSectionsClickable(true);
|
||||
treeHeader->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
connect(treeHeader, SIGNAL(sectionClicked(int)), this, SLOT(OnSummaryTreeHeaderSectionClicked(int)), Qt::QueuedConnection);
|
||||
connect(tableHeader, SIGNAL(sectionResized(int, int, int)), this, SLOT(OnSummaryTableHeaderResized(int, int, int)), Qt::QueuedConnection);
|
||||
SetFixedTableHeader(ui.SummaryTable->verticalHeader());
|
||||
|
||||
ui.SummaryTable->setItem(0, 0, m_InfoNameItem = new QTableWidgetItem(""));
|
||||
ui.SummaryTable->setItem(1, 0, m_InfoPaletteItem = new QTableWidgetItem(""));
|
||||
ui.SummaryTable->setItem(2, 0, m_Info3dItem = new QTableWidgetItem(""));
|
||||
ui.SummaryTable->setItem(3, 0, m_InfoXaosItem = new QTableWidgetItem(""));
|
||||
ui.SummaryTable->setItem(4, 0, m_InfoXformCountItem = new QTableWidgetItem(""));
|
||||
ui.SummaryTable->setItem(5, 0, m_InfoFinalXformItem = new QTableWidgetItem(""));
|
||||
ui.InfoTabWidget->setCurrentIndex(0);//Make summary tab focused by default.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -93,7 +92,6 @@ 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.
|
||||
QSize size(table->columnWidth(0), table->rowHeight(1) + 1);
|
||||
m_Fractorium->m_InfoPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
@ -112,19 +110,18 @@ void FractoriumEmberController<T>::FillSummary()
|
||||
if (!m_Ember.IsFinalXform(xform) && index != -1)
|
||||
{
|
||||
item1->setText(0, "Xform " +
|
||||
QString::number(x + 1) +
|
||||
" (" + QLocale::system().toString(xform->m_Weight, pc, p) + ") (" +
|
||||
QLocale::system().toString(double(m_NormalizedWeights[index]), pc, p) + ") " +
|
||||
linked);
|
||||
QString::number(x + 1) +
|
||||
" (" + QLocale::system().toString(xform->m_Weight, pc, p) + ") (" +
|
||||
QLocale::system().toString(double(m_NormalizedWeights[index]), pc, p) + ") " +
|
||||
linked);
|
||||
}
|
||||
else
|
||||
item1->setText(0, "Final xform");
|
||||
|
||||
item1->setText(1, xform->m_Name.c_str());
|
||||
|
||||
auto affineItem = new QTreeWidgetItem(item1);
|
||||
affineItem->setText(0, "Affine");
|
||||
|
||||
|
||||
if (xform->m_Affine.IsZero())
|
||||
as += " Empty";
|
||||
else if (xform->m_Affine.IsID())
|
||||
@ -139,7 +136,6 @@ void FractoriumEmberController<T>::FillSummary()
|
||||
}
|
||||
|
||||
affineItem->setText(1, as);
|
||||
|
||||
auto colorIndexItem = new QTreeWidgetItem(item1);
|
||||
colorIndexItem->setText(0, "Color index");
|
||||
colorIndexItem->setText(1, QLocale::system().toString(xform->m_ColorX, pc, p));
|
||||
@ -147,15 +143,12 @@ void FractoriumEmberController<T>::FillSummary()
|
||||
color.setAlphaF(xform->m_Opacity);
|
||||
colorIndexItem->setBackgroundColor(1, color);
|
||||
colorIndexItem->setTextColor(1, VisibleColor(color));
|
||||
|
||||
auto colorSpeedItem = new QTreeWidgetItem(item1);
|
||||
colorSpeedItem->setText(0, "Color speed");
|
||||
colorSpeedItem->setText(1, QLocale::system().toString(xform->m_ColorSpeed, pc, p));
|
||||
|
||||
auto opacityItem = new QTreeWidgetItem(item1);
|
||||
opacityItem->setText(0, "Opacity");
|
||||
opacityItem->setText(1, QLocale::system().toString(xform->m_Opacity, pc, p));
|
||||
|
||||
auto dcItem = new QTreeWidgetItem(item1);
|
||||
dcItem->setText(0, "Direct color");
|
||||
dcItem->setText(1, QLocale::system().toString(xform->m_DirectColor, pc, p));
|
||||
@ -163,7 +156,6 @@ void FractoriumEmberController<T>::FillSummary()
|
||||
while (auto var = xform->GetVariation(i++))
|
||||
{
|
||||
auto vitem = new QTreeWidgetItem(item1);
|
||||
|
||||
vitem->setText(0, QString::fromStdString(var->Name()));
|
||||
vitem->setText(1, QLocale::system().toString(var->m_Weight, pc, vp).rightJustified(vlen, ' '));
|
||||
|
||||
@ -176,7 +168,6 @@ void FractoriumEmberController<T>::FillSummary()
|
||||
if (!params[j].IsPrecalc())
|
||||
{
|
||||
auto pitem = new QTreeWidgetItem(vitem);
|
||||
|
||||
pitem->setText(0, params[j].Name().c_str());
|
||||
pitem->setText(1, QLocale::system().toString(params[j].ParamVal(), pc, vp).rightJustified(vlen, ' '));
|
||||
}
|
||||
@ -229,19 +220,16 @@ void Fractorium::UpdateHistogramBounds()
|
||||
sprintf_s(m_LRString, 32, "LR: %3.3f, %3.3f", -r->LowerLeftX(), r->LowerLeftY());
|
||||
sprintf_s(m_LLString, 32, "LL: %3.3f, %3.3f", r->LowerLeftX(), r->LowerLeftY());
|
||||
sprintf_s(m_WHString, 32, "W x H: %4lu x %4lu", r->SuperRasW(), r->SuperRasH());
|
||||
|
||||
ui.InfoBoundsLabelUL->setText(QString(m_ULString));
|
||||
ui.InfoBoundsLabelUR->setText(QString(m_URString));
|
||||
ui.InfoBoundsLabelLR->setText(QString(m_LRString));
|
||||
ui.InfoBoundsLabelLL->setText(QString(m_LLString));
|
||||
ui.InfoBoundsLabelWH->setText(QString(m_WHString));
|
||||
|
||||
ui.InfoBoundsTable->item(0, 1)->setText(ToString<qulonglong>(r->GutterWidth()));
|
||||
|
||||
if (r->GetDensityFilter())
|
||||
{
|
||||
uint deWidth = (r->GetDensityFilter()->FilterWidth() * 2) + 1;
|
||||
|
||||
sprintf_s(m_DEString, 16, "%d x %d", deWidth, deWidth);
|
||||
ui.InfoBoundsTable->item(1, 1)->setText(QString(m_DEString));
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ void Fractorium::InitParamsUI()
|
||||
double dmax = numeric_limits<double>::max();
|
||||
vector<string> comboVals;
|
||||
QTableWidget* table = ui.ColorTable;
|
||||
|
||||
//Because QTableWidget does not allow for a single title bar/header
|
||||
//at the top of a multi-column table, the workaround hack is to just
|
||||
//make another single column table with no rows, and use the single
|
||||
@ -21,14 +20,12 @@ void Fractorium::InitParamsUI()
|
||||
SetFixedTableHeader(ui.GeometryTableHeader->horizontalHeader());
|
||||
SetFixedTableHeader(ui.FilterTableHeader->horizontalHeader());
|
||||
SetFixedTableHeader(ui.IterationTableHeader->horizontalHeader());
|
||||
|
||||
//Color.
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_BrightnessSpin, spinHeight, 0.05, 100, 1, SIGNAL(valueChanged(double)), SLOT(OnBrightnessChanged(double)), true, 4.0, 4.0, 4.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaSpin, spinHeight, 1, 9999, 0.5, SIGNAL(valueChanged(double)), SLOT(OnGammaChanged(double)), true, 4.0, 4.0, 4.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, 10, 0.01, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_VibrancySpin, spinHeight, 0, 30, 0.01, SIGNAL(valueChanged(double)), SLOT(OnVibrancyChanged(double)), true, 1.0, 1.0, 0.0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 2.0, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, -1.0, -1.0, -1.0);
|
||||
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, -1.0, -1.0, -1.0);
|
||||
m_GammaThresholdSpin->setDecimals(4);
|
||||
m_BackgroundColorButton = new QPushButton("...", table);
|
||||
m_BackgroundColorButton->setMinimumWidth(21);
|
||||
@ -37,11 +34,10 @@ void Fractorium::InitParamsUI()
|
||||
table->item(row, 1)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
connect(m_BackgroundColorButton, SIGNAL(clicked(bool)), this, SLOT(OnBackgroundColorButtonClicked(bool)), Qt::QueuedConnection);
|
||||
row++;
|
||||
|
||||
comboVals.push_back("Step");
|
||||
comboVals.push_back("Linear");
|
||||
SetupCombo(table, this, row, 1, m_PaletteModeCombo, comboVals, SIGNAL(currentIndexChanged(int)), SLOT(OnPaletteModeComboCurrentIndexChanged(int)));
|
||||
|
||||
m_PaletteModeCombo->SetCurrentIndexStealth(PALETTE_LINEAR);
|
||||
//Geometry.
|
||||
row = 0;
|
||||
table = ui.GeometryTable;
|
||||
@ -57,31 +53,24 @@ void Fractorium::InitParamsUI()
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_PitchSpin, spinHeight, -180, 180, 1, SIGNAL(valueChanged(double)), SLOT(OnPitchChanged(double)), true, 0, 45, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_YawSpin, spinHeight, -180, 180, 1, SIGNAL(valueChanged(double)), SLOT(OnYawChanged(double)), true, 0, 45, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DepthBlurSpin, spinHeight, -100, 100, 0.01, SIGNAL(valueChanged(double)), SLOT(OnDepthBlurChanged(double)), true, 0, 1, 0);
|
||||
|
||||
//Set w/h max values.
|
||||
m_CenterXSpin->setDecimals(3);
|
||||
m_CenterYSpin->setDecimals(3);
|
||||
m_ZPosSpin->setDecimals(3);
|
||||
m_PerspectiveSpin->setDecimals(4);
|
||||
m_DepthBlurSpin->setDecimals(3);
|
||||
|
||||
//Filter.
|
||||
row = 0;
|
||||
table = ui.FilterTable;
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_SpatialFilterWidthSpin, spinHeight, 0.1, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnSpatialFilterWidthChanged(double)), true, 1.0, 1.0, 1.0);
|
||||
|
||||
comboVals = SpatialFilterCreator<float>::FilterTypes();
|
||||
SetupCombo(table, this, row, 1, m_SpatialFilterTypeCombo, comboVals, SIGNAL(currentIndexChanged(const QString&)), SLOT(OnSpatialFilterTypeComboCurrentIndexChanged(const QString&)));
|
||||
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_TemporalFilterWidthSpin, spinHeight, 1, 10, 1, SIGNAL(valueChanged(double)), SLOT(OnTemporalFilterWidthChanged(double)), true, 1);
|
||||
|
||||
comboVals = TemporalFilterCreator<float>::FilterTypes();
|
||||
SetupCombo(table, this, row, 1, m_TemporalFilterTypeCombo, comboVals, SIGNAL(currentIndexChanged(const QString&)), SLOT(OnTemporalFilterTypeComboCurrentIndexChanged(const QString&)));
|
||||
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DEFilterMinRadiusSpin, spinHeight, 0, 25, 1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterMinRadiusWidthChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DEFilterMaxRadiusSpin, spinHeight, 0, 25, 1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterMaxRadiusWidthChanged(double)), true, 0.0, 9.0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DECurveSpin, spinHeight, 0.15, 5, 0.1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterCurveWidthChanged(double)), true, 0.4, 0.4, 0.4);
|
||||
|
||||
//Iteration.
|
||||
row = 0;
|
||||
table = ui.IterationTable;
|
||||
@ -90,12 +79,10 @@ void Fractorium::InitParamsUI()
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, 10, 10, 10);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 1, 1, 1);
|
||||
SetupSpinner<SpinBox, int>( table, this, row, 1, m_TemporalSamplesSpin, spinHeight, 1, 5000, 1, SIGNAL(valueChanged(int)), SLOT(OnTemporalSamplesChanged(int)), true, 1000);
|
||||
|
||||
comboVals.clear();
|
||||
comboVals.push_back("Step");
|
||||
comboVals.push_back("Linear");
|
||||
SetupCombo(table, this, row, 1, m_AffineInterpTypeCombo, comboVals, SIGNAL(currentIndexChanged(int)), SLOT(OnAffineInterpTypeComboCurrentIndexChanged(int)));
|
||||
|
||||
comboVals.clear();
|
||||
comboVals.push_back("Linear");
|
||||
comboVals.push_back("Smooth");
|
||||
@ -277,10 +264,10 @@ void Fractorium::OnZPosChanged(double d) { m_Controller->ZPosChanged(d); }
|
||||
template <typename T> void FractoriumEmberController<T>::PerspectiveChanged(double d) { Update([&] { m_Ember.m_CamPerspective = d; }); }
|
||||
void Fractorium::OnPerspectiveChanged(double d) { m_Controller->PerspectiveChanged(d); }
|
||||
|
||||
template <typename T> void FractoriumEmberController<T>::PitchChanged(double d) { Update([&] { m_Ember.m_CamPitch = d * DEG_2_RAD; }); }
|
||||
template <typename T> void FractoriumEmberController<T>::PitchChanged(double d) { Update([&] { m_Ember.m_CamPitch = d* DEG_2_RAD; }); }
|
||||
void Fractorium::OnPitchChanged(double d) { m_Controller->PitchChanged(d); }
|
||||
|
||||
template <typename T> void FractoriumEmberController<T>::YawChanged(double d) { Update([&] { m_Ember.m_CamYaw = d * DEG_2_RAD; }); }
|
||||
template <typename T> void FractoriumEmberController<T>::YawChanged(double d) { Update([&] { m_Ember.m_CamYaw = d* DEG_2_RAD; }); }
|
||||
void Fractorium::OnYawChanged(double d) { m_Controller->YawChanged(d); }
|
||||
|
||||
template <typename T> void FractoriumEmberController<T>::DepthBlurChanged(double d) { Update([&] { m_Ember.m_CamDepthBlur = d; }); }
|
||||
@ -408,7 +395,7 @@ void Fractorium::OnFuseChanged(int d) { m_Controller->FuseChanged(d); }
|
||||
/// 20-50 is good for OpenCL.
|
||||
/// Above 500 seems to offer little additional value for final renders.
|
||||
/// Called when the quality spinner is changed.
|
||||
/// If rendering is done, and the value is greater than the last value,
|
||||
/// If rendering is done, and the value is greater than the last value,
|
||||
/// the rendering process is continued, else it's reset.
|
||||
/// </summary>
|
||||
/// <param name="d">The quality in terms of iterations per pixel</param>
|
||||
@ -545,20 +532,17 @@ void FractoriumEmberController<T>::FillParamTablesAndPalette()
|
||||
m_Fractorium->m_TemporalSamplesSpin->SetValueStealth(m_Ember.m_TemporalSamples);
|
||||
m_Fractorium->m_AffineInterpTypeCombo->SetCurrentIndexStealth(m_Ember.m_AffineInterp);
|
||||
m_Fractorium->m_InterpTypeCombo->SetCurrentIndexStealth(m_Ember.m_Interp);
|
||||
|
||||
//Palette related items:
|
||||
//The temp palette is assigned the palette read when the file was parsed/saved. The user can apply adjustments on the GUI later.
|
||||
//These adjustments will be applied to the temp palette, then assigned back to m_Ember.m_Palette.
|
||||
//Normally, the temp palette is assigned whenever the user clicks on a palette cell. But since this is not
|
||||
//called in response to that event, it is skipped here so must do it manually.
|
||||
m_TempPalette = m_Ember.m_Palette;
|
||||
|
||||
//Palette controls are reset on each ember load. This means that if the palette was adjusted, saved, the selected ember
|
||||
//changed to another, then back, the previously adjusted palette will now be considered the base, and all adjustments set to 0.
|
||||
//To fix this, the caller must preserve the temp palette and the adjustment values and reassign. See Fractorium::CreateControllerFromOptions()
|
||||
//for an example.
|
||||
m_Fractorium->ResetPaletteControls();
|
||||
|
||||
auto temp = m_Ember.m_Palette.m_Filename;
|
||||
|
||||
if (temp.get())
|
||||
@ -578,7 +562,6 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::ParamsToEmber(Ember<T>& ember)
|
||||
{
|
||||
QColor 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();
|
||||
@ -614,7 +597,6 @@ void FractoriumEmberController<T>::ParamsToEmber(Ember<T>& ember)
|
||||
ember.m_TemporalSamples = m_Fractorium->m_TemporalSamplesSpin->value();
|
||||
ember.m_AffineInterp = eAffineInterp(m_Fractorium->m_AffineInterpTypeCombo->currentIndex());
|
||||
ember.m_Interp = eInterp(m_Fractorium->m_InterpTypeCombo->currentIndex());
|
||||
|
||||
ember.SyncSize();
|
||||
}
|
||||
|
||||
@ -648,5 +630,5 @@ void Fractorium::SetScale(double scale)
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
||||
|
@ -69,7 +69,7 @@ void FractoriumEmberControllerBase::Shutdown()
|
||||
StopRenderTimer(true);
|
||||
ClearFinalImages();
|
||||
|
||||
while(m_Fractorium->ui.GLDisplay->Drawing())
|
||||
while (m_Fractorium->ui.GLDisplay->Drawing())
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, c
|
||||
QFileInfo fileInfo(filename);
|
||||
QString suffix = fileInfo.suffix();
|
||||
FractoriumSettings* settings = m_Fractorium->m_Settings;
|
||||
|
||||
|
||||
//Ensure dimensions are valid.
|
||||
if (pixels.size() < (width * height * channels * bpc))
|
||||
{
|
||||
@ -145,14 +145,13 @@ void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, c
|
||||
}
|
||||
|
||||
data = pixels.data();//Png and channels == 4.
|
||||
|
||||
|
||||
if ((suffix == "jpg" || suffix == "bmp") && channels)
|
||||
{
|
||||
RgbaToRgb(pixels, vecRgb, width, height);
|
||||
|
||||
data = vecRgb.data();
|
||||
}
|
||||
|
||||
|
||||
string s = filename.toStdString();
|
||||
string id = settings->Id().toStdString();
|
||||
string url = settings->Url().toStdString();
|
||||
@ -207,7 +206,7 @@ eProcessAction FractoriumEmberControllerBase::CondenseAndClearProcessActions()
|
||||
for (auto a : m_ProcessActions)
|
||||
if (a > action)
|
||||
action = a;
|
||||
|
||||
|
||||
m_ProcessActions.clear();
|
||||
m_Cs.Leave();
|
||||
return action;
|
||||
@ -226,7 +225,6 @@ template <typename T>
|
||||
int FractoriumEmberController<T>::ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs)
|
||||
{
|
||||
QString status;
|
||||
|
||||
m_Fractorium->m_ProgressBar->setValue(int(fraction));//Only really applies to iter and filter, because final accum only gives progress 0 and 100.
|
||||
|
||||
if (stage == 0)
|
||||
@ -297,12 +295,10 @@ template <typename T>
|
||||
bool FractoriumEmberController<T>::Render()
|
||||
{
|
||||
m_Rendering = true;
|
||||
|
||||
bool success = true;
|
||||
GLWidget* gl = m_Fractorium->ui.GLDisplay;
|
||||
RendererCL<T, float>* rendererCL = nullptr;
|
||||
eProcessAction qualityAction, action;
|
||||
|
||||
//Quality is the only parameter we update inside the timer.
|
||||
//This is to allow the user to rapidly increase the quality spinner
|
||||
//without fully resetting the render. Instead, it will just keep iterating
|
||||
@ -411,7 +407,6 @@ bool FractoriumEmberController<T>::Render()
|
||||
QString iters = ToString<qulonglong>(stats.m_Iters);
|
||||
QString scaledQuality = ToString(uint(m_Renderer->ScaledQuality()));
|
||||
string renderTime = m_RenderElapsedTimer.Format(m_RenderElapsedTimer.Toc());
|
||||
|
||||
m_Fractorium->m_ProgressBar->setValue(100);
|
||||
|
||||
//Only certain stats can be reported with OpenCL.
|
||||
@ -424,10 +419,9 @@ bool FractoriumEmberController<T>::Render()
|
||||
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);
|
||||
|
||||
m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Bad values: " + badVals + " (" + badPercent + "%). Total time: " + QString::fromStdString(renderTime) + ".");
|
||||
}
|
||||
|
||||
|
||||
if (m_LastEditWasUndoRedo && (m_UndoIndex == m_UndoList.size() - 1))//Traversing through undo list, reached the end, so put back in regular edit mode.
|
||||
{
|
||||
m_EditState = REGULAR_EDIT;
|
||||
@ -445,7 +439,6 @@ bool FractoriumEmberController<T>::Render()
|
||||
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.
|
||||
{
|
||||
Ember<T> ember(m_UndoList[m_UndoIndex]);
|
||||
|
||||
ClearUndo();
|
||||
m_UndoList.push_back(ember);
|
||||
m_UndoList.push_back(m_Ember);
|
||||
@ -458,15 +451,15 @@ bool FractoriumEmberController<T>::Render()
|
||||
m_Fractorium->UpdateHistogramBounds();//Mostly of engineering interest.
|
||||
FillSummary();//Only update summary on render completion since it's not the type of thing the user needs real-time updates on.
|
||||
}
|
||||
|
||||
|
||||
//Update the GL window on start because the output will be forced.
|
||||
//Update it on finish because the rendering process is completely done.
|
||||
if (iterBegin || ProcessState() == ACCUM_DONE)
|
||||
{
|
||||
if (m_FinalImage.size() == m_Renderer->FinalBufferSize())//Make absolutely sure the correct amount of data is passed.
|
||||
gl->update();
|
||||
//gl->repaint();
|
||||
|
||||
|
||||
//gl->repaint();
|
||||
//m_Fractorium->update();
|
||||
//m_Fractorium->ui.GLParentScrollArea->update();
|
||||
//Uncomment for debugging kernel build and execution errors.
|
||||
@ -482,13 +475,12 @@ bool FractoriumEmberController<T>::Render()
|
||||
else//Something went very wrong, show error report.
|
||||
{
|
||||
vector<string> errors = m_Renderer->ErrorReport();
|
||||
|
||||
success = false;
|
||||
m_FailedRenders++;
|
||||
m_Fractorium->m_RenderStatusLabel->setText("Rendering failed, see info tab. Try changing parameters.");
|
||||
m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoRenderingTextEdit);
|
||||
m_Renderer->ClearErrorReport();
|
||||
|
||||
|
||||
if (m_FailedRenders >= 3)
|
||||
{
|
||||
m_Rendering = false;
|
||||
@ -500,19 +492,18 @@ bool FractoriumEmberController<T>::Render()
|
||||
if (rendererCL)
|
||||
{
|
||||
//string s = "OpenCL Kernels: \r\n" + rendererCL->IterKernel() + "\r\n" + rendererCL->DEKernel() + "\r\n" + rendererCL->FinalAccumKernel();
|
||||
|
||||
rendererCL->ClearFinal();
|
||||
//QMetaObject::invokeMethod(m_Fractorium->ui.InfoRenderingTextEdit, "setText", Qt::QueuedConnection, Q_ARG(const QString&, QString::fromStdString(s)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Upon finishing, or having nothing to do, rest.
|
||||
if (ProcessState() == ACCUM_DONE)
|
||||
QThread::msleep(1);
|
||||
//QApplication::processEvents();
|
||||
|
||||
//QApplication::processEvents();
|
||||
m_Rendering = false;
|
||||
return success;
|
||||
}
|
||||
@ -536,7 +527,6 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
{
|
||||
EmberReport emberReport;
|
||||
vector<string> errorReport;
|
||||
|
||||
DeleteRenderer();//Delete the renderer and refresh the textures.
|
||||
//Before starting, must take care of allocations.
|
||||
gl->Allocate(true);//Forcing a realloc of the texture is necessary on AMD, but not on nVidia.
|
||||
@ -564,7 +554,6 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
if (m_RenderType == OPENCL_RENDERER)
|
||||
{
|
||||
auto val = 30 * m_Fractorium->m_Settings->Devices().size();
|
||||
|
||||
m_Fractorium->m_QualitySpin->DoubleClickZero(val);
|
||||
m_Fractorium->m_QualitySpin->DoubleClickNonZero(val);
|
||||
|
||||
@ -588,14 +577,14 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
m_Renderer->YAxisUp(s->YAxisUp());
|
||||
m_Renderer->ThreadCount(s->ThreadCount());
|
||||
m_Renderer->Transparency(s->Transparency());
|
||||
|
||||
|
||||
if (m_Renderer->RendererType() == CPU_RENDERER)
|
||||
m_Renderer->InteractiveFilter(s->CpuDEFilter() ? FILTER_DE : FILTER_LOG);
|
||||
else
|
||||
m_Renderer->InteractiveFilter(s->OpenCLDEFilter() ? FILTER_DE : FILTER_LOG);
|
||||
|
||||
if ((m_Renderer->EarlyClip() != m_PreviewRenderer->EarlyClip()) ||
|
||||
(m_Renderer->YAxisUp() != m_PreviewRenderer->YAxisUp()))
|
||||
(m_Renderer->YAxisUp() != m_PreviewRenderer->YAxisUp()))
|
||||
{
|
||||
StopPreviewRender();
|
||||
m_PreviewRenderer->EarlyClip(m_Renderer->EarlyClip());
|
||||
@ -635,9 +624,9 @@ void Fractorium::ShutdownAndRecreateFromOptions()
|
||||
bool Fractorium::CreateRendererFromOptions()
|
||||
{
|
||||
bool ok = true;
|
||||
bool useOpenCL = m_Info.Ok() && m_Settings->OpenCL();
|
||||
bool useOpenCL = m_Info->Ok() && m_Settings->OpenCL();
|
||||
auto v = Devices(m_Settings->Devices());
|
||||
|
||||
|
||||
//The most important option to process is what kind of renderer is desired, so do it first.
|
||||
if (!m_Controller->CreateRenderer((useOpenCL && !v.empty()) ? OPENCL_RENDERER : CPU_RENDERER, v))
|
||||
{
|
||||
@ -660,13 +649,12 @@ bool Fractorium::CreateRendererFromOptions()
|
||||
bool Fractorium::CreateControllerFromOptions()
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
size_t elementSize =
|
||||
#ifdef DO_DOUBLE
|
||||
m_Settings->Double() ? sizeof(double) :
|
||||
#endif
|
||||
sizeof(float);
|
||||
|
||||
|
||||
if (!m_Controller.get() || (m_Controller->SizeOfT() != elementSize))
|
||||
{
|
||||
double hue = m_PaletteHueSpin->value();
|
||||
@ -690,11 +678,9 @@ bool Fractorium::CreateControllerFromOptions()
|
||||
if (m_Controller.get())
|
||||
{
|
||||
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);
|
||||
//m_Controller->CopyEmberFile(efd);
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
m_Controller->CopyEmber(ed, [&](Ember<double>& ember) { });
|
||||
m_Controller->CopyEmberFile(efd, [&](Ember<double>& ember) { });
|
||||
@ -706,6 +692,7 @@ bool Fractorium::CreateControllerFromOptions()
|
||||
}
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
|
||||
if (m_Settings->Double())
|
||||
m_Controller = unique_ptr<FractoriumEmberControllerBase>(new FractoriumEmberController<double>(this));
|
||||
else
|
||||
@ -718,7 +705,6 @@ bool Fractorium::CreateControllerFromOptions()
|
||||
ed.m_Palette = tempPalette;//Restore base temp palette. Adjustments will be then be applied and stored back in in m_Ember.m_Palette below.
|
||||
m_Controller->SetEmber(ed);//Convert float to double or set double verbatim. This will assign m_Ember.m_Palette (which was just tempPalette) to m_TempPalette.
|
||||
m_Controller->SetEmberFile(efd);
|
||||
|
||||
//Setting these and updating the GUI overwrites the work of clearing them done in SetEmber() above.
|
||||
//It's a corner case, but doesn't seem to matter.
|
||||
m_PaletteHueSpin->SetValueStealth(hue);
|
||||
@ -728,7 +714,6 @@ bool Fractorium::CreateControllerFromOptions()
|
||||
m_PaletteBlurSpin->SetValueStealth(blur);
|
||||
m_PaletteFrequencySpin->SetValueStealth(freq);
|
||||
m_Controller->PaletteAdjust();//Applies the adjustments to temp and saves in m_Ember.m_Palette, then fills in the palette preview widget.
|
||||
|
||||
//Template specific palette table and variations tree setup in controller constructor, but
|
||||
//must manually setup the library tree here because it's after the embers were assigned.
|
||||
//Passing row re-selects the item that was previously selected.
|
||||
@ -775,5 +760,5 @@ bool Fractorium::ControllersOk() { return m_Controller.get() && m_Controller->GL
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
||||
|
@ -10,11 +10,9 @@ void Fractorium::InitToolbarUI()
|
||||
auto clGroup = new QActionGroup(this);
|
||||
clGroup->addAction(ui.ActionCpu);
|
||||
clGroup->addAction(ui.ActionCL);
|
||||
|
||||
auto spGroup = new QActionGroup(this);
|
||||
spGroup->addAction(ui.ActionSP);
|
||||
spGroup->addAction(ui.ActionDP);
|
||||
|
||||
SyncOptionsToToolbar();
|
||||
connect(ui.ActionCpu, SIGNAL(triggered(bool)), this, SLOT(OnActionCpu(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionCL, SIGNAL(triggered(bool)), this, SLOT(OnActionCL(bool)), Qt::QueuedConnection);
|
||||
@ -90,7 +88,7 @@ void Fractorium::OnActionStyle(bool checked)
|
||||
/// </summary>
|
||||
void Fractorium::SyncOptionsToToolbar()
|
||||
{
|
||||
static bool openCL = !OpenCLInfo::Instance().Devices().empty();
|
||||
static bool openCL = !m_Info->Devices().empty();
|
||||
|
||||
if (!openCL)
|
||||
{
|
||||
|
@ -9,36 +9,30 @@
|
||||
/// <param name="p">The parent widget. Default: nullptr.</param>
|
||||
/// <param name="f">The window flags. Default: 0.</param>
|
||||
FractoriumOptionsDialog::FractoriumOptionsDialog(FractoriumSettings* settings, QWidget* p, Qt::WindowFlags f)
|
||||
: QDialog(p, f),
|
||||
m_Info(OpenCLInfo::Instance())
|
||||
: QDialog(p, f)
|
||||
{
|
||||
int i, row = 0, spinHeight = 20;
|
||||
|
||||
ui.setupUi(this);
|
||||
m_Settings = settings;
|
||||
m_Info = OpenCLInfo::Instance();
|
||||
QTableWidget* table = ui.OptionsXmlSavingTable;
|
||||
ui.ThreadCountSpin->setRange(1, Timing::ProcessorCount());
|
||||
connect(ui.OpenCLCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnOpenCLCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.DeviceTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnDeviceTableCellChanged(int, int)), Qt::QueuedConnection);
|
||||
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 1, m_XmlTemporalSamplesSpin, spinHeight, 1, 1000, 100, "", "", true, 1000);
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 1, m_XmlQualitySpin, spinHeight, 1, 200000, 50, "", "", true, 1000);
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 1, m_XmlSupersampleSpin, spinHeight, 1, 4, 1, "", "", true, 2);
|
||||
|
||||
m_IdEdit = new QLineEdit(ui.OptionsIdentityTable);
|
||||
ui.OptionsIdentityTable->setCellWidget(0, 1, m_IdEdit);
|
||||
|
||||
m_UrlEdit = new QLineEdit(ui.OptionsIdentityTable);
|
||||
ui.OptionsIdentityTable->setCellWidget(1, 1, m_UrlEdit);
|
||||
|
||||
m_NickEdit = new QLineEdit(ui.OptionsIdentityTable);
|
||||
ui.OptionsIdentityTable->setCellWidget(2, 1, m_NickEdit);
|
||||
|
||||
table = ui.DeviceTable;
|
||||
table->clearContents();
|
||||
table->setRowCount(0);
|
||||
|
||||
if (m_Info.Ok() && !m_Info.Devices().empty())
|
||||
if (m_Info->Ok() && !m_Info->Devices().empty())
|
||||
{
|
||||
SetupDeviceTable(table, m_Settings->Devices());
|
||||
|
||||
@ -122,7 +116,6 @@ void FractoriumOptionsDialog::OnDeviceTableRadioToggled(bool checked)
|
||||
void FractoriumOptionsDialog::OnOpenCLCheckBoxStateChanged(int state)
|
||||
{
|
||||
bool checked = state == Qt::Checked;
|
||||
|
||||
ui.DeviceTable->setEnabled(checked);
|
||||
ui.ThreadCountSpin->setEnabled(!checked);
|
||||
ui.CpuSubBatchSpin->setEnabled(!checked);
|
||||
@ -186,13 +179,11 @@ void FractoriumOptionsDialog::GuiToData()
|
||||
m_Settings->CpuDEFilter(ui.CpuFilteringDERadioButton->isChecked());
|
||||
m_Settings->OpenCLDEFilter(ui.OpenCLFilteringDERadioButton->isChecked());
|
||||
m_Settings->Devices(DeviceTableToSettings(ui.DeviceTable));
|
||||
|
||||
//Xml saving.
|
||||
m_Settings->XmlTemporalSamples(m_XmlTemporalSamplesSpin->value());
|
||||
m_Settings->XmlQuality(m_XmlQualitySpin->value());
|
||||
m_Settings->XmlSupersample(m_XmlSupersampleSpin->value());
|
||||
m_Settings->SaveAutoUnique(AutoUnique());
|
||||
|
||||
//Identity.
|
||||
m_Settings->Id(m_IdEdit->text());
|
||||
m_Settings->Url(m_UrlEdit->text());
|
||||
@ -206,7 +197,6 @@ void FractoriumOptionsDialog::DataToGui()
|
||||
{
|
||||
//Interactive rendering.
|
||||
auto devices = m_Settings->Devices();
|
||||
|
||||
ui.EarlyClipCheckBox->setChecked(m_Settings->EarlyClip());
|
||||
ui.YAxisUpCheckBox->setChecked(m_Settings->YAxisUp());
|
||||
ui.TransparencyCheckBox->setChecked(m_Settings->Transparency());
|
||||
@ -235,7 +225,6 @@ void FractoriumOptionsDialog::DataToGui()
|
||||
m_XmlQualitySpin->setValue(m_Settings->XmlQuality());
|
||||
m_XmlSupersampleSpin->setValue(m_Settings->XmlSupersample());
|
||||
ui.AutoUniqueCheckBox->setChecked(m_Settings->SaveAutoUnique());
|
||||
|
||||
//Identity.
|
||||
m_IdEdit->setText(m_Settings->Id());
|
||||
m_UrlEdit->setText(m_Settings->Url());
|
||||
|
@ -52,7 +52,7 @@ private:
|
||||
void GuiToData();
|
||||
|
||||
Ui::OptionsDialog ui;
|
||||
OpenCLInfo& m_Info;
|
||||
shared_ptr<OpenCLInfo> m_Info;
|
||||
SpinBox* m_XmlTemporalSamplesSpin;
|
||||
SpinBox* m_XmlQualitySpin;
|
||||
SpinBox* m_XmlSupersampleSpin;
|
||||
|
Reference in New Issue
Block a user