mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-07-16 05:05:09 -04:00
1.0.0.2 12/05/2016
--User changes -Add many tooltips to help clarify functionality. -Select multiple flames in library for del/move. Still only one allowed to be set as the current. -Show checkbox for current flame. Remember this is not necessarily what's selected. -User can now drag a square to select xforms, which keeps in sync with checkboxes. -Remove --nframes from command line. Replace with new params: --loopframes, --interpframes, --interploops. -Add two new options to EmberGenome: --cwloops --cwinterploops to specify whether rotation should go clockwise instead of the default counter clockwise. -Add these to Fractorium as checkboxes. -Apply All now also works for toggling animate flag on xforms. -Options dialog now allows user to set whether double click toggles spinners, or right click does. --Bug fixes -Selecting final and non-final xforms, and then dragging the non-final did not drag the final with it. -Selecting all xforms when a final was present, then deleting crashed the program. -Remove support for ppm files in the command line programs, it's an outdated format. -Switching between SP and DP kept reapplying the palette adjustments. --Code changes -Move build system to Visual Studio 2015 and Qt 5.6. -SSE used during addition of points to the histogram. -Remove last remnants of old flam3 C code and replace with C++. -Remove unused code involving tbb::task_group. -Make settings object a global shared_ptr singleton, so it doesn't have to be passed around.
This commit is contained in:
@ -442,42 +442,6 @@ public:
|
||||
return b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an integer to a string.
|
||||
/// Just a wrapper around _itoa_s() which wraps the result in a std::string.
|
||||
/// </summary>
|
||||
/// <param name="i">The integer to convert</param>
|
||||
/// <param name="radix">The radix of the integer. Default: 10.</param>
|
||||
/// <returns>The converted string</returns>
|
||||
static string Itos(int i, int radix = 10)
|
||||
{
|
||||
char ch[16];
|
||||
#ifdef _WIN32
|
||||
_itoa_s(i, ch, 16, radix);
|
||||
#else
|
||||
sprintf(ch, "%d", i);
|
||||
#endif
|
||||
return string(ch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an unsigned 64-bit integer to a string.
|
||||
/// Just a wrapper around _ui64toa_s() which wraps the result in a std::string.
|
||||
/// </summary>
|
||||
/// <param name="i">The unsigned 64-bit integer to convert</param>
|
||||
/// <param name="radix">The radix of the integer. Default: 10.</param>
|
||||
/// <returns>The converted string</returns>
|
||||
static string Itos64(size_t i, int radix = 10)
|
||||
{
|
||||
char ch[64];
|
||||
#ifdef _WIN32
|
||||
_ui64toa_s(i, ch, 64, radix);
|
||||
#else
|
||||
sprintf(ch, "%lu", i);
|
||||
#endif
|
||||
return string(ch);
|
||||
}
|
||||
|
||||
static vector<string> m_FlattenNames;
|
||||
|
||||
private:
|
||||
@ -523,7 +487,7 @@ private:
|
||||
if (auto pal = m_PaletteList.GetPalette(PaletteList<T>::m_DefaultFilename, currentEmber.PaletteIndex()))
|
||||
currentEmber.m_Palette = *pal;
|
||||
else
|
||||
AddToReport(string(loc) + " : Error assigning palette with index " + Itos(currentEmber.PaletteIndex()));
|
||||
AddToReport(string(loc) + " : Error assigning palette with index " + std::to_string(currentEmber.PaletteIndex()));
|
||||
}
|
||||
|
||||
if (!currentEmber.XformCount())//Ensure there is always at least one xform or else the renderer will crash when trying to render.
|
||||
@ -532,8 +496,6 @@ private:
|
||||
currentEmber.AddXform(xform);
|
||||
}
|
||||
|
||||
//if (!Interpolater<T>::InterpMissingColors(currentEmber.m_Palette.m_Entries))
|
||||
// AddToReport(string(loc) + " : Error interpolating missing palette colors");
|
||||
currentEmber.CacheXforms();
|
||||
currentEmber.m_Index = embers.size();
|
||||
currentEmber.m_ParentFilename = parentFileString;
|
||||
@ -562,7 +524,6 @@ private:
|
||||
const char* loc = __FUNCTION__;
|
||||
int soloXform = -1;
|
||||
size_t i, count = 0, index = 0;
|
||||
double vals[16];
|
||||
xmlAttrPtr att, curAtt;
|
||||
xmlNodePtr editNode, childNode, motionNode;
|
||||
currentEmber.m_Palette.Clear();//Wipe out the current palette.
|
||||
@ -655,28 +616,16 @@ private:
|
||||
}
|
||||
else if (!Compare(curAtt->name, "size"))
|
||||
{
|
||||
if (sscanf_s(attStr, "%lu %lu", ¤tEmber.m_FinalRasW, ¤tEmber.m_FinalRasH) != 2)
|
||||
{
|
||||
AddToReport(string(loc) + " : Invalid size attribute " + string(attStr));
|
||||
//Assign reasonable defaults.
|
||||
currentEmber.m_FinalRasW = 1000;
|
||||
currentEmber.m_FinalRasH = 1000;
|
||||
}
|
||||
|
||||
istringstream is(attStr);
|
||||
is >> currentEmber.m_FinalRasW >> currentEmber.m_FinalRasH;
|
||||
currentEmber.m_OrigFinalRasW = currentEmber.m_FinalRasW;
|
||||
currentEmber.m_OrigFinalRasH = currentEmber.m_FinalRasH;
|
||||
}
|
||||
else if (!Compare(curAtt->name, "center"))
|
||||
{
|
||||
if (sscanf_s(attStr, "%lf %lf", &vals[0], &vals[1]) != 2)
|
||||
{
|
||||
AddToReport(string(loc) + " : Invalid center attribute " + string(attStr));
|
||||
vals[0] = 0;
|
||||
vals[1] = 0;
|
||||
}
|
||||
|
||||
currentEmber.m_CenterX = T(vals[0]);
|
||||
currentEmber.m_CenterY = currentEmber.m_RotCenterY = T(vals[1]);
|
||||
istringstream is(attStr);
|
||||
is >> currentEmber.m_CenterX >> currentEmber.m_CenterY;
|
||||
currentEmber.m_RotCenterY = currentEmber.m_CenterY;
|
||||
}
|
||||
else if (!Compare(curAtt->name, "filter_shape"))
|
||||
{
|
||||
@ -700,29 +649,22 @@ private:
|
||||
}
|
||||
else if (!Compare(curAtt->name, "background"))
|
||||
{
|
||||
if (sscanf_s(attStr, "%lf %lf %lf", &vals[0], &vals[1], &vals[2]) != 3)
|
||||
{
|
||||
AddToReport(string(loc) + " : Invalid background attribute " + string(attStr));
|
||||
vals[0] = 0;
|
||||
vals[1] = 0;
|
||||
vals[2] = 0;
|
||||
}
|
||||
|
||||
currentEmber.m_Background[0] = T(vals[0]);//[0..1]
|
||||
currentEmber.m_Background[1] = T(vals[1]);
|
||||
currentEmber.m_Background[2] = T(vals[2]);
|
||||
istringstream is(attStr);
|
||||
is >> currentEmber.m_Background[0]//[0..1]
|
||||
>> currentEmber.m_Background[1]
|
||||
>> currentEmber.m_Background[2];
|
||||
}
|
||||
else if (!Compare(curAtt->name, "curves"))
|
||||
{
|
||||
stringstream ss(attStr);
|
||||
istringstream is(attStr);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
for (glm::length_t j = 0; j < 4; j++)
|
||||
{
|
||||
ss >> currentEmber.m_Curves.m_Points[i][j].x;
|
||||
ss >> currentEmber.m_Curves.m_Points[i][j].y;
|
||||
ss >> currentEmber.m_Curves.m_Weights[i][j];
|
||||
is >> currentEmber.m_Curves.m_Points[i][j].x
|
||||
>> currentEmber.m_Curves.m_Points[i][j].y
|
||||
>> currentEmber.m_Curves.m_Weights[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -748,36 +690,24 @@ private:
|
||||
|
||||
for (curAtt = att; curAtt; curAtt = curAtt->next)
|
||||
{
|
||||
attStr = reinterpret_cast<char*>(xmlGetProp(childNode, curAtt->name));
|
||||
a = 255;
|
||||
attStr = reinterpret_cast<char*>(xmlGetProp(childNode, curAtt->name));
|
||||
istringstream is(attStr);
|
||||
//This signifies that a palette is not being retrieved from the palette file, rather it's being parsed directly out of the ember xml.
|
||||
//This also means the palette has already been hue adjusted and it doesn't need to be done again, which would be necessary if it were
|
||||
//coming from the palette file.
|
||||
currentEmber.m_Palette.m_Index = -1;
|
||||
|
||||
if (!Compare(curAtt->name, "index"))
|
||||
{
|
||||
Aton(attStr, index);
|
||||
}
|
||||
else if (!Compare(curAtt->name, "rgb"))
|
||||
{
|
||||
if (sscanf_s(attStr, "%lf %lf %lf", &r, &g, &b) != 3)
|
||||
AddToReport(string(loc) + " : Invalid rgb attribute " + string(attStr));
|
||||
}
|
||||
is >> r >> g >> b;
|
||||
else if (!Compare(curAtt->name, "rgba"))
|
||||
{
|
||||
if (sscanf_s(attStr, "%lf %lf %lf %lf", &r, &g, &b, &a) != 4)
|
||||
AddToReport(string(loc) + " : Invalid rgba attribute " + string(attStr));
|
||||
}
|
||||
is >> r >> g >> b >> a;
|
||||
else if (!Compare(curAtt->name, "a"))
|
||||
{
|
||||
if (sscanf_s(attStr, "%lf", &a) != 1)
|
||||
AddToReport(string(loc) + " : Invalid a attribute " + string(attStr));
|
||||
}
|
||||
is >> a;
|
||||
else
|
||||
{
|
||||
AddToReport(string(loc) + " : Unknown color attribute " + string(CCX(curAtt->name)));
|
||||
}
|
||||
|
||||
xmlFree(attStr);
|
||||
}
|
||||
@ -1051,13 +981,9 @@ private:
|
||||
ret = ret && AttToEmberMotionFloat(att, attStr, eEmberMotionParam::FLAME_MOTION_VIBRANCY, motion);
|
||||
else if (!Compare(curAtt->name, "background"))
|
||||
{
|
||||
double r, g, b;
|
||||
|
||||
if (sscanf_s(attStr, "%lf %lf %lf", &r, &g, &b) != 3)
|
||||
{
|
||||
AddToReport(string(loc) + " : Invalid flame motion background attribute " + string(attStr));
|
||||
r = g = b = 0;
|
||||
}
|
||||
double r = 0, g = 0, b = 0;
|
||||
istringstream is(attStr);
|
||||
is >> r >> g >> b;
|
||||
|
||||
if (r != 0)
|
||||
motion.m_MotionParams.push_back(MotionParam<T>(eEmberMotionParam::FLAME_MOTION_BACKGROUND_R, T(r)));
|
||||
@ -1070,13 +996,9 @@ private:
|
||||
}
|
||||
else if (!Compare(curAtt->name, "center"))
|
||||
{
|
||||
double cx, cy;
|
||||
|
||||
if (sscanf_s(attStr, "%lf %lf", &cx, &cy) != 2)
|
||||
{
|
||||
AddToReport(string(loc) + " : Invalid flame motion center attribute " + string(attStr));
|
||||
cx = cy = 0;
|
||||
}
|
||||
double cx = 0, cy = 0;
|
||||
istringstream is(attStr);
|
||||
is >> cx >> cy;
|
||||
|
||||
if (cx != 0)
|
||||
motion.m_MotionParams.push_back(MotionParam<T>(eEmberMotionParam::FLAME_MOTION_CENTER_X, T(cx)));
|
||||
@ -1148,7 +1070,6 @@ private:
|
||||
size_t j;
|
||||
T temp;
|
||||
double a, b, c, d, e, f;
|
||||
double vals[10];
|
||||
xmlAttrPtr attPtr, curAtt;
|
||||
//Loop through the attributes of the xform element.
|
||||
attPtr = childNode->properties;
|
||||
@ -1203,30 +1124,17 @@ private:
|
||||
}
|
||||
else if (!Compare(curAtt->name, "color"))
|
||||
{
|
||||
xform.m_ColorX = xform.m_ColorY = 0;
|
||||
|
||||
//Try two coords first .
|
||||
if (sscanf_s(attStr, "%lf %lf", &vals[0], &vals[1]) == 2)
|
||||
{
|
||||
xform.m_ColorX = T(vals[0]);
|
||||
xform.m_ColorY = T(vals[1]);
|
||||
}
|
||||
else if (sscanf_s(attStr, "%lf", &vals[0]) == 1)//Try one color.
|
||||
{
|
||||
xform.m_ColorX = T(vals[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
xform.m_ColorX = xform.m_ColorY = T(0.5);
|
||||
AddToReport(string(loc) + " : Malformed xform color attribute " + string(attStr) + ", using 0.5, 0.5");
|
||||
}
|
||||
istringstream is(attStr);
|
||||
xform.m_ColorX = xform.m_ColorY = T(0.5);
|
||||
is >> xform.m_ColorX;
|
||||
is >> xform.m_ColorY;//Very unlikely to be present, but leave for future use.
|
||||
}
|
||||
else if (!Compare(curAtt->name, "chaos"))
|
||||
{
|
||||
stringstream ss(attStr);
|
||||
istringstream is(attStr);
|
||||
j = 0;
|
||||
|
||||
while (ss >> temp)
|
||||
while (is >> temp)
|
||||
{
|
||||
xform.SetXaos(j, temp);
|
||||
j++;
|
||||
@ -1243,12 +1151,9 @@ private:
|
||||
}
|
||||
else if (!Compare(curAtt->name, "coefs"))
|
||||
{
|
||||
if (sscanf_s(attStr, "%lf %lf %lf %lf %lf %lf", &a, &d, &b, &e, &c, &f) != 6)//Original did a complicated parsing scheme. This is easier.//ORIG
|
||||
{
|
||||
a = d = b = e = c = f = 0;
|
||||
AddToReport(string(loc) + " : Bad coeffs attribute " + string(attStr));
|
||||
}
|
||||
|
||||
istringstream is(attStr);
|
||||
a = b = c = d = e = f = 0;
|
||||
is >> a >> d >> b >> e >> c >> f;
|
||||
xform.m_Affine.A(T(a));
|
||||
xform.m_Affine.B(T(b));
|
||||
xform.m_Affine.C(T(c));
|
||||
@ -1258,12 +1163,9 @@ private:
|
||||
}
|
||||
else if (!Compare(curAtt->name, "post"))
|
||||
{
|
||||
if (sscanf_s(attStr, "%lf %lf %lf %lf %lf %lf", &a, &d, &b, &e, &c, &f) != 6)//Original did a complicated parsing scheme. This is easier.//ORIG
|
||||
{
|
||||
a = d = b = e = c = f = 0;
|
||||
AddToReport(string(loc) + " : Bad post coeffs attribute " + string(attStr));
|
||||
}
|
||||
|
||||
istringstream is(attStr);
|
||||
a = b = c = d = e = f = 0;
|
||||
is >> a >> d >> b >> e >> c >> f;
|
||||
xform.m_Post.A(T(a));
|
||||
xform.m_Post.B(T(b));
|
||||
xform.m_Post.C(T(c));
|
||||
@ -1469,64 +1371,33 @@ private:
|
||||
/// <returns>True if there were no errors, else false.</returns>
|
||||
bool ParseHexColors(char* colstr, Ember<T>& ember, size_t numColors, intmax_t chan)
|
||||
{
|
||||
size_t colorIndex = 0;
|
||||
size_t colorCount = 0;
|
||||
uint r, g, b, a;
|
||||
int ret;
|
||||
char tmps[2];
|
||||
size_t skip = std::abs(chan);
|
||||
bool ok = true;
|
||||
const char* loc = __FUNCTION__;
|
||||
stringstream ss, temp(colstr); ss >> std::hex;
|
||||
string s1, s;
|
||||
size_t tmp, colorCount = 0, colorIndex = 0;
|
||||
s.reserve(1536);
|
||||
|
||||
//Strip whitespace prior to first color.
|
||||
while (isspace(static_cast<int>(colstr[colorIndex])))
|
||||
colorIndex++;
|
||||
while (temp >> s1)
|
||||
s += s1;
|
||||
|
||||
do
|
||||
auto length = s.size();
|
||||
|
||||
for (size_t strIndex = 0; strIndex < length;)
|
||||
{
|
||||
//Parse an RGB triplet at a time.
|
||||
if (chan == 3)
|
||||
ret = sscanf_s(&(colstr[colorIndex]), "%2x%2x%2x", &r, &g, &b);
|
||||
else if (chan == -4)
|
||||
ret = sscanf_s(&(colstr[colorIndex]), "00%2x%2x%2x", &r, &g, &b);
|
||||
else // chan==4
|
||||
ret = sscanf_s(&(colstr[colorIndex]), "%2x%2x%2x%2x", &r, &g, &b, &a);
|
||||
|
||||
a = 1;//Original allows for alpha, even though it will most likely never happen. Ember omits support for it.
|
||||
|
||||
if ((chan != 4 && ret != 3) || (chan == 4 && ret != 4))
|
||||
for (glm::length_t i = 0; i < 3 && colorCount < ember.m_Palette.Size(); i++)
|
||||
{
|
||||
ok = false;
|
||||
r = g = b = 0;
|
||||
AddToReport(string(loc) + " : Problem reading hexadecimal color data, assigning to 0");
|
||||
break;
|
||||
const char tmpStr[3] = { s[strIndex++], s[strIndex++], 0 };//Read out and convert the string two characters at a time.
|
||||
ss.clear();//Reset and fill the string stream.
|
||||
ss.str(tmpStr);
|
||||
ss >> tmp;//Do the conversion.
|
||||
ember.m_Palette.m_Entries[colorCount][i] = T(tmp) / T(255);//Hex palette is [0..255], convert to [0..1].
|
||||
}
|
||||
|
||||
colorIndex += 2 * skip;
|
||||
|
||||
while (isspace(static_cast<int>(colstr[colorIndex])))
|
||||
colorIndex++;
|
||||
|
||||
ember.m_Palette.m_Entries[colorCount].r = T(r) / T(255);//Hex palette is [0..255], convert to [0..1].
|
||||
ember.m_Palette.m_Entries[colorCount].g = T(g) / T(255);
|
||||
ember.m_Palette.m_Entries[colorCount].b = T(b) / T(255);
|
||||
ember.m_Palette.m_Entries[colorCount].a = T(a);
|
||||
ember.m_Palette.m_Entries[colorCount][3] = T(1);
|
||||
colorCount++;
|
||||
}
|
||||
while (colorCount < numColors && colorCount < ember.m_Palette.m_Entries.size());
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
if (sscanf_s(&(colstr[colorIndex]), "%1s", tmps, sizeof(tmps)) > 0) //Really need to migrate all of this parsing to C++.//TODO
|
||||
#else
|
||||
if (sscanf_s(&(colstr[colorIndex]), "%1s", tmps) > 0)
|
||||
#endif
|
||||
{
|
||||
AddToReport(string(loc) + " : Extra data at end of hex color data " + string(&(colstr[colorIndex])));
|
||||
ok = false;
|
||||
}
|
||||
|
||||
return ok;
|
||||
return length >= 256;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
Reference in New Issue
Block a user