mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-06-30 21:36:33 -04:00
Features:
--Add support for Exr files which use 32-bit floats for each RGBA channel. Seems to come out too washed out. --Allow for clearing an individual color curve. --Allow for saving multiple image types in EmberRender and EmberAnimate. All writes are threaded. --Remove --bpc command line argument. Add format png16 as a replacement. --Remove --enable_jpg_comments and --enable_png_comments command line arguments, and replace them with --enable_comments which applies to jpg, png and exr. --Add menu items to variations and affine spinners which allow for easy entry of specific numeric values like pi. --Make final render dialog be wider rather than so tall. Bug fixes: --Fix some OpenCL compile errors on Mac. --Remove ability to save bitmap files on all platforms but Windows. Code changes: --New dependency on OpenEXR. --Allow Curves class to interact with objects of a different template type. --Make m_Curves member of Ember always use float as template type. --Set the length of the curves array to always be 2^17 which should offer enough precision with new 32-bit float pixel types. --Set pixel types to always be 32-bit float. This results in a major reduction of code in the final accumulation part of Renderer.h/cpp. --Remove corresponding code from RendererCL and FinalAccumOpenCLKernelCreator. --Remove Transparency, NumChannels and BytesPerPixel setters from Renderer.h/cpp. --Add new global functions to format final image buffers and place all alpha calculation and scaling code in them. --Blending is no longer needed in OpenGLWidget because of the new pixel type. --Make new class, AffineDoubleSpinBox. --Attempt to make file save dialog code work the same on all OSes. --Remove some unused functions.
This commit is contained in:
@ -58,7 +58,7 @@
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.4</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a><span style=" font-size:10pt;"><br/>Lead: Matt Feemster<br/>Contributors: Simon Detheridge, Michel Mastriani</span></p></body></html></string>
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.5</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a><span style=" font-size:10pt;"><br/>Lead: Matt Feemster<br/>Contributors: Simon Detheridge, Michel Mastriani</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
|
@ -169,7 +169,7 @@ void DoubleSpinBox::OnTimeout()
|
||||
/// <returns>false</returns>
|
||||
bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
|
||||
auto me = dynamic_cast<QMouseEvent*>(e);
|
||||
|
||||
if (isEnabled() && me)
|
||||
{
|
||||
@ -287,3 +287,124 @@ void DoubleSpinBox::StopTimer()
|
||||
s_Timer.stop();
|
||||
disconnect(&s_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that passes agruments to the base and assigns the m_Param and m_Variation members.
|
||||
/// It also sets up the context menu for special numerical values.
|
||||
/// </summary>
|
||||
/// <param name="p">The parent widget</param>
|
||||
/// <param name="widgetItem">The widget item this spinner is contained in</param>
|
||||
/// <param name="id">The variation this spinner is for</param>
|
||||
/// <param name="param">The name of the parameter this is for</param>
|
||||
/// <param name="h">The height of the spin box. Default: 16.</param>
|
||||
/// <param name="step">The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.05.</param>
|
||||
VariationTreeDoubleSpinBox::VariationTreeDoubleSpinBox(QWidget* p, VariationTreeWidgetItem* widgetItem, eVariationId id, const string& param, int h, double step)
|
||||
: DoubleSpinBox(p, h, step)
|
||||
{
|
||||
m_WidgetItem = widgetItem;
|
||||
m_Param = param;
|
||||
m_Id = id;
|
||||
setDecimals(3);
|
||||
//PI
|
||||
auto piAction = new QAction("PI", this);
|
||||
connect(piAction, SIGNAL(triggered(bool)), this, SLOT(PiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(piAction);
|
||||
//PI * 2
|
||||
auto twoPiAction = new QAction("2 PI", this);
|
||||
connect(twoPiAction, SIGNAL(triggered(bool)), this, SLOT(TwoPiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(twoPiAction);
|
||||
//PI / 2
|
||||
auto piOver2Action = new QAction("PI / 2", this);
|
||||
connect(piOver2Action, SIGNAL(triggered(bool)), this, SLOT(PiOver2ActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(piOver2Action);
|
||||
//PI / 3
|
||||
auto piOver3Action = new QAction("PI / 3", this);
|
||||
connect(piOver3Action, SIGNAL(triggered(bool)), this, SLOT(PiOver3ActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(piOver3Action);
|
||||
//PI / 4
|
||||
auto piOver4Action = new QAction("PI / 4", this);
|
||||
connect(piOver4Action, SIGNAL(triggered(bool)), this, SLOT(PiOver4ActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(piOver4Action);
|
||||
//PI / 6
|
||||
auto piOver6Action = new QAction("PI / 6", this);
|
||||
connect(piOver6Action, SIGNAL(triggered(bool)), this, SLOT(PiOver6ActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(piOver6Action);
|
||||
//1 / PI
|
||||
auto oneOverPiAction = new QAction("1 / PI", this);
|
||||
connect(oneOverPiAction, SIGNAL(triggered(bool)), this, SLOT(OneOverPiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(oneOverPiAction);
|
||||
//2 / PI
|
||||
auto twoOverPiAction = new QAction("2 / PI", this);
|
||||
connect(twoOverPiAction, SIGNAL(triggered(bool)), this, SLOT(TwoOverPiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(twoOverPiAction);
|
||||
//3 / PI
|
||||
auto threeOverPiAction = new QAction("3 / PI", this);
|
||||
connect(threeOverPiAction, SIGNAL(triggered(bool)), this, SLOT(ThreeOverPiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(threeOverPiAction);
|
||||
//4 / PI
|
||||
auto fourOverPiAction = new QAction("4 / PI", this);
|
||||
connect(fourOverPiAction, SIGNAL(triggered(bool)), this, SLOT(FourOverPiActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(fourOverPiAction);
|
||||
//Sqrt(2)
|
||||
auto sqrtTwoAction = new QAction("Sqrt(2)", this);
|
||||
connect(sqrtTwoAction, SIGNAL(triggered(bool)), this, SLOT(SqrtTwoActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(sqrtTwoAction);
|
||||
//Sqrt(2)
|
||||
auto sqrtThreeAction = new QAction("Sqrt(3)", this);
|
||||
connect(sqrtThreeAction, SIGNAL(triggered(bool)), this, SLOT(SqrtThreeActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(sqrtThreeAction);
|
||||
//Need this for it to show up properly.
|
||||
this->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
}
|
||||
|
||||
void VariationTreeDoubleSpinBox::PiActionTriggered(bool checked) { setValue(M_PI); }
|
||||
void VariationTreeDoubleSpinBox::TwoPiActionTriggered(bool checked) { setValue(M_PI * 2); }
|
||||
void VariationTreeDoubleSpinBox::PiOver2ActionTriggered(bool checked) { setValue(M_PI_2); }
|
||||
void VariationTreeDoubleSpinBox::PiOver3ActionTriggered(bool checked) { setValue(M_PI / 3); }
|
||||
void VariationTreeDoubleSpinBox::PiOver4ActionTriggered(bool checked) { setValue(M_PI / 4); }
|
||||
void VariationTreeDoubleSpinBox::PiOver6ActionTriggered(bool checked) { setValue(M_PI / 6); }
|
||||
void VariationTreeDoubleSpinBox::OneOverPiActionTriggered(bool checked) { setValue(1 / M_PI); }
|
||||
void VariationTreeDoubleSpinBox::TwoOverPiActionTriggered(bool checked) { setValue(2 / M_PI); }
|
||||
void VariationTreeDoubleSpinBox::ThreeOverPiActionTriggered(bool checked) { setValue(3 / M_PI); }
|
||||
void VariationTreeDoubleSpinBox::FourOverPiActionTriggered(bool checked) { setValue(4 / M_PI); }
|
||||
void VariationTreeDoubleSpinBox::SqrtTwoActionTriggered(bool checked) { setValue(M_SQRT2); }
|
||||
void VariationTreeDoubleSpinBox::SqrtThreeActionTriggered(bool checked) { setValue(std::sqrt(3.0)); }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that sets up the context menu for special numerical values specific to affine spinners.
|
||||
/// </summary>
|
||||
/// <param name="p">The parent widget</param>
|
||||
/// <param name="h">The height of the spin box. Default: 20.</param>
|
||||
/// <param name="step">The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.01.</param>
|
||||
AffineDoubleSpinBox::AffineDoubleSpinBox(QWidget* p, int h, double step)
|
||||
: DoubleSpinBox(p, h, step)
|
||||
{
|
||||
//-1
|
||||
auto neg1Action = new QAction("-1", this);
|
||||
connect(neg1Action, SIGNAL(triggered(bool)), this, SLOT(NegOneActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(neg1Action);
|
||||
//0
|
||||
auto zeroAction = new QAction("0", this);
|
||||
connect(zeroAction, SIGNAL(triggered(bool)), this, SLOT(ZeroActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(zeroAction);
|
||||
//1
|
||||
auto oneAction = new QAction("1", this);
|
||||
connect(oneAction, SIGNAL(triggered(bool)), this, SLOT(OneActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(oneAction);
|
||||
//45
|
||||
auto fortyFiveAction = new QAction("45", this);
|
||||
connect(fortyFiveAction, SIGNAL(triggered(bool)), this, SLOT(FortyFiveActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(fortyFiveAction);
|
||||
//-45
|
||||
auto negFortyFiveAction = new QAction("-45", this);
|
||||
connect(negFortyFiveAction, SIGNAL(triggered(bool)), this, SLOT(NegFortyFiveActionTriggered(bool)), Qt::QueuedConnection);
|
||||
this->addAction(negFortyFiveAction);
|
||||
//Need this for it to show up properly.
|
||||
this->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
}
|
||||
|
||||
void AffineDoubleSpinBox::NegOneActionTriggered(bool checked) { setValue(-1); }
|
||||
void AffineDoubleSpinBox::ZeroActionTriggered(bool checked) { setValue(0); }
|
||||
void AffineDoubleSpinBox::OneActionTriggered(bool checked) { setValue(1); }
|
||||
void AffineDoubleSpinBox::FortyFiveActionTriggered(bool checked) { setValue(0.707107); }
|
||||
void AffineDoubleSpinBox::NegFortyFiveActionTriggered(bool checked) { setValue(-0.707107); }
|
||||
|
@ -71,33 +71,52 @@ class VariationTreeWidgetItem;
|
||||
/// </summary>
|
||||
class VariationTreeDoubleSpinBox : public DoubleSpinBox
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor that passes agruments to the base and assigns the m_Param and m_Variation members.
|
||||
/// </summary>
|
||||
/// <param name="p">The parent widget</param>
|
||||
/// <param name="widgetItem">The widget item this spinner is contained in</param>
|
||||
/// <param name="id">The variation this spinner is for</param>
|
||||
/// <param name="param">The name of the parameter this is for</param>
|
||||
/// <param name="h">The height of the spin box. Default: 16.</param>
|
||||
/// <param name="step">The step used to increment/decrement the spin box when using the mouse wheel. Default: 0.05.</param>
|
||||
explicit VariationTreeDoubleSpinBox(QWidget* p, VariationTreeWidgetItem* widgetItem, eVariationId id, const string& param, int h = 16, double step = 0.05)
|
||||
: DoubleSpinBox(p, h, step)
|
||||
{
|
||||
m_WidgetItem = widgetItem;
|
||||
m_Param = param;
|
||||
m_Id = id;
|
||||
setDecimals(3);
|
||||
}
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VariationTreeDoubleSpinBox(QWidget* p, VariationTreeWidgetItem* widgetItem, eVariationId id, const string& param, int h = 16, double step = 0.05);
|
||||
virtual ~VariationTreeDoubleSpinBox() { }
|
||||
bool IsParam() { return !m_Param.empty(); }
|
||||
string ParamName() { return m_Param; }
|
||||
eVariationId GetVariationId() { return m_Id; }
|
||||
VariationTreeWidgetItem* WidgetItem() { return m_WidgetItem; }
|
||||
|
||||
public slots:
|
||||
void PiActionTriggered(bool checked = false);
|
||||
void TwoPiActionTriggered(bool checked = false);
|
||||
void PiOver2ActionTriggered(bool checked = false);
|
||||
void PiOver3ActionTriggered(bool checked = false);
|
||||
void PiOver4ActionTriggered(bool checked = false);
|
||||
void PiOver6ActionTriggered(bool checked = false);
|
||||
void OneOverPiActionTriggered(bool checked = false);
|
||||
void TwoOverPiActionTriggered(bool checked = false);
|
||||
void ThreeOverPiActionTriggered(bool checked = false);
|
||||
void FourOverPiActionTriggered(bool checked = false);
|
||||
void SqrtTwoActionTriggered(bool checked = false);
|
||||
void SqrtThreeActionTriggered(bool checked = false);
|
||||
|
||||
private:
|
||||
string m_Param;
|
||||
eVariationId m_Id;
|
||||
VariationTreeWidgetItem* m_WidgetItem;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Derivation for the double spin boxes that are in the
|
||||
/// affine controls.
|
||||
/// </summary>
|
||||
class AffineDoubleSpinBox : public DoubleSpinBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AffineDoubleSpinBox(QWidget* p, int h = 20, double step = 0.01);
|
||||
virtual ~AffineDoubleSpinBox() { }
|
||||
|
||||
public slots:
|
||||
void NegOneActionTriggered(bool checked = false);
|
||||
void ZeroActionTriggered(bool checked = false);
|
||||
void OneActionTriggered(bool checked = false);
|
||||
void FortyFiveActionTriggered(bool checked = false);
|
||||
void NegFortyFiveActionTriggered(bool checked = false);
|
||||
};
|
||||
|
@ -34,10 +34,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
//~EmberTreeWidgetItemBase()
|
||||
//{
|
||||
// qDebug() << "~EmberTreeWidgetItemBase()";
|
||||
//}
|
||||
~EmberTreeWidgetItemBase()
|
||||
{
|
||||
//qDebug() << "~EmberTreeWidgetItemBase()";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the preview image for the tree widget item.
|
||||
|
@ -52,8 +52,12 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
m_ItersCellIndex = row++;//Iters.
|
||||
m_PathCellIndex = row;
|
||||
QStringList comboList;
|
||||
#ifndef _WIN32
|
||||
comboList.append("bmp");
|
||||
#endif
|
||||
comboList.append("jpg");
|
||||
comboList.append("png");
|
||||
comboList.append("exr");
|
||||
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);
|
||||
@ -116,6 +120,7 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
ui.FinalRenderSaveXmlCheckBox->setChecked( m_Settings->FinalSaveXml());
|
||||
ui.FinalRenderDoAllCheckBox->setChecked( m_Settings->FinalDoAll());
|
||||
ui.FinalRenderDoSequenceCheckBox->setChecked( m_Settings->FinalDoSequence());
|
||||
ui.FinalRenderPng16BitCheckBox->setChecked( m_Settings->FinalPng16Bit());
|
||||
ui.FinalRenderKeepAspectCheckBox->setChecked( m_Settings->FinalKeepAspect());
|
||||
ui.FinalRenderThreadCountSpin->setValue( m_Settings->FinalThreadCount());
|
||||
#ifdef _WIN32
|
||||
@ -136,11 +141,27 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
m_SupersampleSpin->setValue(m_Settings->FinalSupersample());
|
||||
m_StripsSpin->setValue(int(m_Settings->FinalStrips()));
|
||||
Scale(eScaleType(m_Settings->FinalScale()));
|
||||
int index = 0;
|
||||
#ifdef _WIN32
|
||||
|
||||
if (m_Settings->FinalExt() == "jpg")
|
||||
m_Tbcw->m_Combo->setCurrentIndex(0);
|
||||
else
|
||||
m_Tbcw->m_Combo->setCurrentIndex(1);
|
||||
if (m_Settings->FinalExt().endsWith("bmp", Qt::CaseInsensitive))
|
||||
m_Tbcw->m_Combo->setCurrentIndex(index);
|
||||
|
||||
index++;
|
||||
#endif
|
||||
|
||||
if (m_Settings->FinalExt().endsWith("jpg", Qt::CaseInsensitive))
|
||||
m_Tbcw->m_Combo->setCurrentIndex(index);
|
||||
|
||||
index++;
|
||||
|
||||
if (m_Settings->FinalExt().endsWith("png", Qt::CaseInsensitive))
|
||||
m_Tbcw->m_Combo->setCurrentIndex(index);
|
||||
|
||||
index++;
|
||||
|
||||
if (m_Settings->FinalExt().endsWith("exr", Qt::CaseInsensitive))
|
||||
m_Tbcw->m_Combo->setCurrentIndex(index);
|
||||
|
||||
//Explicitly call these to enable/disable the appropriate controls.
|
||||
OnOpenCLCheckBoxStateChanged(ui.FinalRenderOpenCLCheckBox->isChecked());
|
||||
@ -150,23 +171,20 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
|
||||
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);
|
||||
ui.FinalRenderThreadHorizontalLayout->setAlignment(ui.FinalRenderThreadCountSpin, Qt::AlignLeft);
|
||||
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.
|
||||
QWidget* w = SetTabOrder(this, ui.FinalRenderEarlyClipCheckBox, ui.FinalRenderYAxisUpCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderTransparencyCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderOpenCLCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderPng16BitCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDoublePrecisionCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderSaveXmlCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDoAllCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDoSequenceCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderCurrentSpin);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderDeviceTable);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderApplyToAllCheckBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderThreadCountSpin);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderThreadPriorityComboBox);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderApplyToAllCheckBox);
|
||||
w = SetTabOrder(this, w, m_WidthScaleSpin);
|
||||
w = SetTabOrder(this, w, m_HeightScaleSpin);
|
||||
w = SetTabOrder(this, w, ui.FinalRenderScaleNoneRadioButton);
|
||||
@ -215,9 +233,10 @@ bool FractoriumFinalRenderDialog::Double() { return ui.FinalRenderDoublePrecisio
|
||||
bool FractoriumFinalRenderDialog::SaveXml() { return ui.FinalRenderSaveXmlCheckBox->isChecked(); }
|
||||
bool FractoriumFinalRenderDialog::DoAll() { return ui.FinalRenderDoAllCheckBox->isChecked(); }
|
||||
bool FractoriumFinalRenderDialog::DoSequence() { return ui.FinalRenderDoSequenceCheckBox->isChecked(); }
|
||||
bool FractoriumFinalRenderDialog::Png16Bit() { return ui.FinalRenderPng16BitCheckBox->isChecked(); }
|
||||
bool FractoriumFinalRenderDialog::KeepAspect() { return ui.FinalRenderKeepAspectCheckBox->isChecked(); }
|
||||
bool FractoriumFinalRenderDialog::ApplyToAll() { return ui.FinalRenderApplyToAllCheckBox->isChecked(); }
|
||||
QString FractoriumFinalRenderDialog::Ext() { return m_Tbcw->m_Combo->currentIndex() == 0 ? "jpg" : "png"; }
|
||||
QString FractoriumFinalRenderDialog::Ext() { return m_Tbcw->m_Combo->currentText(); }
|
||||
QString FractoriumFinalRenderDialog::Path() { return ui.FinalRenderParamsTable->item(m_PathCellIndex, 1)->text(); }
|
||||
void FractoriumFinalRenderDialog::Path(const QString& s) { ui.FinalRenderParamsTable->item(m_PathCellIndex, 1)->setText(s); }
|
||||
QString FractoriumFinalRenderDialog::Prefix() { return m_PrefixEdit->text(); }
|
||||
@ -261,6 +280,7 @@ FinalRenderGuiState FractoriumFinalRenderDialog::State()
|
||||
state.m_SaveXml = SaveXml();
|
||||
state.m_DoAll = DoAll();
|
||||
state.m_DoSequence = DoSequence();
|
||||
state.m_Png16Bit = Png16Bit();
|
||||
state.m_KeepAspect = KeepAspect();
|
||||
state.m_Scale = Scale();
|
||||
state.m_Path = Path();
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
bool SaveXml();
|
||||
bool DoAll();
|
||||
bool DoSequence();
|
||||
bool Png16Bit();
|
||||
bool KeepAspect();
|
||||
bool ApplyToAll();
|
||||
eScaleType Scale();
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>519</width>
|
||||
<height>941</height>
|
||||
<width>573</width>
|
||||
<height>751</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -63,8 +63,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>507</width>
|
||||
<height>929</height>
|
||||
<width>561</width>
|
||||
<height>739</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
@ -83,96 +83,12 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="FinalRenderGridLayout" columnstretch="0,0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderEarlyClipCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: clip colors and gamma correct after density filtering.</p><p>Unchecked: do it after spatial filtering.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Early Clip</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderYAxisUpCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: Positive Y direction is up.</p><p>Unchecked: Positive Y direction is down.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Positive Y Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderOpenCLCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use OpenCL to render if your video card supports it.</p><p>This is highly recommended as it will dramatically speed up render time.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use OpenCL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderTransparencyCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use transparency in the final image.</p><p>Only supported for Png format.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transparency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoublePrecisionCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: use 64-bit double precision numbers (slower, but better image quality).</p><p>Unchecked: use 32-bit single precision numbers (faster, but worse image quality).</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Double Precision</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderSaveXmlCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Save an Xml parameter file for each flame rendered</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Xml</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoAllCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Render all open flames instead of just the current one</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoSequenceCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Use temporal samples value to achieve motion blur effect between flames</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render as Animation Sequence</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="FinalRenderGridLayout2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="FinalRenderPreviewLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
@ -215,7 +131,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="0" column="2">
|
||||
<widget class="QSpinBox" name="FinalRenderCurrentSpin">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@ -237,6 +153,100 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="FinalRenderGridLayout" columnstretch="0,0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderEarlyClipCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: clip colors and gamma correct after density filtering.</p><p>Unchecked: do it after spatial filtering.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Early Clip</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderYAxisUpCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: Positive Y direction is up.</p><p>Unchecked: Positive Y direction is down.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Positive Y Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderOpenCLCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use OpenCL to render if your video card supports it.</p><p>This is highly recommended as it will dramatically speed up render time.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use OpenCL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderTransparencyCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Use transparency in the final image.</p><p>Only supported for Png format.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transparency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoublePrecisionCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Checked: use 64-bit double precision numbers (slower, but better image quality).</p><p>Unchecked: use 32-bit single precision numbers (faster, but worse image quality).</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Double Precision</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderSaveXmlCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Save an Xml parameter file for each flame rendered</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Xml</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoAllCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Render all open flames instead of just the current one</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="FinalRenderDoSequenceCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Use temporal samples value to achieve motion blur effect between flames</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render as Animation Sequence</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="FinalRenderPng16BitCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Save each RGBA component as 16-bits when saving Png files.</p><p>This leads to greater color precision for use in high end rendering and display on HDR monitors, however it makes the file size larger.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save 16-bit Png</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@ -328,7 +338,10 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="FinalRenderThreadHorizontalLayout" stretch="0,0,0">
|
||||
<layout class="QHBoxLayout" name="FinalRenderThreadHorizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="FinalRenderThreadCountSpin">
|
||||
<property name="sizePolicy">
|
||||
@ -405,6 +418,19 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@ -928,6 +954,146 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="FinalRenderTextOutput">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="FinalRenderGridLayout3" rowstretch="0,0,0,0" columnstretch="1,4">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderFilteringProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="FinalRenderIterationProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Iteration:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="FinalRenderAccumProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Final Accumulation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderIterationProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderAccumProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="FinalRenderFilteringProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Density Filtering:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="FinalRenderTotalProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Total Progress:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderTotalProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="FinalRenderImageCountLabel">
|
||||
<property name="text">
|
||||
@ -938,142 +1104,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="FinalRenderGridLayout3" rowstretch="0,0,0,0" columnstretch="1,4">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderFilteringProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="FinalRenderIterationProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Iteration:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="FinalRenderAccumProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Final Accumulation:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderIterationProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderAccumProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="FinalRenderFilteringProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Density Filtering:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="FinalRenderTotalProgressLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Total Progress:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QProgressBar" name="FinalRenderTotalProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="FinalRenderTextOutput">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="FinalRenderButtonHBoxLayout">
|
||||
<property name="spacing">
|
||||
@ -1160,13 +1190,22 @@
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>FinalRenderEarlyClipCheckBox</tabstop>
|
||||
<tabstop>FinalRenderDoublePrecisionCheckBox</tabstop>
|
||||
<tabstop>FinalRenderYAxisUpCheckBox</tabstop>
|
||||
<tabstop>FinalRenderSaveXmlCheckBox</tabstop>
|
||||
<tabstop>FinalRenderTransparencyCheckBox</tabstop>
|
||||
<tabstop>FinalRenderDoAllCheckBox</tabstop>
|
||||
<tabstop>FinalRenderOpenCLCheckBox</tabstop>
|
||||
<tabstop>FinalRenderParamsTable</tabstop>
|
||||
<tabstop>FinalRenderTextOutput</tabstop>
|
||||
<tabstop>FinalRenderStartButton</tabstop>
|
||||
<tabstop>FinalRenderDoSequenceCheckBox</tabstop>
|
||||
<tabstop>FinalRenderPng16BitCheckBox</tabstop>
|
||||
<tabstop>FinalRenderCurrentSpin</tabstop>
|
||||
<tabstop>FinalRenderStopButton</tabstop>
|
||||
<tabstop>FinalRenderStartButton</tabstop>
|
||||
<tabstop>FinalRenderScaleWidthRadioButton</tabstop>
|
||||
<tabstop>FinalRenderScaleHeightRadioButton</tabstop>
|
||||
<tabstop>FinalRenderScaleNoneRadioButton</tabstop>
|
||||
<tabstop>FinalRenderKeepAspectCheckBox</tabstop>
|
||||
<tabstop>FinalRenderTextOutput</tabstop>
|
||||
<tabstop>FinalRenderCloseButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
|
@ -80,7 +80,7 @@ bool FinalRenderEmberControllerBase::CreateRendererFromGUI()
|
||||
bool useOpenCL = m_Info->Ok() && m_FinalRenderDialog->OpenCL();
|
||||
auto v = Devices(m_FinalRenderDialog->Devices());
|
||||
return CreateRenderer((useOpenCL && !v.empty()) ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER,
|
||||
v, false); //Not shared.
|
||||
v, false, false); //Not shared.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -178,7 +178,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
size_t ftime;
|
||||
size_t finalImageIndex = 0;
|
||||
std::thread writeThread;
|
||||
vector<byte> finalImages[2];
|
||||
vector<v4F> finalImages[2];
|
||||
EmberStats stats;
|
||||
EmberImageComments comments;
|
||||
Timing renderTimer;
|
||||
@ -225,8 +225,8 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
|
||||
finalImages[threadFinalImageIndex],
|
||||
renderer->FinalRasW(),
|
||||
renderer->FinalRasH(),
|
||||
renderer->NumChannels(),
|
||||
renderer->BytesPerChannel());
|
||||
m_FinalRenderDialog->Png16Bit(),
|
||||
m_FinalRenderDialog->Transparency());
|
||||
}, ftime, finalImageIndex);
|
||||
m_FinishedImageCount.fetch_add(1);
|
||||
RenderComplete(*m_EmberFile.Get(ftime), stats, renderTimer);
|
||||
@ -422,10 +422,9 @@ bool FinalRenderEmberController<T>::Render()
|
||||
/// <param name="shared">True if shared with OpenGL, else false. Always false in this case.</param>
|
||||
/// <returns>True if nothing went wrong, else false.</returns>
|
||||
template <typename T>
|
||||
bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared)
|
||||
bool FinalRenderEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared)
|
||||
{
|
||||
bool ok = true;
|
||||
//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));
|
||||
CancelRender();
|
||||
@ -542,35 +541,24 @@ template <typename T>
|
||||
bool FinalRenderEmberController<T>::SyncGuiToRenderer()
|
||||
{
|
||||
bool ok = true;
|
||||
uint channels = m_FinalRenderDialog->Ext().endsWith("png", Qt::CaseInsensitive) ? 4 : 3;
|
||||
|
||||
if (m_Renderer.get())
|
||||
{
|
||||
if (m_Renderer->RendererType() == eRendererType::OPENCL_RENDERER)
|
||||
channels = 4;//Always using 4 since the GL texture is RGBA.
|
||||
|
||||
m_Renderer->Callback(this);
|
||||
m_Renderer->NumChannels(channels);
|
||||
m_Renderer->EarlyClip(m_FinalRenderDialog->EarlyClip());
|
||||
m_Renderer->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_Renderer->ThreadCount(m_FinalRenderDialog->ThreadCount());
|
||||
m_Renderer->Priority((eThreadPriority)m_FinalRenderDialog->ThreadPriority());
|
||||
m_Renderer->Transparency(m_FinalRenderDialog->Transparency());
|
||||
}
|
||||
else if (!m_Renderers.empty())
|
||||
{
|
||||
for (size_t i = 0; i < m_Renderers.size(); i++)
|
||||
{
|
||||
if (m_Renderers[i]->RendererType() == eRendererType::OPENCL_RENDERER)
|
||||
channels = 4;//Always using 4 since the GL texture is RGBA.
|
||||
|
||||
m_Renderers[i]->Callback(!i ? this : nullptr);
|
||||
m_Renderers[i]->NumChannels(channels);
|
||||
m_Renderers[i]->EarlyClip(m_FinalRenderDialog->EarlyClip());
|
||||
m_Renderers[i]->YAxisUp(m_FinalRenderDialog->YAxisUp());
|
||||
m_Renderers[i]->ThreadCount(m_FinalRenderDialog->ThreadCount());
|
||||
m_Renderers[i]->Priority((eThreadPriority)m_FinalRenderDialog->ThreadPriority());
|
||||
m_Renderers[i]->Transparency(m_FinalRenderDialog->Transparency());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -627,11 +615,11 @@ void FinalRenderEmberController<T>::ResetProgress(bool total)
|
||||
/// specified in the widgets and compute the amount of memory required to render.
|
||||
/// This includes the memory needed for the final output image.
|
||||
/// </summary>
|
||||
/// <returns>If successful, memory required in bytes, else zero.</returns>
|
||||
/// <returns>If successful, a tuple specifying the memory required in bytes for the histogram int he first element, the total memory in the second, and the iter count in the last, else zero.</returns>
|
||||
template <typename T>
|
||||
tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemory()
|
||||
{
|
||||
size_t iterCount;
|
||||
size_t iterCount = 0;
|
||||
pair<size_t, size_t> p(0, 0);
|
||||
size_t strips;
|
||||
uint channels = m_FinalRenderDialog->Ext() == "png" ? 4 : 3;//4 channels for Png, else 3.
|
||||
@ -642,7 +630,6 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
strips = VerifyStrips(m_Ember->m_FinalRasH, m_FinalRenderDialog->Strips(),
|
||||
[&](const string & s) {}, [&](const string & s) {}, [&](const string & s) {});
|
||||
m_Renderer->SetEmber(*m_Ember, eProcessAction::FULL_RENDER, true);
|
||||
m_Renderer->NumChannels(channels);
|
||||
m_FinalPreviewRenderer->Render(UINT_MAX, UINT_MAX);
|
||||
p = m_Renderer->MemoryRequired(strips, true, m_FinalRenderDialog->DoSequence());
|
||||
iterCount = m_Renderer->TotalIterCount(strips);
|
||||
@ -652,7 +639,6 @@ tuple<size_t, size_t, size_t> FinalRenderEmberController<T>::SyncAndComputeMemor
|
||||
for (auto& renderer : m_Renderers)
|
||||
{
|
||||
renderer->SetEmber(*m_Ember, eProcessAction::FULL_RENDER, true);
|
||||
renderer->NumChannels(channels);
|
||||
}
|
||||
|
||||
m_FinalPreviewRenderer->Render(UINT_MAX, UINT_MAX);
|
||||
@ -711,24 +697,24 @@ template<typename T>
|
||||
void FinalRenderEmberController<T>::SaveCurrentRender(Ember<T>& ember)
|
||||
{
|
||||
auto comments = m_Renderer->ImageComments(m_Stats, 0, true);
|
||||
SaveCurrentRender(ember, comments, m_FinalImage, m_Renderer->FinalRasW(), m_Renderer->FinalRasH(), m_Renderer->NumChannels(), m_Renderer->BytesPerChannel());
|
||||
SaveCurrentRender(ember, comments, m_FinalImage, m_Renderer->FinalRasW(), m_Renderer->FinalRasH(), m_FinalRenderDialog->Png16Bit(), m_FinalRenderDialog->Transparency());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save the output of the render.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember whose rendered output will be saved</param>
|
||||
/// <param name="comments">The comments to save in the png or jpg</param>
|
||||
/// <param name="comments">The comments to save in the png, jpg or exr</param>
|
||||
/// <param name="pixels">The buffer containing the pixels</param>
|
||||
/// <param name="width">The width in pixels of the image</param>
|
||||
/// <param name="height">The height in pixels of the image</param>
|
||||
/// <param name="channels">The number of channels, 3 or 4.</param>
|
||||
/// <param name="bpc">The bytes per channel, almost always 1.</param>
|
||||
/// <param name="png16Bit">Whether to use 16 bits per channel per pixel when saving as Png.</param>
|
||||
/// <param name="transparency">Whether to use alpha when saving as Png or Exr.</param>
|
||||
template<typename T>
|
||||
void FinalRenderEmberController<T>::SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc)
|
||||
void FinalRenderEmberController<T>::SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<v4F>& pixels, size_t width, size_t height, bool png16Bit, bool transparency)
|
||||
{
|
||||
QString filename = ComposePath(QString::fromStdString(ember.m_Name));
|
||||
FractoriumEmberControllerBase::SaveCurrentRender(filename, comments, pixels, width, height, channels, bpc);
|
||||
FractoriumEmberControllerBase::SaveCurrentRender(filename, comments, pixels, width, height, png16Bit, transparency);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -806,6 +792,7 @@ void FinalRenderEmberController<T>::RenderComplete(Ember<T>& ember, const EmberS
|
||||
m_Settings->FinalSaveXml(m_GuiState.m_SaveXml);
|
||||
m_Settings->FinalDoAll(m_GuiState.m_DoAll);
|
||||
m_Settings->FinalDoSequence(m_GuiState.m_DoSequence);
|
||||
m_Settings->FinalPng16Bit(m_GuiState.m_Png16Bit);
|
||||
m_Settings->FinalKeepAspect(m_GuiState.m_KeepAspect);
|
||||
m_Settings->FinalScale(uint(m_GuiState.m_Scale));
|
||||
m_Settings->FinalExt(m_GuiState.m_Ext);
|
||||
@ -960,6 +947,7 @@ void FinalRenderPreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
QLabel* widget = d->ui.FinalRenderPreviewLabel;
|
||||
//Determine how to scale the scaled ember to fit in the label with a max of 100x100.
|
||||
auto e = m_Controller->m_Ember;
|
||||
auto settings = FractoriumSettings::Instance();
|
||||
|
||||
if (e->m_FinalRasW >= e->m_FinalRasH)
|
||||
scalePercentage = T(maxDim) / e->m_FinalRasW;
|
||||
@ -974,9 +962,7 @@ void FinalRenderPreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
m_PreviewEmber.m_PixelsPerUnit = scalePercentage * e->m_PixelsPerUnit;
|
||||
m_PreviewRenderer.EarlyClip(d->EarlyClip());
|
||||
m_PreviewRenderer.YAxisUp(d->YAxisUp());
|
||||
m_PreviewRenderer.Transparency(d->Transparency());
|
||||
m_PreviewRenderer.Callback(nullptr);
|
||||
m_PreviewRenderer.NumChannels(4);
|
||||
m_PreviewRenderer.SetEmber(m_PreviewEmber);
|
||||
m_PreviewRenderer.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, d->Strips(),
|
||||
@ -987,8 +973,10 @@ void FinalRenderPreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
[&](size_t strip) {},//Error.
|
||||
[&](Ember<T>& finalEmber)//Final strip.
|
||||
{
|
||||
m_PreviewVec.resize(finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);
|
||||
Rgba32ToRgba8(m_PreviewFinalImage.data(), m_PreviewVec.data(), finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, d->Transparency());
|
||||
QImage image(int(finalEmber.m_FinalRasW), int(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.
|
||||
memcpy(image.scanLine(0), m_PreviewVec.data(), SizeOf(m_PreviewVec));//Memcpy the data in.
|
||||
QPixmap pixmap(QPixmap::fromImage(image));
|
||||
QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap));
|
||||
});
|
||||
|
@ -28,6 +28,7 @@ struct FinalRenderGuiState
|
||||
bool m_Double;
|
||||
bool m_SaveXml;
|
||||
bool m_DoAll;
|
||||
bool m_Png16Bit;
|
||||
bool m_DoSequence;
|
||||
bool m_KeepAspect;
|
||||
eScaleType m_Scale;
|
||||
@ -111,7 +112,7 @@ public:
|
||||
#endif
|
||||
virtual void SetEmber(size_t index, bool verbatim) override;
|
||||
virtual bool Render() override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared = true) override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared = true) override;
|
||||
virtual int ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs) override;
|
||||
virtual size_t Index() const override { return m_Ember->m_Index; }
|
||||
virtual uint SizeOfT() const override { return sizeof(T); }
|
||||
@ -134,7 +135,7 @@ public:
|
||||
protected:
|
||||
void HandleFinishedProgress();
|
||||
void SaveCurrentRender(Ember<T>& ember);
|
||||
void SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc);
|
||||
void SaveCurrentRender(Ember<T>& ember, const EmberImageComments& comments, vector<v4F>& pixels, size_t width, size_t height, bool png16Bit, bool transparency);
|
||||
void RenderComplete(Ember<T>& ember);
|
||||
void RenderComplete(Ember<T>& ember, const EmberStats& stats, Timing& renderTimer);
|
||||
void SyncGuiToEmber(Ember<T>& ember, size_t widthOverride = 0, size_t heightOverride = 0);
|
||||
@ -158,6 +159,7 @@ class FinalRenderPreviewRenderer : public PreviewRenderer<T>
|
||||
{
|
||||
public:
|
||||
using PreviewRenderer<T>::m_PreviewRun;
|
||||
using PreviewRenderer<T>::m_PreviewVec;
|
||||
using PreviewRenderer<T>::m_PreviewEmber;
|
||||
using PreviewRenderer<T>::m_PreviewRenderer;
|
||||
using PreviewRenderer<T>::m_PreviewFinalImage;
|
||||
|
@ -26,6 +26,7 @@ Fractorium::Fractorium(QWidget* p)
|
||||
qRegisterMetaType<size_t>("size_t");
|
||||
qRegisterMetaType<QVector<int>>("QVector<int>");//For previews.
|
||||
qRegisterMetaType<vector<byte>>("vector<byte>");
|
||||
qRegisterMetaType<vv4F>("vv4F");
|
||||
qRegisterMetaType<EmberTreeWidgetItemBase*>("EmberTreeWidgetItemBase*");
|
||||
setDockOptions(DockOption::AllowNestedDocks | DockOption::AllowTabbedDocks);
|
||||
setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::TabPosition::North);
|
||||
@ -505,7 +506,7 @@ void Fractorium::SetFixedTableHeader(QHeaderView* header, QHeaderView::ResizeMod
|
||||
/// Setup and show the open XML dialog.
|
||||
/// This will perform lazy instantiation.
|
||||
/// </summary>
|
||||
/// <returns>The filename selected</returns>
|
||||
/// <returns>The list of filenames selected</returns>
|
||||
QStringList Fractorium::SetupOpenXmlDialog()
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
@ -522,7 +523,7 @@ QStringList Fractorium::SetupOpenXmlDialog()
|
||||
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)");
|
||||
m_FileDialog->setNameFilter("*.flam3;;*.flame;;*.xml");
|
||||
m_FileDialog->setWindowTitle("Open Flame");
|
||||
m_FileDialog->setDirectory(m_Settings->OpenFolder());
|
||||
m_FileDialog->selectNameFilter(m_Settings->OpenXmlExt());
|
||||
@ -567,30 +568,23 @@ QString Fractorium::SetupSaveXmlDialog(const QString& defaultFilename)
|
||||
|
||||
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);
|
||||
m_FileDialog->setDefaultSuffix(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);
|
||||
m_FileDialog->selectFile(defaultFilename);
|
||||
m_FileDialog->setNameFilter("Flam3 (*.flam3);;Flame (*.flame);;Xml (*.xml)");
|
||||
m_FileDialog->setNameFilter(".flam3;;.flame;;.xml");
|
||||
m_FileDialog->setWindowTitle("Save flame as xml");
|
||||
m_FileDialog->setDirectory(m_Settings->SaveFolder());
|
||||
m_FileDialog->selectNameFilter(m_Settings->SaveXmlExt());
|
||||
m_FileDialog->setDefaultSuffix(m_Settings->SaveXmlExt());
|
||||
|
||||
if (m_FileDialog->exec() == QDialog::Accepted)
|
||||
{
|
||||
filename = m_FileDialog->selectedFiles().value(0);
|
||||
//For some reason, linux doesn't automatically append this, but Windows does. Force it to be safe.
|
||||
auto filt = m_FileDialog->selectedNameFilter().split('*');//Qt makes it very hard to get the actual extension used.
|
||||
|
||||
if (filt.size() > 1)//Should always be true.
|
||||
{
|
||||
auto s = filt[1].replace(")", "");
|
||||
|
||||
if (!filename.endsWith(s))
|
||||
filename.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
auto defaultFilter(m_Settings->SaveXmlExt());
|
||||
@ -619,7 +613,11 @@ QString Fractorium::SetupSaveImageDialog(const QString& defaultFilename)
|
||||
|
||||
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);
|
||||
m_FileDialog->setDefaultSuffix(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);
|
||||
@ -627,17 +625,22 @@ QString Fractorium::SetupSaveImageDialog(const QString& defaultFilename)
|
||||
m_FileDialog->setFileMode(QFileDialog::AnyFile);
|
||||
m_FileDialog->setOption(QFileDialog::ShowDirsOnly, false);
|
||||
m_FileDialog->setOption(QFileDialog::DontUseNativeDialog, false);
|
||||
m_FileDialog->setNameFilter("Jpeg (*.jpg);;Png (*.png);;Bmp (*.bmp)");
|
||||
#ifdef _WIN32
|
||||
m_FileDialog->setNameFilter(".bmp;;.jpg;;.png;;.exr");
|
||||
#else
|
||||
m_FileDialog->setNameFilter(".jpg;;.png;;.exr");
|
||||
#endif
|
||||
m_FileDialog->setWindowTitle("Save image");
|
||||
m_FileDialog->setDirectory(m_Settings->SaveFolder());
|
||||
m_FileDialog->selectNameFilter(m_Settings->SaveImageExt());
|
||||
m_FileDialog->setDefaultSuffix(m_Settings->SaveImageExt());
|
||||
|
||||
if (m_FileDialog->exec() == QDialog::Accepted)
|
||||
filename = m_FileDialog->selectedFiles().value(0);
|
||||
|
||||
#else
|
||||
auto defaultFilter(m_Settings->SaveImageExt());
|
||||
auto filename = QFileDialog::getSaveFileName(this, tr("Save image"), m_Settings->SaveFolder() + "/" + defaultFilename, tr("Jpeg (*.jpg);;Png (*.png);;Bmp (*.bmp)"), &defaultFilter);
|
||||
auto filename = QFileDialog::getSaveFileName(this, tr("Save image"), m_Settings->SaveFolder() + "/" + defaultFilename, tr("Jpg (*.jpg);;Png (*.png);;Exr (*.exr)"), &defaultFilter);
|
||||
m_Settings->SaveImageExt(defaultFilter);
|
||||
#endif
|
||||
return filename;
|
||||
|
@ -339,18 +339,18 @@ public slots:
|
||||
void OnSummaryTreeHeaderSectionClicked(int logicalIndex);
|
||||
|
||||
//Rendering/progress.
|
||||
void StartRenderTimer();
|
||||
void StartRenderTimer(bool updatePreviews);
|
||||
void IdleTimer();
|
||||
bool ControllersOk();
|
||||
void ShowCritical(const QString& title, const QString& text, bool invokeRequired = false);
|
||||
|
||||
//Can't have a template function be a slot.
|
||||
void SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vector<byte>& v, uint w, uint h);
|
||||
void SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vv4F& v, uint w, uint h);
|
||||
|
||||
public:
|
||||
//template<typename spinType, typename valType>//See below.
|
||||
//static void SetupSpinner(QTableWidget* table, const QObject* receiver, int& row, int col, spinType*& spinBox, int height, valType min, valType max, valType step, const char* signal, const char* slot, bool incRow = true, valType val = 0, valType doubleClickZero = -999, valType doubleClickNonZero = -999);
|
||||
static void SetupAffineSpinner(QTableWidget* table, const QObject* receiver, int row, int col, DoubleSpinBox*& spinBox, int height, double min, double max, double step, double prec, const char* signal, const char* slot);
|
||||
static void SetupAffineSpinner(QTableWidget* table, const QObject* receiver, int row, int col, AffineDoubleSpinBox*& spinBox, int height, double min, double max, double step, double prec, const char* signal, const char* slot);
|
||||
static void 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 = Qt::QueuedConnection);
|
||||
static void SetFixedTableHeader(QHeaderView* header, QHeaderView::ResizeMode mode = QHeaderView::Fixed);
|
||||
|
||||
@ -422,8 +422,8 @@ private:
|
||||
void ErrorReportToQTextEdit(const vector<string>& errors, QTextEdit* textEdit, bool clear = true);
|
||||
|
||||
//Rendering/progress.
|
||||
void ShutdownAndRecreateFromOptions();
|
||||
bool CreateRendererFromOptions();
|
||||
void ShutdownAndRecreateFromOptions(bool updatePreviews);
|
||||
bool CreateRendererFromOptions(bool updatePreviews);
|
||||
bool CreateControllerFromOptions();
|
||||
void EnableRenderControls(bool enable);
|
||||
|
||||
@ -489,22 +489,22 @@ private:
|
||||
DoubleSpinBox* m_XformDirectColorSpin;
|
||||
|
||||
//Xforms Affine.
|
||||
DoubleSpinBox* m_PreX1Spin;//Pre.
|
||||
DoubleSpinBox* m_PreX2Spin;
|
||||
DoubleSpinBox* m_PreY1Spin;
|
||||
DoubleSpinBox* m_PreY2Spin;
|
||||
DoubleSpinBox* m_PreO1Spin;
|
||||
DoubleSpinBox* m_PreO2Spin;
|
||||
AffineDoubleSpinBox* m_PreX1Spin;//Pre.
|
||||
AffineDoubleSpinBox* m_PreX2Spin;
|
||||
AffineDoubleSpinBox* m_PreY1Spin;
|
||||
AffineDoubleSpinBox* m_PreY2Spin;
|
||||
AffineDoubleSpinBox* m_PreO1Spin;
|
||||
AffineDoubleSpinBox* m_PreO2Spin;
|
||||
|
||||
DoubleSpinBox* m_PostX1Spin;//Post.
|
||||
DoubleSpinBox* m_PostX2Spin;
|
||||
DoubleSpinBox* m_PostY1Spin;
|
||||
DoubleSpinBox* m_PostY2Spin;
|
||||
DoubleSpinBox* m_PostO1Spin;
|
||||
DoubleSpinBox* m_PostO2Spin;
|
||||
AffineDoubleSpinBox* m_PostX1Spin;//Post.
|
||||
AffineDoubleSpinBox* m_PostX2Spin;
|
||||
AffineDoubleSpinBox* m_PostY1Spin;
|
||||
AffineDoubleSpinBox* m_PostY2Spin;
|
||||
AffineDoubleSpinBox* m_PostO1Spin;
|
||||
AffineDoubleSpinBox* m_PostO2Spin;
|
||||
|
||||
DoubleSpinBox* m_PreSpins[6];
|
||||
DoubleSpinBox* m_PostSpins[6];
|
||||
AffineDoubleSpinBox* m_PreSpins[6];
|
||||
AffineDoubleSpinBox* m_PostSpins[6];
|
||||
|
||||
//Xaos.
|
||||
DoubleSpinBox* m_XaosSpinBox;
|
||||
@ -555,6 +555,7 @@ private:
|
||||
int m_VarSortMode;
|
||||
int m_PaletteSortMode;
|
||||
int m_PreviousPaletteRow;
|
||||
vector<byte> m_PreviewVec;
|
||||
shared_ptr<OpenCLInfo> m_Info;
|
||||
unique_ptr<FractoriumEmberControllerBase> m_Controller;
|
||||
Ui::FractoriumClass ui;
|
||||
|
@ -18,7 +18,7 @@ FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractor
|
||||
m_RenderTimer->setInterval(0);
|
||||
m_Fractorium->connect(m_RenderTimer.get(), SIGNAL(timeout()), SLOT(IdleTimer()));
|
||||
m_RenderRestartTimer = make_unique<QTimer>(m_Fractorium);
|
||||
m_Fractorium->connect(m_RenderRestartTimer.get(), SIGNAL(timeout()), SLOT(StartRenderTimer()));
|
||||
m_Fractorium->connect(m_RenderRestartTimer.get(), &QTimer::timeout, [&]() { m_Fractorium->StartRenderTimer(false); });//It's ok to pass false for the first shot because creating the controller will start the preview renders.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -368,7 +368,6 @@ void TreePreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
auto f = m_Controller->m_Fractorium;
|
||||
m_PreviewRenderer.EarlyClip(f->m_Settings->EarlyClip());
|
||||
m_PreviewRenderer.YAxisUp(f->m_Settings->YAxisUp());
|
||||
m_PreviewRenderer.Transparency(f->m_Settings->Transparency());
|
||||
m_PreviewRenderer.ThreadCount(std::max(1u, Timing::ProcessorCount() - 1));//Leave one processor free so the GUI can breathe.
|
||||
|
||||
if (auto top = m_Tree->topLevelItem(0))
|
||||
@ -394,7 +393,7 @@ void TreePreviewRenderer<T>::PreviewRenderFunc(uint start, uint end)
|
||||
//until the update is complete.
|
||||
QMetaObject::invokeMethod(f, "SetLibraryTreeItemData", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(EmberTreeWidgetItemBase*, treeItem),
|
||||
Q_ARG(vector<byte>&, m_PreviewFinalImage),
|
||||
Q_ARG(vv4F&, m_PreviewFinalImage),
|
||||
Q_ARG(uint, PREVIEW_SIZE),
|
||||
Q_ARG(uint, PREVIEW_SIZE));
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ public:
|
||||
virtual void AffineInterpTypeChanged(int i) { }
|
||||
virtual void InterpTypeChanged(int i) { }
|
||||
virtual void BackgroundChanged(const QColor& color) { }
|
||||
virtual void ClearColorCurves() { }
|
||||
virtual void ClearColorCurves(int i) { }
|
||||
virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) { }
|
||||
|
||||
//Xforms.
|
||||
@ -240,7 +240,7 @@ public:
|
||||
|
||||
//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; }
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared = true) { return false; }
|
||||
virtual uint SizeOfT() const { return 0; }
|
||||
virtual void ClearUndo() { }
|
||||
virtual GLEmberControllerBase* GLController() { return nullptr; }
|
||||
@ -252,10 +252,10 @@ public:
|
||||
void Shutdown();
|
||||
void UpdateRender(eProcessAction action = eProcessAction::FULL_RENDER);
|
||||
void DeleteRenderer();
|
||||
void SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc);
|
||||
void SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<v4F>& pixels, size_t width, size_t height, bool png16Bit, bool transparency);
|
||||
RendererBase* Renderer() { return m_Renderer.get(); }
|
||||
vector<byte>* FinalImage() { return &(m_FinalImage); }
|
||||
vector<byte>* PreviewFinalImage() { return &m_PreviewFinalImage; }
|
||||
vector<v4F>* FinalImage() { return &(m_FinalImage); }
|
||||
vector<v4F>* PreviewFinalImage() { return &m_PreviewFinalImage; }
|
||||
EmberStats Stats() { return m_Stats; }
|
||||
|
||||
protected:
|
||||
@ -286,8 +286,8 @@ protected:
|
||||
string m_CurrentPaletteFilePath;
|
||||
std::recursive_mutex m_Cs;
|
||||
std::thread m_WriteThread;
|
||||
vector<byte> m_FinalImage;
|
||||
vector<byte> m_PreviewFinalImage;
|
||||
vector<v4F> m_FinalImage;
|
||||
vector<v4F> m_PreviewFinalImage;
|
||||
vector<eProcessAction> m_ProcessActions;
|
||||
vector<eVariationId> m_FilteredVariations;
|
||||
unique_ptr<EmberNs::RendererBase> m_Renderer;
|
||||
@ -436,7 +436,7 @@ public:
|
||||
virtual void AffineInterpTypeChanged(int index) override;
|
||||
virtual void InterpTypeChanged(int index) override;
|
||||
virtual void BackgroundChanged(const QColor& col) override;
|
||||
virtual void ClearColorCurves() override;
|
||||
virtual void ClearColorCurves(int i) override;
|
||||
virtual void ColorCurveChanged(int curveIndex, int pointInxed, const QPointF& point) override;
|
||||
|
||||
//Xforms.
|
||||
@ -510,7 +510,7 @@ public:
|
||||
|
||||
//Rendering/progress.
|
||||
virtual bool Render() override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared = true) override;
|
||||
virtual bool CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared = true) override;
|
||||
virtual uint SizeOfT() const override { return sizeof(T); }
|
||||
virtual int ProgressFunc(Ember<T>& ember, void* foo, double fraction, int stage, double etaMs) override;
|
||||
virtual void ClearUndo() override;
|
||||
@ -607,11 +607,6 @@ public:
|
||||
return m_PreviewRenderer.YAxisUp();
|
||||
}
|
||||
|
||||
bool Transparency()
|
||||
{
|
||||
return m_PreviewRenderer.Transparency();
|
||||
}
|
||||
|
||||
bool Running()
|
||||
{
|
||||
return m_PreviewRun || m_PreviewResult.isRunning();
|
||||
@ -622,7 +617,8 @@ public:
|
||||
protected:
|
||||
volatile bool m_PreviewRun = false;
|
||||
Ember<T> m_PreviewEmber;
|
||||
vector<byte> m_PreviewFinalImage;
|
||||
vector<byte> m_PreviewVec;
|
||||
vv4F m_PreviewFinalImage;
|
||||
EmberNs::Renderer<T, float> m_PreviewRenderer;
|
||||
|
||||
private:
|
||||
@ -639,6 +635,7 @@ class TreePreviewRenderer : public PreviewRenderer<T>
|
||||
public:
|
||||
using PreviewRenderer<T>::m_PreviewRun;
|
||||
using PreviewRenderer<T>::m_PreviewEmber;
|
||||
using PreviewRenderer<T>::m_PreviewVec;
|
||||
using PreviewRenderer<T>::m_PreviewRenderer;
|
||||
using PreviewRenderer<T>::m_PreviewFinalImage;
|
||||
|
||||
@ -655,10 +652,8 @@ public:
|
||||
{
|
||||
auto f = m_Controller->m_Fractorium;
|
||||
m_PreviewRenderer.Callback(nullptr);
|
||||
m_PreviewRenderer.NumChannels(4);
|
||||
m_PreviewRenderer.EarlyClip(f->m_Settings->EarlyClip());
|
||||
m_PreviewRenderer.YAxisUp(f->m_Settings->YAxisUp());
|
||||
m_PreviewRenderer.Transparency(f->m_Settings->Transparency());
|
||||
}
|
||||
|
||||
virtual void PreviewRenderFunc(uint start, uint end) override;
|
||||
|
@ -96,15 +96,18 @@ vector<pair<size_t, QTreeWidgetItem*>> Fractorium::GetCurrentEmberIndex()
|
||||
/// <param name="v">The vector holding the RGBA bitmap</param>
|
||||
/// <param name="w">The width of the bitmap</param>
|
||||
/// <param name="h">The height of the bitmap</param>
|
||||
void Fractorium::SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vector<byte>& v, uint w, uint h)
|
||||
void Fractorium::SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vv4F& v, uint w, uint h)
|
||||
{
|
||||
item->SetImage(v, w, h);
|
||||
m_PreviewVec.resize(w * h * 4);
|
||||
Rgba32ToRgba8(v.data(), m_PreviewVec.data(), w, h, m_Settings->Transparency());
|
||||
item->SetImage(m_PreviewVec, w, h);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set all libary tree entries to the name of the corresponding ember they represent.
|
||||
/// Set all libary tree entries to point to the underlying ember they represent.
|
||||
/// </summary>
|
||||
/// <param name="update">A bitfield representing the type of synchronizing to do. Update one or more of index, name or pointer.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SyncLibrary(eLibraryUpdate update)
|
||||
{
|
||||
|
@ -349,9 +349,10 @@ void Fractorium::OnActionSaveCurrentScreen(bool checked)
|
||||
auto filename = SetupSaveImageDialog(m_Controller->Name());
|
||||
auto renderer = m_Controller->Renderer();
|
||||
auto& pixels = *m_Controller->FinalImage();
|
||||
auto rendererCL = dynamic_cast<RendererCLBase*>(m_Controller->Renderer());
|
||||
auto rendererCL = dynamic_cast<RendererCLBase*>(renderer);
|
||||
auto stats = m_Controller->Stats();
|
||||
auto comments = renderer->ImageComments(stats, 0, true);
|
||||
auto settings = FractoriumSettings::Instance();
|
||||
|
||||
if (rendererCL && renderer->PrepFinalAccumVector(pixels))
|
||||
{
|
||||
@ -362,7 +363,7 @@ void Fractorium::OnActionSaveCurrentScreen(bool checked)
|
||||
}
|
||||
}
|
||||
|
||||
m_Controller->SaveCurrentRender(filename, comments, pixels, renderer->FinalRasW(), renderer->FinalRasH(), renderer->NumChannels(), renderer->BytesPerChannel());
|
||||
m_Controller->SaveCurrentRender(filename, comments, pixels, renderer->FinalRasW(), renderer->FinalRasH(), settings->Png16Bit(), settings->Transparency());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -879,7 +880,7 @@ void Fractorium::OnActionFinalRender(bool checked)
|
||||
void Fractorium::OnFinalRenderClose(int result)
|
||||
{
|
||||
m_RenderStatusLabel->setText("Renderer starting...");
|
||||
StartRenderTimer();//Re-create the renderer and start rendering again.
|
||||
StartRenderTimer(false);//Re-create the renderer and start rendering again.
|
||||
ui.ActionStartStopRenderer->setChecked(false);//Re-enable any controls that might have been disabled.
|
||||
OnActionStartStopRenderer(false);
|
||||
}
|
||||
@ -892,10 +893,17 @@ void Fractorium::OnFinalRenderClose(int result)
|
||||
/// <param name="checked">Ignored</param>
|
||||
void Fractorium::OnActionOptions(bool checked)
|
||||
{
|
||||
bool ec = m_Settings->EarlyClip();
|
||||
bool yup = m_Settings->YAxisUp();
|
||||
bool trans = m_Settings->Transparency();
|
||||
|
||||
if (m_OptionsDialog->exec())
|
||||
{
|
||||
bool updatePreviews = ec != m_Settings->EarlyClip() ||
|
||||
yup != m_Settings->YAxisUp() ||
|
||||
trans != m_Settings->Transparency();
|
||||
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.
|
||||
ShutdownAndRecreateFromOptions(updatePreviews);//This will recreate the controller and/or the renderer from the options if necessary, then start the render timer.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,21 +491,38 @@ void Fractorium::SetPaletteFileComboIndex(const string& filename)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the color curve values in the current ember to their default state and also update the curves control.
|
||||
/// Reset the color curve values for the selected curve in the current ember to their default state and also update the curves control.
|
||||
/// Called when ResetCurvesButton is clicked.
|
||||
/// Note if they click Reset Curves when the "All" radio button is selected, then it clears all curves.
|
||||
/// Resets the rendering process at either ACCUM_ONLY by default, or FILTER_AND_ACCUM when using early clip.
|
||||
/// </summary>
|
||||
/// <param name="i">The index of the curve to be cleared, 0 to clear all.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ClearColorCurves()
|
||||
void FractoriumEmberController<T>::ClearColorCurves(int i)
|
||||
{
|
||||
Update([&]
|
||||
{
|
||||
m_Ember.m_Curves.Init();
|
||||
if (i)
|
||||
m_Ember.m_Curves.Init(i);
|
||||
else
|
||||
m_Ember.m_Curves.Init(0);
|
||||
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
|
||||
FillCurvesControl();
|
||||
}
|
||||
|
||||
void Fractorium::OnResetCurvesButtonClicked(bool checked) { m_Controller->ClearColorCurves(); }
|
||||
void Fractorium::OnResetCurvesButtonClicked(bool checked)
|
||||
{
|
||||
if (ui.CurvesAllRadio->isChecked())
|
||||
m_Controller->ClearColorCurves(0);
|
||||
else if (ui.CurvesRedRadio->isChecked())
|
||||
m_Controller->ClearColorCurves(1);
|
||||
else if (ui.CurvesGreenRadio->isChecked())
|
||||
m_Controller->ClearColorCurves(2);
|
||||
else if (ui.CurvesBlueRadio->isChecked())
|
||||
m_Controller->ClearColorCurves(3);
|
||||
else
|
||||
m_Controller->ClearColorCurves(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the coordinate of the curve point.
|
||||
|
@ -115,16 +115,16 @@
|
||||
#include <QWidget>
|
||||
#include <QWidgetAction>
|
||||
|
||||
#define GLM_FORCE_RADIANS 1
|
||||
#define GLM_ENABLE_EXPERIMENTAL 1
|
||||
//#define GLM_FORCE_RADIANS 1
|
||||
//#define GLM_ENABLE_EXPERIMENTAL 1
|
||||
|
||||
#ifndef __APPLE__
|
||||
#define GLM_FORCE_INLINE 1
|
||||
#endif
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
#include "glm/gtc/matrix_transform.hpp"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
//#ifndef __APPLE__
|
||||
// #define GLM_FORCE_INLINE 1
|
||||
//#endif
|
||||
//
|
||||
//#include "glm/glm.hpp"
|
||||
//#include "glm/gtc/matrix_transform.hpp"
|
||||
//#include "glm/gtc/type_ptr.hpp"
|
||||
|
||||
#ifndef _WIN32
|
||||
#undef Bool
|
||||
|
@ -111,49 +111,66 @@ void FractoriumEmberControllerBase::DeleteRenderer()
|
||||
/// This will embed the id, url and nick fields from the options in the image comments.
|
||||
/// </summary>
|
||||
/// <param name="filename">The full path and filename</param>
|
||||
/// <param name="comments">The comments to save in the png or jpg</param>
|
||||
/// <param name="comments">The comments to save in the png, jpg or exr</param>
|
||||
/// <param name="pixels">The buffer containing the pixels</param>
|
||||
/// <param name="width">The width in pixels of the image</param>
|
||||
/// <param name="height">The height in pixels of the image</param>
|
||||
/// <param name="channels">The number of channels, 3 or 4.</param>
|
||||
/// <param name="bpc">The bytes per channel, almost always 1.</param>
|
||||
void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<byte>& pixels, size_t width, size_t height, size_t channels, size_t bpc)
|
||||
/// <param name="png16Bit">Whether to use 16 bits per channel per pixel when saving as Png.</param>
|
||||
/// <param name="transparency">Whether to use alpha when saving as Png or Exr.</param>
|
||||
void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, const EmberImageComments& comments, vector<v4F>& pixels, size_t width, size_t height, bool png16Bit, bool transparency)
|
||||
{
|
||||
if (filename != "")
|
||||
{
|
||||
bool b = false;
|
||||
byte* data = nullptr;
|
||||
vector<byte> vecRgb;
|
||||
auto size = width * height;
|
||||
auto settings = m_Fractorium->m_Settings;
|
||||
QFileInfo fileInfo(filename);
|
||||
QString suffix = fileInfo.suffix();
|
||||
auto settings = m_Fractorium->m_Settings;
|
||||
|
||||
//Ensure dimensions are valid.
|
||||
if (pixels.size() < (width * height * channels * bpc))
|
||||
{
|
||||
m_Fractorium->ShowCritical("Save Failed", "Dimensions didn't match, not saving.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
string nick = settings->Nick().toStdString();
|
||||
|
||||
if (suffix == "png")
|
||||
b = WritePng(s.c_str(), data, width, height, 1, true, comments, id, url, nick);
|
||||
else if (suffix == "jpg")
|
||||
b = WriteJpeg(s.c_str(), data, width, height, 100, true, comments, id, url, nick);
|
||||
else if (suffix == "bmp")
|
||||
b = WriteBmp(s.c_str(), data, width, height);
|
||||
//Ensure dimensions are valid.
|
||||
if (pixels.size() < size)
|
||||
{
|
||||
m_Fractorium->ShowCritical("Save Failed", "Dimensions didn't match, not saving.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = pixels.data();
|
||||
|
||||
if (suffix.endsWith("bmp", Qt::CaseInsensitive) || suffix.endsWith("jpg", Qt::CaseInsensitive))
|
||||
{
|
||||
vector<byte> rgb8Image(size * 3);
|
||||
Rgba32ToRgb8(data, rgb8Image.data(), width, height);
|
||||
|
||||
if (suffix.endsWith("bmp", Qt::CaseInsensitive))
|
||||
b = WriteBmp(s.c_str(), rgb8Image.data(), width, height);
|
||||
else if (suffix.endsWith("jpg", Qt::CaseInsensitive))
|
||||
b = WriteJpeg(s.c_str(), rgb8Image.data(), width, height, 100, true, comments, id, url, nick);
|
||||
}
|
||||
else if (suffix.endsWith("png", Qt::CaseInsensitive))
|
||||
{
|
||||
if (!png16Bit)
|
||||
{
|
||||
vector<byte> rgba8Image(size * 4);
|
||||
Rgba32ToRgba8(data, rgba8Image.data(), width, height, transparency);
|
||||
b = WritePng(s.c_str(), rgba8Image.data(), width, height, 1, true, comments, id, url, nick);//Put an opt here for 1 or 2 bytes.//TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<glm::uint16> rgba16Image(size * 4);
|
||||
Rgba32ToRgba16(data, rgba16Image.data(), width, height, transparency);
|
||||
b = WritePng(s.c_str(), (byte*)rgba16Image.data(), width, height, 2, true, comments, id, url, nick);//Put an opt here for 1 or 2 bytes.//TODO
|
||||
}
|
||||
}
|
||||
else if (suffix.endsWith("exr", Qt::CaseInsensitive))
|
||||
{
|
||||
vector<Rgba> rgba32Image(size);
|
||||
Rgba32ToRgbaExr(data, rgba32Image.data(), width, height, transparency);
|
||||
b = WriteExr(s.c_str(), rgba32Image.data(), width, height, true, comments, id, url, nick);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Fractorium->ShowCritical("Save Failed", "Unrecognized format " + suffix + ", not saving.", true);
|
||||
@ -452,7 +469,7 @@ bool FractoriumEmberController<T>::Render()
|
||||
//Update it on finish because the rendering process is completely done.
|
||||
if (update || ProcessState() == eProcessState::ACCUM_DONE)
|
||||
{
|
||||
if (m_FinalImage.size() == m_Renderer->FinalBufferSize())//Make absolutely sure the correct amount of data is passed.
|
||||
if (m_FinalImage.size() == m_Renderer->FinalDimensions())//Make absolutely sure the correct amount of data is passed.
|
||||
gl->update();
|
||||
|
||||
if (ProcessState() == eProcessState::ACCUM_DONE)
|
||||
@ -509,10 +526,11 @@ bool FractoriumEmberController<T>::Render()
|
||||
/// </summary>
|
||||
/// <param name="renderType">The type of render to create</param>
|
||||
/// <param name="devices">The platform,device index pairs of the devices to use</param>
|
||||
/// <param name="updatePreviews">True to re-render the library previews, else false.</param>
|
||||
/// <param name="shared">True if shared with OpenGL, else false. Default: true.</param>
|
||||
/// <returns>True if nothing went wrong, else false.</returns>
|
||||
template <typename T>
|
||||
bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool shared)
|
||||
bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, const vector<pair<size_t, size_t>>& devices, bool updatePreviews, bool shared)
|
||||
{
|
||||
bool ok = true;
|
||||
auto s = m_Fractorium->m_Settings;
|
||||
@ -565,7 +583,6 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
}
|
||||
|
||||
m_Renderer->Callback(this);
|
||||
m_Renderer->NumChannels(4);//Always using 4 since the GL texture is RGBA.
|
||||
m_Renderer->ReclaimOnResize(true);
|
||||
//Give it an initial ember, will be updated many times later.
|
||||
//Even though the bounds are computed when starting the next render. The OpenGL draw calls use these values, which might get called before the render starts.
|
||||
@ -573,17 +590,15 @@ bool FractoriumEmberController<T>::CreateRenderer(eRendererType renderType, cons
|
||||
m_Renderer->EarlyClip(s->EarlyClip());
|
||||
m_Renderer->YAxisUp(s->YAxisUp());
|
||||
m_Renderer->ThreadCount(s->ThreadCount());
|
||||
m_Renderer->Transparency(s->Transparency());
|
||||
|
||||
if (m_Renderer->RendererType() == eRendererType::CPU_RENDERER)
|
||||
m_Renderer->InteractiveFilter(s->CpuDEFilter() ? eInteractiveFilter::FILTER_DE : eInteractiveFilter::FILTER_LOG);
|
||||
else
|
||||
m_Renderer->InteractiveFilter(s->OpenCLDEFilter() ? eInteractiveFilter::FILTER_DE : eInteractiveFilter::FILTER_LOG);
|
||||
|
||||
if ((m_Renderer->EarlyClip() != m_LibraryPreviewRenderer->EarlyClip()) ||
|
||||
(m_Renderer->YAxisUp() != m_LibraryPreviewRenderer->YAxisUp()) ||
|
||||
(m_Renderer->Transparency() != m_LibraryPreviewRenderer->Transparency()))
|
||||
if (updatePreviews)
|
||||
{
|
||||
m_LibraryPreviewRenderer = make_unique<TreePreviewRenderer<T>>(this, m_Fractorium->ui.LibraryTree, m_EmberFile);//Will take the same settings as the main renderer.
|
||||
RenderLibraryPreviews();
|
||||
}
|
||||
|
||||
@ -618,26 +633,28 @@ void Fractorium::EnableRenderControls(bool enable)
|
||||
/// <summary>
|
||||
/// Wrapper to stop the timer, shutdown the controller and recreate, then restart the controller and renderer from the options.
|
||||
/// </summary>
|
||||
void Fractorium::ShutdownAndRecreateFromOptions()
|
||||
/// <param name="updatePreviews">True to re-render the library previews, else false.</param>
|
||||
void Fractorium::ShutdownAndRecreateFromOptions(bool updatePreviews)
|
||||
{
|
||||
//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.
|
||||
StartRenderTimer(updatePreviews);//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>
|
||||
/// <param name="updatePreviews">True to re-render the library previews, else false.</param>
|
||||
/// <returns>True if nothing went wrong, else false.</returns>
|
||||
bool Fractorium::CreateRendererFromOptions()
|
||||
bool Fractorium::CreateRendererFromOptions(bool updatePreviews)
|
||||
{
|
||||
bool ok = true;
|
||||
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()) ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, v))
|
||||
if (!m_Controller->CreateRenderer((useOpenCL && !v.empty()) ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, v, updatePreviews))
|
||||
{
|
||||
//If using OpenCL, will only get here if creating RendererCL failed, but creating a backup CPU Renderer succeeded.
|
||||
ShowCritical("Renderer Creation Error", "Error creating renderer, most likely a GPU problem. Using CPU instead.");
|
||||
@ -735,25 +752,30 @@ bool Fractorium::CreateControllerFromOptions()
|
||||
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.
|
||||
}
|
||||
|
||||
return m_Controller.get();
|
||||
}
|
||||
|
||||
return m_Controller.get();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the render timer.
|
||||
/// If a renderer has not been created yet, or differs form the options, it will first be created from the options.
|
||||
/// </summary>
|
||||
void Fractorium::StartRenderTimer()
|
||||
/// <param name="updatePreviews">True to re-render the library previews, else false.</param>
|
||||
void Fractorium::StartRenderTimer(bool updatePreviews)
|
||||
{
|
||||
//Starting the render timer, either for the first time
|
||||
//or from a paused state, such as resizing or applying new options.
|
||||
CreateControllerFromOptions();
|
||||
bool newController = CreateControllerFromOptions();
|
||||
|
||||
if (m_Controller.get())
|
||||
{
|
||||
//On program startup, the renderer does not get initialized until now.
|
||||
CreateRendererFromOptions();
|
||||
//If a new controller was created, then previews will have started, so only start the previews if a new controller
|
||||
//was *not* created and updatePreviews is true.
|
||||
CreateRendererFromOptions(updatePreviews && !newController);
|
||||
|
||||
if (m_Controller->Renderer())
|
||||
m_Controller->StartRenderTimer();
|
||||
|
@ -61,16 +61,16 @@ void FractoriumSettings::EnsureDefaults()
|
||||
FinalScale(0);
|
||||
|
||||
if (OpenXmlExt() == "")
|
||||
OpenXmlExt("Flame (*.flame)");
|
||||
OpenXmlExt("*.flame");
|
||||
|
||||
if (SaveXmlExt() == "")
|
||||
SaveXmlExt("Flame (*.flame)");
|
||||
SaveXmlExt(".flame");
|
||||
|
||||
if (OpenImageExt() == "")
|
||||
OpenImageExt("Png (*.png)");
|
||||
OpenImageExt("*.png");
|
||||
|
||||
if (SaveImageExt() == "")
|
||||
SaveImageExt("Png (*.png)");
|
||||
SaveImageExt(".png");
|
||||
|
||||
if (FinalExt() != "jpg" && FinalExt() != "png")
|
||||
FinalExt("png");
|
||||
@ -121,6 +121,9 @@ void FractoriumSettings::ShowGrid(bool b) { setValue(SHOW
|
||||
bool FractoriumSettings::ToggleType() { return value(TOGGLETYPE).toBool(); }
|
||||
void FractoriumSettings::ToggleType(bool b) { setValue(TOGGLETYPE, b); }
|
||||
|
||||
bool FractoriumSettings::Png16Bit() { return value(PNG16BIT).toBool(); }
|
||||
void FractoriumSettings::Png16Bit(bool b) { setValue(PNG16BIT, b); }
|
||||
|
||||
bool FractoriumSettings::ContinuousUpdate() { return value(CONTUPDATE).toBool(); }
|
||||
void FractoriumSettings::ContinuousUpdate(bool b) { setValue(CONTUPDATE, b); }
|
||||
|
||||
@ -229,6 +232,9 @@ void FractoriumSettings::FinalDoAll(bool b) { setValue(FINALDOALL, b);
|
||||
bool FractoriumSettings::FinalDoSequence() { return value(FINALDOSEQUENCE).toBool(); }
|
||||
void FractoriumSettings::FinalDoSequence(bool b) { setValue(FINALDOSEQUENCE, b); }
|
||||
|
||||
bool FractoriumSettings::FinalPng16Bit() { return value(FINALPNG16BIT).toBool(); }
|
||||
void FractoriumSettings::FinalPng16Bit(bool b) { setValue(FINALPNG16BIT, b); }
|
||||
|
||||
bool FractoriumSettings::FinalKeepAspect() { return value(FINALKEEPASPECT).toBool(); }
|
||||
void FractoriumSettings::FinalKeepAspect(bool b) { setValue(FINALKEEPASPECT, b); }
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define SHOWXFORMS "render/showxforms"
|
||||
#define SHOWGRID "render/showgrid"
|
||||
#define TOGGLETYPE "render/toggletype"
|
||||
#define PNG16BIT "render/png16bit"
|
||||
#define DEVICES "render/devices"
|
||||
#define THREADCOUNT "render/threadcount"
|
||||
#define CPUDEFILTER "render/cpudefilter"
|
||||
@ -50,6 +51,7 @@
|
||||
#define FINALSAVEXML "finalrender/savexml"
|
||||
#define FINALDOALL "finalrender/doall"
|
||||
#define FINALDOSEQUENCE "finalrender/dosequence"
|
||||
#define FINALPNG16BIT "finalrender/png16bit"
|
||||
#define FINALKEEPASPECT "finalrender/keepaspect"
|
||||
#define FINALSCALE "finalrender/scale"
|
||||
#define FINALEXT "finalrender/ext"
|
||||
@ -124,6 +126,9 @@ public:
|
||||
bool ToggleType();
|
||||
void ToggleType(bool b);
|
||||
|
||||
bool Png16Bit();
|
||||
void Png16Bit(bool b);
|
||||
|
||||
bool ContinuousUpdate();
|
||||
void ContinuousUpdate(bool b);
|
||||
|
||||
@ -220,6 +225,9 @@ public:
|
||||
bool FinalDoSequence();
|
||||
void FinalDoSequence(bool b);
|
||||
|
||||
bool FinalPng16Bit();
|
||||
void FinalPng16Bit(bool b);
|
||||
|
||||
bool FinalKeepAspect();
|
||||
void FinalKeepAspect(bool b);
|
||||
|
||||
|
@ -43,7 +43,7 @@ void Fractorium::OnActionCpu(bool checked)
|
||||
if (checked && m_Settings->OpenCL())
|
||||
{
|
||||
m_Settings->OpenCL(false);
|
||||
ShutdownAndRecreateFromOptions();
|
||||
ShutdownAndRecreateFromOptions(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ void Fractorium::OnActionCL(bool checked)
|
||||
if (checked && !m_Settings->OpenCL())
|
||||
{
|
||||
m_Settings->OpenCL(true);
|
||||
ShutdownAndRecreateFromOptions();
|
||||
ShutdownAndRecreateFromOptions(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ void Fractorium::OnActionSP(bool checked)
|
||||
if (checked && m_Settings->Double())
|
||||
{
|
||||
m_Settings->Double(false);
|
||||
ShutdownAndRecreateFromOptions();
|
||||
ShutdownAndRecreateFromOptions(true);//Pass true, but it's not needed because creating a new controller will force a library tree re-render.
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ void Fractorium::OnActionDP(bool checked)
|
||||
if (checked && !m_Settings->Double())
|
||||
{
|
||||
m_Settings->Double(true);
|
||||
ShutdownAndRecreateFromOptions();
|
||||
ShutdownAndRecreateFromOptions(true);//Pass true, but it's not needed because creating a new controller will force a library tree re-render.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ void FractoriumEmberController<T>::AffineSetHelper(double d, int index, bool pre
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
AffineDoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
|
||||
if (m_Fractorium->ui.PolarAffineCheckBox->isChecked())
|
||||
{
|
||||
@ -618,7 +618,7 @@ void FractoriumEmberController<T>::FillBothAffines()
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillAffineWithXform(Xform<T>* xform, bool pre)
|
||||
{
|
||||
DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
AffineDoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
|
||||
if (m_Fractorium->ui.PolarAffineCheckBox->isChecked())
|
||||
@ -715,9 +715,9 @@ void Fractorium::OnPolarAffineCheckBoxStateChanged(int state)
|
||||
/// <param name="prec">The precision of the spinner</param>
|
||||
/// <param name="signal">The signal the spinner emits</param>
|
||||
/// <param name="slot">The slot to receive the signal</param>
|
||||
void Fractorium::SetupAffineSpinner(QTableWidget* table, const QObject* receiver, int row, int col, DoubleSpinBox*& spinBox, int height, double min, double max, double step, double prec, const char* signal, const char* slot)
|
||||
void Fractorium::SetupAffineSpinner(QTableWidget* table, const QObject* receiver, int row, int col, AffineDoubleSpinBox*& spinBox, int height, double min, double max, double step, double prec, const char* signal, const char* slot)
|
||||
{
|
||||
spinBox = new DoubleSpinBox(table, height, step);
|
||||
spinBox = new AffineDoubleSpinBox(table, height, step);
|
||||
spinBox->setRange(min, max);
|
||||
spinBox->setDecimals(prec);
|
||||
table->setCellWidget(row, col, spinBox);
|
||||
|
@ -375,5 +375,5 @@ void Fractorium::OnVariationsFilterClearButtonClicked(bool checked)
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
||||
|
@ -54,8 +54,6 @@ void GLWidget::InitGL()
|
||||
void GLWidget::DrawQuad()
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
auto renderer = m_Fractorium->m_Controller->Renderer();
|
||||
auto finalImage = m_Fractorium->m_Controller->FinalImage();
|
||||
|
||||
@ -65,7 +63,7 @@ void GLWidget::DrawQuad()
|
||||
glBindTexture(GL_TEXTURE_2D, m_OutputTexID);//The texture to draw to.
|
||||
|
||||
//Only draw if the dimensions match exactly.
|
||||
if (m_TexWidth == width() && m_TexHeight == height() && ((m_TexWidth * m_TexHeight * 4) == GLint(finalImage->size())))
|
||||
if (m_TexWidth == width() && m_TexHeight == height() && ((m_TexWidth * m_TexHeight) == GLint(finalImage->size())))
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
@ -77,7 +75,7 @@ void GLWidget::DrawQuad()
|
||||
|
||||
//Copy data from CPU to OpenGL if using a CPU renderer. This is not needed when using OpenCL.
|
||||
if (renderer->RendererType() == eRendererType::CPU_RENDERER)
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_TexWidth, m_TexHeight, GL_RGBA, GL_UNSIGNED_BYTE, finalImage->data());
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_TexWidth, m_TexHeight, GL_RGBA, GL_FLOAT, finalImage->data());
|
||||
|
||||
glBegin(GL_QUADS);//This will need to be converted to a shader at some point in the future.
|
||||
glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
|
||||
@ -94,7 +92,6 @@ void GLWidget::DrawQuad()
|
||||
glBindTexture(GL_TEXTURE_2D, 0);//Stop using this texture.
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
@ -267,10 +264,10 @@ void GLEmberController<T>::DrawImage()
|
||||
|
||||
if (SizesMatch())//Ensure all sizes are correct. If not, do nothing.
|
||||
{
|
||||
vector<byte>* finalImage = m_FractoriumEmberController->FinalImage();
|
||||
auto finalImage = m_FractoriumEmberController->FinalImage();
|
||||
|
||||
if ((renderer->RendererType() == eRendererType::OPENCL_RENDERER) || finalImage)//Final image only matters for CPU renderer.
|
||||
if ((renderer->RendererType() == eRendererType::OPENCL_RENDERER) || finalImage->size() == renderer->FinalBufferSize())
|
||||
if ((renderer->RendererType() == eRendererType::OPENCL_RENDERER) || finalImage->size() == renderer->FinalDimensions())
|
||||
m_GL->DrawQuad();//Output image is drawn here.
|
||||
}
|
||||
|
||||
@ -757,7 +754,7 @@ bool GLWidget::Allocate(bool force)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TexWidth, m_TexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_TexWidth, m_TexHeight, 0, GL_RGBA, GL_FLOAT, nullptr);
|
||||
alloc = true;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ bool FractoriumOptionsDialog::OpenCL() { return ui.OpenCLCheckBox->isChecked();
|
||||
bool FractoriumOptionsDialog::Double() { return ui.DoublePrecisionCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::ShowAllXforms() { return ui.ShowAllXformsCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::ToggleType() { return ui.ToggleTypeCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::Png16Bit() { return ui.Png16BitCheckBox->isChecked(); }
|
||||
bool FractoriumOptionsDialog::AutoUnique() { return ui.AutoUniqueCheckBox->isChecked(); }
|
||||
uint FractoriumOptionsDialog::ThreadCount() { return ui.ThreadCountSpin->value(); }
|
||||
uint FractoriumOptionsDialog::RandomCount() { return ui.RandomCountSpin->value(); }
|
||||
@ -174,6 +175,7 @@ void FractoriumOptionsDialog::GuiToData()
|
||||
m_Settings->Double(Double());
|
||||
m_Settings->ShowAllXforms(ShowAllXforms());
|
||||
m_Settings->ToggleType(ToggleType());
|
||||
m_Settings->Png16Bit(Png16Bit());
|
||||
m_Settings->ThreadCount(ThreadCount());
|
||||
m_Settings->RandomCount(RandomCount());
|
||||
m_Settings->CpuSubBatch(ui.CpuSubBatchSpin->value());
|
||||
@ -207,6 +209,7 @@ void FractoriumOptionsDialog::DataToGui()
|
||||
ui.DoublePrecisionCheckBox->setChecked(m_Settings->Double());
|
||||
ui.ShowAllXformsCheckBox->setChecked(m_Settings->ShowAllXforms());
|
||||
ui.ToggleTypeCheckBox->setChecked(m_Settings->ToggleType());
|
||||
ui.Png16BitCheckBox->setChecked(m_Settings->Png16Bit());
|
||||
ui.ThreadCountSpin->setValue(m_Settings->ThreadCount());
|
||||
ui.RandomCountSpin->setValue(m_Settings->RandomCount());
|
||||
ui.CpuSubBatchSpin->setValue(m_Settings->CpuSubBatch());
|
||||
|
@ -39,13 +39,13 @@ protected:
|
||||
private:
|
||||
bool EarlyClip();
|
||||
bool YAxisUp();
|
||||
bool AlphaChannel();
|
||||
bool Transparency();
|
||||
bool ContinuousUpdate();
|
||||
bool OpenCL();
|
||||
bool Double();
|
||||
bool ShowAllXforms();
|
||||
bool ToggleType();
|
||||
bool Png16Bit();
|
||||
bool AutoUnique();
|
||||
uint ThreadCount();
|
||||
uint RandomCount();
|
||||
|
@ -424,6 +424,16 @@ in interactive mode for each mouse movement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="Png16BitCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Save each RGBA component as 16-bits when saving Png files.</p><p>This leads to greater color precision for use in high end rendering and display on HDR monitors, however it makes the file size larger.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save 16-bit Png</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="OptionsXmlSavingTab">
|
||||
@ -846,6 +856,8 @@ in interactive mode for each mouse movement</string>
|
||||
<tabstop>TransparencyCheckBox</tabstop>
|
||||
<tabstop>ShowAllXformsCheckBox</tabstop>
|
||||
<tabstop>ContinuousUpdateCheckBox</tabstop>
|
||||
<tabstop>ToggleTypeCheckBox</tabstop>
|
||||
<tabstop>Png16BitCheckBox</tabstop>
|
||||
<tabstop>RandomCountSpin</tabstop>
|
||||
<tabstop>ThreadCountSpin</tabstop>
|
||||
<tabstop>CpuSubBatchSpin</tabstop>
|
||||
|
@ -496,7 +496,11 @@ QStringList PaletteEditor::SetupOpenImagesDialog()
|
||||
m_FileDialog->setViewMode(QFileDialog::List);
|
||||
m_FileDialog->setFileMode(QFileDialog::ExistingFile);
|
||||
m_FileDialog->setAcceptMode(QFileDialog::AcceptOpen);
|
||||
#ifdef _WIN32
|
||||
m_FileDialog->setNameFilter("Image Files (*.png *.jpg *.bmp)");
|
||||
#else
|
||||
m_FileDialog->setNameFilter("Image Files ( *.jpg *.png)");
|
||||
#endif
|
||||
m_FileDialog->setWindowTitle("Open Image");
|
||||
m_FileDialog->setDirectory(settings->OpenPaletteImageFolder());
|
||||
m_FileDialog->selectNameFilter("*.jpg");
|
||||
@ -515,7 +519,7 @@ QStringList PaletteEditor::SetupOpenImagesDialog()
|
||||
}
|
||||
|
||||
#else
|
||||
auto filename = QFileDialog::getOpenFileName(this, tr("Open Image"), settings->OpenPaletteImageFolder(), tr("Image Files (*.png *.jpg *.bmp)"));
|
||||
auto filename = QFileDialog::getOpenFileName(this, tr("Open Image"), settings->OpenPaletteImageFolder(), tr("Image Files (*.jpg *.png)"));
|
||||
|
||||
if (filename.size() > 0)
|
||||
{
|
||||
|
@ -146,7 +146,7 @@ void SpinBox::OnTimeout()
|
||||
/// <returns>false</returns>
|
||||
bool SpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
|
||||
auto me = dynamic_cast<QMouseEvent*>(e);
|
||||
|
||||
if (isEnabled() && me)
|
||||
{
|
||||
|
Reference in New Issue
Block a user