mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-22 05:30:06 -05:00
5bd593b42f
Allow for setting rendering thread priorities from the command line and final render dialog. Currently only implemented on Windows. Show estimated time left on the final render dialog. Sort palette list by name, instead of by index in the palette file. Sorting can be flipped by clicking the column headers of the palette table. --Code changes Remove unnecessary connect() statement in Variations tab.
322 lines
12 KiB
C++
322 lines
12 KiB
C++
#include "FractoriumPch.h"
|
|
#include "Fractorium.h"
|
|
|
|
/// <summary>
|
|
/// Initialize the xforms variations UI.
|
|
/// </summary>
|
|
void Fractorium::InitXformsVariationsUI()
|
|
{
|
|
QTreeWidget* tree = ui.VariationsTree;
|
|
|
|
tree->clear();
|
|
tree->header()->setSectionsClickable(true);
|
|
connect(tree->header(), SIGNAL(sectionClicked(int)), this, SLOT(OnTreeHeaderSectionClicked(int)));
|
|
connect(ui.VariationsFilterLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnVariationsFilterLineEditTextChanged(const QString&)));
|
|
connect(ui.VariationsFilterClearButton, SIGNAL(clicked(bool)), this, SLOT(OnVariationsFilterClearButtonClicked(bool)));
|
|
|
|
//Setting dimensions in the designer with a layout is futile, so must hard code here.
|
|
tree->setColumnWidth(0, 160);
|
|
tree->setColumnWidth(1, 23);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dynamically populate the variation tree widget with VariationTreeWidgetItem and VariationTreeDoubleSpinBox
|
|
/// templated with the correct type.
|
|
/// This will clear any previous contents.
|
|
/// Called upon initialization, or controller type change.
|
|
/// </summary>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::SetupVariationTree()
|
|
{
|
|
T fMin = TLOW;
|
|
T fMax = TMAX;
|
|
QSize hint0(75, 16);
|
|
QSize hint1(30, 16);
|
|
QTreeWidget* tree = m_Fractorium->ui.VariationsTree;
|
|
|
|
tree->clear();
|
|
tree->blockSignals(true);
|
|
|
|
for (size_t i = 0; i < m_VariationList.Size(); i++)
|
|
{
|
|
Variation<T>* var = m_VariationList.GetVariation(i);
|
|
ParametricVariation<T>* parVar = dynamic_cast<ParametricVariation<T>*>(var);
|
|
|
|
//First add the variation, with a spinner for its weight.
|
|
VariationTreeWidgetItem<T>* item = new VariationTreeWidgetItem<T>(var->VariationId(), tree);
|
|
VariationTreeDoubleSpinBox<T>* spinBox = new VariationTreeDoubleSpinBox<T>(tree, item, parVar ? parVar : var, "");
|
|
|
|
item->setText(0, QString::fromStdString(var->Name()));
|
|
item->setSizeHint(0, hint0);
|
|
item->setSizeHint(1, hint1);
|
|
spinBox->setRange(fMin, fMax);
|
|
spinBox->DoubleClick(true);
|
|
spinBox->DoubleClickZero(1);
|
|
spinBox->DoubleClickNonZero(0);
|
|
spinBox->SmallStep(0.001);
|
|
spinBox->setDecimals(4);
|
|
tree->setItemWidget(item, 1, spinBox);
|
|
m_Fractorium->connect(spinBox, SIGNAL(valueChanged(double)), SLOT(OnVariationSpinBoxValueChanged(double)), Qt::QueuedConnection);
|
|
|
|
//Check to see if the variation was parametric, and add a tree entry with a spinner for each parameter.
|
|
if (parVar)
|
|
{
|
|
ParamWithName<T>* params = parVar->Params();
|
|
|
|
for (size_t j = 0; j < parVar->ParamCount(); j++)
|
|
{
|
|
if (!params[j].IsPrecalc())
|
|
{
|
|
VariationTreeWidgetItem<T>* paramWidget = new VariationTreeWidgetItem<T>(var->VariationId(), item);
|
|
VariationTreeDoubleSpinBox<T>* varSpinBox = new VariationTreeDoubleSpinBox<T>(tree, paramWidget, parVar, params[j].Name());
|
|
|
|
paramWidget->setText(0, params[j].Name().c_str());
|
|
paramWidget->setSizeHint(0, hint0);
|
|
paramWidget->setSizeHint(1, hint1);
|
|
varSpinBox->setRange(params[j].Min(), params[j].Max());
|
|
varSpinBox->setValue(params[j].ParamVal());
|
|
varSpinBox->DoubleClick(true);
|
|
varSpinBox->DoubleClickZero(1);
|
|
varSpinBox->DoubleClickNonZero(0);
|
|
|
|
if (params[j].Type() == INTEGER || params[j].Type() == INTEGER_NONZERO)
|
|
{
|
|
varSpinBox->setSingleStep(1);
|
|
varSpinBox->Step(1);
|
|
varSpinBox->SmallStep(1);
|
|
}
|
|
|
|
varSpinBox->setDecimals(4);
|
|
tree->setItemWidget(paramWidget, 1, varSpinBox);
|
|
m_Fractorium->connect(varSpinBox, SIGNAL(valueChanged(double)), SLOT(OnVariationSpinBoxValueChanged(double)), Qt::QueuedConnection);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tree->blockSignals(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set every spinner in the variation tree, including params, to zero.
|
|
/// </summary>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::ClearVariationsTree()
|
|
{
|
|
QTreeWidget* tree = m_Fractorium->ui.VariationsTree;
|
|
|
|
for (uint i = 0; i < tree->topLevelItemCount(); i++)
|
|
{
|
|
QTreeWidgetItem* item = tree->topLevelItem(i);
|
|
VariationTreeDoubleSpinBox<T>* spinBox = dynamic_cast<VariationTreeDoubleSpinBox<T>*>(tree->itemWidget(item, 1));
|
|
|
|
spinBox->SetValueStealth(0);
|
|
|
|
for (uint j = 0; j < item->childCount(); j++)//Iterate through all of the children, which will be the params.
|
|
{
|
|
if ((spinBox = dynamic_cast<VariationTreeDoubleSpinBox<T>*>(tree->itemWidget(item->child(j), 1))))//Cast the child widget to the VariationTreeDoubleSpinBox type.
|
|
spinBox->SetValueStealth(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the value of a variation or param spinner to its corresponding value
|
|
/// in the currently selected xform.
|
|
/// Called when any spinner in the variations tree is changed.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="d">The spinner value</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would be awesome to make this work for all.//TODO
|
|
{
|
|
QObject* objSender = m_Fractorium->sender();
|
|
QTreeWidget* tree = m_Fractorium->ui.VariationsTree;
|
|
VariationTreeDoubleSpinBox<T>* sender = dynamic_cast<VariationTreeDoubleSpinBox<T>*>(objSender);
|
|
Xform<T>* xform = m_Ember.GetTotalXform(m_Fractorium->ui.CurrentXformCombo->currentIndex());//Will retrieve normal xform or final if needed.
|
|
|
|
if (sender && xform)
|
|
{
|
|
Variation<T>* var = sender->GetVariation();//The variation attached to the sender, for reference only.
|
|
ParametricVariation<T>* parVar = dynamic_cast<ParametricVariation<T>*>(var);//The parametric cast of that variation.
|
|
Variation<T>* xformVar = xform->GetVariationById(var->VariationId());//The corresponding variation in the currently selected xform.
|
|
VariationTreeWidgetItem<T>* widgetItem = sender->WidgetItem();
|
|
bool isParam = parVar && sender->IsParam();
|
|
|
|
if (isParam)
|
|
{
|
|
//Do not take action if the xform doesn't contain the variation which this param is part of.
|
|
if (ParametricVariation<T>* xformParVar = dynamic_cast<ParametricVariation<T>*>(xformVar))//The parametric cast of the xform's variation.
|
|
{
|
|
if (xformParVar->SetParamVal(sender->ParamName().c_str(), d))
|
|
{
|
|
UpdateRender();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//If they spun down to zero, and it wasn't a parameter item,
|
|
//and the current xform contained the variation, then remove the variation.
|
|
if (IsNearZero(d))
|
|
{
|
|
if (xformVar)
|
|
xform->DeleteVariationById(var->VariationId());
|
|
|
|
widgetItem->setBackgroundColor(0, QColor(255, 255, 255));//Ensure background is always white if weight goes to zero.
|
|
}
|
|
else
|
|
{
|
|
if (xformVar)//The xform already contained this variation, which means they just went from a non-zero weight to another non-zero weight (the simple case).
|
|
{
|
|
xformVar->m_Weight = d;
|
|
}
|
|
else
|
|
{
|
|
//If the item wasn't a param and the xform did not contain this variation,
|
|
//it means they went from zero to a non-zero weight, so add a new copy of this xform.
|
|
Variation<T>* newVar = var->Copy();//Create a new one with default values.
|
|
|
|
newVar->m_Weight = d;
|
|
xform->AddVariation(newVar);
|
|
widgetItem->setBackgroundColor(0, QColor(200, 200, 200));//Set background to gray when a variation has non-zero weight in this xform.
|
|
|
|
//If they've added a new parametric variation, then grab the values currently in the spinners
|
|
//for the child parameters and assign them to the newly added variation.
|
|
if (parVar)
|
|
{
|
|
ParametricVariation<T>* newParVar = dynamic_cast<ParametricVariation<T>*>(newVar);
|
|
|
|
for (int i = 0; i < widgetItem->childCount(); i++)//Iterate through all of the children, which will be the params.
|
|
{
|
|
QTreeWidgetItem* childItem = widgetItem->child(i);//Get the child.
|
|
QWidget* itemWidget = tree->itemWidget(childItem, 1);//Get the widget for the child.
|
|
|
|
if (VariationTreeDoubleSpinBox<T>* spinBox = dynamic_cast<VariationTreeDoubleSpinBox<T>*>(itemWidget))//Cast the widget to the VariationTreeDoubleSpinBox type.
|
|
{
|
|
string s = childItem->text(0).toStdString();//Use the name of the child, and the value of the spinner widget to assign the param.
|
|
|
|
newParVar->SetParamVal(s.c_str(), spinBox->value());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
UpdateRender();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Fractorium::OnVariationSpinBoxValueChanged(double d) { m_Controller->VariationSpinBoxValueChanged(d); }
|
|
|
|
/// <summary>
|
|
/// Fill the variation tree values from passed in xform and apply the current sorting mode.
|
|
/// Called when the currently selected xform changes.
|
|
/// </summary>
|
|
/// <param name="xform">The xform whose variation values will be used to fill the tree</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::FillVariationTreeWithXform(Xform<T>* xform)
|
|
{
|
|
QTreeWidget* tree = m_Fractorium->ui.VariationsTree;
|
|
|
|
tree->blockSignals(true);
|
|
|
|
for (uint i = 0; i < tree->topLevelItemCount(); i++)
|
|
{
|
|
VariationTreeWidgetItem<T>* item = dynamic_cast<VariationTreeWidgetItem<T>*>(tree->topLevelItem(i));
|
|
Variation<T>* var = xform->GetVariationById(item->Id());//See if this variation in the tree was contained in the xform.
|
|
ParametricVariation<T>* parVar = dynamic_cast<ParametricVariation<T>*>(var);//Attempt cast to parametric variation for later.
|
|
ParametricVariation<T>* origParVar = dynamic_cast<ParametricVariation<T>*>(m_VariationList.GetVariation(item->Id()));
|
|
|
|
if (VariationTreeDoubleSpinBox<T>* spinBox = dynamic_cast<VariationTreeDoubleSpinBox<T>*>(tree->itemWidget(item, 1)))//Get the widget for the item, and cast the widget to the VariationTreeDoubleSpinBox type.
|
|
{
|
|
spinBox->SetValueStealth(var ? var->m_Weight : 0);//If the variation was present, set the spin box to its weight, else zero.
|
|
item->setBackgroundColor(0, var ? QColor(200, 200, 200) : QColor(255, 255, 255));//Ensure background is always white if the value goes to zero, else gray if var present.
|
|
|
|
for (uint j = 0; j < item->childCount(); j++)//Iterate through all of the children, which will be the params if it was a parametric variation.
|
|
{
|
|
T* param = nullptr;
|
|
QTreeWidgetItem* childItem = item->child(j);//Get the child.
|
|
QWidget* childItemWidget = tree->itemWidget(childItem, 1);//Get the widget for the child.
|
|
|
|
if (VariationTreeDoubleSpinBox<T>* childSpinBox = dynamic_cast<VariationTreeDoubleSpinBox<T>*>(childItemWidget))//Cast the widget to the VariationTreeDoubleSpinBox type.
|
|
{
|
|
string s = childItem->text(0).toStdString();//Get the name of the child.
|
|
|
|
if (parVar)
|
|
{
|
|
if ((param = parVar->GetParam(s.c_str())))//Retrieve pointer to the param.
|
|
childSpinBox->SetValueStealth(*param);
|
|
}
|
|
else if (origParVar)//Parametric variation was not present in this xform, so set child values to defaults.
|
|
{
|
|
if ((param = origParVar->GetParam(s.c_str())))
|
|
childSpinBox->SetValueStealth(*param);
|
|
else
|
|
childSpinBox->SetValueStealth(0);//Will most likely never happen, but just to be safe.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tree->blockSignals(false);
|
|
m_Fractorium->OnTreeHeaderSectionClicked(m_Fractorium->m_VarSortMode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Change the sorting to be either by variation ID, or by weight.
|
|
/// If sorting by variation ID, repeated clicks will alternate ascending or descending.
|
|
/// Called when user clicks the tree headers.
|
|
/// </summary>
|
|
/// <param name="logicalIndex">Column index of the header clicked. Sort by name if 0, sort by weight if 1.</param>
|
|
void Fractorium::OnTreeHeaderSectionClicked(int logicalIndex)
|
|
{
|
|
m_VarSortMode = logicalIndex;
|
|
ui.VariationsTree->sortItems(m_VarSortMode, m_VarSortMode == 0 ? Qt::AscendingOrder : Qt::DescendingOrder);
|
|
|
|
if (m_VarSortMode == 1)
|
|
ui.VariationsTree->scrollToTop();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply the text in the variation filter text box to only show variations whose names
|
|
/// contain the substring.
|
|
/// Called when the user types in the variation filter text box.
|
|
/// </summary>
|
|
/// <param name="text">The text to filter on</param>
|
|
void Fractorium::OnVariationsFilterLineEditTextChanged(const QString& text)
|
|
{
|
|
QTreeWidget* tree = ui.VariationsTree;
|
|
|
|
tree->setUpdatesEnabled(false);
|
|
|
|
for (uint i = 0; i < uint(tree->topLevelItemCount()); i++)
|
|
{
|
|
QTreeWidgetItem* item = tree->topLevelItem(i);
|
|
QString varName = item->text(0);
|
|
|
|
item->setHidden(!varName.contains(text, Qt::CaseInsensitive));
|
|
}
|
|
|
|
OnTreeHeaderSectionClicked(m_VarSortMode);//Must re-sort every time the filter changes.
|
|
tree->setUpdatesEnabled(true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clear the variation name filter, which will display all variations.
|
|
/// Called when clear variations filter button is clicked.
|
|
/// </summary>
|
|
/// <param name="checked">Ignored</param>
|
|
void Fractorium::OnVariationsFilterClearButtonClicked(bool checked)
|
|
{
|
|
ui.VariationsFilterLineEdit->clear();
|
|
}
|
|
|
|
template class FractoriumEmberController<float>;
|
|
|
|
#ifdef DO_DOUBLE
|
|
template class FractoriumEmberController<double>;
|
|
#endif
|