mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 21:20:07 -05:00
018ba26b5f
-Add support for multiple GPU devices. --These options are present in the command line and in Fractorium. -Change scheme of specifying devices from platform,device to just total device index. --Single number on the command line. --Change from combo boxes for device selection to a table of all devices in Fractorium. -Temporal samples defaults to 100 instead of 1000 which was needless overkill. --Bug fixes -EmberAnimate, EmberRender, FractoriumSettings, FinalRenderDialog: Fix wrong order of arguments to Clamp() when assigning thread priority. -VariationsDC.h: Fix NVidia OpenCL compilation error in DCTriangleVariation. -FractoriumXformsColor.cpp: Checking for null pixmap pointer is not enough, must also check if the underlying buffer is null via call to QPixmap::isNull(). --Code changes -Ember.h: Add case for FLAME_MOTION_NONE and default in ApplyFlameMotion(). -EmberMotion.h: Call base constructor. -EmberPch.h: #pragma once only on Windows. -EmberToXml.h: --Handle different types of exceptions. --Add default cases to ToString(). -Isaac.h: Remove unused variable in constructor. -Point.h: Call base constructor in Color(). -Renderer.h/cpp: --Add bool to Alloc() to only allocate memory for the histogram. Needed for multi-GPU. --Make CoordMap() return a const ref, not a pointer. -SheepTools.h: --Use 64-bit types like the rest of the code already does. --Fix some comment misspellings. -Timing.h: Make BeginTime(), EndTime(), ElapsedTime() and Format() be const functions. -Utils.h: --Add new functions Equal() and Split(). --Handle more exception types in ReadFile(). --Get rid of most legacy blending of C and C++ argument parsing. -XmlToEmber.h: --Get rid of most legacy blending of C and C++ code from flam3. --Remove some unused variables. -EmberAnimate: --Support multi-GPU processing that alternates full frames between devices. --Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option. --Remove bucketT template parameter, and hard code float in its place. --If a render fails, exit since there is no point in continuing an animation with a missing frame. --Pass variables to threaded save better, which most likely fixes a very subtle bug that existed before. --Remove some unused variables. -EmberGenome, EmberRender: --Support multi-GPU processing that alternates full frames between devices. --Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option. --Remove bucketT template parameter, and hard code float in its place. -EmberRender: --Support multi-GPU processing that alternates full frames between devices. --Use OpenCLInfo instead of OpenCLWrapper for --openclinfo option. --Remove bucketT template parameter, and hard code float in its place. --Only print values when not rendering with OpenCL, since they're always 0 in that case. -EmberCLPch.h: --#pragma once only on Windows. --#include <atomic>. -IterOpenCLKernelCreator.h: Add new kernel for summing two histograms. This is needed for multi-GPU. -OpenCLWrapper.h: --Move all OpenCL info related code into its own class OpenCLInfo. --Add members to cache the values of global memory size and max allocation size. -RendererCL.h/cpp: --Redesign to accomodate multi-GPU. --Constructor now takes a vector of devices. --Remove DumpErrorReport() function, it's handled in the base. --ClearBuffer(), ReadPoints(), WritePoints(), ReadHist() and WriteHist() now optionally take a device index as a parameter. --MakeDmap() override and m_DmapCL member removed because it no longer applies since the histogram is always float since the last commit. --Add new function SumDeviceHist() to sum histograms from two devices by first copying to a temporary on the host, then a temporary on the device, then summing. --m_Calls member removed, as it's now per-device. --OpenCLWrapper removed. --m_Seeds member is now a vector of vector of seeds, to accomodate a separate and different array of seeds for each device. --Added member m_Devices, a vector of unique_ptr of RendererCLDevice. -EmberCommon.h --Added Devices() function to convert from a vector of device indices to a vector of platform,device indices. --Changed CreateRenderer() to accept a vector of devices to create a single RendererCL which will split work across multiple devices. --Added CreateRenderers() function to accept a vector of devices to create multiple RendererCL, each which will render on a single device. --Add more comments to some existing functions. -EmberCommonPch.h: #pragma once only on Windows. -EmberOptions.h: --Remove --platform option, it's just sequential device number now with the --device option. --Make --out be OPT_USE_RENDER instead of OPT_RENDER_ANIM since it's an error condition when animating. It makes no sense to write all frames to a single image. --Add Devices() function to parse comma separated --device option string and return a vector of device indices. --Make int and uint types be 64-bit, so intmax_t and size_t. --Make better use of macros. -JpegUtils.h: Make string parameters to WriteJpeg() and WritePng() be const ref. -All project files: Turn off buffer security check option in Visual Studio (/Gs-) -deployment.pri: Remove the line OTHER_FILES +=, it's pointless and was causing problems. -Ember.pro, EmberCL.pro: Add CONFIG += plugin, otherwise it wouldn't link. -EmberCL.pro: Add new files for multi-GPU support. -build_all.sh: use -j4 and QMAKE=${QMAKE:/usr/bin/qmake} -shared_settings.pri: -Add version string. -Remove old DESTDIR definitions. -Add the following lines or else nothing would build: CONFIG(release, debug|release) { CONFIG += warn_off DESTDIR = ../../../Bin/release } CONFIG(debug, debug|release) { DESTDIR = ../../../Bin/debug } QMAKE_POST_LINK += $$quote(cp --update ../../../Data/flam3-palettes.xml $${DESTDIR}$$escape_expand(\n\t)) LIBS += -L/usr/lib -lpthread -AboutDialog.ui: Another futile attempt to make it look correct on Linux. -FinalRenderDialog.h/cpp: --Add support for multi-GPU. --Change from combo boxes for device selection to a table of all devices. --Ensure device selection makes sense. --Remove "FinalRender" prefix of various function names, it's implied given the context. -FinalRenderEmberController.h/cpp: --Add support for multi-GPU. --Change m_FinishedImageCount to be atomic. --Move CancelRender() from the base to FinalRenderEmberController<T>. --Refactor RenderComplete() to omit any progress related functionality or image saving since it can be potentially ran in a thread. --Consolidate setting various renderer fields into SyncGuiToRenderer(). -Fractorium.cpp: Allow for resizing of the options dialog to show the entire device table. -FractoriumCommon.h: Add various functions to handle a table showing the available OpenCL devices on the system. -FractoriumEmberController.h/cpp: Remove m_FinalImageIndex, it's no longer needed. -FractoriumRender.cpp: Scale the interactive sub batch count and quality by the number of devices used. -FractoriumSettings.h/cpp: --Temporal samples defaults to 100 instead of 1000 which was needless overkill. --Add multi-GPU support, remove old device,platform pair. -FractoriumToolbar.cpp: Disable OpenCL toolbar button if there are no devices present on the system. -FractoriumOptionsDialog.h/cpp: --Add support for multi-GPU. --Consolidate more assignments in DataToGui(). --Enable/disable CPU/OpenCL items in response to OpenCL checkbox event. -Misc: Convert almost everything to size_t for unsigned, intmax_t for signed.
412 lines
16 KiB
C++
412 lines
16 KiB
C++
#include "FractoriumPch.h"
|
|
#include "Fractorium.h"
|
|
#include "PaletteTableWidgetItem.h"
|
|
|
|
#define PALETTE_CELL_HEIGHT 16
|
|
|
|
/// <summary>
|
|
/// Initialize the palette UI.
|
|
/// </summary>
|
|
void Fractorium::InitPaletteUI()
|
|
{
|
|
int spinHeight = 20, row = 0;
|
|
QTableWidget* paletteTable = ui.PaletteListTable;
|
|
QTableWidget* palettePreviewTable = ui.PalettePreviewTable;
|
|
|
|
connect(ui.PaletteFilenameCombo, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnPaletteFilenameComboChanged(const QString&)), Qt::QueuedConnection);
|
|
|
|
connect(paletteTable, SIGNAL(cellClicked(int, int)), this, SLOT(OnPaletteCellClicked(int, int)), Qt::QueuedConnection);
|
|
connect(paletteTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(OnPaletteCellDoubleClicked(int, int)), Qt::QueuedConnection);
|
|
|
|
//Palette adjustment table.
|
|
QTableWidget* table = ui.PaletteAdjustTable;
|
|
table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//Split width over all columns evenly.
|
|
|
|
SetupSpinner<SpinBox, int>(table, this, row, 1, m_PaletteHueSpin, spinHeight, -180, 180, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
|
|
SetupSpinner<SpinBox, int>(table, this, row, 1, m_PaletteSaturationSpin, spinHeight, -100, 100, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
|
|
SetupSpinner<SpinBox, int>(table, this, row, 1, m_PaletteBrightnessSpin, spinHeight, -255, 255, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
|
|
row = 0;
|
|
|
|
SetupSpinner<SpinBox, int>(table, this, row, 3, m_PaletteContrastSpin, spinHeight, -100, 100, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
|
|
SetupSpinner<SpinBox, int>(table, this, row, 3, m_PaletteBlurSpin, spinHeight, 0, 127, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
|
|
SetupSpinner<SpinBox, int>(table, this, row, 3, m_PaletteFrequencySpin, spinHeight, 1, 10, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 1, 1, 1);
|
|
|
|
connect(ui.PaletteRandomSelect, SIGNAL(clicked(bool)), this, SLOT(OnPaletteRandomSelectButtonClicked(bool)), Qt::QueuedConnection);
|
|
connect(ui.PaletteRandomAdjust, SIGNAL(clicked(bool)), this, SLOT(OnPaletteRandomAdjustButtonClicked(bool)), Qt::QueuedConnection);
|
|
|
|
//Preview table.
|
|
palettePreviewTable->setRowCount(1);
|
|
palettePreviewTable->setColumnWidth(1, 260);//256 plus small margin on each side.
|
|
QTableWidgetItem* previewNameCol = new QTableWidgetItem("");
|
|
palettePreviewTable->setItem(0, 0, previewNameCol);
|
|
QTableWidgetItem* previewPaletteItem = new QTableWidgetItem();
|
|
palettePreviewTable->setItem(0, 1, previewPaletteItem);
|
|
|
|
connect(ui.PaletteFilterLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnPaletteFilterLineEditTextChanged(const QString&)));
|
|
connect(ui.PaletteFilterClearButton, SIGNAL(clicked(bool)), this, SLOT(OnPaletteFilterClearButtonClicked(bool)));
|
|
paletteTable->setColumnWidth(1, 260);//256 plus small margin on each side.
|
|
paletteTable->horizontalHeader()->setSectionsClickable(true);
|
|
connect(paletteTable->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(OnPaletteHeaderSectionClicked(int)), Qt::QueuedConnection);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read all palette Xml files in the specified folder and populate the palette list with the contents.
|
|
/// This will clear any previous contents.
|
|
/// Called upon initialization, or controller type change.
|
|
/// </summary>
|
|
/// <param name="s">The full path to the palette files folder</param>
|
|
/// <returns>The number of palettes successfully added</returns>
|
|
template <typename T>
|
|
int FractoriumEmberController<T>::InitPaletteList(const string& s)
|
|
{
|
|
QDirIterator it(s.c_str(), QStringList() << "*.xml", QDir::Files, QDirIterator::FollowSymlinks);
|
|
|
|
m_PaletteList.Clear();
|
|
m_Fractorium->ui.PaletteFilenameCombo->clear();
|
|
m_Fractorium->ui.PaletteFilenameCombo->setProperty("path", QString::fromStdString(s));
|
|
|
|
while (it.hasNext())
|
|
{
|
|
auto path = it.next().toStdString();
|
|
auto qfilename = it.fileName();
|
|
|
|
if (m_PaletteList.Add(path))
|
|
m_Fractorium->ui.PaletteFilenameCombo->addItem(qfilename);
|
|
}
|
|
|
|
return m_PaletteList.Size();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Read a palette Xml file and populate the palette table with the contents.
|
|
/// This will clear any previous contents.
|
|
/// Called upon initialization, palette combo index change, and controller type change.
|
|
/// </summary>
|
|
/// <param name="s">The name to the palette file without the path</param>
|
|
/// <returns>True if successful, else false.</returns>
|
|
template <typename T>
|
|
bool FractoriumEmberController<T>::FillPaletteTable(const string& s)
|
|
{
|
|
if (!s.empty())//This occasionally seems to get called with an empty string for reasons unknown.
|
|
{
|
|
QTableWidget* paletteTable = m_Fractorium->ui.PaletteListTable;
|
|
QTableWidget* palettePreviewTable = m_Fractorium->ui.PalettePreviewTable;
|
|
|
|
m_CurrentPaletteFilePath = m_Fractorium->ui.PaletteFilenameCombo->property("path").toString().toStdString() + "/" + s;
|
|
|
|
if (size_t paletteSize = m_PaletteList.Size(m_CurrentPaletteFilePath))
|
|
{
|
|
paletteTable->clear();
|
|
paletteTable->blockSignals(true);
|
|
paletteTable->setRowCount(paletteSize);
|
|
|
|
//Headers get removed when clearing, so must re-create here.
|
|
QTableWidgetItem* nameHeader = new QTableWidgetItem("Name");
|
|
QTableWidgetItem* paletteHeader = new QTableWidgetItem("Palette");
|
|
|
|
nameHeader->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
|
paletteHeader->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
|
|
|
paletteTable->setHorizontalHeaderItem(0, nameHeader);
|
|
paletteTable->setHorizontalHeaderItem(1, paletteHeader);
|
|
|
|
//Palette list table.
|
|
for (size_t i = 0; i < paletteSize; i++)
|
|
{
|
|
if (auto p = m_PaletteList.GetPalette(m_CurrentPaletteFilePath, i))
|
|
{
|
|
auto v = p->MakeRgbPaletteBlock(PALETTE_CELL_HEIGHT);
|
|
auto nameCol = new QTableWidgetItem(p->m_Name.c_str());
|
|
|
|
nameCol->setToolTip(p->m_Name.c_str());
|
|
paletteTable->setItem(i, 0, nameCol);
|
|
|
|
QImage image(v.data(), p->Size(), PALETTE_CELL_HEIGHT, QImage::Format_RGB888);
|
|
auto paletteItem = new PaletteTableWidgetItem<T>(p);
|
|
|
|
paletteItem->setData(Qt::DecorationRole, QPixmap::fromImage(image));
|
|
paletteTable->setItem(i, 1, paletteItem);
|
|
}
|
|
}
|
|
|
|
paletteTable->blockSignals(false);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
vector<string> errors = m_PaletteList.ErrorReport();
|
|
|
|
m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit);
|
|
m_Fractorium->ShowCritical("Palette Read Error", "Could not load palette file, all images will be black. See info tab for details.");
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void Fractorium::OnPaletteFilenameComboChanged(const QString& text)
|
|
{
|
|
m_Controller->FillPaletteTable(text.toStdString());
|
|
ui.PaletteListTable->sortItems(0, m_PaletteSortMode == 0 ? Qt::AscendingOrder : Qt::DescendingOrder);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply adjustments to the current ember's palette.
|
|
/// </summary>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::ApplyPaletteToEmber()
|
|
{
|
|
int i, rot = 0;
|
|
uint blur = m_Fractorium->m_PaletteBlurSpin->value();
|
|
uint freq = m_Fractorium->m_PaletteFrequencySpin->value();
|
|
double sat = double(m_Fractorium->m_PaletteSaturationSpin->value() / 100.0);
|
|
double brightness = double(m_Fractorium->m_PaletteBrightnessSpin->value() / 255.0);
|
|
double contrast = double(m_Fractorium->m_PaletteContrastSpin->value() > 0 ? (m_Fractorium->m_PaletteContrastSpin->value() * 2) : m_Fractorium->m_PaletteContrastSpin->value()) / 100.0;
|
|
double hue = double(m_Fractorium->m_PaletteHueSpin->value()) / 360.0;
|
|
|
|
//Use the temp palette as the base and apply the adjustments gotten from the GUI and save the result in the ember palette.
|
|
m_TempPalette.MakeAdjustedPalette(m_Ember.m_Palette, 0, hue, sat, brightness, contrast, blur, freq);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Use adjusted palette to update all related GUI controls with new color values.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="palette">The palette to use</param>
|
|
/// <param name="paletteName">Name of the palette</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::UpdateAdjustedPaletteGUI(Palette<T>& palette)
|
|
{
|
|
Xform<T>* xform = CurrentXform();
|
|
QTableWidget* palettePreviewTable = m_Fractorium->ui.PalettePreviewTable;
|
|
QTableWidgetItem* previewPaletteItem = palettePreviewTable->item(0, 1);
|
|
QString paletteName = QString::fromStdString(m_Ember.m_Palette.m_Name);
|
|
|
|
if (previewPaletteItem)//This can be null if the palette file was moved or corrupted.
|
|
{
|
|
//Use the adjusted palette to fill the preview palette control so the user can see the effects of applying the adjustements.
|
|
vector<byte> v = palette.MakeRgbPaletteBlock(PALETTE_CELL_HEIGHT);//Make the palette repeat for PALETTE_CELL_HEIGHT rows.
|
|
|
|
m_FinalPaletteImage = QImage(palette.Size(), PALETTE_CELL_HEIGHT, QImage::Format_RGB888);//Create a QImage out of it.
|
|
memcpy(m_FinalPaletteImage.scanLine(0), v.data(), v.size() * sizeof(v[0]));//Memcpy the data in.
|
|
QPixmap pixmap = QPixmap::fromImage(m_FinalPaletteImage);//Create a QPixmap out of the QImage.
|
|
previewPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(QSize(pixmap.width(), palettePreviewTable->rowHeight(0) + 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));//Set the pixmap on the palette tab.
|
|
m_Fractorium->SetPaletteTableItem(&pixmap, m_Fractorium->ui.XformPaletteRefTable, m_Fractorium->m_PaletteRefItem, 0, 0);//Set the palette ref table on the xforms | color tab.
|
|
|
|
QTableWidgetItem* previewNameItem = palettePreviewTable->item(0, 0);
|
|
previewNameItem->setText(paletteName);//Finally, set the name of the palette to be both the text and the tooltip.
|
|
previewNameItem->setToolTip(paletteName);
|
|
}
|
|
|
|
//Update the current xform's color and reset the rendering process.
|
|
if (xform)
|
|
XformColorIndexChanged(xform->m_ColorX, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply all adjustments to the selected palette, show it
|
|
/// and assign it to the current ember.
|
|
/// Called when any adjustment spinner is modified.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::PaletteAdjust()
|
|
{
|
|
Update([&]()
|
|
{
|
|
ApplyPaletteToEmber();
|
|
UpdateAdjustedPaletteGUI(m_Ember.m_Palette);
|
|
});
|
|
}
|
|
|
|
void Fractorium::OnPaletteAdjust(int d) { m_Controller->PaletteAdjust(); }
|
|
|
|
/// <summary>
|
|
/// Set the selected palette as the current one,
|
|
/// applying any adjustments previously specified.
|
|
/// Called when a palette cell is clicked. Unfortunately,
|
|
/// this will get called twice on a double click when moving
|
|
/// from one palette to another. It happens quickly so it shouldn't
|
|
/// be too much of a problem.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="row">The table row clicked</param>
|
|
/// <param name="col">The table column clicked</param>
|
|
template <typename T>
|
|
void FractoriumEmberController<T>::PaletteCellClicked(int row, int col)
|
|
{
|
|
if (auto palette = m_PaletteList.GetPalette(m_CurrentPaletteFilePath, row))
|
|
{
|
|
m_TempPalette = *palette;//Deep copy.
|
|
ApplyPaletteToEmber();//Copy temp palette to ember palette and apply adjustments.
|
|
UpdateAdjustedPaletteGUI(m_Ember.m_Palette);//Show the adjusted palette.
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Map the palette in the clicked row index to the index
|
|
/// in the palette list, then pass that index to PaletteCellClicked().
|
|
/// This resolves the case where the sort order of the palette table
|
|
/// is different than the internal order of the palette list.
|
|
/// </summary>
|
|
/// <param name="row">The table row clicked</param>
|
|
/// <param name="col">The table column clicked, ignored</param>
|
|
void Fractorium::OnPaletteCellClicked(int row, int col)
|
|
{
|
|
if (auto item = dynamic_cast<PaletteTableWidgetItemBase*>(ui.PaletteListTable->item(row, 1)))
|
|
{
|
|
auto index = item->Index();
|
|
|
|
if (m_PreviousPaletteRow != index)
|
|
{
|
|
m_Controller->PaletteCellClicked(index, col);
|
|
m_PreviousPaletteRow = index;//Save for comparison on next click.
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the selected palette as the current one,
|
|
/// resetting any adjustments previously specified.
|
|
/// Called when a palette cell is double clicked.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="row">The table row clicked</param>
|
|
/// <param name="col">The table column clicked</param>
|
|
void Fractorium::OnPaletteCellDoubleClicked(int row, int col)
|
|
{
|
|
ResetPaletteControls();
|
|
m_PreviousPaletteRow = -1;
|
|
OnPaletteCellClicked(row, col);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the selected palette to a randomly selected one,
|
|
/// applying any adjustments previously specified if the checked parameter is true.
|
|
/// Called when the Random Palette button is clicked.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
/// <param name="checked">True to clear the current adjustments, else leave current adjustments and apply them to the newly selected palette.</param>
|
|
void Fractorium::OnPaletteRandomSelectButtonClicked(bool checked)
|
|
{
|
|
uint i = 0;
|
|
int rowCount = ui.PaletteListTable->rowCount() - 1;
|
|
|
|
while ((i = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Rand(rowCount)) == uint(m_PreviousPaletteRow));
|
|
|
|
if (checked)
|
|
OnPaletteCellDoubleClicked(i, 1);//Will clear the adjustments.
|
|
else
|
|
OnPaletteCellClicked(i, 1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply random adjustments to the selected palette.
|
|
/// Called when the Random Adjustment button is clicked.
|
|
/// Resets the rendering process.
|
|
/// </summary>
|
|
void Fractorium::OnPaletteRandomAdjustButtonClicked(bool checked)
|
|
{
|
|
QTIsaac<ISAAC_SIZE, ISAAC_INT>* gRand = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand.get();
|
|
|
|
m_PaletteHueSpin->setValue(-180 + gRand->Rand(361));
|
|
m_PaletteSaturationSpin->setValue(-50 + gRand->Rand(101));//Full range of these leads to bad palettes, so clamp range.
|
|
m_PaletteBrightnessSpin->setValue(-50 + gRand->Rand(101));
|
|
m_PaletteContrastSpin->setValue(-50 + gRand->Rand(101));
|
|
|
|
//Doing frequency and blur together gives bad palettes that are just a solid color.
|
|
if (gRand->RandBit())
|
|
{
|
|
m_PaletteBlurSpin->setValue(gRand->Rand(21));
|
|
m_PaletteFrequencySpin->setValue(1);
|
|
}
|
|
else
|
|
{
|
|
m_PaletteBlurSpin->setValue(0);
|
|
m_PaletteFrequencySpin->setValue(1 + gRand->Rand(10));
|
|
}
|
|
|
|
OnPaletteAdjust(0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apply the text in the palette filter text box to only show palettes whose names
|
|
/// contain the substring.
|
|
/// Called when the user types in the palette filter text box.
|
|
/// </summary>
|
|
/// <param name="text">The text to filter on</param>
|
|
void Fractorium::OnPaletteFilterLineEditTextChanged(const QString& text)
|
|
{
|
|
auto table = ui.PaletteListTable;
|
|
|
|
table->setUpdatesEnabled(false);
|
|
|
|
for (int i = 0; i < table->rowCount(); i++)
|
|
{
|
|
if (auto item = table->item(i, 0))
|
|
{
|
|
if (!item->text().contains(text, Qt::CaseInsensitive))
|
|
table->hideRow(i);
|
|
else
|
|
table->showRow(i);
|
|
}
|
|
}
|
|
|
|
ui.PaletteListTable->sortItems(0, m_PaletteSortMode == 0 ? Qt::AscendingOrder : Qt::DescendingOrder);//Must re-sort every time the filter changes.
|
|
table->setUpdatesEnabled(true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clear the palette name filter, which will display all palettes.
|
|
/// Called when clear palette filter button is clicked.
|
|
/// </summary>
|
|
/// <param name="checked">Ignored</param>
|
|
void Fractorium::OnPaletteFilterClearButtonClicked(bool checked)
|
|
{
|
|
ui.PaletteFilterLineEdit->clear();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Change the sorting to be either ascending or descending.
|
|
/// Called when user clicks the table headers.
|
|
/// </summary>
|
|
/// <param name="col">Column index of the header clicked, ignored.</param>
|
|
void Fractorium::OnPaletteHeaderSectionClicked(int col)
|
|
{
|
|
m_PaletteSortMode = !m_PaletteSortMode;
|
|
ui.PaletteListTable->sortItems(0, m_PaletteSortMode == 0 ? Qt::AscendingOrder : Qt::DescendingOrder);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset the palette controls.
|
|
/// Usually in response to a palette cell double click.
|
|
/// </summary>
|
|
void Fractorium::ResetPaletteControls()
|
|
{
|
|
m_PaletteHueSpin->SetValueStealth(0);
|
|
m_PaletteSaturationSpin->SetValueStealth(0);
|
|
m_PaletteBrightnessSpin->SetValueStealth(0);
|
|
m_PaletteContrastSpin->SetValueStealth(0);
|
|
m_PaletteBlurSpin->SetValueStealth(0);
|
|
m_PaletteFrequencySpin->SetValueStealth(1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the index of the palette file combo box.
|
|
/// This is for display purposes only so the user can see which file, if any,
|
|
/// the current palette came from.
|
|
/// For embedded palettes with no filename, this will have no effect.
|
|
/// </summary>
|
|
/// <param name="filename">The string to set the index to</param>
|
|
void Fractorium::SetPaletteFileComboIndex(const string& filename)
|
|
{
|
|
if (!filename.empty())
|
|
ui.PaletteFilenameCombo->setCurrentText(QFileInfo(QString::fromStdString(filename)).fileName());
|
|
}
|
|
|
|
template class FractoriumEmberController<float>;
|
|
|
|
#ifdef DO_DOUBLE
|
|
template class FractoriumEmberController<double>;
|
|
#endif
|