--User changes

-Add toolbar buttons to switch some rendering options without having to open the options dialog.

--Bug fixes
 -Only update summary on render completion, no need to constantly update it.
 -Properly handle cancel even on variations dialog.

--Code changes
 -Add small function ShutdownAndRecreateFromOptions() to wrap shutting down the timer and recreating the renderer.
 -Use the overridden accept() and reject() functions more consistently across dialogs.
This commit is contained in:
mfeemster 2015-07-29 17:25:02 -07:00
parent e16c6a825f
commit 2317be332a
12 changed files with 268 additions and 76 deletions

View File

@ -145,6 +145,10 @@ public slots:
void OnActionAbout(bool checked);//Help.
//Toolbar.
void OnActionCpu(bool checked);
void OnActionCL(bool checked);
void OnActionSP(bool checked);
void OnActionDP(bool checked);
//Library.
void OnEmberTreeItemChanged(QTreeWidgetItem* item, int col);
@ -324,6 +328,9 @@ private:
//Embers.
bool HaveFinal();
//Toolbar.
void SyncOptionsToToolbar();
//Library.
pair<size_t, QTreeWidgetItem*> GetCurrentEmberIndex();
@ -358,6 +365,7 @@ private:
void SetTableWidgetBackgroundColor();
//Rendering/progress.
void ShutdownAndRecreateFromOptions();
bool CreateRendererFromOptions();
bool CreateControllerFromOptions();

View File

@ -6196,9 +6196,12 @@ SpinBox
<addaction name="ActionStopRenderingPreviews"/>
<addaction name="ActionFinalRender"/>
<addaction name="separator"/>
<addaction name="ActionOptions"/>
<addaction name="separator"/>
<addaction name="ActionVariationsDialog"/>
<addaction name="ActionCpu"/>
<addaction name="ActionCL"/>
<addaction name="ActionSP"/>
<addaction name="ActionDP"/>
<addaction name="ActionOptions"/>
</widget>
<action name="ActionNewFlock">
<property name="icon">
@ -6541,6 +6544,50 @@ SpinBox
<string>Show variations filter window</string>
</property>
</action>
<action name="ActionCpu">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>CPU</string>
</property>
<property name="toolTip">
<string>Use CPU to render</string>
</property>
</action>
<action name="ActionCL">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>CL</string>
</property>
<property name="toolTip">
<string>Use OpenCL to render</string>
</property>
</action>
<action name="ActionSP">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>SP</string>
</property>
<property name="toolTip">
<string>Use single precision to render</string>
</property>
</action>
<action name="ActionDP">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>DP</string>
</property>
<property name="toolTip">
<string>Use DP to render</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

View File

@ -217,7 +217,6 @@ template <typename T>
void FractoriumEmberController<T>::Update(std::function<void (void)> func, bool updateRender, eProcessAction action)
{
func();
FillSummary();
if (updateRender)
UpdateRender(action);
@ -295,8 +294,6 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
break;
}
FillSummary();
if (updateRender)
UpdateRender(action);
}
@ -339,7 +336,6 @@ void FractoriumEmberController<T>::SetEmberPrivate(const Ember<U>& ember, bool v
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.

View File

@ -228,7 +228,6 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
}
tree->blockSignals(false);
FillSummary();
}
else if (auto parentItem = dynamic_cast<QTreeWidgetItem*>(item))
{

View File

@ -844,10 +844,8 @@ void Fractorium::OnActionOptions(bool checked)
{
if (m_OptionsDialog->exec())
{
//First completely stop what the current rendering process is doing.
m_Controller->Shutdown();
StartRenderTimer();//This will recreate the controller and/or the renderer from the options if necessary, then start the render timer.
m_Settings->sync();
SyncOptionsToToolbar();//This won't trigger a recreate, the call below handles it.
ShutdownAndRecreateFromOptions();//This will recreate the controller and/or the renderer from the options if necessary, then start the render timer.
}
}

View File

@ -396,7 +396,7 @@ bool FractoriumEmberController<T>::Render()
m_Fractorium->m_ProgressBar->setValue(100);
//Only certain status can be reported with OpenCL.
//Only certain stats can be reported with OpenCL.
if (m_Renderer->RendererType() == OPENCL_RENDERER)
{
m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Total time: " + QString::fromStdString(renderTime));
@ -438,6 +438,7 @@ bool FractoriumEmberController<T>::Render()
m_LastEditWasUndoRedo = false;
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.
@ -599,6 +600,17 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, uint
return ok;
}
/// <summary>
/// Wrapper to stop the timer, shutdown the controller and recreate, then restart the controller and renderer from the options.
/// </summary>
void Fractorium::ShutdownAndRecreateFromOptions()
{
//First completely stop what the current rendering process is doing.
m_Controller->Shutdown();
StartRenderTimer();//This will recreate the controller and/or the renderer from the options if necessary, then start the render timer.
m_Settings->sync();
}
/// <summary>
/// Create a new renderer from the options.
/// </summary>

View File

@ -6,5 +6,98 @@
/// </summary>
void Fractorium::InitToolbarUI()
{
//Empty for the moment, all functionality is handled in the designer.
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);//Need to sync these with options dialog.//TODO
connect(ui.ActionCL, SIGNAL(triggered(bool)), this, SLOT(OnActionCL(bool)), Qt::QueuedConnection);
connect(ui.ActionSP, SIGNAL(triggered(bool)), this, SLOT(OnActionSP(bool)), Qt::QueuedConnection);
connect(ui.ActionDP, SIGNAL(triggered(bool)), this, SLOT(OnActionDP(bool)), Qt::QueuedConnection);
}
/// <summary>
/// Called when the CPU render option on the toolbar is clicked.
/// </summary>
/// <param name="checked">Check state, action only taken if true.</param>
void Fractorium::OnActionCpu(bool checked)
{
if (checked && m_Settings->OpenCL())
{
m_Settings->OpenCL(false);
ShutdownAndRecreateFromOptions();
}
}
/// <summary>
/// Called when the OpenCL render option on the toolbar is clicked.
/// </summary>
/// <param name="checked">Check state, action only taken if true.</param>
void Fractorium::OnActionCL(bool checked)
{
if (checked && !m_Settings->OpenCL())
{
m_Settings->OpenCL(true);
ShutdownAndRecreateFromOptions();
}
}
/// <summary>
/// Called when the single precision render option on the toolbar is clicked.
/// </summary>
/// <param name="checked">Check state, action only taken if true.</param>
void Fractorium::OnActionSP(bool checked)
{
if (checked && m_Settings->Double())
{
m_Settings->Double(false);
ShutdownAndRecreateFromOptions();
}
}
/// <summary>
/// Called when the double precision render option on the toolbar is clicked.
/// </summary>
/// <param name="checked">Check state, action only taken if true.</param>
void Fractorium::OnActionDP(bool checked)
{
if (checked && !m_Settings->Double())
{
m_Settings->Double(true);
ShutdownAndRecreateFromOptions();
}
}
/// <summary>
/// Sync options data to the check state of the toolbar buttons.
/// This does not trigger a clicked() event.
/// </summary>
void Fractorium::SyncOptionsToToolbar()
{
if (m_Settings->OpenCL())
{
ui.ActionCpu->setChecked(false);
ui.ActionCL->setChecked(true);
}
else
{
ui.ActionCpu->setChecked(true);
ui.ActionCL->setChecked(false);
}
if (m_Settings->Double())
{
ui.ActionSP->setChecked(false);
ui.ActionDP->setChecked(true);
}
else
{
ui.ActionSP->setChecked(true);
ui.ActionDP->setChecked(false);
}
}

View File

@ -209,7 +209,6 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
{
if (xformParVar->SetParamVal(sender->ParamName().c_str(), d))
{
FillSummary();
UpdateRender();
}
}
@ -263,7 +262,6 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
}
}
FillSummary();
UpdateRender();
}
}

View File

@ -149,6 +149,35 @@ void FractoriumOptionsDialog::OnPlatformComboCurrentIndexChanged(int index)
/// Not called if cancelled or closed with the X.
/// </summary>
void FractoriumOptionsDialog::accept()
{
GuiToData();
QDialog::accept();
}
/// <summary>
/// Restore all GUI items to what was originally in the settings object.
/// Called when the user clicks cancel or closes with the X.
/// </summary>
void FractoriumOptionsDialog::reject()
{
DataToGui();
QDialog::reject();
}
/// <summary>
/// Copy the state of the map to the checkboxes and show the dialog.
/// </summary>
/// <param name="e">Event, passed to base.</param>
void FractoriumOptionsDialog::showEvent(QShowEvent* e)
{
DataToGui();
QDialog::showEvent(e);
}
/// <summary>
/// Copy the state of the Gui to the settings object.
/// </summary>
void FractoriumOptionsDialog::GuiToData()
{
//Interactive rendering.
m_Settings->EarlyClip(EarlyClip());
@ -176,15 +205,12 @@ void FractoriumOptionsDialog::accept()
m_Settings->Id(m_IdEdit->text());
m_Settings->Url(m_UrlEdit->text());
m_Settings->Nick(m_NickEdit->text());
QDialog::accept();
}
/// <summary>
/// Restore all GUI items to what was originally in the settings object.
/// Called when the user clicks cancel or closes with the X.
/// Copy the state of the settings object to the Gui.
/// </summary>
void FractoriumOptionsDialog::reject()
void FractoriumOptionsDialog::DataToGui()
{
//Interactive rendering.
ui.EarlyClipCheckBox->setChecked(m_Settings->EarlyClip());
@ -212,6 +238,4 @@ void FractoriumOptionsDialog::reject()
m_IdEdit->setText(m_Settings->Id());
m_UrlEdit->setText(m_Settings->Url());
m_NickEdit->setText(m_Settings->Nick());
QDialog::reject();
}
}

View File

@ -32,6 +32,9 @@ public slots:
virtual void accept() override;
virtual void reject() override;
protected:
virtual void showEvent(QShowEvent* e) override;
private:
bool EarlyClip();
bool YAxisUp();
@ -45,6 +48,8 @@ private:
uint PlatformIndex();
uint DeviceIndex();
uint ThreadCount();
void DataToGui();
void GuiToData();
Ui::OptionsDialog ui;
OpenCLWrapper m_Wrapper;

View File

@ -26,23 +26,6 @@ FractoriumVariationsDialog::FractoriumVariationsDialog(FractoriumSettings* setti
connect(ui.SelectAllButton, SIGNAL(clicked(bool)), this, SLOT(OnSelectAllButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.InvertSelectionButton, SIGNAL(clicked(bool)), this, SLOT(OnInvertSelectionButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.SelectNoneButton, SIGNAL(clicked(bool)), this, SLOT(OnSelectNoneButtonClicked(bool)), Qt::QueuedConnection);
connect(ui.ButtonBox, SIGNAL(accepted()), this, SLOT(Accept()));
}
/// <summary>
/// Copy the values of the checkboxes to the map.
/// </summary>
void FractoriumVariationsDialog::SyncSettings()
{
QMap<QString, QVariant> m;
ForEachCell([&](QTableWidgetItem* cb)
{
if (!cb->text().isEmpty())
m[cb->text()] = cb->checkState() == Qt::CheckState::Checked;
});
m_Settings->Variations(m);
}
/// <summary>
@ -85,6 +68,32 @@ void FractoriumVariationsDialog::ForEachSelectedCell(std::function<void(QTableWi
table->model()->layoutChanged();
}
/// <summary>
/// Copy the values of the checkboxes to the map.
/// </summary>
void FractoriumVariationsDialog::SyncSettings()
{
QMap<QString, QVariant> m;
ForEachCell([&](QTableWidgetItem* cb)
{
if (!cb->text().isEmpty())
m[cb->text()] = cb->checkState() == Qt::CheckState::Checked;
});
m_Settings->Variations(m);
}
/// <summary>
/// Return a const reference to the map.
/// This will contains the state of the checkboxes after
/// the user clicks ok.
/// </summary>
const QMap<QString, QVariant>& FractoriumVariationsDialog::Map()
{
return m_Vars;
}
/// <summary>
/// Check all of the checkboxes.
/// </summary>
@ -172,19 +181,21 @@ void FractoriumVariationsDialog::OnVariationsTableItemChanged(QTableWidgetItem*
/// Called when the user clicks ok.
/// Copy the state of the checkboxes to the map.
/// </summary>
void FractoriumVariationsDialog::Accept()
void FractoriumVariationsDialog::accept()
{
CheckBoxesToMap();
GuiToData();
QDialog::accept();
}
/// <summary>
/// Return a const reference to the map.
/// This will contains the state of the checkboxes after
/// the user clicks ok.
/// Called when the user clicks cancel.
/// Reset the state of the the checkboxes to what the map previously was
/// when the dialog was shown.
/// </summary>
const QMap<QString, QVariant>& FractoriumVariationsDialog::Map()
void FractoriumVariationsDialog::reject()
{
return m_Vars;
DataToGui();
QDialog::reject();
}
/// <summary>
@ -193,10 +204,34 @@ const QMap<QString, QVariant>& FractoriumVariationsDialog::Map()
/// <param name="e">Event, passed to base.</param>
void FractoriumVariationsDialog::showEvent(QShowEvent* e)
{
MapToCheckBoxes();
DataToGui();
QDialog::showEvent(e);
}
/// <summary>
/// Copy the values in the map to the state of the checkboxes.
/// </summary>
void FractoriumVariationsDialog::DataToGui()
{
ForEachCell([&](QTableWidgetItem* cb)
{
if (auto var = m_VariationList.GetVariation(cb->text().toStdString()))
SetCheckFromMap(cb, var);
});
}
/// <summary>
/// Copy the state of the checkboxes to the map.
/// </summary>
void FractoriumVariationsDialog::GuiToData()
{
ForEachCell([&](QTableWidgetItem* cb)
{
if (auto var = m_VariationList.GetVariation(cb->text().toStdString()))
m_Vars[cb->text()] = (cb->checkState() == Qt::Checked);
});
}
/// <summary>
/// Set the state of the passed in table item checkbox based on the boolean contained
/// in the map for the passed in variation.
@ -216,27 +251,3 @@ void FractoriumVariationsDialog::SetCheckFromMap(QTableWidgetItem* cb, const Var
cb->setCheckState(chk ? Qt::Checked : Qt::Unchecked);
}
}
/// <summary>
/// Copy the values in the map to the state of the checkboxes.
/// </summary>
void FractoriumVariationsDialog::MapToCheckBoxes()
{
ForEachCell([&](QTableWidgetItem* cb)
{
if (auto var = m_VariationList.GetVariation(cb->text().toStdString()))
SetCheckFromMap(cb, var);
});
}
/// <summary>
/// Copy the state of the checkboxes to the map.
/// </summary>
void FractoriumVariationsDialog::CheckBoxesToMap()
{
ForEachCell([&](QTableWidgetItem* cb)
{
if (auto var = m_VariationList.GetVariation(cb->text().toStdString()))
m_Vars[cb->text()] = (cb->checkState() == Qt::Checked);
});
}

View File

@ -20,24 +20,25 @@ class FractoriumVariationsDialog : public QDialog
Q_OBJECT
public:
FractoriumVariationsDialog(FractoriumSettings* settings, QWidget* p = nullptr, Qt::WindowFlags f = nullptr);
const QMap<QString, QVariant>& Map();
void ForEachCell(std::function<void(QTableWidgetItem* cb)> func);
void ForEachSelectedCell(std::function<void(QTableWidgetItem* cb)> func);
void SyncSettings();
const QMap<QString, QVariant>& Map();
public slots:
void OnSelectAllButtonClicked(bool checked);
void OnInvertSelectionButtonClicked(bool checked);
void OnSelectNoneButtonClicked(bool checked);
void Accept();
void OnVariationsTableItemChanged(QTableWidgetItem* item);
virtual void accept() override;
virtual void reject() override;
protected:
virtual void showEvent(QShowEvent* e) override;
private:
void MapToCheckBoxes();
void CheckBoxesToMap();
void DataToGui();
void GuiToData();
void Populate();
void SetCheckFromMap(QTableWidgetItem* cb, const Variation<float>* var);
VariationList<float> m_VariationList;