--User changes

-Show image index in the library and sequence trees.
 -Add progress bar showing when preview renders are complete.
 -Automatically show animation preview when sequence generation is done.
 -Add the ability in the final render dialog to start a render within a sequence from a given point, rather than always having to start from the beginning.
 --Allow using the image index as its name rather than the file name.
This commit is contained in:
Person
2023-12-19 13:24:50 -07:00
parent c3078f018a
commit 9990d538f6
20 changed files with 191 additions and 93 deletions

View File

@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c)
namespace EmberNs
{
#define EMBER_VERSION "23.23.8.101"
#define EMBER_VERSION "23.23.8.102"
//#define FLAM3_COMPAT 1//Uncomment this if you want full compatibility with flam3 regarding some of the trig-based variations in Variations01.h
#define EPS6 T(1e-6)
#define EPS std::numeric_limits<T>::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.

View File

@ -61,7 +61,7 @@
<enum>QFrame::NoFrame</enum>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Fractorium 23.23.8.101&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;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.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;a href=&quot;http://fractorium.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;fractorium.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Fractorium 23.23.8.102&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;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.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;a href=&quot;http://fractorium.com&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;fractorium.com&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>

View File

@ -2,6 +2,9 @@
#include "FractoriumPch.h"
#define INDEX_COL 0
#define NAME_COL 1
template <typename T> class FractoriumEmberController;
/// <summary>
@ -59,7 +62,7 @@ public:
m_Image = QImage(width, height, QImage::Format_RGBA8888);
memcpy(m_Image.scanLine(0), v.data(), SizeOf(v));//Memcpy the data in.
m_Pixmap = QPixmap::fromImage(m_Image).scaled(QSize(size, size), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//Create a QPixmap out of the QImage, scaled to size.
setData(0, Qt::DecorationRole, m_Pixmap);
setData(NAME_COL, Qt::DecorationRole, m_Pixmap);
}
void SetRendered()
@ -92,7 +95,7 @@ public:
m_Ember(ember)
{
setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
setCheckState(0, Qt::Unchecked);
setCheckState(NAME_COL, Qt::Unchecked);
}
/// <summary>
@ -106,18 +109,18 @@ public:
m_Ember(ember)
{
setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
setCheckState(0, Qt::Unchecked);
setCheckState(NAME_COL, Qt::Unchecked);
}
/// <summary>
/// Copy the text of the tree item to the name of the ember.
/// </summary>
void UpdateEmberName() { m_Ember->m_Name = text(0).toStdString(); }
void UpdateEmberName() { m_Ember->m_Name = text(NAME_COL).toStdString(); }
/// <summary>
/// Set the text of the tree item.
/// </summary>
void UpdateEditText() { setText(0, QString::fromStdString(m_Ember->m_Name)); }
void UpdateEditText() { setText(NAME_COL, QString::fromStdString(m_Ember->m_Name)); }
/// <summary>
/// Get a pointer to the ember held by the tree item.

View File

@ -260,14 +260,18 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(QWidget* p, Qt::WindowF
w = SetTabOrder(this, w, ui.FinalRenderSaveXmlCheckBox);
w = SetTabOrder(this, w, ui.FinalRenderDoAllCheckBox);
w = SetTabOrder(this, w, ui.FinalRenderDoSequenceCheckBox);
w = SetTabOrder(this, w, ui.FinalRenderUseNumbersForNames);
w = SetTabOrder(this, w, ui.FinalRenderStartAtCheckBox);
w = SetTabOrder(this, w, ui.FinalRenderCurrentSpin);
w = SetTabOrder(this, w, ui.FinalRenderDeviceTable);
w = SetTabOrder(this, w, ui.FinalRenderApplyToAllCheckBox);
w = SetTabOrder(this, w, ui.FinalRenderDeviceTable);
w = SetTabOrder(this, w, ui.FinalRenderThreadCountSpin);
w = SetTabOrder(this, w, ui.FinalRenderThreadPriorityComboBox);
w = SetTabOrder(this, w, ui.FinalRenderOpenCLSubBatchPctSpin);
w = SetTabOrder(this, w, m_WidthScaleSpin);
w = SetTabOrder(this, w, m_WidthSpin);
w = SetTabOrder(this, w, m_HeightScaleSpin);
w = SetTabOrder(this, w, m_HeightSpin);
w = SetTabOrder(this, w, ui.FinalRenderScaleNoneRadioButton);
w = SetTabOrder(this, w, ui.FinalRenderScaleWidthRadioButton);
w = SetTabOrder(this, w, ui.FinalRenderScaleHeightRadioButton);
@ -314,16 +318,16 @@ void FractoriumFinalRenderDialog::Show(bool fromSequence)
/// <summary>
/// GUI settings wrapper functions, getters only.
/// </summary>
bool FractoriumFinalRenderDialog::EarlyClip() { return ui.FinalRenderEarlyClipCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::YAxisUp() { return ui.FinalRenderYAxisUpCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::Transparency() { return ui.FinalRenderTransparencyCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::OpenCL() { return ui.FinalRenderOpenCLCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::Double() { return ui.FinalRenderDoublePrecisionCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::SaveXml() { return ui.FinalRenderSaveXmlCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::DoAll() { return ui.FinalRenderDoAllCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::DoSequence() { return ui.FinalRenderDoSequenceCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::DoAll() { return ui.FinalRenderDoAllCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::Png16Bit() { return ui.FinalRenderPng16BitCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::UseNumbers() { return ui.FinalRenderUseNumbersForNames->isChecked(); }
bool FractoriumFinalRenderDialog::KeepAspect() { return ui.FinalRenderKeepAspectCheckBox->isChecked(); }
bool FractoriumFinalRenderDialog::ApplyToAll() { return ui.FinalRenderApplyToAllCheckBox->isChecked(); }
QString FractoriumFinalRenderDialog::Ext() { return m_Tbcw->m_Combo->currentText(); }
@ -332,6 +336,7 @@ void FractoriumFinalRenderDialog::Path(const QString& s) { ui.FinalRenderParamsT
QString FractoriumFinalRenderDialog::Prefix() { return m_PrefixEdit->text(); }
QString FractoriumFinalRenderDialog::Suffix() { return m_SuffixEdit->text(); }
uint FractoriumFinalRenderDialog::Current() { return ui.FinalRenderCurrentSpin->value(); }
uint FractoriumFinalRenderDialog::StartAt() { return ui.FinalRenderStartAtCheckBox->isChecked() ? Current() - 1 : 0; }
uint FractoriumFinalRenderDialog::ThreadCount() { return ui.FinalRenderThreadCountSpin->value(); }
#ifdef _WIN32
int FractoriumFinalRenderDialog::ThreadPriority() { return ui.FinalRenderThreadPriorityComboBox->currentIndex() - 2; }
@ -373,6 +378,8 @@ FinalRenderGuiState FractoriumFinalRenderDialog::State()
state.m_DoSequence = DoSequence();
state.m_Png16Bit = Png16Bit();
state.m_KeepAspect = KeepAspect();
state.m_UseNumbers = UseNumbers();
state.m_StartAt = StartAt();
state.m_Scale = Scale();
state.m_Path = Path();
state.m_Ext = Ext();

View File

@ -60,8 +60,9 @@ public:
bool Double();
bool SaveXml();
bool DoAll();
bool DoSequence();
bool Png16Bit();
bool DoSequence();
bool UseNumbers();
bool KeepAspect();
bool ApplyToAll();
eScaleType Scale();
@ -72,6 +73,7 @@ public:
QString Prefix();
QString Suffix();
uint Current();
uint StartAt();
uint ThreadCount();
int ThreadPriority();
double OpenCLSubBatchPct();

View File

@ -131,28 +131,6 @@
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QSpinBox" name="FinalRenderCurrentSpin">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="prefix">
<string/>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QGridLayout" name="FinalRenderGridLayout" columnstretch="0,0">
<item row="0" column="0">
@ -228,7 +206,7 @@
<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>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use temporal samples value to achieve motion blur effect between flames&lt;/p&gt;&lt;p&gt;This increases rendering time and is usually not needed when rendering at a higher frame rate such as 60fps&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Render as Animation Sequence</string>
@ -245,6 +223,52 @@
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="FinalRenderUseNumbersForNames">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use the numerical index of the flame in the file for the output filename instead of the specified filename&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Use Numbers for Names</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<layout class="QGridLayout" name="FinalRenderGridLayout3_2">
<item row="1" column="0">
<widget class="QSpinBox" name="FinalRenderCurrentSpin">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="prefix">
<string/>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="FinalRenderStartAtCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Start rendering at the index specified in the spinner below, rather than starting at the first flame in the file.&lt;/p&gt;&lt;p&gt;This is helpful when resuming a failed/stopped rendering session.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Start at:</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@ -1322,7 +1346,6 @@
<tabstop>FinalRenderOpenCLCheckBox</tabstop>
<tabstop>FinalRenderDoSequenceCheckBox</tabstop>
<tabstop>FinalRenderPng16BitCheckBox</tabstop>
<tabstop>FinalRenderCurrentSpin</tabstop>
<tabstop>FinalRenderThreadCountSpin</tabstop>
<tabstop>FinalRenderThreadPriorityComboBox</tabstop>
<tabstop>FinalRenderOpenCLSubBatchPctSpin</tabstop>

View File

@ -269,6 +269,9 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
if (doAll)
{
m_ImageCount = m_EmberFile.Size();
ostringstream os;
const auto padding = streamsize(std::log10(m_EmberFile.Size())) + 1;
os << setfill('0') << setprecision(0) << fixed;
//Different action required for rendering as animation or not.
if (m_GuiState.m_DoSequence && !m_Renderers.empty())
@ -291,7 +294,7 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
}
else if (it.m_Time <= prev->m_Time)
{
it.m_Time = prev->m_Time + 1;
it.m_Time = prev->m_Time + 1;
}
it.m_TemporalSamples = m_GuiState.m_TemporalSamples;
@ -303,7 +306,19 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
//even when using double precision, which most cards at the time of this writing already exceed.
m_GuiState.m_Strips = 1;
CopyCont(embers, m_EmberFile.m_Embers);
std::atomic<size_t> atomfTime(0);
if (m_GuiState.m_UseNumbers)
{
auto i = 0;
for (auto& it : embers)
{
it.m_Time = i++;
FormatName(it, os, padding);
}
}
std::atomic<size_t> atomfTime(m_GuiState.m_StartAt);
vector<std::thread> threadVec;
threadVec.reserve(m_Renderers.size());
@ -320,13 +335,28 @@ FinalRenderEmberController<T>::FinalRenderEmberController(FractoriumFinalRenderD
else if (m_Renderer.get())//Make sure a renderer was created and render all images, but not as an animation sequence (without temporal samples motion blur).
{
//Render each image, cancelling if m_Run ever gets set to false.
for (auto& it : m_EmberFile.m_Embers)
auto i = m_GuiState.m_StartAt;
while (auto ember = m_EmberFile.Get(i))
{
if (!m_Run)
break;
Output("Image " + ToString<qulonglong>(m_FinishedImageCount.load() + 1) + ":\n" + ComposePath(QString::fromStdString(it.m_Name)));
RenderSingleEmber(it, true, currentStripForProgress);
std::string oldname;
if (m_GuiState.m_UseNumbers)
{
oldname = ember->m_Name;
ember->m_Time = i;
FormatName(*ember, os, padding);
}
Output("Image " + ToString<qulonglong>(m_FinishedImageCount.load() + 1) + ":\n" + ComposePath(QString::fromStdString(ember->m_Name)));
RenderSingleEmber(*ember, true, currentStripForProgress);
i++;
if (m_GuiState.m_UseNumbers)
ember->m_Name = oldname;
}
}
else
@ -1003,6 +1033,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->FinalUseNumbers(m_GuiState.m_UseNumbers);
m_Settings->FinalPng16Bit(m_GuiState.m_Png16Bit);
m_Settings->FinalKeepAspect(m_GuiState.m_KeepAspect);
m_Settings->FinalScale(uint(m_GuiState.m_Scale));

View File

@ -22,7 +22,6 @@ struct FinalRenderGuiState
{
bool m_EarlyClip;
bool m_YAxisUp;
bool m_AlphaChannel;
bool m_Transparency;
bool m_OpenCL;
bool m_Double;
@ -31,12 +30,14 @@ struct FinalRenderGuiState
bool m_Png16Bit;
bool m_DoSequence;
bool m_KeepAspect;
bool m_UseNumbers;
eScaleType m_Scale;
QString m_Path;
QString m_Ext;
QString m_Prefix;
QString m_Suffix;
QList<QVariant> m_Devices;
uint m_StartAt;
uint m_ThreadCount;
int m_ThreadPriority;
double m_SubBatchPct;

View File

@ -6264,8 +6264,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>144</width>
<height>58</height>
<width>269</width>
<height>650</height>
</rect>
</property>
<property name="sizePolicy">
@ -7485,6 +7485,11 @@
<attribute name="headerMinimumSectionSize">
<number>27</number>
</attribute>
<column>
<property name="text">
<string>Index</string>
</property>
</column>
<column>
<property name="text">
<string>Current Flame File</string>
@ -8215,7 +8220,12 @@
</attribute>
<column>
<property name="text">
<string>Sequence</string>
<string>Index</string>
</property>
</column>
<column>
<property name="text">
<string>Image</string>
</property>
</column>
</widget>

View File

@ -83,7 +83,7 @@ void Fractorium::SelectLibraryItem(size_t index)
if (auto emberItem = dynamic_cast<EmberTreeWidgetItemBase*>(top->child(i)))
{
emberItem->setSelected(i == index);
emberItem->setCheckState(0, i == index ? Qt::Checked : Qt::Unchecked);
emberItem->setCheckState(NAME_COL, i == index ? Qt::Checked : Qt::Unchecked);
}
}
}
@ -111,7 +111,7 @@ vector<pair<size_t, QTreeWidgetItem*>> Fractorium::GetCurrentEmberIndex(bool isC
{
if (isChecked)
{
if (item->checkState(0) == Qt::Checked)
if (item->checkState(NAME_COL) == Qt::Checked)
v.push_back(make_pair(index, item));
}
else
@ -154,19 +154,21 @@ void FractoriumEmberController<T>::SyncLibrary(eLibraryUpdate update)
{
for (int i = 0; i < top->childCount() && it != m_EmberFile.m_Embers.end(); ++i, ++it)//Iterate through all of the children, which will represent the open embers.
{
if (auto item = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))//Cast the child widget to the EmberTreeWidgetItem type.
if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(top->child(i)))//Cast the child widget to the EmberTreeWidgetItem type.
{
if (static_cast<uint>(update) & static_cast<uint>(eLibraryUpdate::INDEX))
it->m_Index = i;
if (static_cast<uint>(update) & static_cast<uint>(eLibraryUpdate::NAME))
item->setText(0, QString::fromStdString(it->m_Name));
emberItem->setText(NAME_COL, QString::fromStdString(it->m_Name));
if (static_cast<uint>(update) & static_cast<uint>(eLibraryUpdate::POINTER))
item->SetEmberPointer(&(*it));
emberItem->SetEmberPointer(&(*it));
if (item->checkState(0) == Qt::Checked)
m_EmberFilePointer = item->GetEmber();
if (emberItem->checkState(NAME_COL) == Qt::Checked)
m_EmberFilePointer = emberItem->GetEmber();
emberItem->setText(INDEX_COL, ToString(i));
}
}
}
@ -188,21 +190,23 @@ void FractoriumEmberController<T>::FillLibraryTree(int selectIndex)
tree->clear();
auto fileItem = new QTreeWidgetItem(tree);
QFileInfo info(m_EmberFile.m_Filename);
fileItem->setText(0, info.fileName());
fileItem->setToolTip(0, m_EmberFile.m_Filename);
fileItem->setText(NAME_COL, info.fileName());
fileItem->setToolTip(NAME_COL, m_EmberFile.m_Filename);
fileItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled);
uint i = 0;
for (auto& it : m_EmberFile.m_Embers)
{
auto emberItem = new EmberTreeWidgetItem<T>(&it, fileItem);
auto istr = ToString(i++);
emberItem->setText(INDEX_COL, istr);
if (it.m_Name.empty())
emberItem->setText(0, ToString(i++));
emberItem->setText(NAME_COL, istr);
else
emberItem->setText(0, it.m_Name.c_str());
emberItem->setText(NAME_COL, it.m_Name.c_str());
emberItem->setToolTip(0, emberItem->text(0));
emberItem->setToolTip(NAME_COL, emberItem->text(NAME_COL));
emberItem->SetImage(empy_preview, size, size);
}
@ -233,13 +237,15 @@ void FractoriumEmberController<T>::UpdateLibraryTree()
for (auto it = Advance(m_EmberFile.m_Embers.begin(), i); it != m_EmberFile.m_Embers.end(); ++it)
{
auto emberItem = new EmberTreeWidgetItem<T>(&(*it), top);
auto istr = ToString(i++);
emberItem->setText(INDEX_COL, istr);
if (it->m_Name.empty())
emberItem->setText(0, ToString(i++));
emberItem->setText(NAME_COL, istr);
else
emberItem->setText(0, it->m_Name.c_str());
emberItem->setText(NAME_COL, it->m_Name.c_str());
emberItem->setToolTip(0, emberItem->text(0));
emberItem->setToolTip(NAME_COL, emberItem->text(NAME_COL));
emberItem->SetImage(empy_preview, size, size);
}
@ -270,7 +276,7 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item))
{
auto oldName = emberItem->GetEmber()->m_Name;//First preserve the previous name.
auto newName = emberItem->text(0).toStdString();
auto newName = emberItem->text(NAME_COL).toStdString();
//Checking/unchecking other items shouldn't perform the processing below.
//If nothing changed, nothing to do.
@ -296,7 +302,7 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i
}
else if (const auto parentItem = dynamic_cast<QTreeWidgetItem*>(item))
{
const auto text = parentItem->text(0);
const auto text = parentItem->text(NAME_COL);
if (text != "")
{
@ -485,12 +491,11 @@ template <typename T>
void FractoriumEmberController<T>::AddAnimationItem()
{
auto fileItem = new QTreeWidgetItem(m_Fractorium->ui.SequenceTree);
fileItem->setText(0, "Rendered Animation");
fileItem->setToolTip(0, "Rendered frames can be animated here");
fileItem->setText(NAME_COL, "Rendered Animation");
fileItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
auto emberItem = new EmberTreeWidgetItemBase(fileItem);
emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
emberItem->setToolTip(0, "Animated Frame");
emberItem->setToolTip(INDEX_COL, "Animated Frame");
const uint size = PREVIEW_SIZE;
vector<unsigned char> empy_preview(size * size * 4);
emberItem->SetImage(empy_preview, size, size);
@ -509,34 +514,43 @@ void FractoriumEmberController<T>::FillSequenceTree()
vector<unsigned char> empy_preview(size * size * 4);
const auto tree = m_Fractorium->ui.SequenceTree;
tree->clear();
// Add extra TreeWidget for animation at index 0
//Add extra TreeWidget for animation at index 0.
AddAnimationItem();
m_AnimateTimer->stop();
auto fileItem = new QTreeWidgetItem(tree);
QFileInfo info(m_SequenceFile.m_Filename);
fileItem->setText(0, info.fileName());
fileItem->setToolTip(0, m_SequenceFile.m_Filename);
fileItem->setText(NAME_COL, info.fileName());
fileItem->setToolTip(NAME_COL, m_SequenceFile.m_Filename);
fileItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
uint i = 0;
for (auto& it : m_SequenceFile.m_Embers)
{
auto emberItem = new EmberTreeWidgetItemBase(fileItem);
auto istr = ToString(i++);
if (it.m_Name.empty())
emberItem->setText(0, ToString(i));
emberItem->setText(NAME_COL, istr);
else
emberItem->setText(0, it.m_Name.c_str());
emberItem->setText(NAME_COL, it.m_Name.c_str());
i++;
emberItem->setText(INDEX_COL, istr);
emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
emberItem->setToolTip(0, emberItem->text(0));
emberItem->setToolTip(NAME_COL, emberItem->text(NAME_COL));
emberItem->SetImage(empy_preview, size, size);
}
tree->expandAll();
// Hide the animation item
//Hide, then show the animation item.
tree->collapseItem(tree->topLevelItem(0));
RenderSequencePreviews(0, uint(m_SequenceFile.Size()));
if (const auto animation = tree->topLevelItem(0))
{
animation->setExpanded(true);
m_AnimateFrame = 0;
m_AnimateTimer->start(1000 / m_Fractorium->ui.SequenceAnimationFpsSpinBox->value());
}
}
/// <summary>
@ -550,7 +564,7 @@ void FractoriumEmberController<T>::SequenceTreeItemChanged(QTreeWidgetItem* item
{
if (item == m_Fractorium->ui.SequenceTree->topLevelItem(1))
{
auto text = item->text(0);
auto text = item->text(NAME_COL);
if (text != "")
m_SequenceFile.m_Filename = text;
@ -598,7 +612,7 @@ void Fractorium::SyncFileCountToSequenceCount()
if (const auto top = ui.LibraryTree->topLevelItem(0))
{
const int count = top->childCount() - 1;
ui.LibraryTree->headerItem()->setText(0, "Current Flame File (" + QString::number(top->childCount()) + ")");
ui.LibraryTree->headerItem()->setText(NAME_COL, "Current Flame File (" + QString::number(top->childCount()) + ")");
ui.SequenceStartFlameSpinBox->setMinimum(0);
ui.SequenceStartFlameSpinBox->setMaximum(count);
ui.SequenceStartFlameSpinBox->setValue(0);
@ -835,7 +849,7 @@ void FractoriumEmberController<T>::SequenceAnimateNextFrame()
else
{
animate->m_Pixmap = QPixmap(nth->m_Pixmap);
animate->setData(0, Qt::DecorationRole, animate->m_Pixmap);
animate->setData(NAME_COL, Qt::DecorationRole, animate->m_Pixmap);
}
}
}
@ -859,7 +873,6 @@ void FractoriumEmberController<T>::SequenceAnimateButtonClicked()
{
animation->setExpanded(true);
m_AnimateFrame = 0;
// TODO look at duration based instead of time
m_AnimateTimer->start(1000 / m_Fractorium->ui.SequenceAnimationFpsSpinBox->value());
}
}

View File

@ -87,9 +87,10 @@ void FractoriumSettings::EnsureDefaults()
if (SaveImageExt() == "")
#ifndef __APPLE__
SaveImageExt(".png");
SaveImageExt(".png");
#else
SaveImageExt("Png (*.png)");
SaveImageExt("Png (*.png)");
#endif
if (FinalExt() != "jpg" && FinalExt() != "png" && FinalExt() != "exr"
@ -308,6 +309,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::FinalUseNumbers() { return value(FINALUSENUMBERS).toBool(); }
void FractoriumSettings::FinalUseNumbers(bool b) { setValue(FINALUSENUMBERS, b); }
bool FractoriumSettings::FinalPng16Bit() { return value(FINALPNG16BIT).toBool(); }
void FractoriumSettings::FinalPng16Bit(bool b) { setValue(FINALPNG16BIT, b); }

View File

@ -74,6 +74,7 @@
#define FINALTEMPORALSAMPLES "finalrender/temporalsamples"
#define FINALSUPERSAMPLE "finalrender/supersample"
#define FINALSTRIPS "finalrender/strips"
#define FINALUSENUMBERS "finalrender/usenumbers"
#define XMLWIDTH "xml/width"
#define XMLHEIGHT "xml/height"
@ -270,6 +271,9 @@ public:
bool FinalDoSequence();
void FinalDoSequence(bool b);
bool FinalUseNumbers();
void FinalUseNumbers(bool b);
bool FinalPng16Bit();
void FinalPng16Bit(bool b);