mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-01-21 05:00:06 -05:00
--User changes
-Give tabs a height of 4px in the qss files. Looks a little large on 4k screens, but just right on HD screens which are much more common. -Allow for styling of zero and non-zero variation tree nodes via qss. -Allow for toggling whether to interpolate between colors in the palette editor, or to do hard cuts between colors. -Allow for adjusting spinner values with the + = or up arrow keys to increase, and - _ or down arrow keys to decrease. -Allow for responding to global presses of + = and - _ to cycle up or down to specify which xform is set as the current one. -Allow for adding "layers" via xaos which will add a user-specified number of xforms, and set certain xaos values to 0 or 1. -Add a new menu item under the Edit menu to copy the OpenCL iteration kernel source to the clipboard. -Show text on the status bar which indicates that an OpenCL kernel compilation is taking place. -Show xform name on xform combo box when expanded. Adjust size to fit all names. -Draw post affine circles using dashed lines. -Prevent QSS dialog from styling its editor, which makes it easier to see text when creating styles which have custom colors for text boxes. --Bug fixes -Fix up some table layouts which seemed to have regressed/decayed over time for reasons unknown. -Using undo/redo would create a new flame in the library every time. -Solo was not being preserved when using undo/redo. --Code changes -Make the solo flag be a part of the flame data now. -Fix some tabification in the OpenCL code for EllipticVariation. -Fix tabification in the varState code for OpenCL. -Add an event called m_CompileBegun to RendererCL that is called right before an OpenCL compile is begun. --This required making RendererCLBase not a pure virtual base class. Member functions just return defaults. -Filter key presses on main window to only process the third one. This is due to Qt triggering three events for every key press. -The palette preview table was installing an event filter for seemingly no reason. Remove it. -Mark certain virtual functions as override in SpinBox and DoubleSpinBox.
This commit is contained in:
parent
0deabd45b8
commit
26c558a2f5
1
.gitignore
vendored
1
.gitignore
vendored
@ -254,3 +254,4 @@ Builds/include/GL
|
||||
/Builds/MSVC/VS2017/zlib.props
|
||||
*last.flame
|
||||
/Source/Fractorium/Fractorium - Copy.ui
|
||||
/.vs/slnx.sqlite
|
||||
|
@ -2,12 +2,19 @@
|
||||
This is needed to deal with the large tabs in the fusion theme which is the default on Linux, and optional on Windows.
|
||||
It's not needed for other themes.
|
||||
You should keep this at the top of whatever custom style you make to ensure the tabs aren't unusually large.*/
|
||||
QTabBar::tab { height: 3ex; }
|
||||
QTabBar::tab { height: 4ex; }
|
||||
|
||||
/*This is needed to give the labels on the status bar some padding.*/
|
||||
QStatusBar QLabel { padding-left: 2px; padding-right: 2px; }
|
||||
|
||||
/*Specific styles below this line*/
|
||||
Fractorium
|
||||
{
|
||||
qproperty-VariationTreeColorNonZero:black;
|
||||
qproperty-VariationTreeColorZero:lightgray;
|
||||
qproperty-VariationTreeBgColorNonZero:darkgray;
|
||||
qproperty-VariationTreeBgColorZero:rgb(53, 53, 53);
|
||||
}
|
||||
|
||||
QObject
|
||||
{
|
||||
@ -307,14 +314,12 @@ QTreeView
|
||||
{
|
||||
border: 1px solid gray;
|
||||
background-color: rgb(53, 53, 53);
|
||||
font: 9pt "MS Shell Dlg";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
font: 9pt "MS Shell Dlg 2";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
}
|
||||
|
||||
/*Setting this gives a more consistent look, but removes the ability to gray variations that are included in the xform*/
|
||||
/*Setting this gives a more consistent look. Also, by omitting color and background color, it allows us to set it above with VariationTreeColorNonZero etc...*/
|
||||
QTreeView::item
|
||||
{
|
||||
background-color: rgb(53, 53, 53);
|
||||
color: darkgray;
|
||||
outline: none;
|
||||
margin-right: 1px;
|
||||
}
|
||||
@ -365,7 +370,7 @@ QTableView
|
||||
color: darkgray;
|
||||
selection-color: darkgray;
|
||||
selection-background-color: rgb(53, 53, 53);
|
||||
font: 9pt "MS Shell Dlg";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
font: 9pt "MS Shell Dlg 2";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
}
|
||||
|
||||
QTableView QTableCornerButton::section:enabled
|
||||
@ -630,3 +635,8 @@ QTableView#FinalRenderParamsTable QPushButton
|
||||
margin-bottom: 2px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
QssDialog QssTextEdit#QssEdit
|
||||
{
|
||||
background-color: #FFFCE1;
|
||||
}
|
@ -2,12 +2,19 @@
|
||||
This is needed to deal with the large tabs in the fusion theme which is the default on Linux, and optional on Windows.
|
||||
It's not needed for other themes.
|
||||
You should keep this at the top of whatever custom style you make to ensure the tabs aren't unusually large.*/
|
||||
QTabBar::tab { height: 3ex; }
|
||||
QTabBar::tab { height: 4ex; }
|
||||
|
||||
/*This is needed to give the labels on the status bar some padding.*/
|
||||
QStatusBar QLabel { padding-left: 2px; padding-right: 2px; }
|
||||
|
||||
/*Specific styles below this line*/
|
||||
Fractorium
|
||||
{
|
||||
qproperty-VariationTreeColorNonZero:black;
|
||||
qproperty-VariationTreeColorZero:lightgray;
|
||||
qproperty-VariationTreeBgColorNonZero:darkgray;
|
||||
qproperty-VariationTreeBgColorZero:rgb(53, 53, 53);
|
||||
}
|
||||
|
||||
QObject
|
||||
{
|
||||
@ -307,14 +314,13 @@ QTreeView
|
||||
{
|
||||
border: 1px solid gray;
|
||||
background-color: rgb(53, 53, 53);
|
||||
font: 9pt "MS Shell Dlg";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
font: 9pt "MS Shell Dlg 2";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
}
|
||||
|
||||
/*Setting this gives a more consistent look, but removes the ability to gray variations that are included in the xform*/
|
||||
|
||||
/*Setting this gives a more consistent look. Also, by omitting color and background color, it allows us to set it above with VariationTreeColorNonZero etc...*/
|
||||
QTreeView::item
|
||||
{
|
||||
background-color: rgb(53, 53, 53);
|
||||
color: darkgray;
|
||||
outline: none;
|
||||
margin-right: 1px;
|
||||
}
|
||||
@ -365,7 +371,7 @@ QTableView
|
||||
color: darkgray;
|
||||
selection-color: darkgray;
|
||||
selection-background-color: rgb(53, 53, 53);
|
||||
font: 9pt "MS Shell Dlg";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
font: 9pt "MS Shell Dlg 2";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
}
|
||||
|
||||
QTableView QTableCornerButton::section:enabled
|
||||
@ -630,3 +636,8 @@ QTableView#FinalRenderParamsTable QPushButton
|
||||
margin-bottom: 2px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
QssDialog QssTextEdit#QssEdit
|
||||
{
|
||||
background-color: #FFFCE1;
|
||||
}
|
@ -2,12 +2,19 @@
|
||||
This is needed to deal with the large tabs in the fusion theme which is the default on Linux, and optional on Windows.
|
||||
It's not needed for other themes.
|
||||
You should keep this at the top of whatever custom style you make to ensure the tabs aren't unusually large.*/
|
||||
QTabBar::tab { height: 3ex; }
|
||||
QTabBar::tab { height: 4ex; }
|
||||
|
||||
/*This is needed to give the labels on the status bar some padding.*/
|
||||
QStatusBar QLabel { padding-left: 2px; padding-right: 2px; }
|
||||
|
||||
/*Specific styles below this line*/
|
||||
Fractorium
|
||||
{
|
||||
qproperty-VariationTreeColorNonZero:black;
|
||||
qproperty-VariationTreeColorZero:lightgray;
|
||||
qproperty-VariationTreeBgColorNonZero:darkgray;
|
||||
qproperty-VariationTreeBgColorZero:rgb(53, 53, 53);
|
||||
}
|
||||
|
||||
QObject
|
||||
{
|
||||
@ -307,14 +314,12 @@ QTreeView
|
||||
{
|
||||
border: 1px solid gray;
|
||||
background-color: rgb(53, 53, 53);
|
||||
font: 8pt "MS Shell Dlg";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
font: 8pt "MS Shell Dlg 2";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
}
|
||||
|
||||
/*Setting this gives a more consistent look, but removes the ability to gray variations that are included in the xform*/
|
||||
/*Setting this gives a more consistent look. Also, by omitting color and background color, it allows us to set it above with VariationTreeColorNonZero etc...*/
|
||||
QTreeView::item
|
||||
{
|
||||
background-color: rgb(53, 53, 53);
|
||||
color: darkgray;
|
||||
outline: none;
|
||||
margin-right: 1px;
|
||||
}
|
||||
@ -365,7 +370,7 @@ QTableView
|
||||
color: darkgray;
|
||||
selection-color: darkgray;
|
||||
selection-background-color: rgb(53, 53, 53);
|
||||
font: 8pt "MS Shell Dlg";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
font: 8pt "MS Shell Dlg 2";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/
|
||||
}
|
||||
|
||||
QTableView QTableCornerButton::section:enabled
|
||||
@ -630,3 +635,8 @@ QTableView#FinalRenderParamsTable QPushButton
|
||||
margin-bottom: 2px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
QssDialog QssTextEdit#QssEdit
|
||||
{
|
||||
background-color: #FFFCE1;
|
||||
}
|
@ -178,6 +178,7 @@ public:
|
||||
m_Edits = xmlCopyDoc(ember.m_Edits, 1);
|
||||
|
||||
CopyCont(m_EmberMotionElements, ember.m_EmberMotionElements);
|
||||
m_Solo = ember.m_Solo;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1723,6 +1724,9 @@ public:
|
||||
//The list of motion elements for the top-level flame params
|
||||
vector<EmberMotion<T>> m_EmberMotionElements;
|
||||
|
||||
//Index of xform to have non-zero opacity, while all others have zero. This is an interactive rendering parameter and is not saved to Xml. -1 means solo is not used.
|
||||
intmax_t m_Solo = -1;
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// The type of scaling used when resizing.
|
||||
|
@ -4009,18 +4009,18 @@ public:
|
||||
string weight = WeightDefineString();
|
||||
string weightDivPiDiv2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
|
||||
ss << "\t{\n"
|
||||
<< "double x2 = 2.0 * vIn.x;\n"
|
||||
<< "double u = precalcSumSquares + x2;\n"
|
||||
<< "double v = precalcSumSquares - x2;\n"
|
||||
<< "double xmaxm1 = 0.5 * (Sqrt1pm1(u) + Sqrt1pm1(v));\n"
|
||||
<< "double a = vIn.x / (1 + xmaxm1);\n"
|
||||
<< "double ssx = xmaxm1 < 0 ? 0.0 : sqrt(xmaxm1);\n"
|
||||
<< "vOut.x = (" << weightDivPiDiv2 << " * asin(clamp(a, (double)-1.0, (double)1.0)));\n"
|
||||
<< "\t\tdouble x2 = 2.0 * vIn.x;\n"
|
||||
<< "\t\tdouble u = precalcSumSquares + x2;\n"
|
||||
<< "\t\tdouble v = precalcSumSquares - x2;\n"
|
||||
<< "\t\tdouble xmaxm1 = 0.5 * (Sqrt1pm1(u) + Sqrt1pm1(v));\n"
|
||||
<< "\t\tdouble a = vIn.x / (1 + xmaxm1);\n"
|
||||
<< "\t\tdouble ssx = xmaxm1 < 0 ? 0.0 : sqrt(xmaxm1);\n"
|
||||
<< "\t\tvOut.x = (" << weightDivPiDiv2 << " * asin(clamp(a, (double)-1.0, (double)1.0)));\n"
|
||||
<< "\n"
|
||||
<< "if (vIn.y > 0)\n"
|
||||
<< " vOut.y = " << weightDivPiDiv2 << " * log1p(xmaxm1 + ssx);\n"
|
||||
<< "else\n"
|
||||
<< " vOut.y = -(" << weightDivPiDiv2 << " * log1p(xmaxm1 + ssx));\n"
|
||||
<< "\t\tif (vIn.y > 0)\n"
|
||||
<< "\t\t\tvOut.y = " << weightDivPiDiv2 << " * log1p(xmaxm1 + ssx);\n"
|
||||
<< "\t\telse\n"
|
||||
<< "\t\t\tvOut.y = -(" << weightDivPiDiv2 << " * log1p(xmaxm1 + ssx));\n"
|
||||
<< "\n"
|
||||
<< "\t\tvOut.z = " << DefaultZCl()
|
||||
<< "\t}\n";
|
||||
|
@ -3678,9 +3678,9 @@ public:
|
||||
string prefix = Prefix();
|
||||
//CPU sets fycle and bcycle to 0 at the beginning in Precalc().
|
||||
//Set to random in OpenCL since a value can't be set once and kept between kernel launches without writing it back to an OpenCL buffer.
|
||||
ss << "\n\t\tvarState." << prefix << "hexaplay3D_rswtch" << stateIndex << " = trunc(MwcNext01(&mwc) * 3.0);";
|
||||
ss << "\n\t\tvarState." << prefix << "hexaplay3D_fcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 5.0);";
|
||||
ss << "\n\t\tvarState." << prefix << "hexaplay3D_bcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 2.0);";
|
||||
ss << "\n\tvarState." << prefix << "hexaplay3D_rswtch" << stateIndex << " = trunc(MwcNext01(&mwc) * 3.0);";
|
||||
ss << "\n\tvarState." << prefix << "hexaplay3D_fcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 5.0);";
|
||||
ss << "\n\tvarState." << prefix << "hexaplay3D_bcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 2.0);";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@ -4068,9 +4068,9 @@ public:
|
||||
string prefix = Prefix();
|
||||
//CPU sets fycle and bcycle to 0 at the beginning in Precalc().
|
||||
//Set to random in OpenCL since a value can't be set once and kept between kernel launches without writing it back to an OpenCL buffer.
|
||||
ss << "\n\t\tvarState." << prefix << "hexnix3D_rswtch" << stateIndex << " = trunc(MwcNext01(&mwc) * 3.0);";
|
||||
ss << "\n\t\tvarState." << prefix << "hexnix3D_fcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 5.0);";
|
||||
ss << "\n\t\tvarState." << prefix << "hexnix3D_bcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 2.0);";
|
||||
ss << "\n\tvarState." << prefix << "hexnix3D_rswtch" << stateIndex << " = trunc(MwcNext01(&mwc) * 3.0);";
|
||||
ss << "\n\tvarState." << prefix << "hexnix3D_fcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 5.0);";
|
||||
ss << "\n\tvarState." << prefix << "hexnix3D_bcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 2.0);";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
@ -4353,10 +4353,10 @@ public:
|
||||
ss2 << "_" << XformIndexInEmber();
|
||||
string stateIndex = ss2.str();
|
||||
string prefix = Prefix();
|
||||
ss << "\n\t\tvarState." << prefix << "smartcrop_x" << stateIndex << " = 0;";
|
||||
ss << "\n\t\tvarState." << prefix << "smartcrop_y" << stateIndex << " = 0;";
|
||||
ss << "\n\t\tvarState." << prefix << "smartcrop_z" << stateIndex << " = 0;";
|
||||
ss << "\n\t\tvarState." << prefix << "smartcrop_c" << stateIndex << " = 0;";
|
||||
ss << "\n\tvarState." << prefix << "smartcrop_x" << stateIndex << " = 0;";
|
||||
ss << "\n\tvarState." << prefix << "smartcrop_y" << stateIndex << " = 0;";
|
||||
ss << "\n\tvarState." << prefix << "smartcrop_z" << stateIndex << " = 0;";
|
||||
ss << "\n\tvarState." << prefix << "smartcrop_c" << stateIndex << " = 0;";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ RendererCL<T, bucketT>::RendererCL(const vector<pair<size_t, size_t>>& devices,
|
||||
m_PaletteFormat.image_channel_data_type = CL_FLOAT;
|
||||
m_FinalFormat.image_channel_order = CL_RGBA;
|
||||
m_FinalFormat.image_channel_data_type = CL_FLOAT;
|
||||
m_CompileBegun = [&]() { };
|
||||
Init(devices, shared, outputTexID);
|
||||
}
|
||||
|
||||
@ -903,6 +904,7 @@ bool RendererCL<T, bucketT>::BuildIterProgramForEmber(bool doAccum)
|
||||
|
||||
if (b)
|
||||
{
|
||||
m_CompileBegun();
|
||||
m_IterKernel = m_IterOpenCLKernelCreator.CreateIterKernelString(m_Ember, m_Params.first, m_GlobalShared.first, m_LockAccum, doAccum);
|
||||
//cout << "Building: " << "\n" << iterProgram << "\n";
|
||||
vector<std::thread> threads;
|
||||
|
@ -19,9 +19,10 @@ class EMBERCL_API RendererCLBase
|
||||
{
|
||||
public:
|
||||
virtual ~RendererCLBase() { }
|
||||
virtual bool ReadFinal(v4F* pixels) = 0;
|
||||
virtual bool ClearFinal() = 0;
|
||||
virtual bool AnyNvidia() const = 0;
|
||||
virtual bool ReadFinal(v4F* pixels) { return false; }
|
||||
virtual bool ClearFinal() { return false; }
|
||||
virtual bool AnyNvidia() const { return false; }
|
||||
std::function<void(void)> m_CompileBegun;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -230,6 +230,47 @@ bool DoubleSpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
return QDoubleSpinBox::eventFilter(o, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override which is for handling specific key presses while this control is focused.
|
||||
/// In particular, + = and up arrow increase the value, equivalent to scrolling the mouse wheel up, while also observing shift/ctrl modifiers.
|
||||
/// Values are decreased in the same way by pressing - _ or down arrow.
|
||||
/// </summary>
|
||||
/// <param name="ke">The key event</param>
|
||||
void DoubleSpinBox::keyPressEvent(QKeyEvent* ke)
|
||||
{
|
||||
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
bool ctrl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
|
||||
|
||||
if (ke->key() == Qt::Key_Plus || ke->key() == Qt::Key_Equal || ke->key() == Qt::Key_Up)
|
||||
{
|
||||
if (shift)
|
||||
{
|
||||
setSingleStep(m_SmallStep);
|
||||
setValue(value() + m_SmallStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSingleStep(m_Step);
|
||||
setValue(value() + (ctrl ? m_Step * 10 : m_Step));
|
||||
}
|
||||
}
|
||||
else if (ke->key() == Qt::Key_Minus || ke->key() == Qt::Key_Underscore || ke->key() == Qt::Key_Down)
|
||||
{
|
||||
if (shift)
|
||||
{
|
||||
setSingleStep(m_SmallStep);
|
||||
setValue(value() - m_SmallStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSingleStep(m_Step);
|
||||
setValue(value() - (ctrl ? m_Step * 10 : m_Step));
|
||||
}
|
||||
}
|
||||
else
|
||||
QDoubleSpinBox::keyPressEvent(ke);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when focus enters the spinner.
|
||||
/// </summary>
|
||||
|
@ -38,10 +38,11 @@ public slots:
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject* o, QEvent* e) override;
|
||||
virtual void focusInEvent(QFocusEvent* e);
|
||||
virtual void focusOutEvent(QFocusEvent* e);
|
||||
virtual void enterEvent(QEvent* e);
|
||||
virtual void leaveEvent(QEvent* e);
|
||||
virtual void keyPressEvent(QKeyEvent* event) override;
|
||||
virtual void focusInEvent(QFocusEvent* e) override;
|
||||
virtual void focusOutEvent(QFocusEvent* e) override;
|
||||
virtual void enterEvent(QEvent* e) override;
|
||||
virtual void leaveEvent(QEvent* e) override;
|
||||
|
||||
bool m_DoubleClick;
|
||||
shared_ptr<FractoriumSettings> m_Settings;
|
||||
|
@ -89,10 +89,6 @@ Fractorium::Fractorium(QWidget* p)
|
||||
pixmap.fill(m_XformComboColors[i]);
|
||||
m_XformComboIcons[i] = QIcon(pixmap);
|
||||
}
|
||||
|
||||
//Set Default VariationTreeBgColor
|
||||
m_VariationTreeBgColorNoneZero=QColor(200,200,200);
|
||||
m_VariationTreeBgColorZero=QColor(255,255,255);
|
||||
|
||||
QPixmap pixmap(iconSize_, iconSize_);
|
||||
pixmap.fill(m_FinalXformComboColor);
|
||||
@ -348,6 +344,11 @@ void Fractorium::dockLocationChanged(Qt::DockWidgetArea area)
|
||||
/// <returns>false</returns>
|
||||
bool Fractorium::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
static int fcount = 0;//Qt seems to deliver three events for every key press. So a count must be kept to only respond to the third event.
|
||||
static int libdelcount = 0;//Note that if anything ever changes under the hood with Qt, this will likely stop working, so adjust as accordingly.
|
||||
static int xfupcount = 0;
|
||||
static int xfdncount = 0;
|
||||
|
||||
if (o == ui.GLParentScrollArea && e->type() == QEvent::Resize)
|
||||
{
|
||||
m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width() * ui.GLDisplay->devicePixelRatioF());
|
||||
@ -355,24 +356,79 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e)
|
||||
}
|
||||
else if (auto ke = dynamic_cast<QKeyEvent*>(e))
|
||||
{
|
||||
auto combo = ui.CurrentXformCombo;
|
||||
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
|
||||
if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F32)
|
||||
{
|
||||
int val = ke->key() - (int)Qt::Key_F1;
|
||||
fcount++;
|
||||
|
||||
if (val < ui.CurrentXformCombo->count())
|
||||
ui.CurrentXformCombo->setCurrentIndex(val);
|
||||
if (fcount >= 3)
|
||||
{
|
||||
int val = ke->key() - (int)Qt::Key_F1;
|
||||
|
||||
if (val < combo->count())
|
||||
combo->setCurrentIndex(val);
|
||||
|
||||
fcount = 0;
|
||||
qDebug() << "global function key press: " << ke->key() << " " << o->metaObject()->className() << " " << o->objectName();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (o == ui.LibraryTree)
|
||||
{
|
||||
//Require shift for deleting to prevent it from triggering when the user enters delete in the edit box.
|
||||
if (ke->key() == Qt::Key_Delete && e->type() == QEvent::KeyRelease && shift)
|
||||
{
|
||||
auto v = GetCurrentEmberIndex();
|
||||
libdelcount++;
|
||||
|
||||
if (ui.LibraryTree->topLevelItem(0)->childCount() > 1)
|
||||
OnDelete(v);
|
||||
if (libdelcount >= 3)
|
||||
{
|
||||
auto v = GetCurrentEmberIndex();
|
||||
|
||||
if (ui.LibraryTree->topLevelItem(0)->childCount() > 1)
|
||||
OnDelete(v);
|
||||
|
||||
libdelcount = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (o == this)
|
||||
{
|
||||
unsigned int index = combo->currentIndex();
|
||||
|
||||
if (ke->key() == Qt::Key_Plus || ke->key() == Qt::Key_Equal)
|
||||
{
|
||||
xfupcount++;
|
||||
|
||||
if (xfupcount >= 3)
|
||||
{
|
||||
xfupcount = 0;
|
||||
combo->setCurrentIndex((index + 1) % combo->count());
|
||||
qDebug() << "global arrow plus key press: " << ke->key() << " " << o->metaObject()->className() << " " << o->objectName();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (ke->key() == Qt::Key_Minus || ke->key() == Qt::Key_Underscore)
|
||||
{
|
||||
xfdncount++;
|
||||
|
||||
if (xfdncount >= 3)
|
||||
{
|
||||
xfdncount = 0;
|
||||
|
||||
if (index == 0)
|
||||
index = combo->count();
|
||||
|
||||
combo->setCurrentIndex((index - 1) % combo->count());
|
||||
qDebug() << "global arrow minus key press: " << ke->key() << " " << o->metaObject()->className() << " " << o->objectName();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -866,6 +922,10 @@ void Fractorium::SetTabOrders()
|
||||
w = SetTabOrder(this, w, ui.WorldPivotRadio);
|
||||
w = SetTabOrder(this, ui.VariationsFilterLineEdit, ui.VariationsFilterClearButton);//Xforms variation.
|
||||
w = SetTabOrder(this, w, ui.VariationsTree);
|
||||
w = SetTabOrder(this, w, ui.ClearXaosButton);
|
||||
w = SetTabOrder(this, w, ui.RandomXaosButton);
|
||||
w = SetTabOrder(this, w, ui.AddLayerButton);
|
||||
w = SetTabOrder(this, w, ui.AddLayerSpinBox);
|
||||
//Xforms xaos is done dynamically every time.
|
||||
w = SetTabOrder(this, ui.PaletteFilenameCombo, m_PaletteHueSpin);//Palette.
|
||||
w = SetTabOrder(this, w, m_PaletteContrastSpin);
|
||||
|
@ -63,9 +63,11 @@ template <typename T> class FinalRenderEmberController;
|
||||
class Fractorium : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor VariationTreeBgColorNoneZero MEMBER m_VariationTreeBgColorNoneZero)
|
||||
Q_PROPERTY(QColor VariationTreeBgColorZero MEMBER m_VariationTreeBgColorZero)
|
||||
|
||||
Q_PROPERTY(QColor VariationTreeColorNonZero MEMBER m_VariationTreeColorNonZero)
|
||||
Q_PROPERTY(QColor VariationTreeColorZero MEMBER m_VariationTreeColorZero)
|
||||
Q_PROPERTY(QColor VariationTreeBgColorNonZero MEMBER m_VariationTreeBgColorNonZero)
|
||||
Q_PROPERTY(QColor VariationTreeBgColorZero MEMBER m_VariationTreeBgColorZero)
|
||||
|
||||
friend GLWidget;
|
||||
friend QssDialog;
|
||||
friend LibraryTreeWidget;
|
||||
@ -140,6 +142,7 @@ public slots:
|
||||
void OnActionPasteXmlOver(bool checked);
|
||||
void OnActionCopySelectedXforms(bool checked);
|
||||
void OnActionPasteSelectedXforms(bool checked);
|
||||
void OnActionCopyKernel(bool checked);
|
||||
|
||||
void OnActionResetWorkspace(bool checked);//View
|
||||
void OnActionAlternateEditorImage(bool checked);
|
||||
@ -319,6 +322,7 @@ public slots:
|
||||
void OnXaosChanged(double d);
|
||||
void OnClearXaosButtonClicked(bool checked);
|
||||
void OnRandomXaosButtonClicked(bool checked);
|
||||
void OnAddLayerButtonClicked(bool checked);
|
||||
void OnXaosRowDoubleClicked(int logicalIndex);
|
||||
void OnXaosColDoubleClicked(int logicalIndex);
|
||||
void OnXaosTableModelDataChanged(const QModelIndex& indexA, const QModelIndex& indexB);
|
||||
@ -561,7 +565,8 @@ private:
|
||||
char m_CoordinateString[128];
|
||||
QColor m_XformComboColors[XFORM_COLOR_COUNT], m_FinalXformComboColor;
|
||||
QIcon m_XformComboIcons[XFORM_COLOR_COUNT], m_FinalXformComboIcon;
|
||||
QColor m_VariationTreeBgColorNoneZero, m_VariationTreeBgColorZero;
|
||||
QColor m_VariationTreeColorNonZero, m_VariationTreeColorZero;
|
||||
QColor m_VariationTreeBgColorNonZero, m_VariationTreeBgColorZero;
|
||||
vector<QDockWidget*> m_Docks;
|
||||
|
||||
int m_FontSize;
|
||||
@ -572,7 +577,7 @@ private:
|
||||
shared_ptr<OpenCLInfo> m_Info;
|
||||
unique_ptr<FractoriumEmberControllerBase> m_Controller;
|
||||
Ui::FractoriumClass ui;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
@ -41,6 +41,9 @@
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="dockOptions">
|
||||
<set>QMainWindow::AllowNestedDocks|QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks|QMainWindow::GroupedDragging</set>
|
||||
</property>
|
||||
@ -432,7 +435,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>15</number>
|
||||
@ -513,7 +516,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>15</number>
|
||||
@ -575,6 +578,9 @@
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
@ -600,7 +606,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>15</number>
|
||||
@ -697,7 +703,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>15</number>
|
||||
@ -1587,7 +1593,7 @@
|
||||
<number>1</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>15</number>
|
||||
@ -1891,6 +1897,48 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_4" rowminimumheight="0" columnminimumwidth="0,0">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="AddLayerButton">
|
||||
<property name="toolTip">
|
||||
<string>Add N new xforms with all to/from xaos values to each other set to 1, and the remainder set to 0</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Layer</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="SpinBox" name="AddLayerSpinBox">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> Xforms</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="XaosTableView">
|
||||
<property name="sizePolicy">
|
||||
@ -2805,6 +2853,9 @@
|
||||
<property name="maxVisibleItems">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>9</width>
|
||||
@ -3096,7 +3147,7 @@
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>110</number>
|
||||
@ -3179,7 +3230,7 @@
|
||||
<enum>QTabWidget::Triangular</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="XformColorTab">
|
||||
<property name="sizePolicy">
|
||||
@ -6924,6 +6975,8 @@
|
||||
<addaction name="separator"/>
|
||||
<addaction name="ActionCopySelectedXforms"/>
|
||||
<addaction name="ActionPasteSelectedXforms"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="ActionCopyKernel"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="MenuView">
|
||||
<property name="title">
|
||||
@ -8286,6 +8339,17 @@
|
||||
<string>Reset Scale</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="ActionCopyKernel">
|
||||
<property name="text">
|
||||
<string>Copy &Kernel</string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Copy the OpenCL program to the clipboard for debugging.</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+K</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
@ -8310,6 +8374,11 @@
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>LibraryTreeWidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>spinbox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>LibraryDockWidget</tabstop>
|
||||
|
@ -495,12 +495,61 @@ static QString BaseStyle()
|
||||
"It's not needed for other themes."
|
||||
"You should keep this at the top of whatever custom style you make to ensure the tabs aren't unusually large.*/\n"
|
||||
#ifndef _WIN32
|
||||
"QTabBar::tab { height: 3ex; }\n\n"
|
||||
"QTabBar::tab { height: 4ex; }\n\n"
|
||||
#else
|
||||
"QTabBar::tab { height: 3ex; }\n\n"
|
||||
"QTabBar::tab { height: 4ex; }\n\n"
|
||||
#endif
|
||||
"/*This is needed to give the labels on the status bar some padding.*/\n"
|
||||
"QStatusBar QLabel { padding-left: 2px; padding-right: 2px; }\n\n"
|
||||
"QStatusBar QLabel { padding-left: 2px; padding-right: 2px; }\n"
|
||||
"\n"
|
||||
"Fractorium\n"
|
||||
"{\n"
|
||||
"\tqproperty-VariationTreeColorNonZero:black;\n"
|
||||
"\tqproperty-VariationTreeColorZero:black;\n"
|
||||
"\tqproperty-VariationTreeBgColorNonZero:lightgray;\n"
|
||||
"\tqproperty-VariationTreeBgColorZero:white;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"/*For some reason, Qt does not draw table headers correctly, so the style must always be manually specified.*/\n"
|
||||
"QHeaderView::section::vertical:enabled\n"
|
||||
"{\n"
|
||||
"\tcolor: black;\n"
|
||||
"\tbackground-color: lightgray;\n"
|
||||
"\tborder: none;\n"
|
||||
"\tborder-bottom: 1px solid gray;\n"
|
||||
"\tpadding: 4px;\n"
|
||||
"\tfont: 8pt \"MS Shell Dlg 2\";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"QHeaderView::section::horizontal:enabled\n"
|
||||
"{\n"
|
||||
"\tcolor: black;\n"
|
||||
"\tbackground-color: lightgray;\n"
|
||||
"\tborder: 0px solid darkgray;\n"
|
||||
"\tborder-right: 1px solid gray;\n"
|
||||
"\tpadding: 4px;\n"
|
||||
"\tfont: 8pt \"MS Shell Dlg 2\";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"QHeaderView::section::vertical:disabled\n"
|
||||
"{\n"
|
||||
"\tcolor: rgb(35, 35, 35);\n"
|
||||
"\tbackground-color: rgb(53, 53, 53);\n"
|
||||
"\tborder: 0px none darkgray;\n"
|
||||
"\tborder-bottom: 1px solid rgb(53, 53, 53);\n"
|
||||
"\tpadding: 4px;\n"
|
||||
"\tfont: 8pt \"MS Shell Dlg 2\";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"QHeaderView::section::horizontal:disabled\n"
|
||||
"{\n"
|
||||
"\tcolor:rgb(35, 35, 35);\n"
|
||||
"\tbackground-color: rgb(53, 53, 53);\n"
|
||||
"\tborder: 0px none darkgray;\n"
|
||||
"\tborder-right: 0px solid rgb(53, 53, 53);\n"
|
||||
"\tpadding: 4px;\n"
|
||||
"\tfont: 8pt \"MS Shell Dlg 2\";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/\n"
|
||||
"}\n"
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -336,8 +336,6 @@ void FractoriumEmberController<T>::SetEmberPrivate(const Ember<U>& ember, bool v
|
||||
|
||||
if (updatePointer && (typeid(T) == typeid(U)))
|
||||
m_EmberFilePointer = (Ember<T>*)&ember;
|
||||
else
|
||||
m_EmberFilePointer = nullptr;
|
||||
|
||||
if (!verbatim)
|
||||
{
|
||||
|
@ -109,6 +109,7 @@ public:
|
||||
virtual void PasteXmlOver() { }
|
||||
virtual void CopySelectedXforms() { }
|
||||
virtual void PasteSelectedXforms() { }
|
||||
virtual void CopyKernel() { }
|
||||
virtual void AddReflectiveSymmetry() { }//Tools.
|
||||
virtual void AddRotationalSymmetry() { }
|
||||
virtual void AddBothSymmetry() { }
|
||||
@ -184,7 +185,7 @@ public:
|
||||
virtual void XformNameChanged(int row, int col) { }
|
||||
virtual void XformAnimateChanged(int state) { }
|
||||
virtual void FillXforms(int index = 0) { }
|
||||
virtual void UpdateXformName(int index) { }
|
||||
virtual void UpdateXformName(int index) { }
|
||||
|
||||
//Xforms Affine.
|
||||
virtual void AffineSetHelper(double d, int index, bool pre) { }
|
||||
@ -210,6 +211,7 @@ public:
|
||||
virtual void XformColorSpeedChanged(double d) { }
|
||||
virtual void XformOpacityChanged(double d) { }
|
||||
virtual void XformDirectColorChanged(double d) { }
|
||||
virtual void SoloXformCheckBoxStateChanged(int state, int index) { }
|
||||
virtual QColor ColorIndexToQColor(double d) { return QColor(); }
|
||||
|
||||
//Xforms Variations.
|
||||
@ -218,6 +220,7 @@ public:
|
||||
virtual void ClearVariationsTree() { }
|
||||
virtual void VariationSpinBoxValueChanged(double d) { }
|
||||
virtual void FilteredVariations() { }
|
||||
virtual void FillVariationTreeWithCurrentXform() { }
|
||||
|
||||
//Xforms Selection.
|
||||
|
||||
@ -226,6 +229,7 @@ public:
|
||||
virtual void XaosChanged(int x, int y, double val) { }
|
||||
virtual void ClearXaos() { }
|
||||
virtual void RandomXaos() { }
|
||||
virtual void AddLayer(int xforms) { }
|
||||
|
||||
//Palette.
|
||||
virtual size_t InitPaletteList(const QString& s) { return 0; }
|
||||
@ -375,6 +379,7 @@ public:
|
||||
virtual void PasteXmlOver() override;
|
||||
virtual void CopySelectedXforms() override;
|
||||
virtual void PasteSelectedXforms() override;
|
||||
virtual void CopyKernel() override;
|
||||
virtual void AddReflectiveSymmetry() override;
|
||||
virtual void AddRotationalSymmetry() override;
|
||||
virtual void AddBothSymmetry() override;
|
||||
@ -451,7 +456,7 @@ public:
|
||||
virtual void XformNameChanged(int row, int col) override;
|
||||
virtual void XformAnimateChanged(int state) override;
|
||||
virtual void FillXforms(int index = 0) override;
|
||||
virtual void UpdateXformName(int index) override;
|
||||
virtual void UpdateXformName(int index) override;
|
||||
void FillWithXform(Xform<T>* xform);
|
||||
Xform<T>* CurrentXform();
|
||||
void UpdateXform(std::function<void(Xform<T>*, size_t, size_t)> func, eXformUpdate updateType = eXformUpdate::UPDATE_CURRENT, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER, size_t index = 0);
|
||||
@ -480,6 +485,7 @@ public:
|
||||
virtual void XformColorSpeedChanged(double d) override;
|
||||
virtual void XformOpacityChanged(double d) override;
|
||||
virtual void XformDirectColorChanged(double d) override;
|
||||
virtual void SoloXformCheckBoxStateChanged(int state, int index) override;
|
||||
virtual QColor ColorIndexToQColor(double d) override;
|
||||
void FillColorWithXform(Xform<T>* xform);
|
||||
|
||||
@ -489,6 +495,7 @@ public:
|
||||
virtual void ClearVariationsTree() override;
|
||||
virtual void VariationSpinBoxValueChanged(double d) override;
|
||||
virtual void FilteredVariations() override;
|
||||
virtual void FillVariationTreeWithCurrentXform() override;
|
||||
void FillVariationTreeWithXform(Xform<T>* xform);
|
||||
|
||||
//Xforms Xaos.
|
||||
@ -496,6 +503,7 @@ public:
|
||||
virtual void XaosChanged(int x, int y, double val) override;
|
||||
virtual void ClearXaos() override;
|
||||
virtual void RandomXaos() override;
|
||||
virtual void AddLayer(int xforms) override;
|
||||
|
||||
//Xforms Selection.
|
||||
bool XformCheckboxAt(int i, std::function<void(QCheckBox*)> func);
|
||||
|
@ -25,6 +25,7 @@ void Fractorium::InitMenusUI()
|
||||
connect(ui.ActionPasteXmlOver, SIGNAL(triggered(bool)), this, SLOT(OnActionPasteXmlOver(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionCopySelectedXforms, SIGNAL(triggered(bool)), this, SLOT(OnActionCopySelectedXforms(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionPasteSelectedXforms, SIGNAL(triggered(bool)), this, SLOT(OnActionPasteSelectedXforms(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ActionCopyKernel, SIGNAL(triggered(bool)), this, SLOT(OnActionCopyKernel(bool)), Qt::QueuedConnection);
|
||||
ui.ActionPasteSelectedXforms->setEnabled(false);
|
||||
//View menu.
|
||||
connect(ui.ActionResetWorkspace, SIGNAL(triggered(bool)), this, SLOT(OnActionResetWorkspace(bool)), Qt::QueuedConnection);
|
||||
@ -471,10 +472,10 @@ void FractoriumEmberController<T>::Undo()
|
||||
int index = m_Ember.GetTotalXformIndex(current, forceFinal);
|
||||
m_LastEditWasUndoRedo = true;
|
||||
m_UndoIndex = std::max<size_t>(0u, m_UndoIndex - 1u);
|
||||
SetEmber(m_UndoList[m_UndoIndex], true, false);//Don't update pointer because it's coming from the undo list...
|
||||
SetEmber(m_UndoList[m_UndoIndex], true, false);//Don't update pointer because it's coming from the undo list.
|
||||
m_EditState = eEditUndoState::UNDO_REDO;
|
||||
|
||||
if (index >= 0)
|
||||
if (index >= 0 && index < m_Fractorium->ui.CurrentXformCombo->count())
|
||||
m_Fractorium->CurrentXform(index);
|
||||
|
||||
m_Fractorium->ui.ActionUndo->setEnabled(m_UndoList.size() > 1 && (m_UndoIndex > 0));
|
||||
@ -497,10 +498,10 @@ void FractoriumEmberController<T>::Redo()
|
||||
int index = m_Ember.GetTotalXformIndex(current, forceFinal);
|
||||
m_LastEditWasUndoRedo = true;
|
||||
m_UndoIndex = std::min<size_t>(m_UndoIndex + 1, m_UndoList.size() - 1);
|
||||
SetEmber(m_UndoList[m_UndoIndex], true, false);
|
||||
SetEmber(m_UndoList[m_UndoIndex], true, false);//Don't update pointer because it's coming from the undo list.
|
||||
m_EditState = eEditUndoState::UNDO_REDO;
|
||||
|
||||
if (index >= 0)
|
||||
if (index >= 0 && index < m_Fractorium->ui.CurrentXformCombo->count())
|
||||
m_Fractorium->CurrentXform(index);
|
||||
|
||||
m_Fractorium->ui.ActionUndo->setEnabled(m_UndoList.size() > 1 && (m_UndoIndex > 0));
|
||||
@ -713,6 +714,19 @@ void Fractorium::OnActionPasteSelectedXforms(bool checked)
|
||||
m_Controller->PasteSelectedXforms();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the text of the OpenCL iteration kernel to the clipboard.
|
||||
/// This performs no action if the renderer is not of type RendererCL.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::CopyKernel()
|
||||
{
|
||||
if (auto rendererCL = dynamic_cast<RendererCL<T, float>*>(m_Renderer.get()))
|
||||
QApplication::clipboard()->setText(QString::fromStdString(rendererCL->IterKernel()));
|
||||
}
|
||||
|
||||
void Fractorium::OnActionCopyKernel(bool checked) { m_Controller->CopyKernel(); }
|
||||
|
||||
/// <summary>
|
||||
/// Reset dock widgets and tabs to their default position.
|
||||
/// Note that there is a bug in Qt, where it will only move them all to the left side if at least
|
||||
@ -837,7 +851,7 @@ void FractoriumEmberController<T>::Flatten()
|
||||
{
|
||||
ember.Flatten(XmlToEmber<T>::m_FlattenNames);
|
||||
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
||||
FillVariationTreeWithXform(CurrentXform());
|
||||
FillVariationTreeWithCurrentXform();
|
||||
}
|
||||
void Fractorium::OnActionFlatten(bool checked) { m_Controller->Flatten(); }
|
||||
|
||||
@ -852,7 +866,7 @@ void FractoriumEmberController<T>::Unflatten()
|
||||
{
|
||||
ember.Unflatten();
|
||||
}, true, eProcessAction::FULL_RENDER, m_Fractorium->ApplyAll());
|
||||
FillVariationTreeWithXform(CurrentXform());
|
||||
FillVariationTreeWithCurrentXform();
|
||||
}
|
||||
void Fractorium::OnActionUnflatten(bool checked) { m_Controller->Unflatten(); }
|
||||
|
||||
|
@ -38,7 +38,6 @@ void Fractorium::InitPaletteUI()
|
||||
palettePreviewTable->setItem(0, 0, previewNameCol);
|
||||
auto previewPaletteItem = new QTableWidgetItem();
|
||||
palettePreviewTable->setItem(0, 1, previewPaletteItem);
|
||||
palettePreviewTable->installEventFilter(this);
|
||||
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.
|
||||
@ -392,6 +391,7 @@ void FractoriumEmberController<T>::PaletteEditorButtonClicked()
|
||||
ed->SetColorIndices(colorIndices);
|
||||
ed->SetPaletteFile(m_CurrentPaletteFilePath);
|
||||
|
||||
//ed->setpal
|
||||
if (ed->exec() == QDialog::Accepted)
|
||||
{
|
||||
//Copy all just to be safe, because they may or may not have synced.
|
||||
|
@ -346,7 +346,7 @@ bool FractoriumEmberController<T>::Render()
|
||||
if (action != eProcessAction::NOTHING)
|
||||
{
|
||||
size_t i = 0;
|
||||
int solo = m_Fractorium->ui.CurrentXformCombo->property("soloxform").toInt();
|
||||
int solo = m_Ember.m_Solo;
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
|
||||
if (solo != -1)
|
||||
@ -667,9 +667,11 @@ bool Fractorium::CreateRendererFromOptions(bool updatePreviews)
|
||||
bool ok = true;
|
||||
bool useOpenCL = m_Info->Ok() && m_Settings->OpenCL();
|
||||
auto v = Devices(m_Settings->Devices());
|
||||
bool doOpenCL = useOpenCL && !v.empty();
|
||||
ui.ActionCopyKernel->setEnabled(doOpenCL);
|
||||
|
||||
//The most important option to process is what kind of renderer is desired, so do it first.
|
||||
if (!m_Controller->CreateRenderer((useOpenCL && !v.empty()) ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, v, updatePreviews, useOpenCL && m_Settings->SharedTexture()))
|
||||
if (!m_Controller->CreateRenderer(doOpenCL ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, v, updatePreviews, doOpenCL && m_Settings->SharedTexture()))
|
||||
{
|
||||
//If using OpenCL, will only get here if creating RendererCL failed, but creating a backup CPU Renderer succeeded.
|
||||
ShowCritical("Renderer Creation Error", "Error creating renderer, most likely a GPU problem. Using CPU instead.");
|
||||
@ -677,12 +679,21 @@ bool Fractorium::CreateRendererFromOptions(bool updatePreviews)
|
||||
m_Settings->SharedTexture(false);
|
||||
ui.ActionCpu->setChecked(true);
|
||||
ui.ActionCL->setChecked(false);
|
||||
ui.ActionCopyKernel->setEnabled(false);
|
||||
m_OptionsDialog->ui.OpenCLCheckBox->setChecked(false);
|
||||
m_OptionsDialog->ui.SharedTextureCheckBox->setChecked(false);
|
||||
m_FinalRenderDialog->ui.FinalRenderOpenCLCheckBox->setChecked(false);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (auto rendererCL = dynamic_cast<RendererCLBase*>(m_Controller->Renderer()))
|
||||
rendererCL->m_CompileBegun = [&]()
|
||||
{
|
||||
m_RenderStatusLabel->setText("Compiling OpenCL kernel...");
|
||||
m_RenderStatusLabel->repaint();
|
||||
QApplication::processEvents();
|
||||
};
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ void Fractorium::InitXaosUI()
|
||||
connect(m_XaosSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnXaosChanged(double)), Qt::QueuedConnection);
|
||||
connect(ui.ClearXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnClearXaosButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.RandomXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnRandomXaosButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.AddLayerButton, SIGNAL(clicked(bool)), this, SLOT(OnAddLayerButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.XaosTableView->verticalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnXaosRowDoubleClicked(int)), Qt::QueuedConnection);
|
||||
connect(ui.XaosTableView->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnXaosColDoubleClicked(int)), Qt::QueuedConnection);
|
||||
}
|
||||
@ -165,6 +166,49 @@ void FractoriumEmberController<T>::RandomXaos()
|
||||
|
||||
void Fractorium::OnRandomXaosButtonClicked(bool checked) { m_Controller->RandomXaos(); }
|
||||
|
||||
/// <summary>
|
||||
/// Add a layer using the specified number of xforms.
|
||||
/// A layer is defined as a new set of xforms whose xaos values are the following:
|
||||
/// From existing to existing: unchanged.
|
||||
/// From existing to new: 0.
|
||||
/// From new to existing: 0.
|
||||
/// From new to new: 1.
|
||||
/// </summary>
|
||||
/// <param name="xforms">The number of new xforms to add to create the layer</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddLayer(int xforms)
|
||||
{
|
||||
Update([&]
|
||||
{
|
||||
auto origXformCount = m_Ember.XformCount();
|
||||
m_Ember.AddXforms(xforms);
|
||||
|
||||
for (auto i = 0; i < m_Ember.XformCount(); i++)
|
||||
{
|
||||
auto xf = m_Ember.GetXform(i);
|
||||
|
||||
if (i < origXformCount)
|
||||
{
|
||||
for (auto j = 0; j < m_Ember.XformCount(); j++)
|
||||
if (j >= origXformCount)
|
||||
xf->SetXaos(j, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto j = 0; j < m_Ember.XformCount(); j++)
|
||||
if (j < origXformCount)
|
||||
xf->SetXaos(j, 0);
|
||||
else
|
||||
xf->SetXaos(j, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
FillXforms();
|
||||
FillSummary();
|
||||
}
|
||||
|
||||
void Fractorium::OnAddLayerButtonClicked(bool checked) { m_Controller->AddLayer(ui.AddLayerSpinBox->value()); }
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all xaos values in one row.
|
||||
/// Resets the rendering process.
|
||||
|
@ -15,25 +15,28 @@ void Fractorium::InitXformsUI()
|
||||
connect(ui.AddFinalXformButton, SIGNAL(clicked(bool)), this, SLOT(OnAddFinalXformButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.CurrentXformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnCurrentXformComboChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.AnimateXformCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnXformAnimateCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
SetFixedTableHeader(ui.XformWeightNameTable->horizontalHeader(),QHeaderView::ResizeToContents);
|
||||
SetFixedTableHeader(ui.XformWeightNameTable->horizontalHeader(), QHeaderView::ResizeToContents);
|
||||
//Use SetupSpinner() just to create the spinner, but use col of -1 to prevent it from being added to the table.
|
||||
SetupSpinner<DoubleSpinBox, double>(ui.XformWeightNameTable, this, row, -1, m_XformWeightSpin, spinHeight, 0, 1000, 0.05, SIGNAL(valueChanged(double)), SLOT(OnXformWeightChanged(double)), false, 0, 1, 0);
|
||||
m_XformWeightSpin->setDecimals(3);
|
||||
m_XformWeightSpin->SmallStep(0.001);
|
||||
m_XformWeightSpin->setMinimumWidth(40);
|
||||
m_XformWeightSpin->setMinimumWidth(40);
|
||||
m_XformWeightSpinnerButtonWidget = new SpinnerLabelButtonWidget(m_XformWeightSpin, "=", 20, 19, ui.XformWeightNameTable);
|
||||
m_XformWeightSpinnerButtonWidget->m_SpinBox->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed);
|
||||
m_XformWeightSpinnerButtonWidget->m_Label->setStyleSheet("border: 0px;");
|
||||
m_XformWeightSpinnerButtonWidget->m_Label->setAlignment(Qt::AlignRight| Qt::AlignVCenter);
|
||||
m_XformWeightSpinnerButtonWidget->m_Label->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed);
|
||||
m_XformWeightSpinnerButtonWidget->m_Button->setToolTip("Equalize weights");
|
||||
m_XformWeightSpinnerButtonWidget->m_SpinBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
m_XformWeightSpinnerButtonWidget->m_Label->setStyleSheet("border: 0px;");
|
||||
m_XformWeightSpinnerButtonWidget->m_Label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
m_XformWeightSpinnerButtonWidget->m_Label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
m_XformWeightSpinnerButtonWidget->m_Button->setToolTip("Equalize weights");
|
||||
m_XformWeightSpinnerButtonWidget->m_Button->setStyleSheet("text-align: center center");
|
||||
m_XformWeightSpinnerButtonWidget->setMaximumWidth(130);
|
||||
m_XformWeightSpinnerButtonWidget->setMaximumWidth(130);
|
||||
connect(m_XformWeightSpinnerButtonWidget->m_Button, SIGNAL(clicked(bool)), this, SLOT(OnEqualWeightButtonClicked(bool)), Qt::QueuedConnection);
|
||||
ui.XformWeightNameTable->setCellWidget(0, 0, m_XformWeightSpinnerButtonWidget);
|
||||
ui.XformWeightNameTable->setItem(0, 1, new QTableWidgetItem());
|
||||
connect(ui.XformWeightNameTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnXformNameChanged(int, int)), Qt::QueuedConnection);
|
||||
ui.CurrentXformCombo->setProperty("soloxform", -1);
|
||||
ui.CurrentXformCombo->view()->setMinimumWidth(100);
|
||||
ui.CurrentXformCombo->view()->setMaximumWidth(500);
|
||||
//ui.CurrentXformCombo->view()->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
ui.CurrentXformCombo->view()->setSizeAdjustPolicy(QAbstractScrollArea::SizeAdjustPolicy::AdjustToContentsOnFirstShow);
|
||||
#ifndef _WIN32
|
||||
//For some reason linux makes these 24x24, even though the designer explicitly says 16x16.
|
||||
ui.AddXformButton->setIconSize(QSize(16, 16));
|
||||
@ -63,7 +66,7 @@ Xform<T>* FractoriumEmberController<T>::CurrentXform()
|
||||
void Fractorium::CurrentXform(uint i)
|
||||
{
|
||||
if (i < uint(ui.CurrentXformCombo->count()))
|
||||
ui.CurrentXformCombo->setCurrentIndex(i);
|
||||
ui.CurrentXformCombo->setCurrentIndex(i);
|
||||
}
|
||||
/// <summary>
|
||||
/// Set the current xform and populate all GUI widgets.
|
||||
@ -79,7 +82,7 @@ void FractoriumEmberController<T>::CurrentXformComboChanged(int index)
|
||||
{
|
||||
FillWithXform(xform);
|
||||
m_GLController->SetSelectedXform(xform);
|
||||
int solo = m_Fractorium->ui.CurrentXformCombo->property("soloxform").toInt();
|
||||
int solo = m_Ember.m_Solo;
|
||||
m_Fractorium->ui.SoloXformCheckBox->blockSignals(true);
|
||||
m_Fractorium->ui.SoloXformCheckBox->setChecked(solo == index);
|
||||
m_Fractorium->ui.SoloXformCheckBox->blockSignals(false);
|
||||
@ -244,7 +247,7 @@ void FractoriumEmberController<T>::ClearXform()
|
||||
{
|
||||
xform->ClearAndDeleteVariations();//Note xaos is left alone.
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
FillVariationTreeWithXform(CurrentXform());
|
||||
FillVariationTreeWithCurrentXform();
|
||||
}
|
||||
|
||||
void Fractorium::OnClearXformButtonClicked(bool checked) { m_Controller->ClearXform(); }
|
||||
@ -393,11 +396,13 @@ void FractoriumEmberController<T>::XformNameChanged(int row, int col)
|
||||
}, eXformUpdate::UPDATE_CURRENT, false);
|
||||
FillSummary();//Manually update because this does not trigger a render, which is where this would normally be called.
|
||||
}
|
||||
|
||||
void Fractorium::OnXformNameChanged(int row, int col)
|
||||
{
|
||||
m_Controller->XformNameChanged(row, col);
|
||||
m_Controller->UpdateXformName(ui.CurrentXformCombo->currentIndex());
|
||||
m_Controller->XformNameChanged(row, col);
|
||||
m_Controller->UpdateXformName(ui.CurrentXformCombo->currentIndex());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the animate field of the selected xforms, this allows excluding current if it's not checked, but applies only to it if none are checked.
|
||||
/// This has no effect on interactive rendering, it only sets a value
|
||||
@ -480,9 +485,8 @@ void FractoriumEmberController<T>::SetNormalizedWeightText(Xform<T>* xform)
|
||||
m_Ember.CalcNormalizedWeights(m_NormalizedWeights);
|
||||
|
||||
if (index != -1 && index < m_NormalizedWeights.size())
|
||||
//m_Fractorium->m_XformWeightSpin->setSuffix(QString(" (") + QLocale::system().toString(double(m_NormalizedWeights[index]), 'g', 3) + ")");
|
||||
m_Fractorium->m_XformWeightSpinnerButtonWidget->m_Label->setText(QString(" (") + QLocale::system().toString(double(m_NormalizedWeights[index]), 'g', 3) + ")");
|
||||
}
|
||||
m_Fractorium->m_XformWeightSpinnerButtonWidget->m_Label->setText(QString(" (") + QLocale::system().toString(double(m_NormalizedWeights[index]), 'g', 3) + ")");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Determine whether the specified xform is the final xform in the ember.
|
||||
@ -517,7 +521,7 @@ void FractoriumEmberController<T>::FillXforms(int index)
|
||||
{
|
||||
combo->addItem(ToString(i + 1));
|
||||
combo->setItemIcon(i, m_Fractorium->m_XformComboIcons[i % XFORM_COLOR_COUNT]);
|
||||
UpdateXformName(i);
|
||||
UpdateXformName(i);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
@ -553,7 +557,7 @@ void FractoriumEmberController<T>::FillXforms(int index)
|
||||
m_Fractorium->m_XformsSelectionLayout->addRow(cb, new QWidget(m_Fractorium));
|
||||
combo->addItem("Final");
|
||||
combo->setItemIcon(i, m_Fractorium->m_FinalXformComboIcon);
|
||||
UpdateXformName(i);
|
||||
UpdateXformName(i);
|
||||
}
|
||||
|
||||
m_Fractorium->m_XformsSelectionLayout->blockSignals(false);
|
||||
@ -562,31 +566,50 @@ void FractoriumEmberController<T>::FillXforms(int index)
|
||||
if (index < combo->count())
|
||||
combo->setCurrentIndex(index);
|
||||
|
||||
m_Fractorium->ui.SoloXformCheckBox->blockSignals(true);
|
||||
|
||||
if (m_Ember.m_Solo == combo->currentIndex())
|
||||
m_Fractorium->ui.SoloXformCheckBox->setChecked(true);
|
||||
else
|
||||
m_Fractorium->ui.SoloXformCheckBox->setChecked(false);
|
||||
|
||||
SoloXformCheckBoxStateChanged(m_Ember.m_Solo > -1 ? Qt::Checked : Qt::Unchecked, m_Ember.m_Solo);
|
||||
m_Fractorium->ui.SoloXformCheckBox->blockSignals(false);
|
||||
m_Fractorium->FillXaosTable();
|
||||
m_Fractorium->OnSoloXformCheckBoxStateChanged(Qt::Unchecked);
|
||||
m_Fractorium->OnCurrentXformComboChanged(index);//Make sure the event gets called, because it won't if the zero index is already selected.
|
||||
m_Fractorium->OnCurrentXformComboChanged(index);//Make sure the event gets called, because it won't if the zero index is already selected.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the text in xforms combo box to show the name of Xform.
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the Xform to update.</param>
|
||||
///
|
||||
///
|
||||
template<typename T>
|
||||
void FractoriumEmberController<T>::UpdateXformName(int index)
|
||||
{
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
bool isFinal = m_Ember.FinalXform() == m_Ember.GetTotalXform(index, forceFinal);
|
||||
QString name = isFinal ? "Final" : QString::number(index + 1);
|
||||
|
||||
if (auto xform = m_Ember.GetTotalXform(index, forceFinal))
|
||||
{
|
||||
if (!xform->m_Name.empty())
|
||||
{
|
||||
name += " " + QString::fromStdString(xform->m_Name);
|
||||
}
|
||||
m_Fractorium->ui.CurrentXformCombo->setItemText(index,name);
|
||||
}
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
bool isFinal = m_Ember.FinalXform() == m_Ember.GetTotalXform(index, forceFinal);
|
||||
QString name = isFinal ? "Final" : QString::number(index + 1);
|
||||
|
||||
if (auto xform = m_Ember.GetTotalXform(index, forceFinal))
|
||||
{
|
||||
if (!xform->m_Name.empty())
|
||||
name += " " + QString::fromStdString(xform->m_Name);
|
||||
|
||||
m_Fractorium->ui.CurrentXformCombo->setItemText(index, name);
|
||||
auto view = m_Fractorium->ui.CurrentXformCombo->view();
|
||||
auto fontMetrics1 = view->fontMetrics();
|
||||
auto textWidth = m_Fractorium->ui.CurrentXformCombo->width();
|
||||
auto ww = fontMetrics1.width("WW");
|
||||
|
||||
for (int i = 0; i < m_Fractorium->ui.CurrentXformCombo->count(); ++i)
|
||||
textWidth = std::max(fontMetrics1.width(m_Fractorium->ui.CurrentXformCombo->itemText(i)) + ww, textWidth);
|
||||
|
||||
view->setMinimumWidth(textWidth);
|
||||
view->setMaximumWidth(textWidth);
|
||||
}
|
||||
}
|
||||
|
||||
template class FractoriumEmberController<float>;
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
|
@ -181,28 +181,32 @@ void Fractorium::OnXformDirectColorChanged(double d) { m_Controller->XformDirect
|
||||
/// If checked, current is solo, if unchecked, none are solo.
|
||||
/// Solo means that all other xforms will have their opacity temporarily
|
||||
/// set to zero while rendering so that only the effect of current xform is visible.
|
||||
/// This will not permanently alter the ember, as the temporary opacity values will be applied
|
||||
/// This will not permanently alter the opacities of ember, as the temporary opacity values will be applied
|
||||
/// right before rendering and reset right after.
|
||||
/// Called when solo xform check box is checked.
|
||||
/// Resets the rendering process.
|
||||
/// </summary>
|
||||
/// <param name="state">The state of the checkbox</param>
|
||||
void Fractorium::OnSoloXformCheckBoxStateChanged(int state)
|
||||
/// <param name="index">The index which has been specified as the solo xform, -1 to specify none.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::SoloXformCheckBoxStateChanged(int state, int index)
|
||||
{
|
||||
if (state == Qt::Checked)
|
||||
{
|
||||
ui.CurrentXformCombo->setProperty("soloxform", ui.CurrentXformCombo->currentIndex());
|
||||
ui.SoloXformCheckBox->setText("Solo (" + ToString(ui.CurrentXformCombo->currentIndex() + 1) + ")");
|
||||
m_Ember.m_Solo = index;
|
||||
m_Fractorium->ui.SoloXformCheckBox->setText("Solo (" + ToString(index + 1) + ")");
|
||||
}
|
||||
else if (state == Qt::Unchecked)
|
||||
{
|
||||
ui.CurrentXformCombo->setProperty("soloxform", -1);
|
||||
ui.SoloXformCheckBox->setText("Solo");
|
||||
m_Ember.m_Solo = -1;
|
||||
m_Fractorium->ui.SoloXformCheckBox->setText("Solo");
|
||||
}
|
||||
|
||||
m_Controller->UpdateRender();
|
||||
UpdateRender();
|
||||
}
|
||||
|
||||
void Fractorium::OnSoloXformCheckBoxStateChanged(int state) { m_Controller->SoloXformCheckBoxStateChanged(state, ui.CurrentXformCombo->currentIndex()); }
|
||||
|
||||
/// <summary>
|
||||
/// Redraw the palette ref table.
|
||||
/// Called on resize.
|
||||
|
@ -16,6 +16,11 @@ void Fractorium::InitXformsVariationsUI()
|
||||
//Setting dimensions in the designer with a layout is futile, so must hard code here.
|
||||
tree->setColumnWidth(0, 160);
|
||||
tree->setColumnWidth(1, 23);
|
||||
//Set Default variation tree text and background colors for zero and non zero cases.
|
||||
m_VariationTreeColorNonZero = Qt::black;
|
||||
m_VariationTreeColorZero = Qt::black;
|
||||
m_VariationTreeBgColorNonZero = Qt::lightGray;
|
||||
m_VariationTreeBgColorZero = Qt::white;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -226,8 +231,9 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
|
||||
if (xformVar)
|
||||
xform->DeleteVariationById(var->VariationId());
|
||||
|
||||
// widgetItem->setBackgroundColor(0, QColor(255, 255, 255));//Ensure background is always white if weight goes to zero.
|
||||
widgetItem->setBackgroundColor(0, m_Fractorium->m_VariationTreeBgColorZero); }
|
||||
widgetItem->setTextColor(0, m_Fractorium->m_VariationTreeColorZero);
|
||||
widgetItem->setBackgroundColor(0, m_Fractorium->m_VariationTreeBgColorZero);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xformVar)//The xform already contained this variation, which means they just went from a non-zero weight to another non-zero weight (the simple case).
|
||||
@ -241,8 +247,9 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
|
||||
auto newVar = var->Copy();//Create a new one with default values.
|
||||
newVar->m_Weight = d;
|
||||
xform->AddVariation(newVar);
|
||||
// widgetItem->setBackgroundColor(0, QColor(200, 200, 200));//Set background to gray when a variation has non-zero weight in this xform.
|
||||
widgetItem->setBackgroundColor(0, m_Fractorium->m_VariationTreeBgColorNoneZero);
|
||||
widgetItem->setTextColor(0, m_Fractorium->m_VariationTreeColorNonZero);
|
||||
widgetItem->setBackgroundColor(0, m_Fractorium->m_VariationTreeBgColorNonZero);
|
||||
|
||||
//If they've added a new parametric variation, then grab the values currently in the spinners
|
||||
//for the child parameters and assign them to the newly added variation.
|
||||
if (parVar)
|
||||
@ -275,6 +282,15 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
|
||||
|
||||
void Fractorium::OnVariationSpinBoxValueChanged(double d) { m_Controller->VariationSpinBoxValueChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Fill in the variations tree with the values from the current xform.
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillVariationTreeWithCurrentXform()
|
||||
{
|
||||
FillVariationTreeWithXform(CurrentXform());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fill the variation tree values from passed in xform and apply the current sorting mode.
|
||||
/// Called when the currently selected xform changes.
|
||||
@ -300,9 +316,9 @@ void FractoriumEmberController<T>::FillVariationTreeWithXform(Xform<T>* xform)
|
||||
item->setHidden(false);
|
||||
|
||||
spinBox->SetValueStealth(var ? var->m_Weight : 0);//If the variation was present, set the spin box to its weight, else zero.
|
||||
// item->setBackgroundColor(0, var ? Qt::darkGray : Qt::lightGray);//Ensure background is always white if the value goes to zero, else gray if var present.
|
||||
// item->setBackgroundColor(0, var ? QColor(200, 200, 200) : QColor(255, 255, 255));//Ensure background is always white if the value goes to zero, else gray if var present.
|
||||
item->setBackgroundColor(0, var ? m_Fractorium->m_VariationTreeBgColorNoneZero : m_Fractorium->m_VariationTreeBgColorZero);
|
||||
item->setTextColor(0, var ? m_Fractorium->m_VariationTreeColorNonZero : m_Fractorium->m_VariationTreeColorZero);
|
||||
item->setBackgroundColor(0, var ? m_Fractorium->m_VariationTreeBgColorNonZero : m_Fractorium->m_VariationTreeBgColorZero);
|
||||
|
||||
for (int j = 0; j < item->childCount(); j++)//Iterate through all of the children, which will be the params if it was a parametric variation.
|
||||
{
|
||||
T* param = nullptr;
|
||||
|
@ -685,7 +685,7 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
GLfloat(m_DragHandlePos.x), GLfloat(m_DragHandlePos.y)
|
||||
};
|
||||
QVector4D col(1.0f, 1.0f, 0.5f, 1.0f);
|
||||
m_GL->DrawPointOrLine(col, vertices, 1, GL_POINTS, 6.0f);
|
||||
m_GL->DrawPointOrLine(col, vertices, 1, GL_POINTS, false, 6.0f);
|
||||
#endif
|
||||
}
|
||||
else if (m_DragState == eDragState::DragSelect)
|
||||
@ -733,7 +733,7 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
GLfloat(m_HoverHandlePos.x), GLfloat(m_HoverHandlePos.y)
|
||||
};
|
||||
QVector4D col(0.5f, 1.0f, 1.0f, 1.0f);
|
||||
m_GL->DrawPointOrLine(col, vertices, 1, GL_POINTS, 6.0f);
|
||||
m_GL->DrawPointOrLine(col, vertices, 1, GL_POINTS, false, 6.0f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1091,10 +1091,11 @@ void GLWidget::wheelEvent(QWheelEvent* e)
|
||||
/// <param name="col">The color to draw with</param>
|
||||
/// <param name="vertices">The vertices to use</param>
|
||||
/// <param name="drawType">The type of primitive to draw, such as GL_POINT or GL_LINES</param>
|
||||
/// <param name="dashed">True to draw dashed lines, else solid</param>
|
||||
/// <param name="pointSize">The size in pixels of points, which is internally scaled by the device pixel ratio.</param>
|
||||
void GLWidget::DrawPointOrLine(const QVector4D& col, const std::vector<float>& vertices, int drawType, GLfloat pointSize)
|
||||
void GLWidget::DrawPointOrLine(const QVector4D& col, const std::vector<float>& vertices, int drawType, bool dashed, GLfloat pointSize)
|
||||
{
|
||||
DrawPointOrLine(col, vertices.data(), int(vertices.size() / 2), drawType, pointSize);
|
||||
DrawPointOrLine(col, vertices.data(), int(vertices.size() / 2), drawType, dashed, pointSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1104,10 +1105,18 @@ void GLWidget::DrawPointOrLine(const QVector4D& col, const std::vector<float>& v
|
||||
/// <param name="vertices">The vertices to use</param>
|
||||
/// <param name="size">The number of verticies. This is usually the size of vertices / 2.</param>
|
||||
/// <param name="drawType">The type of primitive to draw, such as GL_POINT or GL_LINES</param>
|
||||
/// <param name="dashed">True to draw dashed lines, else solid</param>
|
||||
/// <param name="pointSize">The size in pixels of points, which is internally scaled by the device pixel ratio.</param>
|
||||
void GLWidget::DrawPointOrLine(const QVector4D& col, const GLfloat* vertices, int size, int drawType, GLfloat pointSize)
|
||||
void GLWidget::DrawPointOrLine(const QVector4D& col, const GLfloat* vertices, int size, int drawType, bool dashed, GLfloat pointSize)
|
||||
{
|
||||
#ifdef USE_GLSL
|
||||
|
||||
if (dashed && drawType == GL_LINES)
|
||||
{
|
||||
glLineStipple(1, 0XFF00);
|
||||
glEnable(GL_LINE_STIPPLE);
|
||||
}
|
||||
|
||||
m_ModelViewProjectionMatrix = m_ProjMatrix * m_ModelViewMatrix;
|
||||
m_Program->setUniformValue(m_ColAttr, col);
|
||||
m_Program->setUniformValue(m_PointSizeUniform, pointSize * GLfloat(devicePixelRatioF()));
|
||||
@ -1116,6 +1125,10 @@ void GLWidget::DrawPointOrLine(const QVector4D& col, const GLfloat* vertices, in
|
||||
this->glEnableVertexAttribArray(0);
|
||||
this->glDrawArrays(drawType, 0, size);
|
||||
this->glDisableVertexAttribArray(0);
|
||||
|
||||
if (dashed && drawType == GL_LINES)
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1509,7 +1522,7 @@ void GLEmberController<T>::DrawAffine(Xform<T>* xform, bool pre, bool selected)
|
||||
m_Verts.push_back(0.0f);
|
||||
m_Verts.push_back(0.0f);
|
||||
m_Verts.push_back(1.0f);
|
||||
m_GL->DrawPointOrLine(col, m_Verts, GL_POINTS, 5.0f);//Three black points, one in the center and two on the circle. Drawn big 5px first to give a black outline.
|
||||
m_GL->DrawPointOrLine(col, m_Verts, GL_POINTS, !pre, 5.0f);//Three black points, one in the center and two on the circle. Drawn big 5px first to give a black outline.
|
||||
//
|
||||
m_GL->glLineWidth(2.0f * m_GL->devicePixelRatioF());//Draw lines again for y axis only, without drawing the circle, using the color of the selected xform.
|
||||
m_Verts.clear();
|
||||
@ -1518,7 +1531,7 @@ void GLEmberController<T>::DrawAffine(Xform<T>* xform, bool pre, bool selected)
|
||||
m_Verts.push_back(0.0f);
|
||||
m_Verts.push_back(1.0f);
|
||||
col = QVector4D(color.r, color.g, color.b, 1.0f);
|
||||
m_GL->DrawPointOrLine(col, m_Verts, GL_LINES);
|
||||
m_GL->DrawPointOrLine(col, m_Verts, GL_LINES, !pre);
|
||||
//
|
||||
m_Verts.clear();
|
||||
m_Verts.push_back(0.0f);
|
||||
@ -1528,7 +1541,7 @@ void GLEmberController<T>::DrawAffine(Xform<T>* xform, bool pre, bool selected)
|
||||
m_Verts.push_back(0.0f);
|
||||
m_Verts.push_back(1.0f);
|
||||
col = QVector4D(1.0f, 1.0f, 1.0f, selected ? 1.0f : 0.5f);
|
||||
m_GL->DrawPointOrLine(col, m_Verts, GL_POINTS, 3.0f);//Draw smaller white points, to give a black outline effect.
|
||||
m_GL->DrawPointOrLine(col, m_Verts, GL_POINTS, false, 3.0f);//Draw smaller white points, to give a black outline effect.
|
||||
m_GL->m_ModelViewMatrix.setToIdentity();
|
||||
#endif
|
||||
}
|
||||
@ -1628,7 +1641,7 @@ void GLWidget::DrawAffineHelper(int index, bool selected, bool pre, bool final,
|
||||
}
|
||||
}
|
||||
|
||||
DrawPointOrLine(color, m_Verts, GL_LINES);
|
||||
DrawPointOrLine(color, m_Verts, GL_LINES, !pre);
|
||||
|
||||
//Lines from center to circle.
|
||||
if (!background)
|
||||
@ -1649,7 +1662,7 @@ void GLWidget::DrawAffineHelper(int index, bool selected, bool pre, bool final,
|
||||
m_Verts.push_back(0);
|
||||
m_Verts.push_back(1);
|
||||
m_Verts.push_back(0);
|
||||
DrawPointOrLine(color, m_Verts, GL_LINES);
|
||||
DrawPointOrLine(color, m_Verts, GL_LINES, !pre);
|
||||
|
||||
if (background)
|
||||
color = QVector4D(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
@ -1659,7 +1672,7 @@ void GLWidget::DrawAffineHelper(int index, bool selected, bool pre, bool final,
|
||||
m_Verts.push_back(0);
|
||||
m_Verts.push_back(0);
|
||||
m_Verts.push_back(1);
|
||||
DrawPointOrLine(color, m_Verts, GL_LINES);
|
||||
DrawPointOrLine(color, m_Verts, GL_LINES, !pre);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -66,8 +66,8 @@ protected:
|
||||
virtual void mouseMoveEvent(QMouseEvent* e) override;
|
||||
virtual void wheelEvent(QWheelEvent* e) override;
|
||||
|
||||
void DrawPointOrLine(const QVector4D& col, const GLfloat* vertices, int size, int drawType, GLfloat pointSize = 1.0f);
|
||||
void DrawPointOrLine(const QVector4D& col, const std::vector<float>& vertices, int drawType, GLfloat pointSize = 1.0f);
|
||||
void DrawPointOrLine(const QVector4D& col, const GLfloat* vertices, int size, int drawType, bool dashed = false, GLfloat pointSize = 1.0f);
|
||||
void DrawPointOrLine(const QVector4D& col, const std::vector<float>& vertices, int drawType, bool dashed = false, GLfloat pointSize = 1.0f);
|
||||
|
||||
private:
|
||||
void SetDimensions(int w, int h);
|
||||
|
@ -70,11 +70,11 @@
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
@ -213,17 +213,17 @@
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="AdjustmentLeftGridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="SyncCheckBox">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="AutoDistributeCheckBox">
|
||||
<property name="text">
|
||||
<string>Sync</string>
|
||||
<string>Auto Distribute</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QSpinBox" name="ArrowsSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
@ -251,10 +251,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="AutoDistributeCheckBox">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="SyncCheckBox">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auto Distribute</string>
|
||||
<string>Sync</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="BlendCheckBox">
|
||||
<property name="text">
|
||||
<string>Blend</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
|
@ -36,6 +36,24 @@ GradientColorsView::GradientColorsView(QWidget* p)
|
||||
ResetToDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get whether to interpolate color keys.
|
||||
/// </summary>
|
||||
/// <returns>True to interpolate (blend), false to do hard cuts.</returns>
|
||||
bool GradientColorsView::Blend()
|
||||
{
|
||||
return m_Blend;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set whether to interpolate color keys.
|
||||
/// </summary>
|
||||
/// <param name="blend">rue to interpolate (blend), false to do hard cuts.</param>
|
||||
void GradientColorsView::Blend(bool blend)
|
||||
{
|
||||
m_Blend = blend;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the focus to the arrow at the given normalized position.
|
||||
/// </summary>
|
||||
@ -374,23 +392,37 @@ Palette<float>& GradientColorsView::GetPalette(int size)
|
||||
{
|
||||
if (!m_Arrows.empty())
|
||||
{
|
||||
QPainter p;
|
||||
QSize imageSize(size, 1);
|
||||
QImage image(imageSize, QImage::Format_ARGB32_Premultiplied);
|
||||
QLinearGradient grad(QPoint(0, 0), QPoint(imageSize.width(), imageSize.height()));
|
||||
m_Palette.m_SourceColors.clear();
|
||||
QPainter painter(&image);
|
||||
float start = 0;
|
||||
|
||||
for (auto& it : m_Arrows)
|
||||
if (Blend())
|
||||
{
|
||||
auto pos = it.first;
|
||||
auto col = it.second.Color();
|
||||
m_Palette.m_SourceColors[pos] = v4F(col.red() / 255.0f, col.green() / 255.0f, col.blue() / 255.0f, 1.0f);
|
||||
grad.setColorAt(pos, col);
|
||||
QLinearGradient grad(QPoint(0, 0), QPoint(imageSize.width(), imageSize.height()));
|
||||
|
||||
for (auto& it : m_Arrows)
|
||||
{
|
||||
auto col = it.second.Color();
|
||||
m_Palette.m_SourceColors[it.first] = v4F(col.red() / 255.0f, col.green() / 255.0f, col.blue() / 255.0f, 1.0f);
|
||||
grad.setColorAt(it.first, col);
|
||||
}
|
||||
|
||||
painter.fillRect(image.rect(), grad);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& it : m_Arrows)
|
||||
{
|
||||
auto col = it.second.Color();
|
||||
m_Palette.m_SourceColors[it.first] = v4F(col.red() / 255.0f, col.green() / 255.0f, col.blue() / 255.0f, 1.0f);
|
||||
painter.setBrush(col);
|
||||
painter.fillRect(start, 0, imageSize.width(), imageSize.height(), col);
|
||||
start = std::ceil(it.first * imageSize.width());
|
||||
}
|
||||
}
|
||||
|
||||
p.begin(&image);
|
||||
p.fillRect(image.rect(), grad);
|
||||
p.end();
|
||||
m_Palette.m_Entries.reserve(image.width());
|
||||
|
||||
for (int i = 0; i < image.width(); i++)
|
||||
@ -493,13 +525,25 @@ void GradientColorsView::paintEvent(QPaintEvent*)
|
||||
QPoint gradStart = QPoint(m_ViewRect.topLeft().x(), m_ViewRect.bottomLeft().y() / 2);
|
||||
QPoint gradStop = QPoint(m_ViewRect.topRight().x(), m_ViewRect.bottomRight().y() / 2);
|
||||
QLinearGradient grad(gradStart, gradStop);
|
||||
float start = m_ViewRect.x();
|
||||
|
||||
for (auto& it : m_Arrows)
|
||||
{
|
||||
GradientArrow& arrow = it.second;
|
||||
grad.setColorAt(it.first, arrow.Color());
|
||||
auto offset = std::ceil(it.first * RectWidth());
|
||||
|
||||
if (Blend())
|
||||
{
|
||||
grad.setColorAt(it.first, arrow.Color());
|
||||
}
|
||||
else
|
||||
{
|
||||
painter.fillRect(start, m_ViewRect.y(), m_ViewRect.right() - start, m_ViewRect.height(), arrow.Color());
|
||||
start = m_ViewRect.x() + offset;
|
||||
}
|
||||
|
||||
QPolygon arrowPolygon = arrow.Area();
|
||||
int iPosX = it.first * RectWidth(),
|
||||
int iPosX = offset,
|
||||
iPosY = m_ViewRect.height() + m_ViewRect.top() + 3;
|
||||
arrowPolygon.translate(iPosX, iPosY);
|
||||
QPainterPath paintPath;
|
||||
@ -513,8 +557,11 @@ void GradientColorsView::paintEvent(QPaintEvent*)
|
||||
painter.setBrush(QBrush(Qt::NoBrush));
|
||||
}
|
||||
|
||||
QBrush brush(grad);
|
||||
painter.fillRect(m_ViewRect, brush);
|
||||
if (Blend())
|
||||
{
|
||||
painter.fillRect(m_ViewRect, grad);
|
||||
}
|
||||
|
||||
painter.drawRect(m_ViewRect);
|
||||
}
|
||||
else
|
||||
@ -534,8 +581,6 @@ void GradientColorsView::paintEvent(QPaintEvent*)
|
||||
//Draw text inside of the arrow.
|
||||
painter.drawText(topArrowRect.x() + (topArrowRect.width() - (topArrow.Width() - 5)) / 2.0, topArrowRect.y() + (topArrowRect.height() - 5), topArrow.Text());
|
||||
}
|
||||
|
||||
painter.end();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -35,6 +35,8 @@ class GradientColorsView : public QWidget
|
||||
|
||||
public:
|
||||
explicit GradientColorsView(QWidget* p = nullptr);
|
||||
bool Blend();
|
||||
void Blend(bool blend);
|
||||
void SetFocus(float position);
|
||||
void SetFocus(size_t position);
|
||||
void SetFocusColor(const QColor& col);
|
||||
@ -74,6 +76,7 @@ private:
|
||||
int RectHeight();
|
||||
bool m_ArrowMoving = false;
|
||||
bool m_ColorIndexArrowMoving = false;
|
||||
bool m_Blend = true;
|
||||
QPoint m_ViewRectSize;
|
||||
QPoint m_ViewRectOffset = QPoint(5, 15);
|
||||
QPoint m_ViewRectTranslate = QPoint(5, 5);
|
||||
|
@ -34,9 +34,10 @@ PaletteEditor::PaletteEditor(QWidget* p) :
|
||||
connect(ui->RemoveColorButton, SIGNAL(clicked()), this, SLOT(OnRemoveColorButtonClicked()));
|
||||
connect(ui->InvertColorsButton, SIGNAL(clicked()), this, SLOT(OnInvertColorsButtonClicked()));
|
||||
connect(ui->ResetColorsButton, SIGNAL(clicked()), this, SLOT(OnResetToDefaultButtonClicked()));
|
||||
connect(ui->DistributeColorsButton, SIGNAL(clicked()), this, SLOT(OnDistributeColorsButtonClicked()));
|
||||
connect(ui->RandomColorsButton, SIGNAL(clicked()), this, SLOT(OnRandomColorsButtonClicked()));
|
||||
connect(ui->DistributeColorsButton, SIGNAL(clicked()), this, SLOT(OnDistributeColorsButtonClicked()));
|
||||
connect(ui->SyncCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnSyncCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui->BlendCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnBlendCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui->PaletteFilenameCombo, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnPaletteFilenameComboChanged(const QString&)), Qt::QueuedConnection);
|
||||
connect(ui->PaletteListTable, SIGNAL(cellClicked(int, int)), this, SLOT(OnPaletteCellClicked(int, int)), Qt::QueuedConnection);
|
||||
connect(ui->PaletteListTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnPaletteCellChanged(int, int)), Qt::QueuedConnection);
|
||||
@ -290,6 +291,18 @@ void PaletteEditor::OnSyncCheckBoxStateChanged(int state)
|
||||
EmitColorIndexChanged(std::numeric_limits<size_t>::max(), 0);//Pass special value to update all.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Change whether palette colors are blended between points, or instead do hard cuts.
|
||||
/// Called when the Blend checkbox is checked/unchecked.
|
||||
/// </summary>
|
||||
/// <param name="state">Ignored</param>
|
||||
void PaletteEditor::OnBlendCheckBoxStateChanged(int state)
|
||||
{
|
||||
m_GradientColorView->Blend((bool)state);
|
||||
m_GradientColorView->update();
|
||||
EmitPaletteChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the palette file based on the currently selected index in the combo box.
|
||||
/// Called when the index of the palette filename combo box changes.
|
||||
@ -607,6 +620,7 @@ void PaletteEditor::EnablePaletteControls()
|
||||
ui->AddColorButton->setEnabled(b);
|
||||
ui->DistributeColorsButton->setEnabled(b);
|
||||
ui->AutoDistributeCheckBox->setEnabled(b);
|
||||
ui->BlendCheckBox->setEnabled(b);
|
||||
ui->RandomColorsButton->setEnabled(b);
|
||||
ui->RemoveColorButton->setEnabled(b);
|
||||
ui->ResetColorsButton->setEnabled(b);
|
||||
|
@ -54,6 +54,7 @@ private Q_SLOTS:
|
||||
void OnColorPickerColorChanged(const QColor& col);
|
||||
void OnArrowDoubleClicked(const GradientArrow& arrow);
|
||||
void OnSyncCheckBoxStateChanged(int state);
|
||||
void OnBlendCheckBoxStateChanged(int state);
|
||||
void OnArrowMoved(qreal lastPos, const GradientArrow& arrow);
|
||||
void OnColorIndexMove(size_t index, float value);
|
||||
void OnPaletteFilenameComboChanged(const QString& text);
|
||||
|
@ -315,6 +315,7 @@ void QssDialog::reject()
|
||||
m_Parent->m_Settings->Theme(m_LastTheme->objectName());
|
||||
}
|
||||
|
||||
m_Parent->m_Controller->FillVariationTreeWithCurrentXform();
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
@ -466,6 +467,7 @@ void QssDialog::SlotApplyCss()
|
||||
label->setText(tr("Valid Style Sheet"));
|
||||
label->setStyleSheet(QStringLiteral("color: green"));
|
||||
m_Parent->setStyleSheet(style);
|
||||
m_Parent->m_Controller->FillVariationTreeWithCurrentXform();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -161,9 +161,12 @@ void SpinBox::OnTimeout()
|
||||
/// <returns>false</returns>
|
||||
bool SpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
{
|
||||
if (!isEnabled())
|
||||
return QSpinBox::eventFilter(o, e);
|
||||
|
||||
auto me = dynamic_cast<QMouseEvent*>(e);
|
||||
|
||||
if (isEnabled() && me)
|
||||
if (me)
|
||||
{
|
||||
if (!m_Settings->ToggleType() &&//Ensure double click toggles, not right click.
|
||||
me->type() == QMouseEvent::MouseButtonPress &&
|
||||
@ -222,6 +225,47 @@ bool SpinBox::eventFilter(QObject* o, QEvent* e)
|
||||
return QSpinBox::eventFilter(o, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override which is for handling specific key presses while this control is focused.
|
||||
/// In particular, + = and up arrow increase the value, equivalent to scrolling the mouse wheel up, while also observing shift/ctrl modifiers.
|
||||
/// Values are decreased in the same way by pressing - _ or down arrow.
|
||||
/// </summary>
|
||||
/// <param name="ke">The key event</param>
|
||||
void SpinBox::keyPressEvent(QKeyEvent* ke)
|
||||
{
|
||||
bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
bool ctrl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
|
||||
|
||||
if (ke->key() == Qt::Key_Plus || ke->key() == Qt::Key_Equal || ke->key() == Qt::Key_Up)
|
||||
{
|
||||
if (shift)
|
||||
{
|
||||
setSingleStep(m_SmallStep);
|
||||
setValue(value() + m_SmallStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSingleStep(m_Step);
|
||||
setValue(value() + (ctrl ? m_Step * 10 : m_Step));
|
||||
}
|
||||
}
|
||||
else if (ke->key() == Qt::Key_Minus || ke->key() == Qt::Key_Underscore || ke->key() == Qt::Key_Down)
|
||||
{
|
||||
if (shift)
|
||||
{
|
||||
setSingleStep(m_SmallStep);
|
||||
setValue(value() - m_SmallStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSingleStep(m_Step);
|
||||
setValue(value() - (ctrl ? m_Step * 10 : m_Step));
|
||||
}
|
||||
}
|
||||
else
|
||||
QSpinBox::keyPressEvent(ke);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when focus enters the spinner.
|
||||
/// </summary>
|
||||
|
@ -38,11 +38,12 @@ public slots:
|
||||
void OnTimeout();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject* o, QEvent* e);
|
||||
virtual void focusInEvent(QFocusEvent* e);
|
||||
virtual void focusOutEvent(QFocusEvent* e);
|
||||
virtual void enterEvent(QEvent* e);
|
||||
virtual void leaveEvent(QEvent* e);
|
||||
virtual bool eventFilter(QObject* o, QEvent* e) override;
|
||||
virtual void keyPressEvent(QKeyEvent* event) override;
|
||||
virtual void focusInEvent(QFocusEvent* e) override;
|
||||
virtual void focusOutEvent(QFocusEvent* e) override;
|
||||
virtual void enterEvent(QEvent* e) override;
|
||||
virtual void leaveEvent(QEvent* e) override;
|
||||
|
||||
private:
|
||||
void StartTimer();
|
||||
|
@ -34,7 +34,6 @@ public:
|
||||
m_Button1 = new QPushButton(caption1, p);
|
||||
m_Button2 = new QPushButton(caption2, p);
|
||||
m_Combo = new QComboBox(p);
|
||||
|
||||
m_Combo->addItems(comboStrings);
|
||||
|
||||
if (w1 != -1)
|
||||
@ -55,14 +54,12 @@ public:
|
||||
m_Button2->setMaximumHeight(h);
|
||||
m_Combo->setMinimumHeight(h - 3);
|
||||
m_Combo->setMaximumHeight(h - 3);
|
||||
|
||||
l->addWidget(m_Combo);
|
||||
l->addWidget(m_Button1);
|
||||
l->addWidget(m_Button2);
|
||||
l->setAlignment(Qt::AlignLeft);
|
||||
l->setMargin(0);
|
||||
l->setSpacing(2);
|
||||
|
||||
setLayout(l);
|
||||
}
|
||||
|
||||
@ -105,13 +102,11 @@ public:
|
||||
|
||||
m_Button->setMinimumHeight(h);
|
||||
m_Button->setMaximumHeight(h);
|
||||
|
||||
l->addWidget(spinBox);
|
||||
l->addWidget(m_Button);
|
||||
l->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
l->setMargin(0);
|
||||
l->setSpacing(0);
|
||||
|
||||
setLayout(l);
|
||||
}
|
||||
|
||||
@ -125,8 +120,8 @@ class SpinnerLabelButtonWidget : public QWidget
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor that passes the parent to the base, then creates a QLabel,
|
||||
/// then creates a QPushButton and sets up its caption and dimensions, then
|
||||
/// Constructor that passes the parent to the base, then creates a QLabel,
|
||||
/// then creates a QPushButton and sets up its caption and dimensions, then
|
||||
/// assigns the DoubleSpinBox.
|
||||
/// </summary>
|
||||
/// <param name="spinBox">The pre-created DoubleSpinBox</param>
|
||||
@ -139,12 +134,12 @@ public:
|
||||
{
|
||||
QHBoxLayout* l = new QHBoxLayout(this);
|
||||
m_Button = new QPushButton(buttonCaption, p);
|
||||
m_SpinBox = spinBox;
|
||||
m_SpinBox = spinBox;
|
||||
m_Label = new QLabel(p);
|
||||
m_Label->setMinimumHeight(h);
|
||||
m_Label->setMaximumHeight(h);
|
||||
|
||||
if (w != -1)
|
||||
m_Label->setMinimumHeight(h);
|
||||
m_Label->setMaximumHeight(h);
|
||||
|
||||
if (w != -1)
|
||||
{
|
||||
m_Button->setMinimumWidth(w);
|
||||
m_Button->setMaximumWidth(w);
|
||||
@ -152,9 +147,8 @@ public:
|
||||
|
||||
m_Button->setMinimumHeight(h);
|
||||
m_Button->setMaximumHeight(h);
|
||||
|
||||
l->addWidget(spinBox);
|
||||
l->addWidget(m_Label);
|
||||
l->addWidget(m_Label);
|
||||
l->addWidget(m_Button);
|
||||
l->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
l->setMargin(0);
|
||||
@ -164,5 +158,5 @@ public:
|
||||
|
||||
DoubleSpinBox* m_SpinBox;
|
||||
QPushButton* m_Button;
|
||||
QLabel* m_Label;
|
||||
QLabel* m_Label;
|
||||
};
|
||||
|
@ -194,10 +194,8 @@ void FractoriumVariationsDialog::OnSelectionCheckBoxStateChanged(int i)
|
||||
static vector<string> dc{ "m_ColorX" };
|
||||
static vector<string> assign{ "outPoint->m_X =", "outPoint->m_Y =", "outPoint->m_Z =",
|
||||
"outPoint->m_X=", "outPoint->m_Y=", "outPoint->m_Z=" };
|
||||
//static vector<const Variation<T>*> excluded;
|
||||
static std::set<eVariationId> excluded;
|
||||
excluded.clear();
|
||||
//excluded.reserve(size_t(eVariationId::LAST_VAR));
|
||||
|
||||
if (auto s = dynamic_cast<QCheckBox*>(sender()))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user