mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-02-01 18:40:12 -05:00
--User changes
-Allow locking of the scale at which affine circles are displayed. -Allow user to toggle whether xform will be animated when generating sequences. Also show the animate value when loading. --Code changes -More conversion to C++11 style code. -Add another value to the eXformUpdate enum called UPDATE_CURRENT_AND_SELECTED in anticipation of future work. -Remove some old #defines.
This commit is contained in:
parent
96d53113a0
commit
f10e4e610a
@ -112,6 +112,22 @@ typename v2T Affine2D<T>::operator * (const v2T& v)
|
||||
return TransformVector(v);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a copy of the object with all values A-F scaled by the specified amount.
|
||||
/// </summary>
|
||||
/// <param name="amount">The amount to scale by</param>
|
||||
/// <returns>A new Affine2D which a scaled copy of this instance</returns>
|
||||
template <typename T>
|
||||
Affine2D<T> Affine2D<T>:: operator * (const T& t)
|
||||
{
|
||||
return Affine2D<T>(A() * t,
|
||||
D() * t,
|
||||
B() * t,
|
||||
E() * t,
|
||||
C() * t,
|
||||
F() * t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make this affine transform the identity matrix.
|
||||
/// A and E = 1, all else 0.
|
||||
@ -172,6 +188,21 @@ bool Affine2D<T>::IsEmpty() const
|
||||
(IsClose<T>(F(), EMPTYFIELD));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scales all values A-F by the specified amount.
|
||||
/// </summary>
|
||||
/// <param name="amount">The amount to scale by</param>
|
||||
template <typename T>
|
||||
void Affine2D<T>::Scale(T amount)
|
||||
{
|
||||
A(A() * amount);
|
||||
B(B() * amount);
|
||||
C(C() * amount);
|
||||
D(D() * amount);
|
||||
E(E() * amount);
|
||||
F(F() * amount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotate this affine transform around its origin by the specified angle in degrees.
|
||||
/// </summary>
|
||||
@ -181,7 +212,6 @@ void Affine2D<T>::Rotate(T angle)
|
||||
{
|
||||
m4T origMat4 = ToMat4ColMajor(true);//Must center and use column major for glm to work.
|
||||
m4T newMat4 = glm::rotate(origMat4, angle * DEG_2_RAD_T, v3T(0, 0, 1));//Assuming only rotating around z.
|
||||
|
||||
A(newMat4[0][0]);//Use direct assignments instead of constructor to skip assigning C and F.
|
||||
B(newMat4[0][1]);
|
||||
D(newMat4[1][0]);
|
||||
@ -206,7 +236,6 @@ template <typename T>
|
||||
void Affine2D<T>::RotateScaleXTo(const v2T& v)
|
||||
{
|
||||
Affine2D<T> rs = CalcRotateScale(X(), v);
|
||||
|
||||
X(rs.TransformNormal(X()));
|
||||
Y(rs.TransformNormal(Y()));
|
||||
}
|
||||
@ -219,7 +248,6 @@ template <typename T>
|
||||
void Affine2D<T>::RotateScaleYTo(const v2T& v)
|
||||
{
|
||||
Affine2D<T> rs = CalcRotateScale(Y(), v);
|
||||
|
||||
X(rs.TransformNormal(X()));
|
||||
Y(rs.TransformNormal(Y()));
|
||||
}
|
||||
@ -232,10 +260,9 @@ template <typename T>
|
||||
Affine2D<T> Affine2D<T>::Inverse() const
|
||||
{
|
||||
T det = A() * E() - D() * B();
|
||||
|
||||
return Affine2D<T>(E() / det, -D() / det,
|
||||
-B() / det, A() / det,
|
||||
(F() * B() - C() * E()) / det, (C() * D() - F() * A()) / det);
|
||||
-B() / det, A() / det,
|
||||
(F() * B() - C() * E()) / det, (C() * D() - F() * A()) / det);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -294,9 +321,8 @@ typename m4T Affine2D<T>::ToMat4ColMajor(bool center) const
|
||||
{
|
||||
m4T mat(A(), B(), 0, center ? 0 : C(), //Col0...
|
||||
D(), E(), 0, center ? 0 : F(), //1
|
||||
0, 0, 1, 0, //2
|
||||
0, 0, 0, 1);//3
|
||||
|
||||
0, 0, 1, 0, //2
|
||||
0, 0, 0, 1);//3
|
||||
return mat;
|
||||
}
|
||||
|
||||
@ -310,9 +336,8 @@ typename m4T Affine2D<T>::ToMat4RowMajor(bool center) const
|
||||
{
|
||||
m4T mat(A(), D(), 0, 0,
|
||||
B(), E(), 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 1, 0,
|
||||
center ? 0 : C(), center ? 0 : F(), 0, 1);
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
@ -351,7 +376,6 @@ template <typename T>
|
||||
Affine2D<T> Affine2D<T>::CalcRotateScale(const v2T& from, const v2T& to)
|
||||
{
|
||||
T a, c;
|
||||
|
||||
CalcRSAC(from, to, a, c);
|
||||
return Affine2D<T>(a, c, -c, a, 0, 0);
|
||||
}
|
||||
@ -368,7 +392,6 @@ template <typename T>
|
||||
void Affine2D<T>::CalcRSAC(const v2T& from, const v2T& to, T& a, T& c)
|
||||
{
|
||||
T lsq = from.x * from.x + from.y * from.y;
|
||||
|
||||
a = (from.y * to.y + from.x * to.x) / lsq;
|
||||
c = (from.x * to.y - from.y * to.x) / lsq;
|
||||
}
|
||||
|
@ -64,17 +64,19 @@ public:
|
||||
D(T(affine.D()));
|
||||
E(T(affine.E()));
|
||||
F(T(affine.F()));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator == (const Affine2D<T>& affine);
|
||||
v2T operator * (const v2T& v);
|
||||
Affine2D<T> operator * (const T& t);
|
||||
|
||||
void MakeID();
|
||||
bool IsID() const;
|
||||
bool IsZero() const;
|
||||
bool IsEmpty() const;
|
||||
void Scale(T amount);
|
||||
Affine2D<T> ScaleCopy(T amount);
|
||||
void Rotate(T angle);
|
||||
void Translate(const v2T& v);
|
||||
void RotateScaleXTo(const v2T& v);
|
||||
|
@ -314,8 +314,6 @@ public:
|
||||
/// <returns>True if success, else false.</returns>
|
||||
bool DeleteXform(size_t i)
|
||||
{
|
||||
Xform<T>* xform;
|
||||
|
||||
if (i < XformCount())
|
||||
{
|
||||
m_Xforms.erase(m_Xforms.begin() + i);
|
||||
@ -323,7 +321,7 @@ public:
|
||||
//Now shuffle xaos values from i on back by 1 for every xform.
|
||||
for (size_t x1 = 0; x1 < XformCount(); x1++)
|
||||
{
|
||||
if ((xform = GetXform(x1)))
|
||||
if (auto xform = GetXform(x1))
|
||||
{
|
||||
for (size_t x2 = i + 1; x2 <= XformCount(); x2++)//Iterate from the position after the deletion index up to the old count.
|
||||
xform->SetXaos(x2 - 1, xform->Xaos(x2));
|
||||
@ -463,7 +461,7 @@ public:
|
||||
{
|
||||
for (size_t i = 0; i < TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = GetTotalXform(i);
|
||||
auto xform = GetTotalXform(i);
|
||||
xform->CacheColorVals();
|
||||
xform->SetPrecalcFlags();
|
||||
}
|
||||
@ -824,7 +822,7 @@ public:
|
||||
//This includes all xforms plus final.
|
||||
for (size_t i = 0; i < totalXformCount; i++)
|
||||
{
|
||||
Xform<T>* thisXform = GetTotalXform(i);
|
||||
auto thisXform = GetTotalXform(i);
|
||||
|
||||
if (size == 2 && stagger > 0 && thisXform != &m_FinalXform)
|
||||
{
|
||||
@ -845,7 +843,7 @@ public:
|
||||
|
||||
for (size_t k = 0; k < size; k++)//For each ember in the list.
|
||||
{
|
||||
Xform<T>* tempXform = embers[k].GetTotalXform(i);//Xform in this position in this ember, including final.
|
||||
auto tempXform = embers[k].GetTotalXform(i);//Xform in this position in this ember, including final.
|
||||
|
||||
if (tempXform)
|
||||
{
|
||||
@ -904,7 +902,7 @@ public:
|
||||
{
|
||||
if (i < embers[k].TotalXformCount())//Xform in this position in this ember.
|
||||
{
|
||||
Xform<T>* tempXform = embers[k].GetTotalXform(i);
|
||||
auto tempXform = embers[k].GetTotalXform(i);
|
||||
allID &= tempXform->m_Post.IsID();
|
||||
}
|
||||
}
|
||||
@ -931,7 +929,7 @@ public:
|
||||
|
||||
for (size_t k = 0; k < size; k++)
|
||||
{
|
||||
Xform<T>* tempXform = embers[k].GetTotalXform(i);//Xform in this position in this ember.
|
||||
auto tempXform = embers[k].GetTotalXform(i);//Xform in this position in this ember.
|
||||
|
||||
if (tempXform)
|
||||
{
|
||||
@ -971,7 +969,7 @@ public:
|
||||
//Now fill them with interpolated values.
|
||||
for (size_t j = 0; j < size; j++)//For each ember in the list.
|
||||
{
|
||||
Xform<T>* tempXform = embers[j].GetXform(i);
|
||||
auto tempXform = embers[j].GetXform(i);
|
||||
|
||||
for (size_t k = 0; k < XformCount(); k++)//For each xaos entry in this xform's xaos array, sum it with the same entry in all of the embers multiplied by the coef for that ember.
|
||||
{
|
||||
|
@ -41,7 +41,6 @@ public:
|
||||
bool aligned = true;
|
||||
bool currentFinal, final = sourceEmbers[0].UseFinalXform();
|
||||
size_t i, xf, currentCount, maxCount = sourceEmbers[0].XformCount();
|
||||
Xform<T>* destXform;
|
||||
Xform<T>* destOtherXform;
|
||||
|
||||
//Determine the max number of xforms present in sourceEmbers.
|
||||
@ -84,7 +83,7 @@ public:
|
||||
|
||||
for (xf = 0; xf < maxCount; xf++)//This will include both normal xforms and the final.
|
||||
{
|
||||
destXform = destEmbers[i].GetTotalXform(xf, final);
|
||||
auto destXform = destEmbers[i].GetTotalXform(xf, final);
|
||||
|
||||
//Ensure every parametric variation contained in every xform at either position i - 1 or i + 1 is also contained in the dest xform.
|
||||
if (i > 0)
|
||||
@ -607,7 +606,7 @@ public:
|
||||
//Keep translation linear.
|
||||
zlm[0] = zlm[1] = 0;
|
||||
|
||||
if (Xform<T>* xform = embers[k].GetTotalXform(xfi))
|
||||
if (auto xform = embers[k].GetTotalXform(xfi))
|
||||
{
|
||||
for (col = 0; col < 2; col++)
|
||||
{
|
||||
@ -650,7 +649,7 @@ public:
|
||||
{
|
||||
for (k = 1; k < size; k++)
|
||||
{
|
||||
if (Xform<T>* xform = embers[k].GetTotalXform(xfi))
|
||||
if (auto xform = embers[k].GetTotalXform(xfi))
|
||||
{
|
||||
//Adjust angles differently if an asymmetric case.
|
||||
if (xform->m_Wind[col] > 0 && cflag == 0)
|
||||
|
@ -98,7 +98,7 @@ public:
|
||||
{
|
||||
size_t i;
|
||||
size_t distribCount = ember.XaosPresent() ? ember.XformCount() + 1 : 1;
|
||||
const Xform<T>* xforms = ember.Xforms();
|
||||
auto xforms = ember.Xforms();
|
||||
|
||||
if (m_XformDistributions.size() < CHOOSE_XFORM_GRAIN * distribCount)
|
||||
m_XformDistributions.resize(CHOOSE_XFORM_GRAIN * distribCount);
|
||||
@ -306,7 +306,7 @@ public:
|
||||
{
|
||||
size_t i, badVals = 0;
|
||||
Point<T> tempPoint, p1;
|
||||
Xform<T>* xforms = ember.NonConstXforms();
|
||||
auto xforms = ember.NonConstXforms();
|
||||
|
||||
if (ember.ProjBits())
|
||||
{
|
||||
@ -473,7 +473,7 @@ public:
|
||||
size_t lastXformUsed = 0;
|
||||
size_t badVals = 0;
|
||||
Point<T> tempPoint, p1;
|
||||
Xform<T>* xforms = ember.NonConstXforms();
|
||||
auto xforms = ember.NonConstXforms();
|
||||
|
||||
if (ember.ProjBits())
|
||||
{
|
||||
|
@ -118,7 +118,7 @@ public:
|
||||
//First clear out any xforms that are not the final, and have a density of less than 0.001.
|
||||
for (i = 0; i < ember.XformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = ember.GetXform(i);
|
||||
auto xform = ember.GetXform(i);
|
||||
|
||||
if (xform->m_Weight < T(0.001))
|
||||
{
|
||||
@ -131,7 +131,7 @@ public:
|
||||
//Now consider all xforms, including final.
|
||||
for (i = 0; i < ember.TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = ember.GetTotalXform(i);
|
||||
auto xform = ember.GetTotalXform(i);
|
||||
|
||||
do
|
||||
{
|
||||
@ -223,8 +223,8 @@ public:
|
||||
|
||||
for (size_t i = 0; i < ember.TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform1 = ember.GetTotalXform(i);
|
||||
Xform<T>* xform2 = mutation.GetTotalXform(i);
|
||||
auto xform1 = ember.GetTotalXform(i);
|
||||
auto xform2 = mutation.GetTotalXform(i);
|
||||
|
||||
if (xform1 && xform2)
|
||||
{
|
||||
@ -254,8 +254,8 @@ public:
|
||||
Random(mutation, useVars, sym, 2, maxVars);
|
||||
//Which xform to mutate?
|
||||
modXform = m_Rand.Rand() % ember.TotalXformCount();
|
||||
Xform<T>* xform1 = ember.GetTotalXform(modXform);
|
||||
Xform<T>* xform2 = mutation.GetTotalXform(0);
|
||||
auto xform1 = ember.GetTotalXform(modXform);
|
||||
auto xform2 = mutation.GetTotalXform(0);
|
||||
os << "mutate xform " << modXform << " coefs";
|
||||
|
||||
//If less than 3 xforms, then change only the translation part.
|
||||
@ -285,7 +285,7 @@ public:
|
||||
for (size_t i = 0; i < ember.TotalXformCount(); i++)
|
||||
{
|
||||
bool copy = (i > 0) && same;
|
||||
Xform<T>* xform = ember.GetTotalXform(i);
|
||||
auto xform = ember.GetTotalXform(i);
|
||||
|
||||
if (copy)//Copy the post from the first xform to the rest of them.
|
||||
{
|
||||
@ -400,8 +400,8 @@ public:
|
||||
//Change all the coefs by a fraction of the random.
|
||||
for (size_t x = 0; x < ember.TotalXformCount(); x++)
|
||||
{
|
||||
Xform<T>* xform1 = ember.GetTotalXform(x);
|
||||
Xform<T>* xform2 = mutation.GetTotalXform(x);
|
||||
auto xform1 = ember.GetTotalXform(x);
|
||||
auto xform2 = mutation.GetTotalXform(x);
|
||||
|
||||
for (glm::length_t i = 0; i < 2; i++)
|
||||
for (glm::length_t j = 0; j < 3; j++)
|
||||
@ -498,7 +498,7 @@ public:
|
||||
{
|
||||
if (i < ember1.XformCount() && ember1.GetXform(i)->m_Weight > 0)
|
||||
{
|
||||
Xform<T>* xform = emberOut.GetXform(i);
|
||||
auto xform = emberOut.GetXform(i);
|
||||
*xform = *ember1.GetXform(i);
|
||||
os << " 1";
|
||||
got1 = 1;
|
||||
@ -513,7 +513,7 @@ public:
|
||||
{
|
||||
if (i < ember0.XformCount() && ember0.GetXform(i)->m_Weight > 0)
|
||||
{
|
||||
Xform<T>* xform = emberOut.GetXform(i);
|
||||
auto xform = emberOut.GetXform(i);
|
||||
*xform = *ember0.GetXform(i);
|
||||
os << " 0";
|
||||
got0 = 1;
|
||||
@ -654,7 +654,7 @@ public:
|
||||
//Loop over xforms.
|
||||
for (i = 0; i < ember.TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = ember.GetTotalXform(i);
|
||||
auto xform = ember.GetTotalXform(i);
|
||||
xform->m_Weight = T(1) / ember.TotalXformCount();
|
||||
xform->m_ColorX = m_Rand.Frand01<T>();//Original pingponged between 0 and 1, which gives bad coloring. Ember does random instead.
|
||||
xform->m_ColorY = m_Rand.Frand01<T>();//Will need to update this if 2D coordinates are ever supported.
|
||||
@ -699,7 +699,7 @@ public:
|
||||
if (samed && i > 0)
|
||||
{
|
||||
//Copy the same variations from the previous xform.
|
||||
Xform<T>* prevXform = ember.GetXform(i - 1);
|
||||
auto prevXform = ember.GetXform(i - 1);
|
||||
|
||||
for (j = 0; j < prevXform->TotalVariationCount(); j++)
|
||||
if (xform->TotalVariationCount() < maxVars)
|
||||
@ -893,10 +893,6 @@ public:
|
||||
/// <param name="changePalette">Change palette if true, else don't</param>
|
||||
void ChangeColors(Ember<T>& ember, bool changePalette)
|
||||
{
|
||||
size_t i;
|
||||
Xform<T>* xform0;
|
||||
Xform<T>* xform1;
|
||||
|
||||
if (changePalette)
|
||||
{
|
||||
if (m_PaletteList.Size())
|
||||
@ -910,14 +906,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ember.TotalXformCount(); i++)
|
||||
for (size_t i = 0; i < ember.TotalXformCount(); i++)
|
||||
{
|
||||
ember.GetTotalXform(i)->m_ColorX = m_Rand.Frand01<T>();
|
||||
ember.GetTotalXform(i)->m_ColorY = m_Rand.Frand01<T>();
|
||||
}
|
||||
|
||||
xform0 = RandomXform(ember, -1);
|
||||
xform1 = RandomXform(ember, ember.GetXformIndex(xform0));
|
||||
auto xform0 = RandomXform(ember, -1);
|
||||
auto xform1 = RandomXform(ember, ember.GetXformIndex(xform0));
|
||||
|
||||
if (xform0 && (m_Rand.Rand() & 1))
|
||||
{
|
||||
@ -949,7 +945,7 @@ public:
|
||||
|
||||
if (i != excluded)
|
||||
{
|
||||
Xform<T>* xform = ember.GetTotalXform(i);
|
||||
auto xform = ember.GetTotalXform(i);
|
||||
|
||||
if (xform->m_Weight > 0)
|
||||
return xform;
|
||||
@ -975,8 +971,8 @@ public:
|
||||
//the result xforms before rotate is called.
|
||||
for (size_t i = 0; i < ember.TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform1 = ember.GetTotalXform(i);
|
||||
Xform<T>* xform2 = rotated.GetTotalXform(i);
|
||||
auto xform1 = ember.GetTotalXform(i);
|
||||
auto xform2 = rotated.GetTotalXform(i);
|
||||
|
||||
if (!xform1->m_Motion.empty())
|
||||
xform2->ApplyMotion(*xform1, blend);
|
||||
@ -1009,7 +1005,7 @@ public:
|
||||
|
||||
for (i = 0; i < embers[si].TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = embers[si].GetTotalXform(i);
|
||||
auto xform = embers[si].GetTotalXform(i);
|
||||
|
||||
if (!xform->m_Motion.empty())
|
||||
xform->ApplyMotion(*(prealign[si].GetTotalXform(i)), blend);//Apply motion parameters to result.xform[i] using blend parameter.
|
||||
|
@ -54,7 +54,7 @@ string IterOpenCLKernelCreator<T>::CreateIterKernelString(const Ember<T>& ember,
|
||||
|
||||
for (i = 0; i < totalXformCount; i++)
|
||||
{
|
||||
Xform<T>* xform = ember.GetTotalXform(i);
|
||||
auto xform = ember.GetTotalXform(i);
|
||||
bool needPrecalcSumSquares = false;
|
||||
bool needPrecalcSqrtSumSquares = false;
|
||||
bool needPrecalcAngles = false;
|
||||
@ -831,9 +831,9 @@ bool IterOpenCLKernelCreator<T>::IsBuildRequired(const Ember<T>& ember1, const E
|
||||
|
||||
for (i = 0; i < xformCount; i++)
|
||||
{
|
||||
Xform<T>* xform1 = ember1.GetTotalXform(i);
|
||||
Xform<T>* xform2 = ember2.GetTotalXform(i);
|
||||
size_t varCount = xform1->TotalVariationCount();
|
||||
auto xform1 = ember1.GetTotalXform(i);
|
||||
auto xform2 = ember2.GetTotalXform(i);
|
||||
auto varCount = xform1->TotalVariationCount();
|
||||
|
||||
if (xform1->HasPost() != xform2->HasPost())
|
||||
return true;
|
||||
|
@ -1750,7 +1750,7 @@ void RendererCL<T, bucketT>::ConvertEmber(Ember<T>& ember, EmberCL<T>& emberCL,
|
||||
|
||||
for (size_t i = 0; i < ember.TotalXformCount() && i < xformsCL.size(); i++)
|
||||
{
|
||||
Xform<T>* xform = ember.GetTotalXform(i);
|
||||
auto xform = ember.GetTotalXform(i);
|
||||
xformsCL[i].m_A = xform->m_Affine.A();
|
||||
xformsCL[i].m_B = xform->m_Affine.B();
|
||||
xformsCL[i].m_C = xform->m_Affine.C();
|
||||
|
@ -1880,7 +1880,6 @@ void DistribTester()
|
||||
size_t distribCount = 1;
|
||||
size_t xformCount = 3;
|
||||
vector<byte> m_XformDistributions;
|
||||
//const Xform<T>* xforms = 3;
|
||||
size_t j = 0;
|
||||
vector<T> weights { T(0.333333), T(1.0), T(0.25) };
|
||||
double tempDensity = 0, currentDensityLimit = 0, densityPerElement;
|
||||
|
@ -247,7 +247,7 @@ void FractoriumEmberController<T>::ApplyXmlSavingTemplate(Ember<T>& ember)
|
||||
/// <returns>True if the current ember contains a final xform, else false.</returns>
|
||||
bool Fractorium::HaveFinal()
|
||||
{
|
||||
QComboBox* combo = ui.CurrentXformCombo;
|
||||
auto combo = ui.CurrentXformCombo;
|
||||
return (combo->count() > 0 && combo->itemText(combo->count() - 1) == "Final");
|
||||
}
|
||||
|
||||
@ -389,7 +389,9 @@ void Fractorium::dragEnterEvent(QDragEnterEvent* e)
|
||||
{
|
||||
if (e->mimeData()->hasUrls())
|
||||
{
|
||||
foreach (QUrl url, e->mimeData()->urls())
|
||||
auto urls = e->mimeData()->urls();
|
||||
|
||||
for (auto& url : urls)
|
||||
{
|
||||
QString localFile = url.toLocalFile();
|
||||
QFileInfo fileInfo(localFile);
|
||||
@ -426,7 +428,9 @@ void Fractorium::dropEvent(QDropEvent* e)
|
||||
|
||||
if (e->mimeData()->hasUrls())
|
||||
{
|
||||
foreach (QUrl url, e->mimeData()->urls())
|
||||
auto urls = e->mimeData()->urls();
|
||||
|
||||
for (auto& url : urls)
|
||||
{
|
||||
QString localFile = url.toLocalFile();
|
||||
QFileInfo fileInfo(localFile);
|
||||
|
@ -203,8 +203,10 @@ public slots:
|
||||
void OnXformWeightChanged(double d);
|
||||
void OnEqualWeightButtonClicked(bool checked);
|
||||
void OnXformNameChanged(int row, int col);
|
||||
void OnXformAnimateCheckBoxStateChanged(int state);
|
||||
|
||||
//Xforms Affine.
|
||||
void OnLockAffineScaleCheckBoxStateChanged(int state);
|
||||
void OnPreAffineRowDoubleClicked(int logicalIndex);
|
||||
void OnPreAffineColDoubleClicked(int logicalIndex);
|
||||
void OnPostAffineRowDoubleClicked(int logicalIndex);
|
||||
|
@ -2350,7 +2350,7 @@
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>291</width>
|
||||
<height>613</height>
|
||||
<height>632</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="features">
|
||||
@ -2756,7 +2756,7 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<widget class="QTabWidget" name="XformsTabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="MinimumExpanding">
|
||||
@ -2780,7 +2780,7 @@
|
||||
<enum>QTabWidget::Triangular</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="XformColorTab">
|
||||
<property name="sizePolicy">
|
||||
@ -3444,6 +3444,13 @@
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LockAffineCheckBox">
|
||||
<property name="text">
|
||||
<string>Lock Affine Scale</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="AffineTabScrollArea">
|
||||
<property name="autoFillBackground">
|
||||
@ -3464,7 +3471,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>263</width>
|
||||
<height>743</height>
|
||||
<height>700</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
@ -5479,7 +5486,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>259</width>
|
||||
<height>673</height>
|
||||
<height>652</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -5529,6 +5536,16 @@
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="AnimateXformCheckBox">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Rotate this xform when creating a sequence for animation</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Animate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
@ -15,6 +15,7 @@ FractoriumEmberControllerBase::FractoriumEmberControllerBase(Fractorium* fractor
|
||||
m_Shared = true;
|
||||
m_FailedRenders = 0;
|
||||
m_UndoIndex = 0;
|
||||
m_LockedScale = 1;
|
||||
m_RenderType = eRendererType::CPU_RENDERER;
|
||||
m_OutputTexID = 0;
|
||||
m_SubBatchCount = 1;//Will be ovewritten by the options on first render.
|
||||
@ -224,6 +225,7 @@ void FractoriumEmberController<T>::Update(std::function<void (void)> func, bool
|
||||
/// <summary>
|
||||
/// Wrapper to call a function on the specified xforms, then optionally add the requested action to the rendering queue.
|
||||
/// If no xforms are selected via the checkboxes, and the update type is UPDATE_SELECTED, then the function will be called only on the currently selected xform.
|
||||
/// If the update type is UPDATE_CURRENT_AND_SELECTED, and the current is not among those selected, then the function will be called on the currently selected xform as well.
|
||||
/// </summary>
|
||||
/// <param name="func">The function to call</param>
|
||||
/// <param name="updateType">Whether to apply this update operation on the current, all or selected xforms. Default: eXformUpdate::UPDATE_CURRENT.</param>
|
||||
@ -240,19 +242,48 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
{
|
||||
case eXformUpdate::UPDATE_CURRENT:
|
||||
{
|
||||
if (Xform<T>* xform = CurrentXform())
|
||||
if (auto xform = CurrentXform())
|
||||
func(xform);
|
||||
}
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_CURRENT_AND_SELECTED:
|
||||
{
|
||||
bool currentDone = false;
|
||||
auto current = CurrentXform();
|
||||
|
||||
while (auto xform = m_Ember.GetTotalXform(i))
|
||||
{
|
||||
if (auto child = m_Fractorium->m_XformsSelectionLayout->itemAt(i))
|
||||
{
|
||||
if (auto* w = qobject_cast<QCheckBox*>(child->widget()))
|
||||
{
|
||||
if (w->isChecked())
|
||||
{
|
||||
func(xform);
|
||||
|
||||
if (xform == current)
|
||||
currentDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!currentDone)//Current was not among those selected, so apply to it.
|
||||
func(current);
|
||||
}
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_SELECTED:
|
||||
case eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL:
|
||||
{
|
||||
bool anyUpdated = false;
|
||||
|
||||
while (Xform<T>* xform = (doFinal ? m_Ember.GetTotalXform(i) : m_Ember.GetXform(i)))
|
||||
while (auto xform = (doFinal ? m_Ember.GetTotalXform(i) : m_Ember.GetXform(i)))
|
||||
{
|
||||
if (QLayoutItem* child = m_Fractorium->m_XformsSelectionLayout->itemAt(i))
|
||||
if (auto child = m_Fractorium->m_XformsSelectionLayout->itemAt(i))
|
||||
{
|
||||
if (auto* w = qobject_cast<QCheckBox*>(child->widget()))
|
||||
{
|
||||
@ -269,14 +300,14 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
|
||||
if (!anyUpdated)//None were selected, so just apply to the current.
|
||||
if (doFinal || !isCurrentFinal)//If do final, call func regardless. If not, only call if current is not final.
|
||||
if (Xform<T>* xform = CurrentXform())
|
||||
if (auto xform = CurrentXform())
|
||||
func(xform);
|
||||
}
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_ALL:
|
||||
{
|
||||
while (Xform<T>* xform = m_Ember.GetTotalXform(i++))
|
||||
while (auto xform = m_Ember.GetTotalXform(i++))
|
||||
func(xform);
|
||||
}
|
||||
break;
|
||||
@ -284,7 +315,7 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
case eXformUpdate::UPDATE_ALL_EXCEPT_FINAL:
|
||||
default:
|
||||
{
|
||||
while (Xform<T>* xform = m_Ember.GetXform(i++))
|
||||
while (auto xform = m_Ember.GetXform(i++))
|
||||
func(xform);
|
||||
}
|
||||
break;
|
||||
@ -325,6 +356,7 @@ void FractoriumEmberController<T>::SetEmberPrivate(const Ember<U>& ember, bool v
|
||||
string filename = "last.flame";
|
||||
writer.Save(filename.c_str(), m_Ember, 0, true, false, true);
|
||||
m_GLController->ResetMouseState();
|
||||
m_Fractorium->ui.LockAffineCheckBox->setChecked(false);
|
||||
FillXforms();//Must do this first because the palette setup in FillParamTablesAndPalette() uses the xforms combo.
|
||||
FillParamTablesAndPalette();
|
||||
FillSummary();
|
||||
|
@ -16,7 +16,7 @@ enum class eEditUndoState : et { REGULAR_EDIT, UNDO_REDO, EDIT_UNDO };
|
||||
/// <summary>
|
||||
/// An enum representing which xforms an update should be applied to.
|
||||
/// </summary>
|
||||
enum class eXformUpdate : et { UPDATE_CURRENT, UPDATE_SELECTED, UPDATE_SELECTED_EXCEPT_FINAL, UPDATE_ALL, UPDATE_ALL_EXCEPT_FINAL };
|
||||
enum class eXformUpdate : et { UPDATE_CURRENT, UPDATE_SELECTED, UPDATE_CURRENT_AND_SELECTED, UPDATE_SELECTED_EXCEPT_FINAL, UPDATE_ALL, UPDATE_ALL_EXCEPT_FINAL };
|
||||
|
||||
/// <summary>
|
||||
/// FractoriumEmberController and Fractorium need each other, but each can't include the other.
|
||||
@ -161,6 +161,7 @@ public:
|
||||
virtual void XformWeightChanged(double d) { }
|
||||
virtual void EqualizeWeights() { }
|
||||
virtual void XformNameChanged(int row, int col) { }
|
||||
virtual void XformAnimateChanged(int state) { }
|
||||
virtual void FillXforms(int index = 0) { }
|
||||
|
||||
//Xforms Affine.
|
||||
@ -171,6 +172,8 @@ public:
|
||||
virtual void ScaleXforms(double scale, bool pre) { }
|
||||
virtual void ResetXformsAffine(bool pre) { }
|
||||
virtual void FillBothAffines() { }
|
||||
double LockedScale() { return m_LockedScale; }
|
||||
virtual void LockAffineScaleCheckBoxStateChanged(int state) { }
|
||||
|
||||
//Xforms Color.
|
||||
virtual void XformColorIndexChanged(double d, bool updateRender) { }
|
||||
@ -241,6 +244,7 @@ protected:
|
||||
uint m_SubBatchCount;
|
||||
uint m_FailedRenders;
|
||||
uint m_UndoIndex;
|
||||
double m_LockedScale;
|
||||
eRendererType m_RenderType;
|
||||
eEditUndoState m_EditState;
|
||||
GLuint m_OutputTexID;
|
||||
@ -397,9 +401,11 @@ public:
|
||||
virtual void XformWeightChanged(double d) override;
|
||||
virtual void EqualizeWeights() override;
|
||||
virtual void XformNameChanged(int row, int col) override;
|
||||
virtual void XformAnimateChanged(int state) override;
|
||||
virtual void FillXforms(int index = 0) override;
|
||||
void FillWithXform(Xform<T>* xform);
|
||||
Xform<T>* CurrentXform();
|
||||
void UpdateXform(std::function<void(Xform<T>*)> func, eXformUpdate updateType = eXformUpdate::UPDATE_CURRENT, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER);
|
||||
|
||||
//Xforms Affine.
|
||||
virtual void AffineSetHelper(double d, int index, bool pre) override;
|
||||
@ -409,7 +415,10 @@ public:
|
||||
virtual void ScaleXforms(double scale, bool pre) override;
|
||||
virtual void ResetXformsAffine(bool pre) override;
|
||||
virtual void FillBothAffines() override;
|
||||
virtual void LockAffineScaleCheckBoxStateChanged(int state) override;
|
||||
void FillAffineWithXform(Xform<T>* xform, bool pre);
|
||||
T AffineScaleCurrentToLocked();
|
||||
T AffineScaleLockedToCurrent();
|
||||
|
||||
//Xforms Color.
|
||||
virtual void XformColorIndexChanged(double d, bool updateRender) override;
|
||||
@ -473,7 +482,6 @@ private:
|
||||
QString MakeXformCaption(size_t i);
|
||||
bool XformCheckboxAt(int i, std::function<void(QCheckBox*)> func);
|
||||
bool XformCheckboxAt(Xform<T>* xform, std::function<void(QCheckBox*)> func);
|
||||
void UpdateXform(std::function<void(Xform<T>*)> func, eXformUpdate updateType = eXformUpdate::UPDATE_CURRENT, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER);
|
||||
|
||||
//Palette.
|
||||
void UpdateAdjustedPaletteGUI(Palette<T>& palette);
|
||||
|
@ -176,7 +176,7 @@ void FractoriumEmberController<T>::OpenAndPrepFiles(const QStringList& filenames
|
||||
StopPreviewRender();
|
||||
emberFile.m_Filename = filenames[0];
|
||||
|
||||
foreach (const QString& filename, filenames)
|
||||
for (auto& filename : filenames)
|
||||
{
|
||||
embers.clear();
|
||||
|
||||
@ -694,7 +694,7 @@ void Fractorium::OnActionResetWorkspace(bool checked)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddReflectiveSymmetry()
|
||||
{
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
auto combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
Update([&]()
|
||||
{
|
||||
m_Ember.AddSymmetry(-1, m_Rand);
|
||||
@ -712,7 +712,7 @@ void Fractorium::OnActionAddReflectiveSymmetry(bool checked) { m_Controller->Add
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddRotationalSymmetry()
|
||||
{
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
auto combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
Update([&]()
|
||||
{
|
||||
m_Ember.AddSymmetry(2, m_Rand);
|
||||
@ -730,7 +730,7 @@ void Fractorium::OnActionAddRotationalSymmetry(bool checked) { m_Controller->Add
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AddBothSymmetry()
|
||||
{
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
auto combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
Update([&]()
|
||||
{
|
||||
m_Ember.AddSymmetry(-2, m_Rand);
|
||||
@ -772,7 +772,7 @@ void FractoriumEmberController<T>::ClearFlame()
|
||||
|
||||
if (m_Ember.XformCount() == 1)
|
||||
{
|
||||
if (Xform<T>* xform = m_Ember.GetXform(0))
|
||||
if (auto xform = m_Ember.GetXform(0))
|
||||
{
|
||||
xform->Clear();
|
||||
xform->ParentEmber(&m_Ember);
|
||||
|
@ -10,38 +10,30 @@
|
||||
void Fractorium::InitPaletteUI()
|
||||
{
|
||||
int spinHeight = 20, row = 0;
|
||||
QTableWidget* paletteTable = ui.PaletteListTable;
|
||||
QTableWidget* palettePreviewTable = ui.PalettePreviewTable;
|
||||
|
||||
auto paletteTable = ui.PaletteListTable;
|
||||
auto palettePreviewTable = ui.PalettePreviewTable;
|
||||
connect(ui.PaletteFilenameCombo, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnPaletteFilenameComboChanged(const QString&)), Qt::QueuedConnection);
|
||||
|
||||
connect(paletteTable, SIGNAL(cellClicked(int, int)), this, SLOT(OnPaletteCellClicked(int, int)), Qt::QueuedConnection);
|
||||
connect(paletteTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(OnPaletteCellDoubleClicked(int, int)), Qt::QueuedConnection);
|
||||
|
||||
//Palette adjustment table.
|
||||
QTableWidget* table = ui.PaletteAdjustTable;
|
||||
auto table = ui.PaletteAdjustTable;
|
||||
table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);//Split width over all columns evenly.
|
||||
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 1, m_PaletteHueSpin, spinHeight, -180, 180, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 1, m_PaletteSaturationSpin, spinHeight, -100, 100, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 1, m_PaletteBrightnessSpin, spinHeight, -255, 255, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
|
||||
row = 0;
|
||||
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 3, m_PaletteContrastSpin, spinHeight, -100, 100, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 3, m_PaletteBlurSpin, spinHeight, 0, 127, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 0, 0, 0);
|
||||
SetupSpinner<SpinBox, int>(table, this, row, 3, m_PaletteFrequencySpin, spinHeight, 1, 10, 1, SIGNAL(valueChanged(int)), SLOT(OnPaletteAdjust(int)), true, 1, 1, 1);
|
||||
|
||||
connect(ui.PaletteRandomSelect, SIGNAL(clicked(bool)), this, SLOT(OnPaletteRandomSelectButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PaletteRandomAdjust, SIGNAL(clicked(bool)), this, SLOT(OnPaletteRandomAdjustButtonClicked(bool)), Qt::QueuedConnection);
|
||||
|
||||
//Preview table.
|
||||
palettePreviewTable->setRowCount(1);
|
||||
palettePreviewTable->setColumnWidth(1, 260);//256 plus small margin on each side.
|
||||
QTableWidgetItem* previewNameCol = new QTableWidgetItem("");
|
||||
auto previewNameCol = new QTableWidgetItem("");
|
||||
palettePreviewTable->setItem(0, 0, previewNameCol);
|
||||
QTableWidgetItem* previewPaletteItem = new QTableWidgetItem();
|
||||
auto previewPaletteItem = new QTableWidgetItem();
|
||||
palettePreviewTable->setItem(0, 1, previewPaletteItem);
|
||||
|
||||
connect(ui.PaletteFilterLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnPaletteFilterLineEditTextChanged(const QString&)));
|
||||
connect(ui.PaletteFilterClearButton, SIGNAL(clicked(bool)), this, SLOT(OnPaletteFilterClearButtonClicked(bool)));
|
||||
paletteTable->setColumnWidth(1, 260);//256 plus small margin on each side.
|
||||
@ -60,7 +52,6 @@ template <typename T>
|
||||
int FractoriumEmberController<T>::InitPaletteList(const string& s)
|
||||
{
|
||||
QDirIterator it(s.c_str(), QStringList() << "*.xml", QDir::Files, QDirIterator::FollowSymlinks);
|
||||
|
||||
m_PaletteList.Clear();
|
||||
m_Fractorium->ui.PaletteFilenameCombo->clear();
|
||||
m_Fractorium->ui.PaletteFilenameCombo->setProperty("path", QString::fromStdString(s));
|
||||
@ -89,9 +80,8 @@ 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;
|
||||
|
||||
auto paletteTable = m_Fractorium->ui.PaletteListTable;
|
||||
auto palettePreviewTable = m_Fractorium->ui.PalettePreviewTable;
|
||||
m_CurrentPaletteFilePath = m_Fractorium->ui.PaletteFilenameCombo->property("path").toString().toStdString() + "/" + s;
|
||||
|
||||
if (size_t paletteSize = m_PaletteList.Size(m_CurrentPaletteFilePath))
|
||||
@ -99,14 +89,11 @@ bool FractoriumEmberController<T>::FillPaletteTable(const string& s)
|
||||
paletteTable->clear();
|
||||
paletteTable->blockSignals(true);
|
||||
paletteTable->setRowCount(paletteSize);
|
||||
|
||||
//Headers get removed when clearing, so must re-create here.
|
||||
QTableWidgetItem* nameHeader = new QTableWidgetItem("Name");
|
||||
QTableWidgetItem* paletteHeader = new QTableWidgetItem("Palette");
|
||||
|
||||
auto nameHeader = new QTableWidgetItem("Name");
|
||||
auto paletteHeader = new QTableWidgetItem("Palette");
|
||||
nameHeader->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
paletteHeader->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
|
||||
paletteTable->setHorizontalHeaderItem(0, nameHeader);
|
||||
paletteTable->setHorizontalHeaderItem(1, paletteHeader);
|
||||
|
||||
@ -117,13 +104,10 @@ bool FractoriumEmberController<T>::FillPaletteTable(const string& s)
|
||||
{
|
||||
auto v = p->MakeRgbPaletteBlock(PALETTE_CELL_HEIGHT);
|
||||
auto nameCol = new QTableWidgetItem(p->m_Name.c_str());
|
||||
|
||||
nameCol->setToolTip(p->m_Name.c_str());
|
||||
paletteTable->setItem(i, 0, nameCol);
|
||||
|
||||
QImage image(v.data(), p->Size(), PALETTE_CELL_HEIGHT, QImage::Format_RGB888);
|
||||
auto paletteItem = new PaletteTableWidgetItem<T>(p);
|
||||
|
||||
paletteItem->setData(Qt::DecorationRole, QPixmap::fromImage(image));
|
||||
paletteTable->setItem(i, 1, paletteItem);
|
||||
}
|
||||
@ -135,7 +119,6 @@ bool FractoriumEmberController<T>::FillPaletteTable(const string& s)
|
||||
else
|
||||
{
|
||||
vector<string> errors = m_PaletteList.ErrorReport();
|
||||
|
||||
m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit);
|
||||
m_Fractorium->ShowCritical("Palette Read Error", "Could not load palette file, all images will be black. See info tab for details.");
|
||||
}
|
||||
@ -163,7 +146,6 @@ void FractoriumEmberController<T>::ApplyPaletteToEmber()
|
||||
double brightness = double(m_Fractorium->m_PaletteBrightnessSpin->value() / 255.0);
|
||||
double contrast = double(m_Fractorium->m_PaletteContrastSpin->value() > 0 ? (m_Fractorium->m_PaletteContrastSpin->value() * 2) : m_Fractorium->m_PaletteContrastSpin->value()) / 100.0;
|
||||
double hue = double(m_Fractorium->m_PaletteHueSpin->value()) / 360.0;
|
||||
|
||||
//Use the temp palette as the base and apply the adjustments gotten from the GUI and save the result in the ember palette.
|
||||
m_TempPalette.MakeAdjustedPalette(m_Ember.m_Palette, 0, hue, sat, brightness, contrast, blur, freq);
|
||||
}
|
||||
@ -177,23 +159,21 @@ void FractoriumEmberController<T>::ApplyPaletteToEmber()
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::UpdateAdjustedPaletteGUI(Palette<T>& palette)
|
||||
{
|
||||
Xform<T>* xform = CurrentXform();
|
||||
QTableWidget* palettePreviewTable = m_Fractorium->ui.PalettePreviewTable;
|
||||
QTableWidgetItem* previewPaletteItem = palettePreviewTable->item(0, 1);
|
||||
QString paletteName = QString::fromStdString(m_Ember.m_Palette.m_Name);
|
||||
auto xform = CurrentXform();
|
||||
auto palettePreviewTable = m_Fractorium->ui.PalettePreviewTable;
|
||||
auto previewPaletteItem = palettePreviewTable->item(0, 1);
|
||||
auto paletteName = QString::fromStdString(m_Ember.m_Palette.m_Name);
|
||||
|
||||
if (previewPaletteItem)//This can be null if the palette file was moved or corrupted.
|
||||
{
|
||||
//Use the adjusted palette to fill the preview palette control so the user can see the effects of applying the adjustements.
|
||||
vector<byte> v = palette.MakeRgbPaletteBlock(PALETTE_CELL_HEIGHT);//Make the palette repeat for PALETTE_CELL_HEIGHT rows.
|
||||
|
||||
m_FinalPaletteImage = QImage(palette.Size(), PALETTE_CELL_HEIGHT, QImage::Format_RGB888);//Create a QImage out of it.
|
||||
memcpy(m_FinalPaletteImage.scanLine(0), v.data(), v.size() * sizeof(v[0]));//Memcpy the data in.
|
||||
QPixmap pixmap = QPixmap::fromImage(m_FinalPaletteImage);//Create a QPixmap out of the QImage.
|
||||
auto pixmap = QPixmap::fromImage(m_FinalPaletteImage);//Create a QPixmap out of the QImage.
|
||||
previewPaletteItem->setData(Qt::DecorationRole, pixmap.scaled(QSize(pixmap.width(), palettePreviewTable->rowHeight(0) + 2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));//Set the pixmap on the palette tab.
|
||||
m_Fractorium->SetPaletteTableItem(&pixmap, m_Fractorium->ui.XformPaletteRefTable, m_Fractorium->m_PaletteRefItem, 0, 0);//Set the palette ref table on the xforms | color tab.
|
||||
|
||||
QTableWidgetItem* previewNameItem = palettePreviewTable->item(0, 0);
|
||||
auto previewNameItem = palettePreviewTable->item(0, 0);
|
||||
previewNameItem->setText(paletteName);//Finally, set the name of the palette to be both the text and the tooltip.
|
||||
previewNameItem->setToolTip(paletteName);
|
||||
}
|
||||
@ -308,7 +288,6 @@ void Fractorium::OnPaletteRandomSelectButtonClicked(bool checked)
|
||||
void Fractorium::OnPaletteRandomAdjustButtonClicked(bool checked)
|
||||
{
|
||||
QTIsaac<ISAAC_SIZE, ISAAC_INT>* gRand = QTIsaac<ISAAC_SIZE, ISAAC_INT>::GlobalRand.get();
|
||||
|
||||
m_PaletteHueSpin->setValue(-180 + gRand->Rand(361));
|
||||
m_PaletteSaturationSpin->setValue(-50 + gRand->Rand(101));//Full range of these leads to bad palettes, so clamp range.
|
||||
m_PaletteBrightnessSpin->setValue(-50 + gRand->Rand(101));
|
||||
@ -338,7 +317,6 @@ void Fractorium::OnPaletteRandomAdjustButtonClicked(bool checked)
|
||||
void Fractorium::OnPaletteFilterLineEditTextChanged(const QString& text)
|
||||
{
|
||||
auto table = ui.PaletteListTable;
|
||||
|
||||
table->setUpdatesEnabled(false);
|
||||
|
||||
for (int i = 0; i < table->rowCount(); i++)
|
||||
@ -407,5 +385,5 @@ void Fractorium::SetPaletteFileComboIndex(const string& filename)
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
||||
|
@ -167,12 +167,12 @@ void FractoriumEmberController<T>::BackgroundChanged(const QColor& color)
|
||||
Update([&]
|
||||
{
|
||||
int itemRow = 5;
|
||||
QTableWidget* colorTable = m_Fractorium->ui.ColorTable;
|
||||
auto colorTable = m_Fractorium->ui.ColorTable;
|
||||
colorTable->item(itemRow, 1)->setBackgroundColor(color);
|
||||
|
||||
QString r = ToString(color.red());
|
||||
QString g = ToString(color.green());
|
||||
QString b = ToString(color.blue());
|
||||
auto r = ToString(color.red());
|
||||
auto g = ToString(color.green());
|
||||
auto b = ToString(color.blue());
|
||||
|
||||
colorTable->item(itemRow, 1)->setTextColor(VisibleColor(color));
|
||||
colorTable->item(itemRow, 1)->setText("rgb(" + r + ", " + g + ", " + b + ")");
|
||||
|
@ -56,7 +56,7 @@ void FractoriumEmberController<T>::FillXaos()
|
||||
template <typename T>
|
||||
QString FractoriumEmberController<T>::MakeXaosNameString(uint i)
|
||||
{
|
||||
Xform<T>* xform = m_Ember.GetXform(i);
|
||||
auto xform = m_Ember.GetXform(i);
|
||||
QString name;
|
||||
//if (xform)
|
||||
//{
|
||||
|
@ -7,7 +7,6 @@
|
||||
void Fractorium::InitXformsUI()
|
||||
{
|
||||
int spinHeight = 20, row = 0;
|
||||
|
||||
connect(ui.AddXformButton, SIGNAL(clicked(bool)), this, SLOT(OnAddXformButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.AddLinkedXformButton, SIGNAL(clicked(bool)), this, SLOT(OnAddLinkedXformButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.DuplicateXformButton, SIGNAL(clicked(bool)), this, SLOT(OnDuplicateXformButtonClicked(bool)), Qt::QueuedConnection);
|
||||
@ -15,7 +14,7 @@ void Fractorium::InitXformsUI()
|
||||
connect(ui.DeleteXformButton, SIGNAL(clicked(bool)), this, SLOT(OnDeleteXformButtonClicked(bool)), Qt::QueuedConnection);
|
||||
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());
|
||||
//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);
|
||||
@ -25,11 +24,9 @@ void Fractorium::InitXformsUI()
|
||||
m_XformWeightSpinnerButtonWidget->m_Button->setToolTip("Equalize weights");
|
||||
m_XformWeightSpinnerButtonWidget->m_Button->setStyleSheet("text-align: center center");
|
||||
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);
|
||||
#ifndef WIN32
|
||||
//For some reason linux makes these 24x24, even though the designer explicitly says 16x16.
|
||||
@ -70,19 +67,15 @@ void Fractorium::CurrentXform(uint i)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::CurrentXformComboChanged(int index)
|
||||
{
|
||||
if (Xform<T>* xform = m_Ember.GetTotalXform(index))
|
||||
if (auto xform = m_Ember.GetTotalXform(index))
|
||||
{
|
||||
FillWithXform(xform);
|
||||
m_GLController->SetSelectedXform(xform);
|
||||
|
||||
int solo = m_Fractorium->ui.CurrentXformCombo->property("soloxform").toInt();
|
||||
|
||||
m_Fractorium->ui.SoloXformCheckBox->blockSignals(true);
|
||||
m_Fractorium->ui.SoloXformCheckBox->setChecked(solo == index);
|
||||
m_Fractorium->ui.SoloXformCheckBox->blockSignals(false);
|
||||
|
||||
bool enable = !IsFinal(CurrentXform());
|
||||
|
||||
m_Fractorium->ui.DuplicateXformButton->setEnabled(enable);
|
||||
m_Fractorium->m_XformWeightSpin->setEnabled(enable);
|
||||
m_Fractorium->ui.SoloXformCheckBox->setEnabled(enable);
|
||||
@ -105,7 +98,6 @@ void FractoriumEmberController<T>::AddXform()
|
||||
Update([&]()
|
||||
{
|
||||
Xform<T> newXform;
|
||||
|
||||
newXform.m_Weight = 0.25;
|
||||
newXform.m_ColorX = m_Rand.Frand01<T>();
|
||||
m_Ember.AddXform(newXform);
|
||||
@ -131,7 +123,6 @@ void FractoriumEmberController<T>::AddLinkedXform()
|
||||
{
|
||||
size_t i, count = m_Ember.XformCount();
|
||||
Xform<T> newXform;
|
||||
|
||||
newXform.m_Weight = 0.5;
|
||||
newXform.m_Opacity = 1;
|
||||
newXform.m_ColorSpeed = 1;
|
||||
@ -175,17 +166,14 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::DuplicateXform()
|
||||
{
|
||||
vector<Xform<T>> vec;
|
||||
|
||||
vec.reserve(m_Ember.XformCount());
|
||||
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
vec.push_back(*xform);
|
||||
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL, false);
|
||||
|
||||
Update([&]()
|
||||
{
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
auto combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
for (auto& it : vec)
|
||||
m_Ember.AddXform(it);
|
||||
@ -210,7 +198,6 @@ void FractoriumEmberController<T>::ClearXform()
|
||||
{
|
||||
xform->ClearAndDeleteVariations();//Note xaos is left alone.
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillVariationTreeWithXform(CurrentXform());
|
||||
}
|
||||
|
||||
@ -229,13 +216,12 @@ void FractoriumEmberController<T>::DeleteXforms()
|
||||
int i = 0, offset = 0, current = 0, checked = 0;
|
||||
bool haveFinal = false;
|
||||
size_t count;
|
||||
QComboBox* combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
auto combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
//Iterating over the checkboxes must be done instead of using UpdateXform() to iterate over xforms
|
||||
//because xforms are being deleted inside the loop.
|
||||
//Also manually calling UpdateRender() rather than using the usual Update() call because
|
||||
//it should only be called if an xform has actually been deleted.
|
||||
m_Fractorium->ForEachXformCheckbox([&](int i, QCheckBox* w)
|
||||
m_Fractorium->ForEachXformCheckbox([&](int i, QCheckBox * w)
|
||||
{
|
||||
count = m_Ember.TotalXformCount();
|
||||
haveFinal = m_Ember.UseFinalXform();//Requery every time.
|
||||
@ -252,20 +238,18 @@ void FractoriumEmberController<T>::DeleteXforms()
|
||||
|
||||
if (w->isChecked())
|
||||
{
|
||||
//qDebug() << "Deleting " << w->text();
|
||||
m_Ember.DeleteTotalXform(i - offset);//Subtract offset to account for previously deleted xforms.
|
||||
offset++;
|
||||
}
|
||||
});
|
||||
|
||||
current = combo->currentIndex();
|
||||
count = m_Ember.TotalXformCount();
|
||||
haveFinal = m_Ember.UseFinalXform();//Requery again.
|
||||
|
||||
//Nothing was selected, so just delete current.
|
||||
if (!checked &&
|
||||
!(haveFinal && count <= 2 && current == 0) &&//Again disallow deleting the only remaining non-final xform.
|
||||
!(!haveFinal && count == 1))
|
||||
!(haveFinal && count <= 2 && current == 0) &&//Again disallow deleting the only remaining non-final xform.
|
||||
!(!haveFinal && count == 1))
|
||||
{
|
||||
m_Ember.DeleteTotalXform(current);
|
||||
offset++;
|
||||
@ -298,7 +282,6 @@ void FractoriumEmberController<T>::AddFinalXform()
|
||||
{
|
||||
Xform<T> final;
|
||||
auto combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
final.AddVariation(new LinearVariation<T>());//Just a placeholder so other parts of the code don't see it as being empty.
|
||||
m_Ember.SetFinalXform(final);
|
||||
int index = m_Ember.TotalXformCount() - 1;//Set index to the last item.
|
||||
@ -322,7 +305,6 @@ void FractoriumEmberController<T>::XformWeightChanged(double d)
|
||||
{
|
||||
xform->m_Weight = d;
|
||||
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL);
|
||||
|
||||
SetNormalizedWeightText(CurrentXform());
|
||||
}
|
||||
|
||||
@ -356,19 +338,32 @@ void FractoriumEmberController<T>::XformNameChanged(int row, int col)
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
int index = m_Ember.GetTotalXformIndex(xform);
|
||||
|
||||
xform->m_Name = m_Fractorium->ui.XformWeightNameTable->item(row, col)->text().toStdString();
|
||||
XformCheckboxAt(index, [&](QCheckBox* checkbox) { checkbox->setText(MakeXformCaption(index)); });
|
||||
//if (index != -1)
|
||||
//{
|
||||
// if (QTableWidgetItem* xformNameItem = m_Fractorium->ui.XaosTable->item(index, 0))
|
||||
// xformNameItem->setText(MakeXaosNameString(index));
|
||||
//}
|
||||
XformCheckboxAt(index, [&](QCheckBox * checkbox) { checkbox->setText(MakeXformCaption(index)); });
|
||||
}, eXformUpdate::UPDATE_CURRENT, false);
|
||||
}
|
||||
|
||||
void Fractorium::OnXformNameChanged(int row, int col) { m_Controller->XformNameChanged(row, col); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the animate field of the selected xforms.
|
||||
/// This has no effect on interactive rendering, it only sets a value
|
||||
/// that will later be saved to Xml when the user saves.
|
||||
/// This value is observed when creating sequences for animation.
|
||||
/// Called when the user toggles the animate xform checkbox.
|
||||
/// </summary>
|
||||
/// <param name="state">1 for checked, else false</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformAnimateChanged(int state)
|
||||
{
|
||||
UpdateXform([&](Xform<T>* xform)
|
||||
{
|
||||
xform->m_Animate = state > 0 ? 1 : 0;
|
||||
}, eXformUpdate::UPDATE_SELECTED, false);
|
||||
}
|
||||
|
||||
void Fractorium::OnXformAnimateCheckBoxStateChanged(int state) { m_Controller->XformAnimateChanged(state); }
|
||||
|
||||
/// <summary>
|
||||
/// Fill all GUI widgets with values from the passed in xform.
|
||||
/// </summary>
|
||||
@ -378,8 +373,9 @@ void FractoriumEmberController<T>::FillWithXform(Xform<T>* xform)//Need to see w
|
||||
{
|
||||
m_Fractorium->m_XformWeightSpin->SetValueStealth(xform->m_Weight);
|
||||
SetNormalizedWeightText(xform);
|
||||
m_Fractorium->ui.AnimateXformCheckBox->setChecked(xform->m_Animate > 0 ? true : false);//Make a signal/slot to handle checking this.
|
||||
|
||||
if (QTableWidgetItem* item = m_Fractorium->ui.XformWeightNameTable->item(0, 1))
|
||||
if (auto item = m_Fractorium->ui.XformWeightNameTable->item(0, 1))
|
||||
{
|
||||
m_Fractorium->ui.XformWeightNameTable->blockSignals(true);
|
||||
item->setText(QString::fromStdString(xform->m_Name));
|
||||
@ -402,7 +398,6 @@ void FractoriumEmberController<T>::SetNormalizedWeightText(Xform<T>* xform)
|
||||
if (xform)
|
||||
{
|
||||
int index = m_Ember.GetXformIndex(xform);
|
||||
|
||||
m_Ember.CalcNormalizedWeights(m_NormalizedWeights);
|
||||
|
||||
if (index != -1 && index < m_NormalizedWeights.size())
|
||||
@ -433,10 +428,8 @@ void FractoriumEmberController<T>::FillXforms(int index)
|
||||
{
|
||||
int i = 0, count = int(XformCount());
|
||||
auto combo = m_Fractorium->ui.CurrentXformCombo;
|
||||
|
||||
combo->blockSignals(true);
|
||||
combo->clear();
|
||||
|
||||
//First clear all dynamically created checkboxes.
|
||||
m_Fractorium->ClearXformsSelections();
|
||||
m_Fractorium->m_XformsSelectionLayout->blockSignals(true);
|
||||
@ -449,13 +442,13 @@ void FractoriumEmberController<T>::FillXforms(int index)
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
while (i < count)
|
||||
{
|
||||
if (i < count - 1)
|
||||
{
|
||||
auto cb1 = new QCheckBox(MakeXformCaption(i), m_Fractorium);
|
||||
auto cb2 = new QCheckBox(MakeXformCaption(i + 1), m_Fractorium);
|
||||
|
||||
m_Fractorium->m_XformSelections.push_back(cb1);
|
||||
m_Fractorium->m_XformSelections.push_back(cb2);
|
||||
m_Fractorium->m_XformsSelectionLayout->addRow(cb1, cb2);
|
||||
@ -464,7 +457,6 @@ void FractoriumEmberController<T>::FillXforms(int index)
|
||||
else if (i < count)
|
||||
{
|
||||
auto cb = new QCheckBox(MakeXformCaption(i), m_Fractorium);
|
||||
|
||||
m_Fractorium->m_XformSelections.push_back(cb);
|
||||
m_Fractorium->m_XformsSelectionLayout->addRow(cb, new QWidget(m_Fractorium));
|
||||
i++;
|
||||
@ -475,10 +467,8 @@ void FractoriumEmberController<T>::FillXforms(int index)
|
||||
if (UseFinalXform())
|
||||
{
|
||||
auto cb = new QCheckBox(MakeXformCaption(i), m_Fractorium);
|
||||
|
||||
m_Fractorium->m_XformSelections.push_back(cb);
|
||||
m_Fractorium->m_XformsSelectionLayout->addRow(cb, new QWidget(m_Fractorium));
|
||||
|
||||
combo->addItem("Final");
|
||||
combo->setItemIcon(i, m_Fractorium->m_FinalXformComboIcon);
|
||||
}
|
||||
@ -497,5 +487,5 @@ void FractoriumEmberController<T>::FillXforms(int index)
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
||||
|
@ -8,8 +8,8 @@ void Fractorium::InitXformsAffineUI()
|
||||
{
|
||||
int row = 0, affinePrec = 6, spinHeight = 20;
|
||||
double affineStep = 0.01, affineMin = std::numeric_limits<double>::lowest(), affineMax = std::numeric_limits<double>::max();
|
||||
QTableWidget* table = ui.PreAffineTable;
|
||||
|
||||
auto table = ui.PreAffineTable;
|
||||
connect(ui.LockAffineCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnLockAffineScaleCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
table->verticalHeader()->setVisible(true);//The designer continually clobbers these values, so must manually set them here.
|
||||
table->horizontalHeader()->setVisible(true);
|
||||
table->verticalHeader()->setSectionsClickable(true);
|
||||
@ -18,7 +18,6 @@ void Fractorium::InitXformsAffineUI()
|
||||
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)));
|
||||
SetupAffineSpinner(table, this, 0, 1, m_PreX2Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnX2Changed(double)));
|
||||
@ -26,7 +25,6 @@ void Fractorium::InitXformsAffineUI()
|
||||
SetupAffineSpinner(table, this, 1, 1, m_PreY2Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnY2Changed(double)));
|
||||
SetupAffineSpinner(table, this, 2, 0, m_PreO1Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnO1Changed(double)));
|
||||
SetupAffineSpinner(table, this, 2, 1, m_PreO2Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnO2Changed(double)));
|
||||
|
||||
table = ui.PostAffineTable;
|
||||
table->verticalHeader()->setVisible(true);//The designer continually clobbers these values, so must manually set them here.
|
||||
table->horizontalHeader()->setVisible(true);
|
||||
@ -34,10 +32,8 @@ void Fractorium::InitXformsAffineUI()
|
||||
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)));
|
||||
SetupAffineSpinner(table, this, 0, 1, m_PostX2Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnX2Changed(double)));
|
||||
@ -45,73 +41,60 @@ void Fractorium::InitXformsAffineUI()
|
||||
SetupAffineSpinner(table, this, 1, 1, m_PostY2Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnY2Changed(double)));
|
||||
SetupAffineSpinner(table, this, 2, 0, m_PostO1Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnO1Changed(double)));
|
||||
SetupAffineSpinner(table, this, 2, 1, m_PostO2Spin, spinHeight, affineMin, affineMax, affineStep, affinePrec, SIGNAL(valueChanged(double)), SLOT(OnO2Changed(double)));
|
||||
|
||||
QDoubleValidator* preRotateVal = new QDoubleValidator(ui.PreRotateCombo); preRotateVal->setLocale(QLocale::system());
|
||||
QDoubleValidator* preMoveVal = new QDoubleValidator(ui.PreMoveCombo); preMoveVal->setLocale(QLocale::system());
|
||||
QDoubleValidator* preScaleVal = new QDoubleValidator(ui.PreScaleCombo); preScaleVal->setLocale(QLocale::system());
|
||||
|
||||
QDoubleValidator* postRotateVal = new QDoubleValidator(ui.PostRotateCombo); postRotateVal->setLocale(QLocale::system());
|
||||
QDoubleValidator* postMoveVal = new QDoubleValidator(ui.PostMoveCombo); postMoveVal->setLocale(QLocale::system());
|
||||
QDoubleValidator* postScaleVal = new QDoubleValidator(ui.PostScaleCombo); postScaleVal->setLocale(QLocale::system());
|
||||
|
||||
auto preRotateVal = new QDoubleValidator(ui.PreRotateCombo); preRotateVal->setLocale(QLocale::system());
|
||||
auto preMoveVal = new QDoubleValidator(ui.PreMoveCombo); preMoveVal->setLocale(QLocale::system());
|
||||
auto preScaleVal = new QDoubleValidator(ui.PreScaleCombo); preScaleVal->setLocale(QLocale::system());
|
||||
auto postRotateVal = new QDoubleValidator(ui.PostRotateCombo); postRotateVal->setLocale(QLocale::system());
|
||||
auto postMoveVal = new QDoubleValidator(ui.PostMoveCombo); postMoveVal->setLocale(QLocale::system());
|
||||
auto postScaleVal = new QDoubleValidator(ui.PostScaleCombo); postScaleVal->setLocale(QLocale::system());
|
||||
ui.PreRotateCombo->setValidator(preRotateVal);
|
||||
ui.PreMoveCombo->setValidator(preMoveVal);
|
||||
ui.PreScaleCombo->setValidator(preScaleVal);
|
||||
|
||||
ui.PostRotateCombo->setValidator(postRotateVal);
|
||||
ui.PostMoveCombo->setValidator(postMoveVal);
|
||||
ui.PostScaleCombo->setValidator(postScaleVal);
|
||||
|
||||
QStringList moveList;
|
||||
|
||||
moveList.append(ToString(0.5));
|
||||
moveList.append(ToString(0.25));
|
||||
moveList.append(ToString(0.1));
|
||||
moveList.append(ToString(0.05));
|
||||
moveList.append(ToString(0.025));
|
||||
moveList.append(ToString(0.01));
|
||||
|
||||
ui.PreMoveCombo->addItems(moveList);
|
||||
ui.PostMoveCombo->addItems(moveList);
|
||||
|
||||
connect(ui.PreFlipHorizontalButton, SIGNAL(clicked(bool)), this, SLOT(OnFlipHorizontalButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreFlipVerticalButton, SIGNAL(clicked(bool)), this, SLOT(OnFlipVerticalButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreRotate90CButton, SIGNAL(clicked(bool)), this, SLOT(OnRotate90CButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreRotate90CcButton, SIGNAL(clicked(bool)), this, SLOT(OnRotate90CcButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreRotateCButton, SIGNAL(clicked(bool)), this, SLOT(OnRotateCButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreRotateCcButton, SIGNAL(clicked(bool)), this, SLOT(OnRotateCcButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreMoveUpButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveUpButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreMoveDownButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveDownButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreMoveLeftButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveLeftButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreMoveRightButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveRightButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreScaleDownButton, SIGNAL(clicked(bool)), this, SLOT(OnScaleDownButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreScaleUpButton, SIGNAL(clicked(bool)), this, SLOT(OnScaleUpButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreResetButton, SIGNAL(clicked(bool)), this, SLOT(OnResetAffineButtonClicked(bool)), Qt::QueuedConnection);
|
||||
|
||||
connect(ui.PostFlipHorizontalButton, SIGNAL(clicked(bool)), this, SLOT(OnFlipHorizontalButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostFlipVerticalButton, SIGNAL(clicked(bool)), this, SLOT(OnFlipVerticalButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostRotate90CcButton, SIGNAL(clicked(bool)), this, SLOT(OnRotate90CcButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostRotateCcButton, SIGNAL(clicked(bool)), this, SLOT(OnRotateCcButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostRotateCButton, SIGNAL(clicked(bool)), this, SLOT(OnRotateCButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostRotate90CButton, SIGNAL(clicked(bool)), this, SLOT(OnRotate90CButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostMoveUpButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveUpButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostMoveDownButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveDownButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostMoveLeftButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveLeftButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostMoveRightButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveRightButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostScaleDownButton, SIGNAL(clicked(bool)), this, SLOT(OnScaleDownButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostScaleUpButton, SIGNAL(clicked(bool)), this, SLOT(OnScaleUpButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostResetButton, SIGNAL(clicked(bool)), this, SLOT(OnResetAffineButtonClicked(bool)), Qt::QueuedConnection);
|
||||
|
||||
connect(ui.PreAffineGroupBox, SIGNAL(toggled(bool)), this, SLOT(OnAffineGroupBoxToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostAffineGroupBox, SIGNAL(toggled(bool)), this, SLOT(OnAffineGroupBoxToggled(bool)), Qt::QueuedConnection);
|
||||
|
||||
connect(ui.ShowPreAffineAllRadio, SIGNAL(toggled(bool)), this, SLOT(OnAffineDrawAllCurrentRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ShowPreAffineCurrentRadio, SIGNAL(toggled(bool)), this, SLOT(OnAffineDrawAllCurrentRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ShowPostAffineAllRadio, SIGNAL(toggled(bool)), this, SLOT(OnAffineDrawAllCurrentRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ShowPostAffineCurrentRadio, SIGNAL(toggled(bool)), this, SLOT(OnAffineDrawAllCurrentRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
|
||||
connect(ui.PolarAffineCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnPolarAffineCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
|
||||
connect(ui.PreFlipHorizontalButton, SIGNAL(clicked(bool)), this, SLOT(OnFlipHorizontalButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreFlipVerticalButton, SIGNAL(clicked(bool)), this, SLOT(OnFlipVerticalButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreRotate90CButton, SIGNAL(clicked(bool)), this, SLOT(OnRotate90CButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreRotate90CcButton, SIGNAL(clicked(bool)), this, SLOT(OnRotate90CcButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreRotateCButton, SIGNAL(clicked(bool)), this, SLOT(OnRotateCButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreRotateCcButton, SIGNAL(clicked(bool)), this, SLOT(OnRotateCcButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreMoveUpButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveUpButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreMoveDownButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveDownButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreMoveLeftButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveLeftButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreMoveRightButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveRightButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreScaleDownButton, SIGNAL(clicked(bool)), this, SLOT(OnScaleDownButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreScaleUpButton, SIGNAL(clicked(bool)), this, SLOT(OnScaleUpButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreResetButton, SIGNAL(clicked(bool)), this, SLOT(OnResetAffineButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostFlipHorizontalButton, SIGNAL(clicked(bool)), this, SLOT(OnFlipHorizontalButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostFlipVerticalButton, SIGNAL(clicked(bool)), this, SLOT(OnFlipVerticalButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostRotate90CcButton, SIGNAL(clicked(bool)), this, SLOT(OnRotate90CcButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostRotateCcButton, SIGNAL(clicked(bool)), this, SLOT(OnRotateCcButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostRotateCButton, SIGNAL(clicked(bool)), this, SLOT(OnRotateCButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostRotate90CButton, SIGNAL(clicked(bool)), this, SLOT(OnRotate90CButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostMoveUpButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveUpButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostMoveDownButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveDownButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostMoveLeftButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveLeftButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostMoveRightButton, SIGNAL(clicked(bool)), this, SLOT(OnMoveRightButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostScaleDownButton, SIGNAL(clicked(bool)), this, SLOT(OnScaleDownButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostScaleUpButton, SIGNAL(clicked(bool)), this, SLOT(OnScaleUpButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostResetButton, SIGNAL(clicked(bool)), this, SLOT(OnResetAffineButtonClicked(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PreAffineGroupBox, SIGNAL(toggled(bool)), this, SLOT(OnAffineGroupBoxToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PostAffineGroupBox, SIGNAL(toggled(bool)), this, SLOT(OnAffineGroupBoxToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ShowPreAffineAllRadio, SIGNAL(toggled(bool)), this, SLOT(OnAffineDrawAllCurrentRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ShowPreAffineCurrentRadio, SIGNAL(toggled(bool)), this, SLOT(OnAffineDrawAllCurrentRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ShowPostAffineAllRadio, SIGNAL(toggled(bool)), this, SLOT(OnAffineDrawAllCurrentRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.ShowPostAffineCurrentRadio, SIGNAL(toggled(bool)), this, SLOT(OnAffineDrawAllCurrentRadioButtonToggled(bool)), Qt::QueuedConnection);
|
||||
connect(ui.PolarAffineCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnPolarAffineCheckBoxStateChanged(int)), Qt::QueuedConnection);
|
||||
#ifndef WIN32
|
||||
//For some reason linux makes these 24x24, even though the designer explicitly says 16x16.
|
||||
//Also, in order to get 4 pixels of spacing between elements in the grid layout, 0 must be specified.
|
||||
@ -130,7 +113,6 @@ void Fractorium::InitXformsAffineUI()
|
||||
ui.PreResetButton->setIconSize(QSize(16, 16));
|
||||
ui.PreAffineGridLayout->setHorizontalSpacing(0);
|
||||
ui.PreAffineGridLayout->setVerticalSpacing(0);
|
||||
|
||||
ui.PostFlipHorizontalButton->setIconSize(QSize(16, 16));
|
||||
ui.PostFlipVerticalButton->setIconSize(QSize(16, 16));
|
||||
ui.PostRotate90CButton->setIconSize(QSize(16, 16));
|
||||
@ -146,13 +128,11 @@ void Fractorium::InitXformsAffineUI()
|
||||
ui.PostResetButton->setIconSize(QSize(16, 16));
|
||||
ui.PostAffineGridLayout->setHorizontalSpacing(0);
|
||||
ui.PostAffineGridLayout->setVerticalSpacing(0);
|
||||
|
||||
//Further, the size of the dock widget won't be properly adjusted until the xforms tab is shown.
|
||||
//So show it here and it will be switched back in Fractorium's constructor.
|
||||
//ui.ParamsTabWidget->setCurrentIndex(2);
|
||||
//ui.DockWidget->update();
|
||||
#endif
|
||||
|
||||
//Placing pointers to the spin boxes in arrays makes them easier to access in various places.
|
||||
m_PreSpins[0] = m_PreX1Spin;//A
|
||||
m_PreSpins[1] = m_PreY1Spin;//B
|
||||
@ -160,20 +140,58 @@ void Fractorium::InitXformsAffineUI()
|
||||
m_PreSpins[3] = m_PreX2Spin;//D
|
||||
m_PreSpins[4] = m_PreY2Spin;//E
|
||||
m_PreSpins[5] = m_PreO2Spin;//F
|
||||
|
||||
m_PostSpins[0] = m_PostX1Spin;
|
||||
m_PostSpins[1] = m_PostY1Spin;
|
||||
m_PostSpins[2] = m_PostO1Spin;
|
||||
m_PostSpins[3] = m_PostX2Spin;
|
||||
m_PostSpins[4] = m_PostY2Spin;
|
||||
m_PostSpins[5] = m_PostO2Spin;
|
||||
|
||||
ui.PreAffineGroupBox->setChecked(false);//Flip both once to force enabling/disabling the disabling of the group boxes and the corner buttons.
|
||||
ui.PreAffineGroupBox->setChecked(true);//Pre affine enabled.
|
||||
ui.PostAffineGroupBox->setChecked(true);
|
||||
ui.PostAffineGroupBox->setChecked(false);//Post affine disabled.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle whether to lock the visual scale of the affine spinners.
|
||||
/// Called when the user checks LockAffineCheckBox.
|
||||
/// </summary>
|
||||
/// <param name="state">True if checked, else false.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::LockAffineScaleCheckBoxStateChanged(int state)
|
||||
{
|
||||
m_LockedScale = m_Ember.m_PixelsPerUnit;
|
||||
m_Fractorium->ui.GLDisplay->update();
|
||||
}
|
||||
|
||||
void Fractorium::OnLockAffineScaleCheckBoxStateChanged(int state) { m_Controller->LockAffineScaleCheckBoxStateChanged(state); }
|
||||
|
||||
/// <summary>
|
||||
/// Return the value needed to multiply the current scale by to get back to the locked scale.
|
||||
/// </summary>
|
||||
/// <returns>The scale value</returns>
|
||||
template <typename T>
|
||||
T FractoriumEmberController<T>::AffineScaleCurrentToLocked()
|
||||
{
|
||||
if (m_Fractorium->ui.LockAffineCheckBox->isChecked())
|
||||
return LockedScale() / m_Ember.m_PixelsPerUnit;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the value needed to multiply the locked scale by to get to the current scale.
|
||||
/// </summary>
|
||||
/// <returns>The scale value</returns>
|
||||
template <typename T>
|
||||
T FractoriumEmberController<T>::AffineScaleLockedToCurrent()
|
||||
{
|
||||
if (m_Fractorium->ui.LockAffineCheckBox->isChecked())
|
||||
return m_Ember.m_PixelsPerUnit / LockedScale();
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle all pre affine values in one row for the selected xforms.
|
||||
/// Resets the rendering process.
|
||||
@ -226,7 +244,7 @@ void FractoriumEmberController<T>::AffineSetHelper(double d, int index, bool pre
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
DoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
|
||||
if (m_Fractorium->ui.PolarAffineCheckBox->isChecked())
|
||||
@ -238,11 +256,13 @@ void FractoriumEmberController<T>::AffineSetHelper(double d, int index, bool pre
|
||||
affine->A(cos(spinners[0]->value() * DEG_2_RAD) * spinners[3]->value());
|
||||
affine->D(sin(spinners[0]->value() * DEG_2_RAD) * spinners[3]->value());
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 4:
|
||||
affine->B(cos(spinners[1]->value() * DEG_2_RAD) * spinners[4]->value());
|
||||
affine->E(sin(spinners[1]->value() * DEG_2_RAD) * spinners[4]->value());
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 5:
|
||||
default:
|
||||
@ -258,18 +278,23 @@ void FractoriumEmberController<T>::AffineSetHelper(double d, int index, bool pre
|
||||
case 0:
|
||||
affine->A(d);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
affine->B(d);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
affine->C(d);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
affine->D(d);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
affine->E(d);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
affine->F(d);
|
||||
break;
|
||||
@ -301,7 +326,7 @@ void FractoriumEmberController<T>::FlipXforms(bool horizontal, bool vertical, bo
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
if (horizontal)
|
||||
{
|
||||
@ -320,9 +345,7 @@ void FractoriumEmberController<T>::FlipXforms(bool horizontal, bool vertical, bo
|
||||
if (!m_Fractorium->LocalPivot())
|
||||
affine->F(-affine->F());
|
||||
}
|
||||
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillAffineWithXform(CurrentXform(), pre);
|
||||
}
|
||||
|
||||
@ -340,11 +363,9 @@ void FractoriumEmberController<T>::RotateXformsByAngle(double angle, bool pre)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
affine->Rotate(angle);
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillAffineWithXform(CurrentXform(), pre);
|
||||
}
|
||||
|
||||
@ -367,7 +388,7 @@ void Fractorium::OnRotateCButtonClicked(bool checked)
|
||||
{
|
||||
bool ok;
|
||||
bool pre = sender() == ui.PreRotateCButton;
|
||||
QComboBox* combo = pre ? ui.PreRotateCombo : ui.PostRotateCombo;
|
||||
auto combo = pre ? ui.PreRotateCombo : ui.PostRotateCombo;
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
@ -384,7 +405,7 @@ void Fractorium::OnRotateCcButtonClicked(bool checked)
|
||||
{
|
||||
bool ok;
|
||||
bool pre = sender() == ui.PreRotateCcButton;
|
||||
QComboBox* combo = pre ? ui.PreRotateCombo : ui.PostRotateCombo;
|
||||
auto combo = pre ? ui.PreRotateCombo : ui.PostRotateCombo;
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
@ -403,12 +424,10 @@ void FractoriumEmberController<T>::MoveXforms(double x, double y, bool pre)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
auto* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
affine->C(affine->C() + x);
|
||||
affine->F(affine->F() + y);
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillAffineWithXform(CurrentXform(), pre);
|
||||
}
|
||||
|
||||
@ -422,7 +441,7 @@ void Fractorium::OnMoveUpButtonClicked(bool checked)
|
||||
{
|
||||
bool ok;
|
||||
bool pre = sender() == ui.PreMoveUpButton;
|
||||
QComboBox* combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo;
|
||||
auto combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo;
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
@ -439,7 +458,7 @@ void Fractorium::OnMoveDownButtonClicked(bool checked)
|
||||
{
|
||||
bool ok;
|
||||
bool pre = sender() == ui.PreMoveDownButton;
|
||||
QComboBox* combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo;
|
||||
auto combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo;
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
@ -456,7 +475,7 @@ void Fractorium::OnMoveLeftButtonClicked(bool checked)
|
||||
{
|
||||
bool ok;
|
||||
bool pre = sender() == ui.PreMoveLeftButton;
|
||||
QComboBox* combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo;
|
||||
auto combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo;
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
@ -473,7 +492,7 @@ void Fractorium::OnMoveRightButtonClicked(bool checked)
|
||||
{
|
||||
bool ok;
|
||||
bool pre = sender() == ui.PreMoveRightButton;
|
||||
QComboBox* combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo;
|
||||
auto combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo;
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
@ -491,14 +510,12 @@ void FractoriumEmberController<T>::ScaleXforms(double scale, bool pre)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
affine->A(affine->A() * scale);
|
||||
affine->B(affine->B() * scale);
|
||||
affine->D(affine->D() * scale);
|
||||
affine->E(affine->E() * scale);
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillAffineWithXform(CurrentXform(), pre);
|
||||
}
|
||||
|
||||
@ -512,7 +529,7 @@ void Fractorium::OnScaleDownButtonClicked(bool checked)
|
||||
{
|
||||
bool ok;
|
||||
bool pre = sender() == ui.PreScaleDownButton;
|
||||
QComboBox* combo = pre ? ui.PreScaleCombo : ui.PostScaleCombo;
|
||||
auto combo = pre ? ui.PreScaleCombo : ui.PostScaleCombo;
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
@ -529,7 +546,7 @@ void Fractorium::OnScaleUpButtonClicked(bool checked)
|
||||
{
|
||||
bool ok;
|
||||
bool pre = sender() == ui.PreScaleUpButton;
|
||||
QComboBox* combo = pre ? ui.PreScaleCombo : ui.PostScaleCombo;
|
||||
auto combo = pre ? ui.PreScaleCombo : ui.PostScaleCombo;
|
||||
double d = ToDouble(combo->currentText(), &ok);
|
||||
|
||||
if (ok)
|
||||
@ -546,11 +563,9 @@ void FractoriumEmberController<T>::ResetXformsAffine(bool pre)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
{
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
|
||||
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
affine->MakeID();
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
|
||||
FillAffineWithXform(CurrentXform(), pre);
|
||||
}
|
||||
|
||||
@ -699,5 +714,5 @@ bool Fractorium::LocalPivot() { return ui.LocalPivotRadio->isChecked();
|
||||
template class FractoriumEmberController<float>;
|
||||
|
||||
#ifdef DO_DOUBLE
|
||||
template class FractoriumEmberController<double>;
|
||||
template class FractoriumEmberController<double>;
|
||||
#endif
|
||||
|
@ -142,6 +142,7 @@ private:
|
||||
m4T m_Projection;
|
||||
|
||||
Affine2D<T> m_DragSrcTransform;
|
||||
vector<Affine2D<T>> m_DragSrcTransforms;
|
||||
|
||||
Xform<T>* m_HoverXform;
|
||||
Xform<T>* m_SelectedXform;
|
||||
|
@ -2,8 +2,6 @@
|
||||
#include "GLWidget.h"
|
||||
#include "Fractorium.h"
|
||||
|
||||
//#define OLDDRAG 1
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which passes parent widget to the base and initializes OpenGL profile.
|
||||
/// This will need to change in the future to implement all drawing as shader programs.
|
||||
@ -142,7 +140,7 @@ void GLEmberControllerBase::ClearControl() { m_DragModifier &= ~et(eDragModifier
|
||||
template <typename T>
|
||||
void GLEmberController<T>::ClearWindow()
|
||||
{
|
||||
Ember<T>* ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
m_GL->makeCurrent();
|
||||
m_GL->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
m_GL->glClearColor(ember->m_Background.r, ember->m_Background.g, ember->m_Background.b, 1.0);
|
||||
@ -211,10 +209,10 @@ void GLWidget::initializeGL()
|
||||
/// </summary>
|
||||
void GLWidget::paintGL()
|
||||
{
|
||||
FractoriumEmberControllerBase* controller = m_Fractorium->m_Controller.get();
|
||||
auto controller = m_Fractorium->m_Controller.get();
|
||||
|
||||
//Ensure there is a renderer and that it's supposed to be drawing, signified by the running timer.
|
||||
if (controller && controller->Renderer() && controller->RenderTimerRunning())
|
||||
if (controller && controller->Renderer())
|
||||
{
|
||||
RendererBase* renderer = controller->Renderer();
|
||||
m_Drawing = true;
|
||||
@ -256,8 +254,8 @@ void GLWidget::paintGL()
|
||||
template <typename T>
|
||||
void GLEmberController<T>::DrawImage()
|
||||
{
|
||||
RendererBase* renderer = m_FractoriumEmberController->Renderer();
|
||||
Ember<T>* ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto renderer = m_FractoriumEmberController->Renderer();
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
m_GL->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
m_GL->glClearColor(ember->m_Background.r, ember->m_Background.g, ember->m_Background.b, 1.0);
|
||||
m_GL->glDisable(GL_DEPTH_TEST);
|
||||
@ -286,14 +284,14 @@ template <typename T>
|
||||
void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
{
|
||||
QueryVMP();//Resolves to float or double specialization function depending on T.
|
||||
Ember<T>* ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
bool dragging = m_DragState == eDragState::DragDragging;
|
||||
|
||||
//Draw grid if control key is pressed.
|
||||
if (m_GL->hasFocus() && GetControl())
|
||||
{
|
||||
m_GL->glLineWidth(1.0f);
|
||||
m_GL->DrawGrid();
|
||||
m_GL->DrawGrid(m_FractoriumEmberController->AffineScaleLockedToCurrent());
|
||||
}
|
||||
|
||||
//When dragging, only draw the selected xform's affine and hide all others.
|
||||
@ -308,7 +306,7 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
{
|
||||
for (size_t i = 0; i < ember->TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = ember->GetTotalXform(i);
|
||||
auto xform = ember->GetTotalXform(i);
|
||||
bool selected = dragging ? (m_SelectedXform == xform) : (m_HoverXform == xform);
|
||||
DrawAffine(xform, true, selected);
|
||||
}
|
||||
@ -322,7 +320,7 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
{
|
||||
for (size_t i = 0; i < ember->TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = ember->GetTotalXform(i);
|
||||
auto xform = ember->GetTotalXform(i);
|
||||
bool selected = dragging ? (m_SelectedXform == xform) : (m_HoverXform == xform);
|
||||
DrawAffine(xform, false, selected);
|
||||
}
|
||||
@ -359,27 +357,12 @@ void GLEmberController<T>::DrawAffines(bool pre, bool post)
|
||||
/// <param name="e">The event</param>
|
||||
bool GLEmberControllerBase::KeyPress_(QKeyEvent* e)
|
||||
{
|
||||
#ifdef OLDDRAG
|
||||
|
||||
if (e->key() == Qt::Key_Shift)
|
||||
SetShift();
|
||||
else if (e->key() == Qt::Key_Control || e->key() == Qt::Key_C)
|
||||
SetControl();
|
||||
else if (e->key() == Qt::Key_Alt || e->key() == Qt::Key_A)
|
||||
SetAlt();
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
#else
|
||||
|
||||
if (e->key() == Qt::Key_Control)
|
||||
{
|
||||
SetControl();
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -401,27 +384,12 @@ void GLWidget::keyPressEvent(QKeyEvent* e)
|
||||
/// <param name="e">The event</param>
|
||||
bool GLEmberControllerBase::KeyRelease_(QKeyEvent* e)
|
||||
{
|
||||
#ifdef OLDDRAG
|
||||
|
||||
if (e->key() == Qt::Key_Shift)
|
||||
ClearShift();
|
||||
else if (e->key() == Qt::Key_Control || e->key() == Qt::Key_C)
|
||||
ClearControl();
|
||||
else if (e->key() == Qt::Key_Alt || e->key() == Qt::Key_A)
|
||||
ClearAlt();
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
#else
|
||||
|
||||
if (e->key() == Qt::Key_Control)
|
||||
{
|
||||
ClearControl();
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -448,8 +416,10 @@ template <typename T>
|
||||
void GLEmberController<T>::MousePress(QMouseEvent* e)
|
||||
{
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatio(), m_Viewport[3] - e->y() * m_GL->devicePixelRatio(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
Ember<T>* ember = m_FractoriumEmberController->CurrentEmber();
|
||||
RendererBase* renderer = m_FractoriumEmberController->Renderer();
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto xforms = ember->TotalXformCount();
|
||||
auto renderer = m_FractoriumEmberController->Renderer();
|
||||
size_t i = 0;
|
||||
|
||||
//Ensure everything has been initialized.
|
||||
if (!renderer)
|
||||
@ -461,7 +431,6 @@ void GLEmberController<T>::MousePress(QMouseEvent* e)
|
||||
m_BoundsDown.x = renderer->LowerLeftY(false);
|
||||
m_BoundsDown.y = renderer->UpperRightX(false);
|
||||
m_BoundsDown.z = renderer->UpperRightY(false);
|
||||
#ifndef OLDDRAG
|
||||
Qt::KeyboardModifiers mod = e->modifiers();
|
||||
|
||||
if (mod.testFlag(Qt::ShiftModifier))
|
||||
@ -472,8 +441,6 @@ void GLEmberController<T>::MousePress(QMouseEvent* e)
|
||||
if (mod.testFlag(Qt::AltModifier))// || mod.testFlag(Qt::Key_A))
|
||||
SetAlt();
|
||||
|
||||
#endif
|
||||
|
||||
if (m_DragState == eDragState::DragNone)//Only take action if the user wasn't already dragging.
|
||||
{
|
||||
m_MouseDownWorldPos = m_MouseWorldPos;//Set the mouse down position to the current position.
|
||||
@ -486,11 +453,16 @@ void GLEmberController<T>::MousePress(QMouseEvent* e)
|
||||
{
|
||||
m_SelectedXform = m_HoverXform;
|
||||
m_DragSrcTransform = Affine2D<T>(m_AffineType == eAffineType::AffinePre ? m_SelectedXform->m_Affine : m_SelectedXform->m_Post);//Copy the affine of the xform that was selected.
|
||||
m_DragHandlePos = m_HoverHandlePos;
|
||||
m_DragHandleOffset = m_DragHandlePos - m_MouseWorldPos;
|
||||
m_DragState = eDragState::DragDragging;
|
||||
//The user has selected an xform by clicking on it, so update the main GUI by selecting this xform in the combo box.
|
||||
m_Fractorium->CurrentXform(xformIndex);
|
||||
m_Fractorium->CurrentXform(xformIndex);//Must do this first so UpdateXform() below properly grabs the current plus any selected.
|
||||
//m_DragSrcTransforms.clear();
|
||||
//m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
//{
|
||||
// m_DragSrcTransforms.push_back(m_AffineType == eAffineType::AffinePre ? xform->m_Affine : xform->m_Post);
|
||||
//}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Don't update renderer here.
|
||||
m_DragHandlePos = m_HoverHandlePos;//The location in local coordinates of the point selected on the spinner, x, y or center.
|
||||
m_DragHandleOffset = m_DragHandlePos - m_MouseWorldPos;//The distance in world coordinates from the point selected to the center of the spinner.
|
||||
m_DragState = eDragState::DragDragging;
|
||||
//Draw large yellow dot on select or drag.
|
||||
m_GL->glPointSize(6.0f);
|
||||
m_GL->glBegin(GL_POINTS);
|
||||
@ -554,9 +526,7 @@ void GLEmberController<T>::MouseRelease(QMouseEvent* e)
|
||||
UpdateHover(mouseFlipped);
|
||||
|
||||
m_DragState = eDragState::DragNone;
|
||||
#ifndef OLDDRAG
|
||||
m_DragModifier = 0;
|
||||
#endif
|
||||
m_GL->repaint();//Force immediate redraw.
|
||||
}
|
||||
|
||||
@ -585,7 +555,7 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
|
||||
bool draw = true;
|
||||
glm::ivec2 mouse(e->x() * m_GL->devicePixelRatio(), e->y() * m_GL->devicePixelRatio());
|
||||
v3T mouseFlipped(e->x() * m_GL->devicePixelRatio(), m_Viewport[3] - e->y() * m_GL->devicePixelRatio(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left.
|
||||
Ember<T>* ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
|
||||
//First check to see if the mouse actually moved.
|
||||
if (mouse == m_MousePos)
|
||||
@ -593,7 +563,6 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
|
||||
|
||||
m_MousePos = mouse;
|
||||
m_MouseWorldPos = WindowToWorld(mouseFlipped, false);
|
||||
//v3T mouseDelta = m_MouseWorldPos - m_MouseDownWorldPos;//Determine how far the mouse has moved in world cartesian coordinates.
|
||||
|
||||
//Update status bar on main window, regardless of whether anything is being dragged.
|
||||
if (m_Fractorium->m_Controller->RenderTimerRunning())
|
||||
@ -605,7 +574,15 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
|
||||
Affine2D<T>* affine = pre ? &m_SelectedXform->m_Affine : &m_SelectedXform->m_Post;//Determine pre or post affine.
|
||||
|
||||
if (m_HoverType == eHoverType::HoverTranslation)
|
||||
{
|
||||
//m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
//{
|
||||
// affine = pre ? &xform->m_Affine : &xform->m_Post;//Determine pre or post affine.
|
||||
// *affine = CalcDragTranslation();
|
||||
//}, eXformUpdate::UPDATE_ALL, false);//Don't need to update render for every xform, just do it once below.
|
||||
*affine = CalcDragTranslation();
|
||||
//CalcDragTranslation();
|
||||
}
|
||||
else if (m_HoverType == eHoverType::HoverXAxis)
|
||||
*affine = CalcDragXAxis();
|
||||
else if (m_HoverType == eHoverType::HoverYAxis)
|
||||
@ -649,7 +626,7 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
|
||||
if (UpdateHover(mouseFlipped) == -1)
|
||||
draw = false;
|
||||
|
||||
//Xform<T>* previousHover = m_HoverXform;
|
||||
//auto previousHover = m_HoverXform;
|
||||
//
|
||||
//if (UpdateHover(mouseFlipped) == -1)
|
||||
// m_HoverXform = m_SelectedXform;
|
||||
@ -690,7 +667,7 @@ void GLWidget::mouseMoveEvent(QMouseEvent* e)
|
||||
template <typename T>
|
||||
void GLEmberController<T>::Wheel(QWheelEvent* e)
|
||||
{
|
||||
Ember<T>* ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
|
||||
if (m_Fractorium && !(e->buttons() & Qt::MiddleButton))//Middle button does whole image translation, so ignore the mouse wheel while panning to avoid inadvertent zooming.
|
||||
m_Fractorium->SetScale(ember->m_PixelsPerUnit + (e->angleDelta().y() >= 0 ? 50 : -50));
|
||||
@ -822,7 +799,7 @@ void GLWidget::SetViewport()
|
||||
template <typename T>
|
||||
bool GLEmberController<T>::SizesMatch()
|
||||
{
|
||||
Ember<T>* ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
return (ember &&
|
||||
ember->m_FinalRasW == m_GL->width() &&
|
||||
ember->m_FinalRasH == m_GL->height() &&
|
||||
@ -837,12 +814,13 @@ bool GLEmberController<T>::SizesMatch()
|
||||
/// The frequency of the grid lines will change depending on the zoom.
|
||||
/// Calculated with the frame always centered, the renderer just moves the camera.
|
||||
/// </summary>
|
||||
void GLWidget::DrawGrid()
|
||||
/// <param name="scale">A value to scale by, used when locking the affine scale</param>
|
||||
void GLWidget::DrawGrid(double scale)
|
||||
{
|
||||
RendererBase* renderer = m_Fractorium->m_Controller->Renderer();
|
||||
float unitX = std::abs(renderer->UpperRightX(false) - renderer->LowerLeftX(false)) / 2.0f;
|
||||
float unitY = std::abs(renderer->UpperRightY(false) - renderer->LowerLeftY(false)) / 2.0f;
|
||||
float rad = std::max(unitX, unitY);
|
||||
float rad = std::max(unitX * scale, unitY * scale);
|
||||
float xLow = floor(-unitX);
|
||||
float xHigh = ceil(unitX);
|
||||
float yLow = floor(-unitY);
|
||||
@ -866,6 +844,9 @@ void GLWidget::DrawGrid()
|
||||
}
|
||||
}
|
||||
|
||||
unitX *= scale;
|
||||
unitY *= scale;
|
||||
|
||||
if (unitX <= 64.0f)
|
||||
{
|
||||
glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
@ -934,16 +915,16 @@ void GLWidget::DrawUnitSquare()
|
||||
template <typename T>
|
||||
void GLEmberController<T>::DrawAffine(Xform<T>* xform, bool pre, bool selected)
|
||||
{
|
||||
Ember<T>* ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
bool final = ember->IsFinalXform(xform);
|
||||
int index = ember->GetXformIndex(xform);
|
||||
size_t size = ember->m_Palette.m_Entries.size();
|
||||
v4T color = ember->m_Palette.m_Entries[Clamp<T>(xform->m_ColorX * size, 0, size - 1)];
|
||||
Affine2D<T>* affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
auto affine = pre ? &xform->m_Affine : &xform->m_Post;
|
||||
//For some incredibly strange reason, even though glm and OpenGL use matrices with a column-major
|
||||
//data layout, nothing will work here unless they are flipped to row major order. This is how it was
|
||||
//done in Fractron.
|
||||
m4T mat = affine->ToMat4RowMajor();
|
||||
m4T mat = (*affine * m_FractoriumEmberController->AffineScaleCurrentToLocked()).ToMat4RowMajor();
|
||||
m_GL->glPushMatrix();
|
||||
m_GL->glLoadIdentity();
|
||||
MultMatrix(mat);
|
||||
@ -1054,7 +1035,7 @@ int GLEmberController<T>::UpdateHover(v3T& glCoords)
|
||||
bool postAll = post && m_Fractorium->DrawAllPost();
|
||||
uint bestIndex = -1;
|
||||
T bestDist = 10;
|
||||
Ember<T>* ember = m_FractoriumEmberController->CurrentEmber();
|
||||
auto ember = m_FractoriumEmberController->CurrentEmber();
|
||||
m_HoverType = eHoverType::HoverNone;
|
||||
|
||||
//If there's a selected/current xform, check it first so it gets precedence over the others.
|
||||
@ -1076,7 +1057,7 @@ int GLEmberController<T>::UpdateHover(v3T& glCoords)
|
||||
//Check all xforms.
|
||||
for (size_t i = 0; i < ember->TotalXformCount(); i++)
|
||||
{
|
||||
Xform<T>* xform = ember->GetTotalXform(i);
|
||||
auto xform = ember->GetTotalXform(i);
|
||||
|
||||
if (preAll || (pre && m_HoverXform == xform))//Only check pre affine if they are shown.
|
||||
{
|
||||
@ -1116,17 +1097,17 @@ template <typename T>
|
||||
bool GLEmberController<T>::CheckXformHover(Xform<T>* xform, v3T& glCoords, T& bestDist, bool pre, bool post)
|
||||
{
|
||||
bool preFound = false, postFound = false;
|
||||
float dist = 0.0f;
|
||||
T dist = 0, scale = m_FractoriumEmberController->AffineScaleCurrentToLocked();
|
||||
v3T pos;
|
||||
Ember<T>* ember = m_FractoriumEmberController->CurrentEmber();
|
||||
|
||||
if (pre)
|
||||
{
|
||||
v3T translation(xform->m_Affine.C()/* - ember->m_CenterX*/, /*ember->m_CenterY + */xform->m_Affine.F(), 0);
|
||||
auto affineScaled = xform->m_Affine * scale;
|
||||
v3T translation(affineScaled.C(), affineScaled.F(), 0);
|
||||
v3T transScreen = glm::project(translation, m_Modelview, m_Projection, m_Viewport);
|
||||
v3T xAxis(xform->m_Affine.A(), xform->m_Affine.D(), 0);
|
||||
v3T xAxis(affineScaled.A(), affineScaled.D(), 0);
|
||||
v3T xAxisScreen = glm::project(translation + xAxis, m_Modelview, m_Projection, m_Viewport);
|
||||
v3T yAxis(xform->m_Affine.B(), xform->m_Affine.E(), 0);
|
||||
v3T yAxis(affineScaled.B(), affineScaled.E(), 0);
|
||||
v3T yAxisScreen = glm::project(translation + yAxis, m_Modelview, m_Projection, m_Viewport);
|
||||
pos = translation;
|
||||
dist = glm::distance(glCoords, transScreen);
|
||||
@ -1167,11 +1148,12 @@ bool GLEmberController<T>::CheckXformHover(Xform<T>* xform, v3T& glCoords, T& be
|
||||
|
||||
if (post)
|
||||
{
|
||||
v3T translation(xform->m_Post.C()/* - ember->m_CenterX*/, /*ember->m_CenterY + */xform->m_Post.F(), 0);
|
||||
auto affineScaled = xform->m_Post * scale;
|
||||
v3T translation(affineScaled.C(), affineScaled.F(), 0);
|
||||
v3T transScreen = glm::project(translation, m_Modelview, m_Projection, m_Viewport);
|
||||
v3T xAxis(xform->m_Post.A(), xform->m_Post.D(), 0);
|
||||
v3T xAxis(affineScaled.A(), affineScaled.D(), 0);
|
||||
v3T xAxisScreen = glm::project(translation + xAxis, m_Modelview, m_Projection, m_Viewport);
|
||||
v3T yAxis(xform->m_Post.B(), xform->m_Post.E(), 0);
|
||||
v3T yAxis(affineScaled.B(), affineScaled.E(), 0);
|
||||
v3T yAxisScreen = glm::project(translation + yAxis, m_Modelview, m_Projection, m_Viewport);
|
||||
pos = translation;
|
||||
dist = glm::distance(glCoords, transScreen);
|
||||
@ -1235,7 +1217,8 @@ template <typename T>
|
||||
Affine2D<T> GLEmberController<T>::CalcDragXAxis()
|
||||
{
|
||||
v3T t3, newAxis, newPos;
|
||||
Affine2D<T> result = m_DragSrcTransform;
|
||||
auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
|
||||
auto result = m_DragSrcTransform;
|
||||
bool worldPivotShiftAlt = !m_Fractorium->LocalPivot() && GetShift() && GetAlt();
|
||||
|
||||
if (worldPivotShiftAlt)
|
||||
@ -1245,7 +1228,7 @@ Affine2D<T> GLEmberController<T>::CalcDragXAxis()
|
||||
|
||||
if (GetShift())
|
||||
{
|
||||
v3T targetAxis = m_MouseWorldPos - t3;
|
||||
v3T targetAxis = (m_MouseWorldPos * scale) - t3;
|
||||
v3T norm = glm::normalize(targetAxis);
|
||||
|
||||
if (GetControl())
|
||||
@ -1263,7 +1246,7 @@ Affine2D<T> GLEmberController<T>::CalcDragXAxis()
|
||||
else
|
||||
newPos = m_MouseWorldPos + m_DragHandleOffset;
|
||||
|
||||
newAxis = newPos - t3;
|
||||
newAxis = (newPos * scale) - t3;
|
||||
}
|
||||
|
||||
if (GetAlt())
|
||||
@ -1278,7 +1261,8 @@ Affine2D<T> GLEmberController<T>::CalcDragXAxis()
|
||||
result.RotateScaleXTo(v2T(newAxis));
|
||||
}
|
||||
|
||||
m_DragHandlePos = v3T(result.O() + result.X(), 0);
|
||||
T scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
|
||||
m_DragHandlePos = v3T((result.O() + result.X()) * scaleBack, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1304,7 +1288,8 @@ template <typename T>
|
||||
Affine2D<T> GLEmberController<T>::CalcDragYAxis()
|
||||
{
|
||||
v3T t3, newAxis, newPos;
|
||||
Affine2D<T> result = m_DragSrcTransform;
|
||||
auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
|
||||
auto result = m_DragSrcTransform;
|
||||
bool worldPivotShiftAlt = !m_Fractorium->LocalPivot() && GetShift() && GetAlt();
|
||||
|
||||
if (worldPivotShiftAlt)
|
||||
@ -1314,7 +1299,7 @@ Affine2D<T> GLEmberController<T>::CalcDragYAxis()
|
||||
|
||||
if (GetShift())
|
||||
{
|
||||
v3T targetAxis = m_MouseWorldPos - t3;
|
||||
v3T targetAxis = (m_MouseWorldPos * scale) - t3;
|
||||
v3T norm = glm::normalize(targetAxis);
|
||||
|
||||
if (GetControl())
|
||||
@ -1332,7 +1317,7 @@ Affine2D<T> GLEmberController<T>::CalcDragYAxis()
|
||||
else
|
||||
newPos = m_MouseWorldPos + m_DragHandleOffset;
|
||||
|
||||
newAxis = newPos - t3;
|
||||
newAxis = (newPos * scale) - t3;
|
||||
}
|
||||
|
||||
if (GetAlt())
|
||||
@ -1347,7 +1332,8 @@ Affine2D<T> GLEmberController<T>::CalcDragYAxis()
|
||||
result.RotateScaleYTo(v2T(newAxis));
|
||||
}
|
||||
|
||||
m_DragHandlePos = v3T(result.O() + result.Y(), 0);
|
||||
T scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
|
||||
m_DragHandlePos = v3T((result.O() + result.Y()) * scaleBack, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1368,8 +1354,9 @@ Affine2D<T> GLEmberController<T>::CalcDragYAxis()
|
||||
template <typename T>
|
||||
Affine2D<T> GLEmberController<T>::CalcDragTranslation()
|
||||
{
|
||||
v3T newPos, newX, newY;
|
||||
Affine2D<T> result = m_DragSrcTransform;
|
||||
v3T newPos;
|
||||
auto scale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
|
||||
auto result = m_DragSrcTransform;
|
||||
bool worldPivotShift = !m_Fractorium->LocalPivot() && GetShift();
|
||||
|
||||
if (GetShift())
|
||||
@ -1387,17 +1374,32 @@ Affine2D<T> GLEmberController<T>::CalcDragTranslation()
|
||||
T endAngle = atan2(newPos.y, newPos.x);
|
||||
T angle = startAngle - endAngle;
|
||||
result.Rotate(angle * RAD_2_DEG);
|
||||
//RotateXformsByAngle
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetControl())
|
||||
{
|
||||
newPos = SnapToGrid(m_MouseWorldPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
newPos = m_MouseWorldPos + m_DragHandleOffset;
|
||||
//bool pre = m_AffineType == eAffineType::AffinePre;
|
||||
//size_t index = 0;
|
||||
//newPos = m_MouseWorldPos;
|
||||
//auto diff = m_MouseWorldPos - m_MouseDownWorldPos;
|
||||
//m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
//{
|
||||
// auto affine = pre ? &xform->m_Affine : &xform->m_Post;//Determine pre or post affine.
|
||||
// affine->O(m_DragSrcTransforms[index++].O() + v2T(diff));
|
||||
//}, eXformUpdate::UPDATE_CURRENT_AND_SELECTED, false);//Don't need to update render for every xform, just do it once below.
|
||||
}
|
||||
}
|
||||
|
||||
result.O(v2T(newPos));
|
||||
T scaleBack = m_FractoriumEmberController->AffineScaleCurrentToLocked();
|
||||
result.O(v2T(newPos * scale));
|
||||
m_DragHandlePos = newPos;
|
||||
return result;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ private:
|
||||
bool Allocate(bool force = false);
|
||||
bool Deallocate();
|
||||
void SetViewport();
|
||||
void DrawGrid();
|
||||
void DrawGrid(double scale);
|
||||
void DrawUnitSquare();
|
||||
void DrawAffineHelper(int index, bool selected, bool pre, bool final, bool background);
|
||||
GLEmberControllerBase* GLController();
|
||||
|
@ -56,7 +56,7 @@ void FractoriumVariationsDialog::ForEachSelectedCell(std::function<void(QTableWi
|
||||
QList<QTableWidgetItem*> selectedItems = table->selectedItems();
|
||||
table->model()->blockSignals(true);
|
||||
|
||||
foreach (QTableWidgetItem* item, selectedItems)
|
||||
for (auto item : selectedItems)
|
||||
if (item)
|
||||
func(item);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user