|  |  |  | @ -7,10 +7,11 @@ | 
		
	
		
			
				|  |  |  |  | void Fractorium::InitLibraryUI() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	ui.LibraryTree->SetMainWindow(this); | 
		
	
		
			
				|  |  |  |  | 	connect(ui.LibraryTree,  SIGNAL(itemChanged(QTreeWidgetItem*, int)),	   this, SLOT(OnEmberTreeItemChanged(QTreeWidgetItem*, int)),	    Qt::QueuedConnection); | 
		
	
		
			
				|  |  |  |  | 	//Making the TreeItemChanged() events use a direct connection is absolutely critical. | 
		
	
		
			
				|  |  |  |  | 	connect(ui.LibraryTree,  SIGNAL(itemChanged(QTreeWidgetItem*, int)),	   this, SLOT(OnEmberTreeItemChanged(QTreeWidgetItem*, int)),	    Qt::DirectConnection); | 
		
	
		
			
				|  |  |  |  | 	connect(ui.LibraryTree,  SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection); | 
		
	
		
			
				|  |  |  |  | 	connect(ui.LibraryTree,  SIGNAL(itemActivated(QTreeWidgetItem*, int)),	   this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection); | 
		
	
		
			
				|  |  |  |  | 	connect(ui.SequenceTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)),	   this, SLOT(OnSequenceTreeItemChanged(QTreeWidgetItem*, int)),	Qt::QueuedConnection); | 
		
	
		
			
				|  |  |  |  | 	connect(ui.SequenceTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)),	   this, SLOT(OnSequenceTreeItemChanged(QTreeWidgetItem*, int)),	Qt::DirectConnection); | 
		
	
		
			
				|  |  |  |  | 	connect(ui.SequenceStartPreviewsButton, SIGNAL(clicked(bool)), this, SLOT(OnSequenceStartPreviewsButtonClicked(bool)), Qt::QueuedConnection); | 
		
	
		
			
				|  |  |  |  | 	connect(ui.SequenceStopPreviewsButton,  SIGNAL(clicked(bool)), this, SLOT(OnSequenceStopPreviewsButtonClicked(bool)),  Qt::QueuedConnection); | 
		
	
		
			
				|  |  |  |  | 	connect(ui.SequenceAllButton,           SIGNAL(clicked(bool)), this, SLOT(OnSequenceAllButtonClicked(bool)),           Qt::QueuedConnection); | 
		
	
	
		
			
				
					
					|  |  |  | @ -68,7 +69,7 @@ void Fractorium::InitLibraryUI() | 
		
	
		
			
				|  |  |  |  | /// <param name="index">The 0-based index of the item in the library tree to select</param> | 
		
	
		
			
				|  |  |  |  | void Fractorium::SelectLibraryItem(size_t index) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	if (auto top = ui.LibraryTree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	if (const auto top = ui.LibraryTree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		for (int i = 0; i < top->childCount(); i++) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
	
		
			
				
					
					|  |  |  | @ -89,10 +90,10 @@ vector<pair<size_t, QTreeWidgetItem*>> Fractorium::GetCurrentEmberIndex() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int index = 0; | 
		
	
		
			
				|  |  |  |  | 	QTreeWidgetItem* item = nullptr; | 
		
	
		
			
				|  |  |  |  | 	auto tree = ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  | 	const auto tree = ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  | 	vector<pair<size_t, QTreeWidgetItem*>> v; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (auto top = tree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	if (const auto top = tree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers. | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
	
		
			
				
					
					|  |  |  | @ -117,7 +118,7 @@ vector<pair<size_t, QTreeWidgetItem*>> Fractorium::GetCurrentEmberIndex() | 
		
	
		
			
				|  |  |  |  | /// <param name="h">The height of the bitmap</param> | 
		
	
		
			
				|  |  |  |  | void Fractorium::SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vv4F& v, uint w, uint h) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	m_PreviewVec.resize(w * h * 4); | 
		
	
		
			
				|  |  |  |  | 	m_PreviewVec.resize(size_t(w) * size_t(h) * 4); | 
		
	
		
			
				|  |  |  |  | 	Rgba32ToRgba8(v.data(), m_PreviewVec.data(), w, h, m_Settings->Transparency()); | 
		
	
		
			
				|  |  |  |  | 	item->SetImage(m_PreviewVec, w, h); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  | @ -131,9 +132,9 @@ template <typename T> | 
		
	
		
			
				|  |  |  |  | void FractoriumEmberController<T>::SyncLibrary(eLibraryUpdate update) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	auto it = m_EmberFile.m_Embers.begin(); | 
		
	
		
			
				|  |  |  |  | 	auto tree = m_Fractorium->ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  | 	const auto tree = m_Fractorium->ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (auto top = tree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	if (const auto top = tree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		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. | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
	
		
			
				
					
					|  |  |  | @ -166,11 +167,10 @@ void FractoriumEmberController<T>::FillLibraryTree(int selectIndex) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	uint size = 64; | 
		
	
		
			
				|  |  |  |  | 	uint i = 0; | 
		
	
		
			
				|  |  |  |  | 	auto tree = m_Fractorium->ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  | 	const auto tree = m_Fractorium->ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  | 	vector<byte> v(size * size * 4); | 
		
	
		
			
				|  |  |  |  | 	StopAllPreviewRenderers(); | 
		
	
		
			
				|  |  |  |  | 	tree->clear(); | 
		
	
		
			
				|  |  |  |  | 	QCoreApplication::processEvents(); | 
		
	
		
			
				|  |  |  |  | 	auto fileItem = new QTreeWidgetItem(tree); | 
		
	
		
			
				|  |  |  |  | 	QFileInfo info(m_EmberFile.m_Filename); | 
		
	
		
			
				|  |  |  |  | 	fileItem->setText(0, info.fileName()); | 
		
	
	
		
			
				
					
					|  |  |  | @ -205,13 +205,13 @@ void FractoriumEmberController<T>::FillLibraryTree(int selectIndex) | 
		
	
		
			
				|  |  |  |  | template <typename T> | 
		
	
		
			
				|  |  |  |  | void FractoriumEmberController<T>::UpdateLibraryTree() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	uint size = 64; | 
		
	
		
			
				|  |  |  |  | 	const uint size = 64; | 
		
	
		
			
				|  |  |  |  | 	vector<byte> v(size * size * 4); | 
		
	
		
			
				|  |  |  |  | 	auto tree = m_Fractorium->ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  | 	const auto tree = m_Fractorium->ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (auto top = tree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		int origChildCount = top->childCount(); | 
		
	
		
			
				|  |  |  |  | 		const int origChildCount = top->childCount(); | 
		
	
		
			
				|  |  |  |  | 		int i = origChildCount; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		for (auto it = Advance(m_EmberFile.m_Embers.begin(), i); it != m_EmberFile.m_Embers.end(); ++it) | 
		
	
	
		
			
				
					
					|  |  |  | @ -249,25 +249,24 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	try | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		auto tree = m_Fractorium->ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  | 		const auto tree = m_Fractorium->ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (auto emberItem = dynamic_cast<EmberTreeWidgetItem<T>*>(item)) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			if (!emberItem->isSelected())//Checking/unchecking other items shouldn't perform the processing below. | 
		
	
		
			
				|  |  |  |  | 			auto oldName = emberItem->GetEmber()->m_Name;//First preserve the previous name. | 
		
	
		
			
				|  |  |  |  | 			auto newName = emberItem->text(0).toStdString(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			//Checking/unchecking other items shouldn't perform the processing below. | 
		
	
		
			
				|  |  |  |  | 			//If nothing changed, nothing to do. | 
		
	
		
			
				|  |  |  |  | 			if (!emberItem->isSelected() && newName == oldName) | 
		
	
		
			
				|  |  |  |  | 				return; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if (emberItem->text(0).isEmpty())//Prevent empty string. | 
		
	
		
			
				|  |  |  |  | 			if (newName.empty())//Prevent empty string. | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				emberItem->UpdateEditText(); | 
		
	
		
			
				|  |  |  |  | 				return; | 
		
	
		
			
				|  |  |  |  | 			} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			string oldName = emberItem->GetEmber()->m_Name;//First preserve the previous name. | 
		
	
		
			
				|  |  |  |  | 			string newName = emberItem->text(0).toStdString(); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if (oldName == newName)//If nothing changed, nothing to do. | 
		
	
		
			
				|  |  |  |  | 				return; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			emberItem->UpdateEmberName();//Copy edit text to the ember's name variable. | 
		
	
		
			
				|  |  |  |  | 			m_EmberFile.MakeNamesUnique();//Ensure all names remain unique. | 
		
	
		
			
				|  |  |  |  | 			SyncLibrary(eLibraryUpdate::NAME);//Copy all ember names to the tree items since some might have changed to be made unique. | 
		
	
	
		
			
				
					
					|  |  |  | @ -281,7 +280,7 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		else if (auto parentItem = dynamic_cast<QTreeWidgetItem*>(item)) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			QString text = parentItem->text(0); | 
		
	
		
			
				|  |  |  |  | 			auto text = parentItem->text(0); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if (text != "") | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
	
		
			
				
					
					|  |  |  | @ -298,7 +297,7 @@ void FractoriumEmberController<T>::EmberTreeItemChanged(QTreeWidgetItem* item, i | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void Fractorium::OnEmberTreeItemChanged(QTreeWidgetItem* item, int col) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	if (ui.LibraryTree->topLevelItemCount())//This can sometimes be spurriously called even when the tree is empty. | 
		
	
		
			
				|  |  |  |  | 	if (item && ui.LibraryTree->topLevelItemCount())//This can sometimes be spurriously called even when the tree is empty. | 
		
	
		
			
				|  |  |  |  | 		m_Controller->EmberTreeItemChanged(item, col); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @ -334,9 +333,9 @@ template <typename T> | 
		
	
		
			
				|  |  |  |  | void FractoriumEmberController<T>::MoveLibraryItems(const QModelIndexList& items, int destRow) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	int i = 0; | 
		
	
		
			
				|  |  |  |  | 	auto startRow = items[0].row(); | 
		
	
		
			
				|  |  |  |  | 	auto tree = m_Fractorium->ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  | 	auto top = tree->topLevelItem(0); | 
		
	
		
			
				|  |  |  |  | 	const auto startRow = items[0].row(); | 
		
	
		
			
				|  |  |  |  | 	const auto tree = m_Fractorium->ui.LibraryTree; | 
		
	
		
			
				|  |  |  |  | 	const auto top = tree->topLevelItem(0); | 
		
	
		
			
				|  |  |  |  | 	list<string> names; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	for (auto& item : items) | 
		
	
	
		
			
				
					
					|  |  |  | @ -344,7 +343,7 @@ void FractoriumEmberController<T>::MoveLibraryItems(const QModelIndexList& items | 
		
	
		
			
				|  |  |  |  | 			names.push_back(temp->m_Name); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	auto b = m_EmberFile.m_Embers.begin(); | 
		
	
		
			
				|  |  |  |  | 	auto result = Gather(b, m_EmberFile.m_Embers.end(), Advance(b, destRow), [&](const Ember<T>& ember) | 
		
	
		
			
				|  |  |  |  | 	const auto result = Gather(b, m_EmberFile.m_Embers.end(), Advance(b, destRow), [&](const Ember<T>& ember) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		auto position = std::find(names.begin(), names.end(), ember.m_Name); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @ -387,7 +386,7 @@ void FractoriumEmberController<T>::Delete(const vector<pair<size_t, QTreeWidgetI | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	//Select the next item in the tree closest to the last one that was deleted. | 
		
	
		
			
				|  |  |  |  | 	if (auto top = m_Fractorium->ui.LibraryTree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	if (const auto top = m_Fractorium->ui.LibraryTree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		last = std::min<uint>(top->childCount() - 1, last); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @ -421,9 +420,9 @@ void FractoriumEmberController<T>::RenderPreviews(QTreeWidget* tree, TreePreview | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if (start == UINT_MAX && end == UINT_MAX) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		if (auto top = tree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 		if (const auto top = tree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			int childCount = top->childCount(); | 
		
	
		
			
				|  |  |  |  | 			const auto childCount = top->childCount(); | 
		
	
		
			
				|  |  |  |  | 			vector<byte> emptyPreview(PREVIEW_SIZE * PREVIEW_SIZE * 4); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			for (int i = 0; i < childCount; i++) | 
		
	
	
		
			
				
					
					|  |  |  | @ -469,13 +468,12 @@ void FractoriumEmberController<T>::StopAllPreviewRenderers() | 
		
	
		
			
				|  |  |  |  | template <typename T> | 
		
	
		
			
				|  |  |  |  | void FractoriumEmberController<T>::FillSequenceTree() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	uint size = 64; | 
		
	
		
			
				|  |  |  |  | 	const uint size = 64; | 
		
	
		
			
				|  |  |  |  | 	uint i = 0; | 
		
	
		
			
				|  |  |  |  | 	auto tree = m_Fractorium->ui.SequenceTree; | 
		
	
		
			
				|  |  |  |  | 	const auto tree = m_Fractorium->ui.SequenceTree; | 
		
	
		
			
				|  |  |  |  | 	vector<byte> v(size * size * 4); | 
		
	
		
			
				|  |  |  |  | 	m_SequencePreviewRenderer->Stop(); | 
		
	
		
			
				|  |  |  |  | 	tree->clear(); | 
		
	
		
			
				|  |  |  |  | 	QCoreApplication::processEvents();//Having to flush events is usually a sign of poor design. However, in this case, it's critical to have this here, else rapid button clicks will crash. | 
		
	
		
			
				|  |  |  |  | 	auto fileItem = new QTreeWidgetItem(tree); | 
		
	
		
			
				|  |  |  |  | 	QFileInfo info(m_SequenceFile.m_Filename); | 
		
	
		
			
				|  |  |  |  | 	fileItem->setText(0, info.fileName()); | 
		
	
	
		
			
				
					
					|  |  |  | @ -512,7 +510,7 @@ void FractoriumEmberController<T>::SequenceTreeItemChanged(QTreeWidgetItem* item | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	if (item == m_Fractorium->ui.SequenceTree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		QString text = item->text(0); | 
		
	
		
			
				|  |  |  |  | 		auto text = item->text(0); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (text != "") | 
		
	
		
			
				|  |  |  |  | 			m_SequenceFile.m_Filename = text; | 
		
	
	
		
			
				
					
					|  |  |  | @ -521,7 +519,7 @@ void FractoriumEmberController<T>::SequenceTreeItemChanged(QTreeWidgetItem* item | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | void Fractorium::OnSequenceTreeItemChanged(QTreeWidgetItem* item, int col) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	if (ui.SequenceTree->topLevelItemCount()) | 
		
	
		
			
				|  |  |  |  | 	if (item && ui.SequenceTree->topLevelItemCount()) | 
		
	
		
			
				|  |  |  |  | 		m_Controller->SequenceTreeItemChanged(item, col); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @ -549,9 +547,9 @@ void Fractorium::OnSequenceStopPreviewsButtonClicked(bool checked) { m_Controlle | 
		
	
		
			
				|  |  |  |  | /// </summary> | 
		
	
		
			
				|  |  |  |  | void Fractorium::SyncFileCountToSequenceCount() | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	if (auto top = ui.LibraryTree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	if (const auto top = ui.LibraryTree->topLevelItem(0)) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		int count = top->childCount() - 1; | 
		
	
		
			
				|  |  |  |  | 		const int count = top->childCount() - 1; | 
		
	
		
			
				|  |  |  |  | 		ui.LibraryTree->headerItem()->setText(0, "Current Flame File (" + QString::number(top->childCount()) + ")"); | 
		
	
		
			
				|  |  |  |  | 		ui.SequenceStartFlameSpinBox->setMinimum(0); | 
		
	
		
			
				|  |  |  |  | 		ui.SequenceStartFlameSpinBox->setMaximum(count); | 
		
	
	
		
			
				
					
					|  |  |  | @ -581,33 +579,33 @@ void FractoriumEmberController<T>::SequenceGenerateButtonClicked() | 
		
	
		
			
				|  |  |  |  | 	auto& ui = m_Fractorium->ui; | 
		
	
		
			
				|  |  |  |  | 	auto s = m_Fractorium->m_Settings; | 
		
	
		
			
				|  |  |  |  | 	//Bools for determining whether to use hard coded vs. random values. | 
		
	
		
			
				|  |  |  |  | 	bool randStagger = ui.SequenceRandomizeStaggerCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	bool randFramesRot = ui.SequenceRandomizeFramesPerRotCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	bool randRot = ui.SequenceRandomizeRotationsCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	bool randBlend = ui.SequenceRandomizeBlendFramesCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	bool randBlendRot = ui.SequenceRandomizeRotationsPerBlendCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	const bool randStagger = ui.SequenceRandomizeStaggerCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	const bool randFramesRot = ui.SequenceRandomizeFramesPerRotCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	const bool randRot = ui.SequenceRandomizeRotationsCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	const bool randBlend = ui.SequenceRandomizeBlendFramesCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	const bool randBlendRot = ui.SequenceRandomizeRotationsPerBlendCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	//The direction to rotate the loops. | 
		
	
		
			
				|  |  |  |  | 	bool loopsCw = ui.SequenceRotationsCWCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	bool loopsBlendCw = ui.SequenceRotationsPerBlendCWCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	const bool loopsCw = ui.SequenceRotationsCWCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	const bool loopsBlendCw = ui.SequenceRotationsPerBlendCWCheckBox->isChecked(); | 
		
	
		
			
				|  |  |  |  | 	//Whether to stagger, default is 1 which means no stagger. | 
		
	
		
			
				|  |  |  |  | 	double stagger = ui.SequenceStaggerSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	double staggerMax = ui.SequenceRandomStaggerMaxSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const double stagger = ui.SequenceStaggerSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const double staggerMax = ui.SequenceRandomStaggerMaxSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	//Rotations on keyframes. | 
		
	
		
			
				|  |  |  |  | 	double rots = ui.SequenceRotationsSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	double rotsMax = ui.SequenceRandomRotationsMaxSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const double rots = ui.SequenceRotationsSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const double rotsMax = ui.SequenceRandomRotationsMaxSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	//Number of frames it takes to rotate a keyframe. | 
		
	
		
			
				|  |  |  |  | 	int framesPerRot = ui.SequenceFramesPerRotSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	int framesPerRotMax = ui.SequenceRandomFramesPerRotMaxSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const int framesPerRot = ui.SequenceFramesPerRotSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const int framesPerRotMax = ui.SequenceRandomFramesPerRotMaxSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	//Number of frames it takes to interpolate. | 
		
	
		
			
				|  |  |  |  | 	int framesBlend = ui.SequenceBlendFramesSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	int framesBlendMax = ui.SequenceRandomBlendMaxFramesSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const int framesBlend = ui.SequenceBlendFramesSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const int framesBlendMax = ui.SequenceRandomBlendMaxFramesSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	//Number of rotations performed during interpolation. | 
		
	
		
			
				|  |  |  |  | 	int rotsPerBlend = ui.SequenceRotationsPerBlendSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	int rotsPerBlendMax = ui.SequenceRotationsPerBlendMaxSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	size_t start = ui.SequenceStartFlameSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	size_t stop = ui.SequenceStopFlameSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	size_t startCount = ui.SequenceStartCountSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	size_t keyFrames = (stop - start) + 1; | 
		
	
		
			
				|  |  |  |  | 	const int rotsPerBlend = ui.SequenceRotationsPerBlendSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const int rotsPerBlendMax = ui.SequenceRotationsPerBlendMaxSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const size_t start = ui.SequenceStartFlameSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const size_t stop = ui.SequenceStopFlameSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const size_t startCount = ui.SequenceStartCountSpinBox->value(); | 
		
	
		
			
				|  |  |  |  | 	const size_t keyFrames = (stop - start) + 1; | 
		
	
		
			
				|  |  |  |  | 	size_t frameCount = 0; | 
		
	
		
			
				|  |  |  |  | 	double frames = 0; | 
		
	
		
			
				|  |  |  |  | 	vector<pair<size_t, size_t>> devices;//Dummy. | 
		
	
	
		
			
				
					
					|  |  |  | @ -674,18 +672,18 @@ void FractoriumEmberController<T>::SequenceGenerateButtonClicked() | 
		
	
		
			
				|  |  |  |  | 	double blend; | 
		
	
		
			
				|  |  |  |  | 	size_t frame; | 
		
	
		
			
				|  |  |  |  | 	Ember<T> embers[2];//Spin needs contiguous array below, and this will also get modified, so a copy is needed to avoid modifying the embers in the original file. | 
		
	
		
			
				|  |  |  |  | 	auto padding = streamsize(std::log10(frames)) + 1; | 
		
	
		
			
				|  |  |  |  | 	const auto padding = streamsize(std::log10(frames)) + 1; | 
		
	
		
			
				|  |  |  |  | 	auto it = Advance(m_EmberFile.m_Embers.begin(), start); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	for (size_t i = start; i <= stop && it != m_EmberFile.m_Embers.end(); i++, ++it) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		double rotations = randRot ? m_Rand.Frand<double>(rots, rotsMax) : rots; | 
		
	
		
			
				|  |  |  |  | 		const auto rotations = randRot ? m_Rand.Frand<double>(rots, rotsMax) : rots; | 
		
	
		
			
				|  |  |  |  | 		embers[0] = *it; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if (rotations > 0) | 
		
	
		
			
				|  |  |  |  | 		{ | 
		
	
		
			
				|  |  |  |  | 			double rotFrames = randFramesRot ? m_Rand.Frand<double>(framesPerRot, framesPerRotMax) : framesPerRot; | 
		
	
		
			
				|  |  |  |  | 			size_t roundFrames = size_t(std::round(rotFrames * rotations)); | 
		
	
		
			
				|  |  |  |  | 			const auto rotFrames = randFramesRot ? m_Rand.Frand<double>(framesPerRot, framesPerRotMax) : framesPerRot; | 
		
	
		
			
				|  |  |  |  | 			const auto roundFrames = size_t(std::round(rotFrames * rotations)); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			for (frame = 0; frame < roundFrames; frame++) | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
	
		
			
				
					
					|  |  |  | @ -711,9 +709,9 @@ void FractoriumEmberController<T>::SequenceGenerateButtonClicked() | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			auto it2 = it;//Need a quick temporary to avoid modifying it which is used in the loop. | 
		
	
		
			
				|  |  |  |  | 			embers[1] = *(++it2);//Get the next ember to be used with blending below. | 
		
	
		
			
				|  |  |  |  | 			size_t blendFrames = randBlend ? m_Rand.Frand<double>(framesBlend, framesBlendMax) : framesBlend; | 
		
	
		
			
				|  |  |  |  | 			double d = randBlendRot ? m_Rand.Frand<double>(rotsPerBlend, rotsPerBlendMax) : double(rotsPerBlend); | 
		
	
		
			
				|  |  |  |  | 			size_t rpb = size_t(std::round(d)); | 
		
	
		
			
				|  |  |  |  | 			const auto blendFrames = randBlend ? m_Rand.Frand<double>(framesBlend, framesBlendMax) : framesBlend; | 
		
	
		
			
				|  |  |  |  | 			const auto d = randBlendRot ? m_Rand.Frand<double>(rotsPerBlend, rotsPerBlendMax) : double(rotsPerBlend); | 
		
	
		
			
				|  |  |  |  | 			const auto rpb = size_t(std::round(d)); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 			if (randStagger) | 
		
	
		
			
				|  |  |  |  | 				tools.Stagger(m_Rand.Frand<double>(stagger, staggerMax)); | 
		
	
	
		
			
				
					
					|  |  |  | @ -722,7 +720,7 @@ void FractoriumEmberController<T>::SequenceGenerateButtonClicked() | 
		
	
		
			
				|  |  |  |  | 			{ | 
		
	
		
			
				|  |  |  |  | 				//if (frame == 43) | 
		
	
		
			
				|  |  |  |  | 				//	cout << frame << endl; | 
		
	
		
			
				|  |  |  |  | 				bool seqFlag = frame == 0 || (frame == blendFrames - 1); | 
		
	
		
			
				|  |  |  |  | 				const auto seqFlag = frame == 0 || (frame == blendFrames - 1); | 
		
	
		
			
				|  |  |  |  | 				blend = frame / double(blendFrames); | 
		
	
		
			
				|  |  |  |  | 				result.Clear(); | 
		
	
		
			
				|  |  |  |  | 				tools.SpinInter(&embers[0], nullptr, result, startCount + frameCount++, seqFlag, blend, rpb, loopsBlendCw); | 
		
	
	
		
			
				
					
					|  |  |  | 
 |