mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-02-01 10:30:08 -05:00
oops
This commit is contained in:
parent
e005b4c20e
commit
2561708ae0
@ -231,6 +231,10 @@ public:
|
||||
if (ember.UseFinalXform())
|
||||
os << ToString(*ember.NonConstFinalXform(), ember.XformCount(), true, false);//Final, don't do motion.
|
||||
|
||||
//Note that only embedded palettes are saved. The old style of specifying a palette index to look up in a default palette file
|
||||
//is no longer supported, as it makes no sense when using multiple palette files. The only way it could work is if the index was
|
||||
//always meant to refer to the default file, or if the filename was embedded as well. It's easier, more straightforward and
|
||||
//less error prone to just embed the palette.
|
||||
if (hexPalette)
|
||||
{
|
||||
os << " <palette count=\"256\" format=\"RGB\">\n";
|
||||
|
@ -145,6 +145,7 @@ public:
|
||||
{
|
||||
m_Index = palette.m_Index;
|
||||
m_Name = palette.m_Name;
|
||||
m_Filename = palette.m_Filename;
|
||||
CopyVec(m_Entries, palette.m_Entries);
|
||||
|
||||
return *this;
|
||||
@ -204,6 +205,7 @@ public:
|
||||
{
|
||||
palette.m_Index = m_Index;
|
||||
palette.m_Name = m_Name;
|
||||
palette.m_Filename = m_Filename;
|
||||
palette.m_Entries.resize(Size());
|
||||
|
||||
for (uint i = 0; i < Size(); i++)
|
||||
@ -263,6 +265,7 @@ public:
|
||||
}
|
||||
|
||||
palette.m_Name = m_Name;
|
||||
palette.m_Filename = m_Filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -340,6 +343,7 @@ public:
|
||||
{
|
||||
palette.m_Index = m_Index;
|
||||
palette.m_Name = m_Name;
|
||||
palette.m_Filename = m_Filename;
|
||||
|
||||
if (palette.Size() != Size())
|
||||
palette.m_Entries.resize(Size());
|
||||
@ -574,6 +578,7 @@ public:
|
||||
|
||||
int m_Index;//Index in the xml palette file of this palette, use -1 for random.
|
||||
string m_Name;//Name of this palette.
|
||||
string m_Filename;//Name of the parent file this palette came from, can be empty.
|
||||
vector<v4T> m_Entries;//Storage for the color values.
|
||||
};
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
|
||||
palettes.clear();
|
||||
palettes.reserve(buf.size() / 2048);//Roughly what it takes per palette.
|
||||
ParsePalettes(rootNode, palettes);
|
||||
ParsePalettes(rootNode, filename, palettes);
|
||||
xmlFreeDoc(doc);
|
||||
added = true;
|
||||
}
|
||||
@ -81,6 +81,7 @@ public:
|
||||
auto p = m_Palettes.begin();
|
||||
int i = 0, paletteFileIndex = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand->Rand() % Size();
|
||||
|
||||
//Move p forward i elements.
|
||||
while (i < paletteFileIndex && p != m_Palettes.end())
|
||||
{
|
||||
++i;
|
||||
@ -218,13 +219,14 @@ public:
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Parses an Xml node for all palettes present and store in the passed in palette vector.
|
||||
/// Parses an Xml node for all palettes present and stores them in the passed in palette vector.
|
||||
/// Note that although the Xml color values are expected to be 0-255, they are converted and
|
||||
/// stored as normalized colors, with values from 0-1.
|
||||
/// </summary>
|
||||
/// <param name="node">The parent note of all palettes in the Xml file.</param>
|
||||
/// <param name="filename">The name of the Xml file.</param>
|
||||
/// <param name="palettes">The vector to store the paresed palettes associated with this file in.</param>
|
||||
void ParsePalettes(xmlNode* node, vector<Palette<T>>& palettes)
|
||||
void ParsePalettes(xmlNode* node, const string& filename, vector<Palette<T>>& palettes)
|
||||
{
|
||||
bool hexError = false;
|
||||
char* val;
|
||||
@ -287,12 +289,13 @@ private:
|
||||
|
||||
if (!hexError)
|
||||
{
|
||||
palette.m_Filename = filename;
|
||||
palettes.push_back(palette);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ParsePalettes(node->children, palettes);
|
||||
ParsePalettes(node->children, filename, palettes);
|
||||
}
|
||||
|
||||
node = node->next;
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "FractoriumPch.h"
|
||||
#include "DoubleSpinBox.h"
|
||||
|
||||
QTimer DoubleSpinBox::m_Timer;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that passes parent to the base and sets up height and step.
|
||||
/// Specific focus policy is used to allow the user to hover over the control
|
||||
@ -21,14 +23,15 @@ DoubleSpinBox::DoubleSpinBox(QWidget* p, int h, double step)
|
||||
m_SmallStep = step / 10.0;
|
||||
setSingleStep(step);
|
||||
setFrame(false);
|
||||
//setAttribute(Qt::WA_PaintOnScreen);
|
||||
setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setMinimumHeight(h);//setGeometry() has no effect, so must set both of these instead.
|
||||
setMaximumHeight(h);
|
||||
setContextMenuPolicy(Qt::PreventContextMenu);
|
||||
lineEdit()->installEventFilter(this);
|
||||
lineEdit()->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
connect(this, SIGNAL(valueChanged(double)), this, SLOT(onSpinBoxValueChanged(double)), Qt::QueuedConnection);
|
||||
|
||||
connect(this, SIGNAL(valueChanged(double)), this, SLOT(OnSpinBoxValueChanged(double)), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -118,11 +121,44 @@ QLineEdit* DoubleSpinBox::lineEdit()
|
||||
/// <summary>
|
||||
/// Another workaround for the persistent text selection bug in Qt.
|
||||
/// </summary>
|
||||
void DoubleSpinBox::onSpinBoxValueChanged(double d)
|
||||
void DoubleSpinBox::OnSpinBoxValueChanged(double d)
|
||||
{
|
||||
lineEdit()->deselect();//Gets rid of nasty "feature" that always has text selected.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called while the timer is activated due to the right mouse button being held down.
|
||||
/// </summary>
|
||||
void DoubleSpinBox::OnTimeout()
|
||||
{
|
||||
int xdistance = m_MouseMovePoint.x() - m_MouseDownPoint.x();
|
||||
int ydistance = m_MouseMovePoint.y() - m_MouseDownPoint.y();
|
||||
int distance = abs(xdistance) > abs(ydistance) ? xdistance : ydistance;
|
||||
double scale, val;
|
||||
double d = value();
|
||||
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
//bool ctrl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
|
||||
double amount = (m_SmallStep + m_Step) * 0.5;
|
||||
|
||||
if (shift)
|
||||
{
|
||||
//qDebug() << "Shift pressed";
|
||||
scale = 0.0001;
|
||||
}
|
||||
/*else if (ctrl)
|
||||
{
|
||||
qDebug() << "Control pressed";
|
||||
scale = 0.01;
|
||||
}*/
|
||||
else
|
||||
scale = 0.001;
|
||||
|
||||
val = d + (distance * amount * scale);
|
||||
setValue(val);
|
||||
|
||||
//qDebug() << "Timer on, orig val: " << d << ", new val: " << val << ", distance " << distance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event filter for taking special action on double click events.
|
||||
/// </summary>
|
||||
@ -131,8 +167,16 @@ void DoubleSpinBox::onSpinBoxValueChanged(double d)
|
||||
/// <returns>false</returns>
|
||||
bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
if (e->type() == QMouseEvent::MouseButtonPress && isEnabled())
|
||||
QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
|
||||
|
||||
if (isEnabled() &&
|
||||
me &&
|
||||
me->type() == QMouseEvent::MouseButtonPress &&
|
||||
me->button() == Qt::RightButton)
|
||||
{
|
||||
m_MouseDownPoint = m_MouseMovePoint = me->pos();
|
||||
StartTimer();
|
||||
//qDebug() << "Right mouse down";
|
||||
// QPoint pt;
|
||||
//
|
||||
// if (QMouseEvent* me = (QMouseEvent*)e)
|
||||
@ -154,6 +198,23 @@ bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
// return true;
|
||||
// }
|
||||
}
|
||||
else if (isEnabled() &&
|
||||
me &&
|
||||
me->type() == QMouseEvent::MouseButtonRelease &&
|
||||
me->button() == Qt::RightButton)
|
||||
{
|
||||
StopTimer();
|
||||
m_MouseDownPoint = m_MouseMovePoint = me->pos();
|
||||
//qDebug() << "Right mouse up";
|
||||
}
|
||||
else if (isEnabled() &&
|
||||
me &&
|
||||
me->type() == QMouseEvent::MouseMove &&
|
||||
QGuiApplication::mouseButtons() & Qt::RightButton)
|
||||
{
|
||||
m_MouseMovePoint = me->pos();
|
||||
qDebug() << "Mouse move while right down. Pt = " << me->pos() << ", global: " << mapToGlobal(me->pos());
|
||||
}
|
||||
else if (m_DoubleClick && e->type() == QMouseEvent::MouseButtonDblClick && isEnabled())
|
||||
{
|
||||
if (IsNearZero(value()))
|
||||
@ -189,6 +250,7 @@ bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
void DoubleSpinBox::focusInEvent(QFocusEvent* e)
|
||||
{
|
||||
//lineEdit()->setReadOnly(false);
|
||||
StopTimer();
|
||||
QDoubleSpinBox::focusInEvent(e);
|
||||
}
|
||||
|
||||
@ -203,6 +265,7 @@ void DoubleSpinBox::focusOutEvent(QFocusEvent* e)
|
||||
{
|
||||
//lineEdit()->deselect();//Clear selection when leaving.
|
||||
//lineEdit()->setReadOnly(true);//Clever hack to clear the cursor when leaving.
|
||||
StopTimer();
|
||||
QDoubleSpinBox::focusOutEvent(e);
|
||||
}
|
||||
|
||||
@ -215,6 +278,7 @@ void DoubleSpinBox::enterEvent(QEvent* e)
|
||||
{
|
||||
//m_Select = true;
|
||||
//setFocus();
|
||||
StopTimer();
|
||||
QDoubleSpinBox::enterEvent(e);
|
||||
}
|
||||
|
||||
@ -226,6 +290,26 @@ void DoubleSpinBox::enterEvent(QEvent* e)
|
||||
void DoubleSpinBox::leaveEvent(QEvent* e)
|
||||
{
|
||||
//m_Select = false;
|
||||
//clearFocus();
|
||||
//clearFocus();.
|
||||
StopTimer();
|
||||
QDoubleSpinBox::leaveEvent(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the timer in response to the right mouse button being pressed.
|
||||
/// </summary>
|
||||
void DoubleSpinBox::StartTimer()
|
||||
{
|
||||
m_Timer.stop();
|
||||
connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
|
||||
m_Timer.start(300);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the timer in response to the left mouse button being pressed.
|
||||
/// </summary>
|
||||
void DoubleSpinBox::StopTimer()
|
||||
{
|
||||
m_Timer.stop();
|
||||
disconnect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
|
||||
}
|
@ -29,7 +29,8 @@ public:
|
||||
QLineEdit* lineEdit();
|
||||
|
||||
public slots:
|
||||
void onSpinBoxValueChanged(double d);
|
||||
void OnSpinBoxValueChanged(double d);
|
||||
void OnTimeout();
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject* o, QEvent* e) override;
|
||||
@ -39,12 +40,18 @@ protected:
|
||||
virtual void leaveEvent(QEvent* e);
|
||||
|
||||
private:
|
||||
void StartTimer();
|
||||
void StopTimer();
|
||||
|
||||
bool m_Select;
|
||||
bool m_DoubleClick;
|
||||
double m_DoubleClickNonZero;
|
||||
double m_DoubleClickZero;
|
||||
double m_Step;
|
||||
double m_SmallStep;
|
||||
QPoint m_MouseDownPoint;
|
||||
QPoint m_MouseMovePoint;
|
||||
static QTimer m_Timer;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -723,6 +723,78 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, ui.InfoRenderingTextEdit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all table spinner values in one row.
|
||||
/// The logic is:
|
||||
/// If any cell in the row is non zero, set all cells to zero, else 1.
|
||||
/// If shift is held down, reverse the logic.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="logicalIndex">The index of the row that was double clicked</param>
|
||||
void Fractorium::ToggleTableRow(TableWidget* table, int logicalIndex)
|
||||
{
|
||||
bool allZero = true;
|
||||
int cols = table->columnCount();
|
||||
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
|
||||
for (int i = 0; i < cols; i++)
|
||||
{
|
||||
if (auto* spinBox = dynamic_cast<DoubleSpinBox*>(table->cellWidget(logicalIndex, i)))
|
||||
{
|
||||
if (!IsNearZero(spinBox->value()))
|
||||
{
|
||||
allZero = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shift)
|
||||
allZero = !allZero;
|
||||
|
||||
double val = allZero ? 1.0 : 0.0;
|
||||
|
||||
for (int i = 0; i < cols; i++)
|
||||
if (auto* spinBox = dynamic_cast<DoubleSpinBox*>(table->cellWidget(logicalIndex, i)))
|
||||
spinBox->setValue(val);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all table spinner values in one column.
|
||||
/// The logic is:
|
||||
/// If any cell in the column is non zero, set all cells to zero, else 1.
|
||||
/// If shift is held down, reverse the logic.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="logicalIndex">The index of the column that was double clicked</param>
|
||||
void Fractorium::ToggleTableCol(TableWidget* table, int logicalIndex)
|
||||
{
|
||||
bool allZero = true;
|
||||
int rows = table->rowCount();
|
||||
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
if (auto* spinBox = dynamic_cast<DoubleSpinBox*>(table->cellWidget(i, logicalIndex)))
|
||||
{
|
||||
if (!IsNearZero(spinBox->value()))
|
||||
{
|
||||
allZero = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shift)
|
||||
allZero = !allZero;
|
||||
|
||||
double val = allZero ? 1.0 : 0.0;
|
||||
|
||||
for (int i = 0; i < rows; i++)
|
||||
if (auto* spinBox = dynamic_cast<DoubleSpinBox*>(table->cellWidget(i, logicalIndex)))
|
||||
spinBox->setValue(val);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is no longer needed and was used to compensate for a different bug
|
||||
/// however the code is interesting, so keep it around for possible future use.
|
||||
|
@ -194,6 +194,11 @@ public slots:
|
||||
void OnXformNameChanged(int row, int col);
|
||||
|
||||
//Xforms Affine.
|
||||
void OnPreAffineRowDoubleClicked(int logicalIndex);
|
||||
void OnPreAffineColDoubleClicked(int logicalIndex);
|
||||
void OnPostAffineRowDoubleClicked(int logicalIndex);
|
||||
void OnPostAffineColDoubleClicked(int logicalIndex);
|
||||
|
||||
void OnX1Changed(double d);
|
||||
void OnX2Changed(double d);
|
||||
void OnY1Changed(double d);
|
||||
@ -299,6 +304,9 @@ private:
|
||||
void InitLibraryUI();
|
||||
void SetTabOrders();
|
||||
|
||||
void ToggleTableRow(TableWidget* table, int logicalIndex);
|
||||
void ToggleTableCol(TableWidget* table, int logicalIndex);
|
||||
|
||||
//Embers.
|
||||
bool HaveFinal();
|
||||
|
||||
@ -324,6 +332,7 @@ private:
|
||||
|
||||
//Palette.
|
||||
void ResetPaletteControls();
|
||||
void SetPaletteFileComboIndex(const string& filename);
|
||||
|
||||
//Info.
|
||||
void UpdateHistogramBounds();
|
||||
|
@ -365,6 +365,9 @@
|
||||
<attribute name="title">
|
||||
<string>Library</string>
|
||||
</attribute>
|
||||
<attribute name="toolTip">
|
||||
<string>All flames in the currently opened file or randomly generated flock</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_10">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
@ -472,6 +475,9 @@
|
||||
<attribute name="title">
|
||||
<string>Flame</string>
|
||||
</attribute>
|
||||
<attribute name="toolTip">
|
||||
<string>General flame parameters</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
@ -1884,6 +1890,9 @@
|
||||
<attribute name="title">
|
||||
<string>Xforms</string>
|
||||
</attribute>
|
||||
<attribute name="toolTip">
|
||||
<string>Xforms in the current flame</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_13">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
@ -1962,11 +1971,14 @@ SpinBox
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Color palette index for the current xform, and curve adjustment.</string>
|
||||
<string/>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Color</string>
|
||||
</attribute>
|
||||
<attribute name="toolTip">
|
||||
<string>Color palette index for the current xform, and curve adjustment</string>
|
||||
</attribute>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
@ -2583,7 +2595,7 @@ SpinBox
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Affine transforms for the current xform.</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
@ -2591,6 +2603,9 @@ SpinBox
|
||||
<attribute name="title">
|
||||
<string>Affine</string>
|
||||
</attribute>
|
||||
<attribute name="toolTip">
|
||||
<string>Affine transforms for the current xform</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
@ -3944,11 +3959,14 @@ SpinBox
|
||||
</widget>
|
||||
<widget class="QWidget" name="XformVariationsTab">
|
||||
<property name="toolTip">
|
||||
<string>Full list of available variations and their weights for the currently selected xform.</string>
|
||||
<string/>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Variations</string>
|
||||
</attribute>
|
||||
<attribute name="toolTip">
|
||||
<string>Full list of available variations and their weights for the currently selected xform</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
@ -4175,7 +4193,7 @@ SpinBox
|
||||
</widget>
|
||||
<widget class="QWidget" name="XformSelectTab">
|
||||
<property name="toolTip">
|
||||
<string>Select multiple xforms to apply operations to.</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
@ -4183,6 +4201,9 @@ SpinBox
|
||||
<attribute name="title">
|
||||
<string>Select</string>
|
||||
</attribute>
|
||||
<attribute name="toolTip">
|
||||
<string>Select multiple xforms to apply operations to</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
@ -4673,6 +4694,9 @@ SpinBox
|
||||
<attribute name="title">
|
||||
<string>Xaos</string>
|
||||
</attribute>
|
||||
<attribute name="toolTip">
|
||||
<string>Xaos weights between xforms</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
@ -4886,6 +4910,9 @@ SpinBox
|
||||
<attribute name="title">
|
||||
<string>Palette</string>
|
||||
</attribute>
|
||||
<attribute name="toolTip">
|
||||
<string>List of available palette files and their palettes</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_16" rowstretch="0,0,0,0,0" columnstretch="0">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
@ -5272,6 +5299,9 @@ SpinBox
|
||||
<attribute name="title">
|
||||
<string>Info</string>
|
||||
</attribute>
|
||||
<attribute name="toolTip">
|
||||
<string>Diagnostic information of engineering interest</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_17" stretch="0">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
|
@ -83,13 +83,14 @@ int FractoriumEmberController<T>::InitPaletteList(const string& s)
|
||||
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;
|
||||
size_t paletteSize = m_PaletteList.Size(m_CurrentPaletteFilePath);
|
||||
|
||||
if (paletteSize)
|
||||
if (size_t paletteSize = m_PaletteList.Size(m_CurrentPaletteFilePath))
|
||||
{
|
||||
paletteTable->clear();
|
||||
paletteTable->blockSignals(true);
|
||||
@ -123,7 +124,6 @@ bool FractoriumEmberController<T>::FillPaletteTable(const string& s)
|
||||
}
|
||||
|
||||
paletteTable->blockSignals(false);
|
||||
m_Fractorium->OnPaletteRandomSelectButtonClicked(true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -133,6 +133,7 @@ bool FractoriumEmberController<T>::FillPaletteTable(const string& s)
|
||||
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;
|
||||
}
|
||||
@ -226,7 +227,6 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::PaletteCellClicked(int row, int col)
|
||||
{
|
||||
Palette<T>* palette = m_PaletteList.GetPalette(m_CurrentPaletteFilePath, row);
|
||||
QTableWidgetItem* nameItem = m_Fractorium->ui.PaletteListTable->item(row, 0);
|
||||
|
||||
if (palette)
|
||||
{
|
||||
@ -266,7 +266,7 @@ void Fractorium::OnPaletteCellDoubleClicked(int row, int col)
|
||||
/// 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.</param>
|
||||
/// <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;
|
||||
@ -323,6 +323,18 @@ void Fractorium::ResetPaletteControls()
|
||||
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.
|
||||
/// </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
|
||||
|
@ -512,6 +512,7 @@ void FractoriumEmberController<T>::SetCenter(double x, double y)
|
||||
|
||||
/// <summary>
|
||||
/// Fill the parameter tables and palette widgets with values from the current ember.
|
||||
/// This takes ~1-2ms.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillParamTablesAndPalette()
|
||||
@ -551,26 +552,18 @@ void FractoriumEmberController<T>::FillParamTablesAndPalette()
|
||||
m_Fractorium->m_AffineInterpTypeCombo->SetCurrentIndexStealth(m_Ember.m_AffineInterp);
|
||||
m_Fractorium->m_InterpTypeCombo->SetCurrentIndexStealth(m_Ember.m_Interp);
|
||||
|
||||
//Xaos.
|
||||
FillXaos();
|
||||
|
||||
//Palette.
|
||||
m_Fractorium->ResetPaletteControls();
|
||||
m_Fractorium->m_PaletteHueSpin->SetValueStealth(NormalizeDeg180<double>(m_Ember.m_Hue * 360.0));//Convert -0.5 to 0.5 range to -180 - 180.
|
||||
|
||||
//Use -1 as a placeholder to mean either generate a random palette from the list or
|
||||
//to just use the values "as-is" without looking them up in the list.
|
||||
if (m_Ember.m_Palette.m_Index >= 0)
|
||||
{
|
||||
m_Fractorium->OnPaletteCellClicked(Clamp<int>(m_Ember.m_Palette.m_Index, 0, m_Fractorium->ui.PaletteListTable->rowCount() - 1), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//An ember with an embedded palette was loaded, rather than one from the list, so assign it directly to the controls without applying adjustments.
|
||||
//Normally, temp palette is assigned whenever the user clicks on a palette cell. But since that is skipped here just make a copy of the ember's palette.
|
||||
//Use the ember's embedded palette, rather than one from the list, so assign it directly to the controls without applying adjustments.
|
||||
//Normally, the temp palette is assigned whenever the user clicks on a palette cell. But since that is skipped here, must do it manually.
|
||||
m_TempPalette = m_Ember.m_Palette;
|
||||
UpdateAdjustedPaletteGUI(m_Ember.m_Palette);//Will clear name string since embedded palettes have no name. This will trigger a full render.
|
||||
}
|
||||
|
||||
//Xaos.
|
||||
FillXaos();
|
||||
m_Fractorium->SetPaletteFileComboIndex(m_Ember.m_Palette.m_Filename);
|
||||
UpdateAdjustedPaletteGUI(m_Ember.m_Palette);//Setting the palette will trigger a full render.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -188,74 +188,22 @@ void Fractorium::OnRandomXaosButtonClicked(bool checked) { m_Controller->RandomX
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all xaos values in one row.
|
||||
/// The logic is:
|
||||
/// If any cell in the row is non zero, set all cells to zero, else 1.
|
||||
/// If shift is held down, reverse the logic.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="logicalIndex">The index of the row that was double clicked</param>
|
||||
void Fractorium::OnXaosRowDoubleClicked(int logicalIndex)
|
||||
{
|
||||
bool allZero = true;
|
||||
int cols = ui.XaosTable->columnCount();
|
||||
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
|
||||
for (int i = 0; i < cols; i++)
|
||||
{
|
||||
if (auto* spinBox = dynamic_cast<DoubleSpinBox*>(ui.XaosTable->cellWidget(logicalIndex, i)))
|
||||
{
|
||||
if (!IsNearZero(spinBox->value()))
|
||||
{
|
||||
allZero = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shift)
|
||||
allZero = !allZero;
|
||||
|
||||
double val = allZero ? 1.0 : 0.0;
|
||||
|
||||
for (int i = 0; i < cols; i++)
|
||||
if (auto* spinBox = dynamic_cast<DoubleSpinBox*>(ui.XaosTable->cellWidget(logicalIndex, i)))
|
||||
spinBox->setValue(val);
|
||||
ToggleTableRow(ui.XaosTable, logicalIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all xaos values in one column.
|
||||
/// The logic is:
|
||||
/// If any cell in the column is non zero, set all cells to zero, else 1.
|
||||
/// If shift is held down, reverse the logic.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="logicalIndex">The index of the column that was double clicked</param>
|
||||
void Fractorium::OnXaosColDoubleClicked(int logicalIndex)
|
||||
{
|
||||
bool allZero = true;
|
||||
int rows = ui.XaosTable->rowCount();
|
||||
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
|
||||
for (int i = 0; i < rows; i++)
|
||||
{
|
||||
if (auto* spinBox = dynamic_cast<DoubleSpinBox*>(ui.XaosTable->cellWidget(i, logicalIndex)))
|
||||
{
|
||||
if (!IsNearZero(spinBox->value()))
|
||||
{
|
||||
allZero = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shift)
|
||||
allZero = !allZero;
|
||||
|
||||
double val = allZero ? 1.0 : 0.0;
|
||||
|
||||
for (int i = 0; i < rows; i++)
|
||||
if (auto* spinBox = dynamic_cast<DoubleSpinBox*>(ui.XaosTable->cellWidget(i, logicalIndex)))
|
||||
spinBox->setValue(val);
|
||||
ToggleTableCol(ui.XaosTable, logicalIndex);
|
||||
}
|
||||
|
||||
template class FractoriumEmberController<float>;
|
||||
|
@ -10,8 +10,15 @@ void Fractorium::InitXformsAffineUI()
|
||||
double affineStep = 0.01, affineMin = std::numeric_limits<double>::lowest(), affineMax = std::numeric_limits<double>::max();
|
||||
QTableWidget* table = ui.PreAffineTable;
|
||||
|
||||
SetFixedTableHeader(table->horizontalHeader(), QHeaderView::Stretch);//The designer continually clobbers these values, so must manually set them here.
|
||||
SetFixedTableHeader(table->verticalHeader());
|
||||
table->verticalHeader()->setVisible(true);//The designer continually clobbers these values, so must manually set them here.
|
||||
table->horizontalHeader()->setVisible(true);
|
||||
table->verticalHeader()->setSectionsClickable(true);
|
||||
table->horizontalHeader()->setSectionsClickable(true);
|
||||
table->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
|
||||
connect(table->verticalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnPreAffineRowDoubleClicked(int)), Qt::QueuedConnection);
|
||||
connect(table->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnPreAffineColDoubleClicked(int)), Qt::QueuedConnection);
|
||||
|
||||
//Pre affine spinners.
|
||||
SetupAffineSpinner(table, this, 0, 0, m_PreX1Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnX1Changed(double)));
|
||||
@ -22,8 +29,15 @@ void Fractorium::InitXformsAffineUI()
|
||||
SetupAffineSpinner(table, this, 2, 1, m_PreO2Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnO2Changed(double)));
|
||||
|
||||
table = ui.PostAffineTable;
|
||||
SetFixedTableHeader(table->horizontalHeader(), QHeaderView::Stretch);//The designer continually clobbers these values, so must manually set them here.
|
||||
SetFixedTableHeader(table->verticalHeader());
|
||||
table->verticalHeader()->setVisible(true);//The designer continually clobbers these values, so must manually set them here.
|
||||
table->horizontalHeader()->setVisible(true);
|
||||
table->verticalHeader()->setSectionsClickable(true);
|
||||
table->horizontalHeader()->setSectionsClickable(true);
|
||||
table->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
|
||||
connect(table->verticalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnPostAffineRowDoubleClicked(int)), Qt::QueuedConnection);
|
||||
connect(table->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnPostAffineColDoubleClicked(int)), Qt::QueuedConnection);
|
||||
|
||||
//Post affine spinners.
|
||||
SetupAffineSpinner(table, this, 0, 0, m_PostX1Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnX1Changed(double)));
|
||||
@ -159,6 +173,46 @@ void Fractorium::InitXformsAffineUI()
|
||||
ui.PostAffineGroupBox->setChecked(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all pre affine values in one row for the selected xforms.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="logicalIndex">The index of the row that was double clicked</param>
|
||||
void Fractorium::OnPreAffineRowDoubleClicked(int logicalIndex)
|
||||
{
|
||||
ToggleTableRow(ui.PreAffineTable, logicalIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all pre affine values in one column for the selected xforms.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="logicalIndex">The index of the row that was double clicked</param>
|
||||
void Fractorium::OnPreAffineColDoubleClicked(int logicalIndex)
|
||||
{
|
||||
ToggleTableCol(ui.PreAffineTable, logicalIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all post affine values in one row for the selected xforms.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="logicalIndex">The index of the row that was double clicked</param>
|
||||
void Fractorium::OnPostAffineRowDoubleClicked(int logicalIndex)
|
||||
{
|
||||
ToggleTableRow(ui.PostAffineTable, logicalIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all post affine values in one column for the selected xforms.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="logicalIndex">The index of the row that was double clicked</param>
|
||||
void Fractorium::OnPostAffineColDoubleClicked(int logicalIndex)
|
||||
{
|
||||
ToggleTableCol(ui.PostAffineTable, logicalIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper for setting the value of a single pre/post affine coefficient.
|
||||
/// Resets the rendering process.
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "FractoriumPch.h"
|
||||
#include "SpinBox.h"
|
||||
|
||||
QTimer SpinBox::m_Timer;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that passes parent to the base and sets up height and step.
|
||||
/// Specific focus policy is used to allow the user to hover over the control
|
||||
@ -97,6 +99,39 @@ void SpinBox::onSpinBoxValueChanged(int i)
|
||||
lineEdit()->deselect();//Gets rid of nasty "feature" that always has text selected.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called while the timer is activated due to the right mouse button being held down.
|
||||
/// </summary>
|
||||
void SpinBox::OnTimeout()
|
||||
{
|
||||
int xdistance = m_MouseMovePoint.x() - m_MouseDownPoint.x();
|
||||
int ydistance = m_MouseMovePoint.y() - m_MouseDownPoint.y();
|
||||
int distance = abs(xdistance) > abs(ydistance) ? xdistance : ydistance;
|
||||
double scale, val;
|
||||
int d = value();
|
||||
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
//bool ctrl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
|
||||
double amount = (m_SmallStep + m_Step) * 0.5;
|
||||
|
||||
if (shift)
|
||||
{
|
||||
//qDebug() << "Shift pressed";
|
||||
scale = 0.001;
|
||||
}
|
||||
/*else if (ctrl)
|
||||
{
|
||||
qDebug() << "Control pressed";
|
||||
scale = 0.01;
|
||||
}*/
|
||||
else
|
||||
scale = 0.01;
|
||||
|
||||
val = d + (distance * amount * scale);
|
||||
setValue(int(val));
|
||||
|
||||
//qDebug() << "Timer on, orig val: " << d << ", new val: " << val << ", distance " << distance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event filter for taking special action on double click events.
|
||||
/// </summary>
|
||||
@ -105,28 +140,53 @@ void SpinBox::onSpinBoxValueChanged(int i)
|
||||
/// <returns>false</returns>
|
||||
bool SpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
if (e->type() == QMouseEvent::MouseButtonPress && isEnabled())
|
||||
QMouseEvent* me = dynamic_cast<QMouseEvent*>(e);
|
||||
|
||||
if (isEnabled() &&
|
||||
me &&
|
||||
me->type() == QMouseEvent::MouseButtonPress &&
|
||||
me->button() == Qt::RightButton)
|
||||
{
|
||||
//QPoint pt;
|
||||
m_MouseDownPoint = m_MouseMovePoint = me->pos();
|
||||
StartTimer();
|
||||
//qDebug() << "Right mouse down";
|
||||
// QPoint pt;
|
||||
//
|
||||
//if (QMouseEvent* me = (QMouseEvent*)e)
|
||||
// if (QMouseEvent* me = (QMouseEvent*)e)
|
||||
// pt = me->localPos().toPoint();
|
||||
//
|
||||
//int pos = lineEdit()->cursorPositionAt(pt);
|
||||
// int pos = lineEdit()->cursorPositionAt(pt);
|
||||
//
|
||||
//if (lineEdit()->selectedText() != "")
|
||||
//{
|
||||
// if (lineEdit()->selectedText() != "")
|
||||
// {
|
||||
// lineEdit()->deselect();
|
||||
// lineEdit()->setCursorPosition(pos);
|
||||
// return true;
|
||||
//}
|
||||
//else if (m_Select)
|
||||
//{
|
||||
// }
|
||||
// else if (m_Select)
|
||||
// {
|
||||
// lineEdit()->setCursorPosition(pos);
|
||||
// selectAll();
|
||||
// m_Select = false;
|
||||
// return true;
|
||||
//}
|
||||
// }
|
||||
}
|
||||
else if (isEnabled() &&
|
||||
me &&
|
||||
me->type() == QMouseEvent::MouseButtonRelease &&
|
||||
me->button() == Qt::RightButton)
|
||||
{
|
||||
StopTimer();
|
||||
m_MouseDownPoint = m_MouseMovePoint = me->pos();
|
||||
//qDebug() << "Right mouse up";
|
||||
}
|
||||
else if (isEnabled() &&
|
||||
me &&
|
||||
me->type() == QMouseEvent::MouseMove &&
|
||||
QGuiApplication::mouseButtons() & Qt::RightButton)
|
||||
{
|
||||
m_MouseMovePoint = me->pos();
|
||||
qDebug() << "Mouse move while right down. Pt = " << me->pos() << ", global: " << mapToGlobal(me->pos());
|
||||
}
|
||||
else if (m_DoubleClick && e->type() == QMouseEvent::MouseButtonDblClick && isEnabled())
|
||||
{
|
||||
@ -163,6 +223,7 @@ bool SpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
void SpinBox::focusInEvent(QFocusEvent* e)
|
||||
{
|
||||
//lineEdit()->setReadOnly(false);
|
||||
StopTimer();
|
||||
QSpinBox::focusInEvent(e);
|
||||
}
|
||||
|
||||
@ -177,6 +238,7 @@ void SpinBox::focusOutEvent(QFocusEvent* e)
|
||||
{
|
||||
//lineEdit()->deselect();//Clear selection when leaving.
|
||||
//lineEdit()->setReadOnly(true);//Clever hack to clear the cursor when leaving.
|
||||
StopTimer();
|
||||
QSpinBox::focusOutEvent(e);
|
||||
}
|
||||
|
||||
@ -189,6 +251,7 @@ void SpinBox::enterEvent(QEvent* e)
|
||||
{
|
||||
//m_Select = true;
|
||||
//setFocus();
|
||||
StopTimer();
|
||||
QSpinBox::enterEvent(e);
|
||||
}
|
||||
|
||||
@ -201,5 +264,25 @@ void SpinBox::leaveEvent(QEvent* e)
|
||||
{
|
||||
//m_Select = false;
|
||||
//clearFocus();
|
||||
StopTimer();
|
||||
QSpinBox::leaveEvent(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the timer in response to the right mouse button being pressed.
|
||||
/// </summary>
|
||||
void SpinBox::StartTimer()
|
||||
{
|
||||
m_Timer.stop();
|
||||
connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
|
||||
m_Timer.start(300);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the timer in response to the left mouse button being pressed.
|
||||
/// </summary>
|
||||
void SpinBox::StopTimer()
|
||||
{
|
||||
m_Timer.stop();
|
||||
disconnect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout()));
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ public:
|
||||
|
||||
public slots:
|
||||
void onSpinBoxValueChanged(int i);
|
||||
void OnTimeout();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject* o, QEvent* e);
|
||||
@ -36,10 +37,16 @@ protected:
|
||||
virtual void leaveEvent(QEvent* e);
|
||||
|
||||
private:
|
||||
void StartTimer();
|
||||
void StopTimer();
|
||||
|
||||
bool m_Select;
|
||||
bool m_DoubleClick;
|
||||
int m_DoubleClickNonZero;
|
||||
int m_DoubleClickZero;
|
||||
int m_Step;
|
||||
int m_SmallStep;
|
||||
QPoint m_MouseDownPoint;
|
||||
QPoint m_MouseMovePoint;
|
||||
static QTimer m_Timer;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user