mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-02-01 10:30:08 -05:00
--User changes
-No longer constrain pitch, yaw or depth spinners to -180 - 180. --Bug fixes -Properly set color index on padded xforms. -Adding a padding final xform included a linear variation with a weight of zero to not appear empty. Made it have a weight of 1. -Always write animate tag on final xform when saving to Xml. -Motion was being applied to the wrong flame in SheepTools::Edge(), so apply it to the correct one. -Prevent divide by zero when normalizing variation weights. -Was accidentally adding the placeholder value of -9999 for motion_offset to varation weights and parameters when applying motion. Set to zero if no value present. -Clamp flame rotation values to -180 - 180 when reading a flame from Xml. -Events were not properly wired for user changes in the random rotations per blend controls in the sequencer. -Fix major UI bugs with sequencer min/max random controls which made it nearly impossible to hand type values. -Values from rotations per blend and rotations per blend max were not being saved to file between program runs. -Checking animate for an xform was not applied to all flames even if Apply All was checked. -Changing interpolation type, temporal filter width, temporal type, and affine interpolation type were not actually saving to the flame when changed. -Grid on the main window was not being drawn at the right scale initially due to some OpenGL initialization occurring in the wrong order. -Severe bugs in sequence generation code: --Improperly detected padding xforms. --When looking for specific variations during xform aligning, only presence was detected, when it should have been presence plus a weight greater than zero. --When adding specific variations during xform aligning, must first remove any variations of that type. --Two variables were unsigned when they should have been signed. This prevented large blocks of code from ever executing. --When interpolating affines, an EPS that was too small was used, causing affine values to interpolate incorrectly. Instead use 1e-10 to ensure results equal to flam3. --Code changes -Modify FractoriumEmberController::UpdateXform() to pass the selected xform index as well as the absolute index to func().
This commit is contained in:
parent
05fabda748
commit
6ff199d1ef
@ -6,7 +6,7 @@
|
||||
<ProductVersion>3.7</ProductVersion>
|
||||
<ProjectGuid>{c8096c47-e358-438c-a520-146d46b0637d}</ProjectGuid>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<OutputName>Fractorium_1.0.0.9</OutputName>
|
||||
<OutputName>Fractorium_1.0.0.10</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<?define ProductVersion="1.0.0.9" ?>
|
||||
<?define ProductVersion="1.0.0.10" ?>
|
||||
<?define ProductName="Fractorium $(var.ProductVersion) ($(var.GpuType))" ?>
|
||||
<?define UpgradeCode="{4714cd15-bfba-44f6-8059-9e1466ebfa6e}"?>
|
||||
<?define Manufacturer="Fractorium"?>
|
||||
@ -13,7 +13,7 @@
|
||||
<!--
|
||||
Change this for every release.
|
||||
-->
|
||||
<?define ProductCode="{956BC0F6-C1AE-4754-8454-209B4C7933F8}"?>
|
||||
<?define ProductCode="{0F26C619-C6EA-439A-ACB7-EFB6401DA47E}"?>
|
||||
|
||||
<Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
|
||||
<Package
|
||||
|
Binary file not shown.
@ -49,8 +49,8 @@
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1, 0, 0, 9
|
||||
PRODUCTVERSION 1, 0, 0, 9
|
||||
FILEVERSION 1, 0, 0, 10
|
||||
PRODUCTVERSION 1, 0, 0, 10
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -67,12 +67,12 @@
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Open Source"
|
||||
VALUE "FileDescription", "Renders fractal flames as animations with motion blur"
|
||||
VALUE "FileVersion", "1.0.0.9"
|
||||
VALUE "FileVersion", "1.0.0.10"
|
||||
VALUE "InternalName", "EmberAnimate.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2017, GPL v3"
|
||||
VALUE "OriginalFilename", "EmberAnimate.exe"
|
||||
VALUE "ProductName", "Ember Animate"
|
||||
VALUE "ProductVersion", "1.0.0.9"
|
||||
VALUE "ProductVersion", "1.0.0.10"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
Binary file not shown.
@ -49,8 +49,8 @@
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1, 0, 0, 9
|
||||
PRODUCTVERSION 1, 0, 0, 9
|
||||
FILEVERSION 1, 0, 0, 10
|
||||
PRODUCTVERSION 1, 0, 0, 10
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -67,12 +67,12 @@
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Open Source"
|
||||
VALUE "FileDescription", "Manipulates fractal flames parameter files"
|
||||
VALUE "FileVersion", "1.0.0.9"
|
||||
VALUE "FileVersion", "1.0.0.10"
|
||||
VALUE "InternalName", "EmberGenome.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2017, GPL v3"
|
||||
VALUE "OriginalFilename", "EmberGenome.exe"
|
||||
VALUE "ProductName", "Ember Genome"
|
||||
VALUE "ProductVersion", "1.0.0.9"
|
||||
VALUE "ProductVersion", "1.0.0.10"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -49,8 +49,8 @@
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1, 0, 0, 9
|
||||
PRODUCTVERSION 1, 0, 0, 9
|
||||
FILEVERSION 1, 0, 0, 10
|
||||
PRODUCTVERSION 1, 0, 0, 10
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -67,12 +67,12 @@
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Open Source"
|
||||
VALUE "FileDescription", "Renders fractal flames as single images"
|
||||
VALUE "FileVersion", "1.0.0.9"
|
||||
VALUE "FileVersion", "1.0.0.10"
|
||||
VALUE "InternalName", "EmberRender.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2017, GPL v3"
|
||||
VALUE "OriginalFilename", "EmberRender.exe"
|
||||
VALUE "ProductName", "Ember Render"
|
||||
VALUE "ProductVersion", "1.0.0.9"
|
||||
VALUE "ProductVersion", "1.0.0.10"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
Binary file not shown.
@ -211,9 +211,12 @@ public:
|
||||
/// <param name="count">The number of xforms to add</param>
|
||||
void AddXforms(size_t count)
|
||||
{
|
||||
auto oldsize = m_Xforms.size();
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
Xform<T> xform;
|
||||
xform.m_ColorX = T((oldsize + i) & 1);
|
||||
xform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
AddXform(xform);
|
||||
}
|
||||
@ -266,15 +269,18 @@ public:
|
||||
if (UseFinalXform())//Caller wanted one and this ember has one.
|
||||
{
|
||||
ember.m_FinalXform = m_FinalXform;
|
||||
ember.m_FinalXform.m_ColorX = T(XformCount() & 1);
|
||||
}
|
||||
else//Caller wanted one and this ember doesn't have one.
|
||||
{
|
||||
//Interpolated-against final xforms need animate & color speed set to 0 and motion elements cleared.
|
||||
ember.m_FinalXform.m_Affine.MakeID();
|
||||
ember.m_FinalXform.m_Post.MakeID();
|
||||
ember.m_FinalXform.m_Animate = 0;
|
||||
ember.m_FinalXform.m_ColorSpeed = 0;
|
||||
ember.m_FinalXform.m_Motion.clear();
|
||||
ember.m_FinalXform.ClearAndDeleteVariations();
|
||||
ember.m_FinalXform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR, 0));//Do this so it doesn't appear empty.
|
||||
ember.m_FinalXform.AddVariation(m_VariationList->GetVariationCopy(eVariationId::VAR_LINEAR));//Do this so it doesn't appear empty.
|
||||
}
|
||||
}
|
||||
|
||||
@ -798,6 +804,9 @@ public:
|
||||
{
|
||||
auto thisXform = GetTotalXform(i);
|
||||
|
||||
//if (i == 10)
|
||||
// cout << i << endl;
|
||||
|
||||
if (size == 2 && stagger > 0 && thisXform != &m_FinalXform)
|
||||
{
|
||||
coefSave[0] = coefs[0];
|
||||
|
@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c)
|
||||
|
||||
namespace EmberNs
|
||||
{
|
||||
#define EMBER_VERSION "1.0.0.9"
|
||||
#define EMBER_VERSION "1.0.0.10"
|
||||
#define EPS6 T(1e-6)
|
||||
#define EPS std::numeric_limits<T>::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.
|
||||
#define ISAAC_SIZE 4
|
||||
|
@ -508,9 +508,7 @@ string EmberToXml<T>::ToString(Xform<T>& xform, size_t xformCount, bool isFinal,
|
||||
string s = xform.m_Name;
|
||||
std::replace(s.begin(), s.end(), ' ', '_');
|
||||
os << "name=\"" << s << "\" ";//Flam3 didn't do this, but Apo does.
|
||||
|
||||
if (!isFinal)
|
||||
os << "animate=\"" << xform.m_Animate << "\" ";
|
||||
os << "animate=\"" << xform.m_Animate << "\" ";//Flam3 only did this for non-final. Ember supports animating final.
|
||||
}
|
||||
|
||||
//Variation writing order differs slightly from the original to make it a bit more readable.
|
||||
|
@ -24,6 +24,25 @@ template <typename T>
|
||||
class EMBER_API Interpolater
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Determine if the xform at a given index in an ember is a padding xform.
|
||||
/// </summary>
|
||||
/// <param name="ember">The ember whose xforms will be examined for padding</param>
|
||||
/// <param name="xf">The index of the ember to examine</param>
|
||||
/// <param name="isFinal">Whether the xform being examined is the final one</param>
|
||||
/// <returns>True the xform at index xf is a padding one, else false.</returns>
|
||||
static bool IsPadding(const Ember<T>& ember, size_t xf, bool isFinal)
|
||||
{
|
||||
if (!isFinal)//Either a final wasn't present in any ember, or if there was, this xform is a normal one, so do not include final in the index check.
|
||||
{
|
||||
return xf >= ember.XformCount();
|
||||
}
|
||||
else//There was a final present, and we are checking it, so just see if its presence differs.
|
||||
{
|
||||
return !ember.UseFinalXform();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aligns the specified array of embers and stores in the output array.
|
||||
/// This is used to prepare embers before interpolating them.
|
||||
@ -41,7 +60,7 @@ public:
|
||||
static void Align(const Ember<T>* sourceEmbers, Ember<T>* destEmbers, size_t count)
|
||||
{
|
||||
bool aligned = true;
|
||||
bool currentFinal, final = sourceEmbers[0].UseFinalXform();
|
||||
bool currentFinal, hasFinal = sourceEmbers[0].UseFinalXform();
|
||||
size_t i, xf, currentCount, maxCount = sourceEmbers[0].XformCount();
|
||||
Xform<T>* destOtherXform;
|
||||
auto variationList = VariationList<T>::Instance();
|
||||
@ -62,18 +81,18 @@ public:
|
||||
|
||||
currentFinal = sourceEmbers[i].UseFinalXform();
|
||||
|
||||
if (final != currentFinal)//Check if any used final.
|
||||
if (hasFinal != currentFinal)//Check if any used final.
|
||||
{
|
||||
aligned = false;
|
||||
final |= currentFinal;
|
||||
hasFinal |= currentFinal;
|
||||
}
|
||||
}
|
||||
|
||||
//Copy them using the max xform count, and do final if any had final.
|
||||
for (i = 0; i < count; i++)
|
||||
destEmbers[i] = sourceEmbers[i].Copy(maxCount, final);
|
||||
destEmbers[i] = sourceEmbers[i].Copy(maxCount, hasFinal);
|
||||
|
||||
if (final)
|
||||
if (hasFinal)
|
||||
maxCount++;
|
||||
|
||||
//Check to see if there's a parametric variation present in one xform
|
||||
@ -82,11 +101,13 @@ public:
|
||||
//All embers will have the same number of xforms at this point.
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
size_t ii;
|
||||
intmax_t ii;
|
||||
|
||||
for (xf = 0; xf < maxCount; xf++)//This will include both normal xforms and the final.
|
||||
{
|
||||
auto destXform = destEmbers[i].GetTotalXform(xf, final);
|
||||
bool isFinal = hasFinal && (xf == maxCount - 1);
|
||||
auto destXform = destEmbers[i].GetTotalXform(xf, hasFinal);
|
||||
Variation<T>* dummyvar = nullptr;
|
||||
|
||||
//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)
|
||||
@ -104,9 +125,9 @@ public:
|
||||
//rings2, fan2, blob, perspective, julian, juliascope, ngon, curl, super_shape, split
|
||||
//If so, can use a better starting point for these.
|
||||
//If the current xform index is greater than what the original xform count was for this ember, then it's a padding xform.
|
||||
if (xf >= sourceEmbers[i].TotalXformCount() && !aligned)
|
||||
if (IsPadding(sourceEmbers[i], xf, isFinal) && !aligned)
|
||||
{
|
||||
size_t found = 0;
|
||||
intmax_t found = 0;
|
||||
//Remove linear.
|
||||
destXform->DeleteVariationById(eVariationId::VAR_LINEAR);
|
||||
|
||||
@ -121,32 +142,36 @@ public:
|
||||
continue;
|
||||
|
||||
//Skip if this is also padding.
|
||||
if (xf >= sourceEmbers[i + ii].TotalXformCount())
|
||||
if (IsPadding(sourceEmbers[i + ii], xf, isFinal))
|
||||
continue;
|
||||
|
||||
destOtherXform = destEmbers[i + ii].GetTotalXform(xf);
|
||||
|
||||
//Spherical / Ngon (trumps all others due to holes)
|
||||
//Interpolate these against a 180 degree rotated identity
|
||||
//with weight -1.
|
||||
//Added JULIAN/JULIASCOPE to get rid of black wedges.
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_SPHERICAL) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_NGON) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_JULIAN) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_JULIASCOPE) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_POLAR) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_WEDGE_SPH) ||
|
||||
destOtherXform->GetVariationById(eVariationId::VAR_WEDGE_JULIA))
|
||||
if (destOtherXform = destEmbers[i + ii].GetTotalXform(xf))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_LINEAR, -1));
|
||||
//Set the coefs appropriately.
|
||||
destXform->m_Affine.A(-1);
|
||||
destXform->m_Affine.D(0);
|
||||
destXform->m_Affine.B(0);
|
||||
destXform->m_Affine.E(-1);
|
||||
destXform->m_Affine.C(0);
|
||||
destXform->m_Affine.F(0);
|
||||
found = -1;
|
||||
//Spherical / Ngon (trumps all others due to holes)
|
||||
//Interpolate these against a 180 degree rotated identity
|
||||
//with weight -1.
|
||||
//Added JULIAN/JULIASCOPE to get rid of black wedges.
|
||||
|
||||
//Testing for variation weight > 0 is to make the behavior match flam3 exactly, even though that doesn't really make sense in the modern era
|
||||
//Because variations can use negative weights.
|
||||
if (((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_SPHERICAL) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_NGON) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_JULIAN) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_JULIASCOPE) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_POLAR) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_WEDGE_SPH) ) && dummyvar->m_Weight > 0) ||
|
||||
((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_WEDGE_JULIA)) && dummyvar->m_Weight > 0))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_LINEAR, -1));
|
||||
//Set the coefs appropriately.
|
||||
destXform->m_Affine.A(-1);
|
||||
destXform->m_Affine.D(0);
|
||||
destXform->m_Affine.B(0);
|
||||
destXform->m_Affine.E(-1);
|
||||
destXform->m_Affine.C(0);
|
||||
destXform->m_Affine.F(0);
|
||||
found = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,79 +185,110 @@ public:
|
||||
continue;
|
||||
|
||||
//Skip if this is also padding.
|
||||
if (xf >= sourceEmbers[i + ii].TotalXformCount())
|
||||
if (IsPadding(sourceEmbers[i + ii], xf, isFinal))
|
||||
continue;
|
||||
|
||||
destOtherXform = destEmbers[i + ii].GetTotalXform(xf);
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_RECTANGLES))
|
||||
if (destOtherXform = destEmbers[i + ii].GetTotalXform(xf))
|
||||
{
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_RECTANGLES))
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_RECTANGLES)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
var->SetParamVal("rectangles_x", 0);
|
||||
var->SetParamVal("rectangles_y", 0);
|
||||
destXform->AddVariation(var);
|
||||
destXform->DeleteVariationById(eVariationId::VAR_RECTANGLES);//In case it was there, remove it first so the add below succeeds.
|
||||
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_RECTANGLES))
|
||||
{
|
||||
var->SetParamVal("rectangles_x", 0);
|
||||
var->SetParamVal("rectangles_y", 0);
|
||||
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_RINGS2))
|
||||
{
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_RINGS2))
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_RINGS2)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
var->SetParamVal("rings2_val", 0);
|
||||
destXform->AddVariation(var);
|
||||
destXform->DeleteVariationById(eVariationId::VAR_RINGS2);
|
||||
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_RINGS2))
|
||||
{
|
||||
var->SetParamVal("rings2_val", 0);
|
||||
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_FAN2))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_FAN2));
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_BLOB))
|
||||
{
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_BLOB))
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_FAN2)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
var->SetParamVal("blob_low", 1);
|
||||
destXform->AddVariation(var);
|
||||
destXform->DeleteVariationById(eVariationId::VAR_FAN2);
|
||||
|
||||
if (auto var = variationList->GetVariationCopy(eVariationId::VAR_FAN2))
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_PERSPECTIVE))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_PERSPECTIVE));
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_CURL))
|
||||
{
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_CURL))
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_BLOB)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
var->SetParamVal("curl_c1", 0);
|
||||
destXform->AddVariation(var);
|
||||
destXform->DeleteVariationById(eVariationId::VAR_BLOB);
|
||||
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_BLOB))
|
||||
{
|
||||
var->SetParamVal("blob_low", 1);
|
||||
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_SUPER_SHAPE))
|
||||
{
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_SUPER_SHAPE))
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_PERSPECTIVE)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
var->SetParamVal("super_shape_n1", 2);
|
||||
var->SetParamVal("super_shape_n2", 2);
|
||||
var->SetParamVal("super_shape_n3", 2);
|
||||
destXform->AddVariation(var);
|
||||
destXform->DeleteVariationById(eVariationId::VAR_PERSPECTIVE);
|
||||
|
||||
if (auto var = variationList->GetVariationCopy(eVariationId::VAR_PERSPECTIVE))
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
found++;
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_CURL)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
destXform->DeleteVariationById(eVariationId::VAR_CURL);
|
||||
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_CURL))
|
||||
{
|
||||
var->SetParamVal("curl_c1", 0);
|
||||
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_SUPER_SHAPE)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
destXform->DeleteVariationById(eVariationId::VAR_SUPER_SHAPE);
|
||||
|
||||
if (auto var = variationList->GetParametricVariationCopy(eVariationId::VAR_SUPER_SHAPE))
|
||||
{
|
||||
var->SetParamVal("super_shape_n1", 2);
|
||||
var->SetParamVal("super_shape_n2", 2);
|
||||
var->SetParamVal("super_shape_n3", 2);
|
||||
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -247,25 +303,36 @@ public:
|
||||
continue;
|
||||
|
||||
//Skip if this is also padding.
|
||||
if (xf >= sourceEmbers[i + ii].TotalXformCount())
|
||||
if (IsPadding(sourceEmbers[i + ii], xf, isFinal))
|
||||
continue;
|
||||
|
||||
destOtherXform = destEmbers[i + ii].GetTotalXform(xf);
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_FAN))
|
||||
if (destOtherXform = destEmbers[i + ii].GetTotalXform(xf))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_FAN));
|
||||
found++;
|
||||
}
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_FAN)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
destXform->DeleteVariationById(eVariationId::VAR_FAN);
|
||||
|
||||
if (destOtherXform->GetVariationById(eVariationId::VAR_RINGS))
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_RINGS));
|
||||
found++;
|
||||
if (auto var = variationList->GetVariationCopy(eVariationId::VAR_FAN))
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
|
||||
found++;
|
||||
}
|
||||
|
||||
if ((dummyvar = destOtherXform->GetVariationById(eVariationId::VAR_RINGS)) && dummyvar->m_Weight > 0)
|
||||
{
|
||||
destXform->DeleteVariationById(eVariationId::VAR_RINGS);
|
||||
|
||||
if (auto var = variationList->GetVariationCopy(eVariationId::VAR_RINGS))
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found > 0)
|
||||
if (destXform && (found > 0))
|
||||
{
|
||||
//Set the coefs appropriately.
|
||||
destXform->m_Affine.A(0);
|
||||
@ -278,14 +345,20 @@ public:
|
||||
}
|
||||
|
||||
//If there still are no matches, switch back to linear.
|
||||
if (found == 0)
|
||||
if (destXform)
|
||||
{
|
||||
destXform->AddVariation(variationList->GetVariationCopy(eVariationId::VAR_LINEAR));
|
||||
}
|
||||
else if (found > 0)
|
||||
{
|
||||
//Otherwise, normalize the weights.
|
||||
destXform->NormalizeVariationWeights();
|
||||
if (found == 0)
|
||||
{
|
||||
destXform->DeleteVariationById(eVariationId::VAR_LINEAR);
|
||||
|
||||
if (auto var = variationList->GetVariationCopy(eVariationId::VAR_LINEAR))
|
||||
if (!destXform->AddVariation(var))
|
||||
delete var;
|
||||
}
|
||||
else if (found > 0)
|
||||
{
|
||||
destXform->NormalizeVariationWeights();//Otherwise, normalize the weights.
|
||||
}
|
||||
}
|
||||
}
|
||||
}//Xforms.
|
||||
@ -448,6 +521,8 @@ public:
|
||||
Align(&embers[i1 - 1], &m_Embers[0], 4);//Should really be doing some sort of checking here to ensure the ember vectors have 4 elements.
|
||||
smoothFlag = true;
|
||||
}
|
||||
|
||||
//smoothFlag = true;
|
||||
}
|
||||
|
||||
result.m_Time = time;
|
||||
@ -602,6 +677,8 @@ public:
|
||||
/// <param name="cxTrn">The vec2 vector to store the polar translation values</param>
|
||||
static void ConvertLinearToPolar(const Ember<T>* embers, size_t size, size_t xfi, size_t cflag, vector<v2T>& cxAng, vector<v2T>& cxMag, vector<v2T>& cxTrn)
|
||||
{
|
||||
const auto LOCALEPS = T(1e-10);//Even though EPS is defined elsewhere, need this here for full compatibility with flam3.
|
||||
|
||||
if (size == cxAng.size() &&
|
||||
size == cxMag.size() &&
|
||||
size == cxTrn.size())
|
||||
@ -687,9 +764,9 @@ public:
|
||||
d = cxAng[k][col] - cxAng[k - 1][col];
|
||||
|
||||
//Adjust to avoid the -pi/pi discontinuity.
|
||||
if (d > M_PI + EPS)
|
||||
if (d > M_PI + LOCALEPS)
|
||||
cxAng[k][col] -= M_2PI;
|
||||
else if (d < -(M_PI - EPS))//Forces clockwise rotation at 180.
|
||||
else if (d < -(M_PI - LOCALEPS))//Forces clockwise rotation at 180.
|
||||
cxAng[k][col] += M_2PI;
|
||||
}
|
||||
}
|
||||
@ -709,6 +786,7 @@ public:
|
||||
/// <param name="count">The size of the embers array</param>
|
||||
static void AsymmetricRefAngles(Ember<T>* embers, size_t count)
|
||||
{
|
||||
const auto LOCALEPS = T(1e-10);//Even though EPS is defined elsewhere, need this here for full compatibility with flam3.
|
||||
size_t k, xfi;
|
||||
T cxang[4][2], c1[2], d;
|
||||
|
||||
@ -734,9 +812,9 @@ public:
|
||||
d = cxang[k][col] - cxang[k - 1][col];
|
||||
|
||||
//Adjust to avoid the -pi/pi discontinuity.
|
||||
if (d > T(M_PI + EPS))
|
||||
if (d > T(M_PI + LOCALEPS))
|
||||
cxang[k][col] -= 2 * T(M_PI);
|
||||
else if (d < -T(M_PI - EPS) )
|
||||
else if (d < -T(M_PI - LOCALEPS))
|
||||
cxang[k][col] += 2 * T(M_PI);
|
||||
|
||||
//If this is an asymmetric case, store the NON-symmetric angle
|
||||
|
@ -995,12 +995,13 @@ public:
|
||||
{
|
||||
m_EdgePrealign[si] = embers[si];
|
||||
|
||||
for (i = 0; i < embers[si].TotalXformCount(); i++)
|
||||
for (i = 0; i < m_EdgePrealign[si].TotalXformCount(); i++)
|
||||
{
|
||||
auto xform = embers[si].GetTotalXform(i);
|
||||
auto prealignxform = m_EdgePrealign[si].GetTotalXform(i);
|
||||
|
||||
if (!xform->m_Motion.empty())
|
||||
xform->ApplyMotion(*(m_EdgePrealign[si].GetTotalXform(i)), blend);//Apply motion parameters to result.xform[i] using blend parameter.
|
||||
prealignxform->ApplyMotion(*xform, blend);//Apply motion parameters to result.xform[i] using blend parameter.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -574,7 +574,7 @@ public:
|
||||
|
||||
for (auto var : variations) norm += var->m_Weight;
|
||||
|
||||
for (auto var : variations) var->m_Weight /= norm;
|
||||
for (auto var : variations) var->m_Weight /= Zeps(norm);//Ensure a divide by zero never happens.
|
||||
});
|
||||
}
|
||||
|
||||
@ -708,10 +708,11 @@ public:
|
||||
for (size_t i = 0; i < xform.m_Motion.size(); i++)
|
||||
{
|
||||
//Original only pulls these from the first motion xform which is a bug. Want to pull it from each one.
|
||||
Xform<T>& currentMot = xform.m_Motion[i];
|
||||
T freq = currentMot.m_MotionFreq;
|
||||
eMotion func = currentMot.m_MotionFunc;
|
||||
T offset = currentMot.m_MotionOffset;
|
||||
auto& currentMot = xform.m_Motion[i];
|
||||
auto freq = currentMot.m_MotionFreq;
|
||||
auto func = currentMot.m_MotionFunc;
|
||||
auto offset = currentMot.m_MotionOffset;
|
||||
auto cleanOffset = offset != EMPTYFIELD ? offset : 0;
|
||||
//Clamp these to the appropriate range after all are applied.
|
||||
APPMOT(m_Weight);
|
||||
APPMOT(m_ColorX);
|
||||
@ -730,13 +731,13 @@ public:
|
||||
if (!var)//It wasn't present, so add it and set the weight.
|
||||
{
|
||||
Variation<T>* newVar = motVar->Copy();
|
||||
newVar->m_Weight = motVar->m_Weight * Interpolater<T>::MotionFuncs(func, freq * (blend + offset));
|
||||
newVar->m_Weight = motVar->m_Weight * Interpolater<T>::MotionFuncs(func, freq * (blend + cleanOffset));
|
||||
AddVariation(newVar);
|
||||
var = newVar;//Use this below for params.
|
||||
}
|
||||
else//It was present, so apply the motion func to the weight.
|
||||
{
|
||||
var->m_Weight += motVar->m_Weight * Interpolater<T>::MotionFuncs(func, freq * (blend + offset));
|
||||
var->m_Weight += motVar->m_Weight * Interpolater<T>::MotionFuncs(func, freq * (blend + cleanOffset));
|
||||
}
|
||||
|
||||
//At this point, we've added if needed, or just applied the motion func to the weight.
|
||||
@ -750,7 +751,7 @@ public:
|
||||
for (size_t k = 0; k < motParVar->ParamCount(); k++)
|
||||
{
|
||||
if (!motParams[k].IsPrecalc())
|
||||
*(params[k].Param()) += motParams[k].ParamVal() * Interpolater<T>::MotionFuncs(func, freq * (blend + offset));
|
||||
*(params[k].Param()) += motParams[k].ParamVal() * Interpolater<T>::MotionFuncs(func, freq * (blend + cleanOffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -547,7 +547,7 @@ bool XmlToEmber<T>::ParseEmberElement(xmlNode* emberNode, Ember<T>& currentEmber
|
||||
//First parse out simple float reads.
|
||||
if (ParseAndAssign(curAtt->name, attStr, "time", currentEmber.m_Time, ret)) {}
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "scale", currentEmber.m_PixelsPerUnit, ret)) { currentEmber.m_OrigPixPerUnit = currentEmber.m_PixelsPerUnit; }
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "rotate", currentEmber.m_Rotate, ret)) {}
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "rotate", currentEmber.m_Rotate, ret)) { currentEmber.m_Rotate = NormalizeDeg180<T>(currentEmber.m_Rotate); }
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "zoom", currentEmber.m_Zoom, ret)) { ClampGteRef<T>(currentEmber.m_Zoom, 0); }
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "cam_zoom", currentEmber.m_Zoom, ret)) { ClampGteRef<T>(currentEmber.m_Zoom, 0); }//JWildfire uses cam_zoom.
|
||||
else if (ParseAndAssign(curAtt->name, attStr, "filter", currentEmber.m_SpatialFilterRadius, ret)) {}
|
||||
@ -884,6 +884,7 @@ bool XmlToEmber<T>::ParseEmberElement(xmlNode* emberNode, Ember<T>& currentEmber
|
||||
if (!Compare(childNode->name, "finalxform"))
|
||||
{
|
||||
Xform<T> finalXform;
|
||||
finalXform.m_Animate = 0;//Do not animate final by default.
|
||||
|
||||
if (!ParseXform(childNode, finalXform, false, fromEmber))
|
||||
{
|
||||
|
@ -57,6 +57,7 @@ class EMBERCL_API RendererCL : public Renderer<T, bucketT>, public RendererCLBas
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::FuseCount;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::DensityFilterOffset;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::PrepFinalAccumVector;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::Paused;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::m_ProgressParameter;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::m_YAxisUp;
|
||||
using EmberNs::Renderer<T, bucketT>::RendererBase::m_LockAccum;
|
||||
|
@ -58,7 +58,7 @@
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.9</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a><span style=" font-size:10pt;"><br/>Lead: Matt Feemster<br/>Contributors: Simon Detheridge, Michel Mastriani</span></p></body></html></string>
|
||||
<string><html><head/><body><p align="center">Fractorium 1.0.0.10</p><p align="center"><span style=" font-size:10pt;">A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><a href="http://fractorium.com"><span style=" text-decoration: underline; color:#0000ff;">fractorium.com</span></a><span style=" font-size:10pt;"><br/>Lead: Matt Feemster<br/>Contributors: Simon Detheridge, Michel Mastriani</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
|
@ -101,7 +101,6 @@ public:
|
||||
|
||||
//Geometry.
|
||||
bool ApplyAll();
|
||||
void SetCenter(float x, float y);
|
||||
void SetRotation(double rot, bool stealth);
|
||||
void SetScale(double scale);
|
||||
void SetCoordinateStatus(int rasX, int rasY, float worldX, float worldY);
|
||||
@ -197,6 +196,8 @@ public slots:
|
||||
void OnSequenceRandomRotationsMaxSpinBoxChanged(double d);
|
||||
void OnSequenceBlendFramesSpinBoxChanged(int d);
|
||||
void OnSequenceRandomBlendMaxFramesSpinBoxChanged(int d);
|
||||
void OnSequenceRandomRotationsPerBlendSpinBoxChanged(int d);
|
||||
void OnSequenceRandomRotationsPerBlendMaxSpinBoxChanged(int d);
|
||||
|
||||
//Params.
|
||||
void OnBrightnessChanged(double d);//Color.
|
||||
|
@ -217,16 +217,18 @@ void FractoriumEmberController<T>::UpdateAll(std::function<void(Ember<T>& ember,
|
||||
/// 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="func">The function to call which will pass the xform under consideration, the absolute xform index, and the index within the selected xforms</param>
|
||||
/// <param name="updateType">Whether to apply this update operation on the current, all or selected xforms. Default: eXformUpdate::UPDATE_CURRENT.</param>
|
||||
/// <param name="updateRender">True to update renderer, else false. Default: true.</param>
|
||||
/// <param name="action">The action to add to the rendering queue. Default: eProcessAction::FULL_RENDER.</param>
|
||||
/// <param name="index">The xform index to use when action is eXformUpdate::UPDATE_SPECIFIC. Default: 0.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> func, eXformUpdate updateType, bool updateRender, eProcessAction action, size_t index)
|
||||
void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*, size_t, size_t)> func, eXformUpdate updateType, bool updateRender, eProcessAction action, size_t index)
|
||||
{
|
||||
int i = 0;
|
||||
size_t selIndex = 0;
|
||||
auto current = CurrentXform();
|
||||
auto currentIndex = m_Fractorium->ui.CurrentXformCombo->currentIndex();
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
bool isCurrentFinal = m_Ember.IsFinalXform(current);
|
||||
bool doFinal = updateType != eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL && updateType != eXformUpdate::UPDATE_ALL_EXCEPT_FINAL;
|
||||
@ -236,14 +238,14 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
case eXformUpdate::UPDATE_SPECIFIC:
|
||||
{
|
||||
if (auto xform = m_Ember.GetTotalXform(index, forceFinal))
|
||||
func(xform);
|
||||
func(xform, index, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_CURRENT:
|
||||
{
|
||||
if (current)
|
||||
func(current);
|
||||
func(current, currentIndex, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -253,25 +255,19 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
|
||||
while (auto xform = m_Ember.GetTotalXform(i, forceFinal))
|
||||
{
|
||||
if (i < m_Fractorium->m_XformSelections.size())
|
||||
if (m_Fractorium->IsXformSelected(i))
|
||||
{
|
||||
if (auto w = m_Fractorium->m_XformSelections[i])
|
||||
{
|
||||
if (w->isChecked())
|
||||
{
|
||||
func(xform);
|
||||
func(xform, i, selIndex++);
|
||||
|
||||
if (xform == current)
|
||||
currentDone = true;
|
||||
}
|
||||
}
|
||||
if (xform == current)
|
||||
currentDone = true;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (!currentDone)//Current was not among those selected, so apply to it.
|
||||
func(current);
|
||||
func(current, currentIndex, selIndex);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -282,16 +278,10 @@ void FractoriumEmberController<T>::UpdateXform(std::function<void(Xform<T>*)> fu
|
||||
|
||||
while (auto xform = (doFinal ? m_Ember.GetTotalXform(i, forceFinal) : m_Ember.GetXform(i)))
|
||||
{
|
||||
if (i < m_Fractorium->m_XformSelections.size())
|
||||
if (m_Fractorium->IsXformSelected(i))
|
||||
{
|
||||
if (auto w = m_Fractorium->m_XformSelections[i])
|
||||
{
|
||||
if (w->isChecked())
|
||||
{
|
||||
func(xform);
|
||||
anyUpdated = true;
|
||||
}
|
||||
}
|
||||
func(xform, i, selIndex++);
|
||||
anyUpdated = true;
|
||||
}
|
||||
|
||||
i++;
|
||||
@ -300,22 +290,22 @@ 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 (current)
|
||||
func(current);
|
||||
func(current, currentIndex, selIndex);
|
||||
}
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_ALL:
|
||||
{
|
||||
while (auto xform = m_Ember.GetTotalXform(i++, forceFinal))
|
||||
func(xform);
|
||||
while (auto xform = m_Ember.GetTotalXform(i, forceFinal))
|
||||
func(xform, i++, selIndex++);
|
||||
}
|
||||
break;
|
||||
|
||||
case eXformUpdate::UPDATE_ALL_EXCEPT_FINAL:
|
||||
default:
|
||||
{
|
||||
while (auto xform = m_Ember.GetXform(i++))
|
||||
func(xform);
|
||||
while (auto xform = m_Ember.GetXform(i))
|
||||
func(xform, i++, selIndex++);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -450,7 +450,7 @@ public:
|
||||
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, size_t index = 0);
|
||||
void UpdateXform(std::function<void(Xform<T>*, size_t, size_t)> func, eXformUpdate updateType = eXformUpdate::UPDATE_CURRENT, bool updateRender = true, eProcessAction action = eProcessAction::FULL_RENDER, size_t index = 0);
|
||||
|
||||
//Xforms Affine.
|
||||
virtual void AffineSetHelper(double d, int index, bool pre) override;
|
||||
|
@ -7,14 +7,6 @@
|
||||
void Fractorium::InitLibraryUI()
|
||||
{
|
||||
ui.LibraryTree->SetMainWindow(this);
|
||||
ui.SequenceStaggerSpinBox->setValue(m_Settings->Stagger());
|
||||
ui.SequenceRandomStaggerMaxSpinBox->setValue(m_Settings->StaggerMax());
|
||||
ui.SequenceFramesPerRotSpinBox->setValue(m_Settings->FramesPerRot());
|
||||
ui.SequenceRandomFramesPerRotMaxSpinBox->setValue(m_Settings->FramesPerRotMax());
|
||||
ui.SequenceRotationsSpinBox->setValue(m_Settings->Rotations());
|
||||
ui.SequenceRandomRotationsMaxSpinBox->setValue(m_Settings->RotationsMax());
|
||||
ui.SequenceBlendFramesSpinBox->setValue(m_Settings->BlendFrames());
|
||||
ui.SequenceRandomBlendMaxFramesSpinBox->setValue(m_Settings->BlendFramesMax());
|
||||
connect(ui.LibraryTree, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemChanged(QTreeWidgetItem*, int)), Qt::QueuedConnection);
|
||||
connect(ui.LibraryTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection);
|
||||
connect(ui.LibraryTree, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(OnEmberTreeItemDoubleClicked(QTreeWidgetItem*, int)), Qt::QueuedConnection);
|
||||
@ -41,6 +33,33 @@ void Fractorium::InitLibraryUI()
|
||||
connect(ui.SequenceRandomRotationsMaxSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnSequenceRandomRotationsMaxSpinBoxChanged(double)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceBlendFramesSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSequenceBlendFramesSpinBoxChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRandomBlendMaxFramesSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSequenceRandomBlendMaxFramesSpinBoxChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRotationsPerBlendSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSequenceRandomRotationsPerBlendSpinBoxChanged(int)), Qt::QueuedConnection);
|
||||
connect(ui.SequenceRotationsPerBlendMaxSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnSequenceRandomRotationsPerBlendMaxSpinBoxChanged(int)), Qt::QueuedConnection);
|
||||
//Stagger
|
||||
ui.SequenceStaggerSpinBox->setValue(m_Settings->Stagger());//Lower.
|
||||
ui.SequenceStaggerSpinBox->setMaximum(std::numeric_limits<int>::max());//Lower max = upper.
|
||||
ui.SequenceRandomStaggerMaxSpinBox->setValue(m_Settings->StaggerMax());//Upper.
|
||||
ui.SequenceRandomStaggerMaxSpinBox->setMinimum(m_Settings->Stagger());//Upper min = lower max.
|
||||
//Frames per rotation.
|
||||
ui.SequenceFramesPerRotSpinBox->setValue(m_Settings->FramesPerRot());//Lower.
|
||||
ui.SequenceFramesPerRotSpinBox->setMaximum(std::numeric_limits<int>::max());//Lower max = upper.
|
||||
ui.SequenceRandomFramesPerRotMaxSpinBox->setValue(m_Settings->FramesPerRotMax());//Upper.
|
||||
ui.SequenceRandomFramesPerRotMaxSpinBox->setMinimum(m_Settings->FramesPerRot());//Upper min = lower max.
|
||||
//Rotations.
|
||||
ui.SequenceRotationsSpinBox->setValue(m_Settings->Rotations());//Lower.
|
||||
ui.SequenceRotationsSpinBox->setMaximum(std::numeric_limits<int>::max());//Lower max = upper.
|
||||
ui.SequenceRandomRotationsMaxSpinBox->setValue(m_Settings->RotationsMax());//Upper.
|
||||
ui.SequenceRandomRotationsMaxSpinBox->setMinimum(m_Settings->Rotations());//Upper min = lower max.
|
||||
//Blend frames.
|
||||
ui.SequenceBlendFramesSpinBox->setValue(m_Settings->BlendFrames());//Lower.
|
||||
ui.SequenceBlendFramesSpinBox->setMaximum(std::numeric_limits<int>::max());//Lower max = upper.
|
||||
ui.SequenceRandomBlendMaxFramesSpinBox->setValue(m_Settings->BlendFramesMax());//Upper.
|
||||
ui.SequenceRandomBlendMaxFramesSpinBox->setMinimum(m_Settings->BlendFrames());//Upper min = lower max.
|
||||
//Rotations per blend.
|
||||
ui.SequenceRotationsPerBlendSpinBox->setValue(m_Settings->RotationsPerBlend());//Lower.
|
||||
ui.SequenceRotationsPerBlendSpinBox->setMaximum(std::numeric_limits<int>::max());//Lower max = upper.
|
||||
ui.SequenceRotationsPerBlendMaxSpinBox->setValue(m_Settings->RotationsPerBlendMax());//Upper.
|
||||
ui.SequenceRotationsPerBlendMaxSpinBox->setMinimum(m_Settings->RotationsPerBlend());//Upper min = lower max.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -627,7 +646,8 @@ void FractoriumEmberController<T>::SequenceGenerateButtonClicked()
|
||||
if (framesPerRot > 1 && !rots)//Because framesPerRot control has a min value of 1, check greater than 1. Also don't need to check the inverse like in EmberGenome.
|
||||
{
|
||||
QMessageBox::critical(m_Fractorium, "Animation sequence parameters error",
|
||||
"Frames per rot cannot be positive while Rotations is zero");
|
||||
"Frames per rot cannot be greater than one while Rotations is zero. Setting it to 1.");
|
||||
ui.SequenceFramesPerRotSpinBox->setValue(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -713,6 +733,8 @@ void FractoriumEmberController<T>::SequenceGenerateButtonClicked()
|
||||
|
||||
for (frame = 0; frame < blendFrames; frame++)
|
||||
{
|
||||
//if (frame == 43)
|
||||
// cout << frame << endl;
|
||||
bool seqFlag = frame == 0 || (frame == blendFrames - 1);
|
||||
blend = frame / double(blendFrames);
|
||||
result.Clear();
|
||||
@ -830,25 +852,59 @@ void FractoriumEmberController<T>::SequenceOpenButtonClicked()
|
||||
|
||||
void Fractorium::OnSequenceOpenButtonClicked(bool checked) { m_Controller->SequenceOpenButtonClicked(); }
|
||||
|
||||
void Fractorium::OnSequenceRandomizeStaggerCheckBoxStateChanged(int state) { ui.SequenceRandomStaggerMaxSpinBox->setEnabled(state); }
|
||||
void Fractorium::OnSequenceRandomizeFramesPerRotCheckBoxStateChanged(int state) { ui.SequenceRandomFramesPerRotMaxSpinBox->setEnabled(state); }
|
||||
void Fractorium::OnSequenceRandomizeRotationsCheckBoxStateChanged(int state) { ui.SequenceRandomRotationsMaxSpinBox->setEnabled(state); }
|
||||
void Fractorium::OnSequenceRandomizeBlendFramesCheckBoxStateChanged(int state) { ui.SequenceRandomBlendMaxFramesSpinBox->setEnabled(state); }
|
||||
void Fractorium::OnSequenceRandomizeRotationsPerBlendCheckBoxStateChanged(int state) { ui.SequenceRotationsPerBlendMaxSpinBox->setEnabled(state); }
|
||||
/// <summary>
|
||||
/// Constrain all min/max spinboxes when the max spinboxes are enabled/disabled via the random checkbox.
|
||||
/// </summary>
|
||||
void Fractorium::OnSequenceRandomizeStaggerCheckBoxStateChanged(int state)
|
||||
{
|
||||
ui.SequenceRandomStaggerMaxSpinBox->setMinimum(ui.SequenceStaggerSpinBox->value());
|
||||
ui.SequenceStaggerSpinBox->setMaximum(state ? ui.SequenceRandomStaggerMaxSpinBox->value() : std::numeric_limits<int>::max());
|
||||
ui.SequenceRandomStaggerMaxSpinBox->setEnabled(state);
|
||||
}
|
||||
|
||||
void Fractorium::OnSequenceRandomizeFramesPerRotCheckBoxStateChanged(int state)
|
||||
{
|
||||
ui.SequenceRandomFramesPerRotMaxSpinBox->setMinimum(ui.SequenceFramesPerRotSpinBox->value());
|
||||
ui.SequenceFramesPerRotSpinBox->setMaximum(state ? ui.SequenceRandomFramesPerRotMaxSpinBox->value() : std::numeric_limits<int>::max());
|
||||
ui.SequenceRandomFramesPerRotMaxSpinBox->setEnabled(state);
|
||||
}
|
||||
|
||||
void Fractorium::OnSequenceRandomizeRotationsCheckBoxStateChanged(int state)
|
||||
{
|
||||
ui.SequenceRandomRotationsMaxSpinBox->setMinimum(ui.SequenceRotationsSpinBox->value());
|
||||
ui.SequenceRotationsSpinBox->setMaximum(state ? ui.SequenceRandomRotationsMaxSpinBox->value() : std::numeric_limits<int>::max());
|
||||
ui.SequenceRandomRotationsMaxSpinBox->setEnabled(state);
|
||||
}
|
||||
|
||||
void Fractorium::OnSequenceRandomizeBlendFramesCheckBoxStateChanged(int state)
|
||||
{
|
||||
ui.SequenceRandomBlendMaxFramesSpinBox->setMinimum(ui.SequenceBlendFramesSpinBox->value());
|
||||
ui.SequenceBlendFramesSpinBox->setMaximum(state ? ui.SequenceRandomBlendMaxFramesSpinBox->value() : std::numeric_limits<int>::max());
|
||||
ui.SequenceRandomBlendMaxFramesSpinBox->setEnabled(state);
|
||||
}
|
||||
|
||||
void Fractorium::OnSequenceRandomizeRotationsPerBlendCheckBoxStateChanged(int state)
|
||||
{
|
||||
ui.SequenceRotationsPerBlendMaxSpinBox->setMinimum(ui.SequenceRotationsPerBlendSpinBox->value());
|
||||
ui.SequenceRotationsPerBlendSpinBox->setMaximum(state ? ui.SequenceRotationsPerBlendMaxSpinBox->value() : std::numeric_limits<int>::max());
|
||||
ui.SequenceRotationsPerBlendMaxSpinBox->setEnabled(state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constrain all min/max spinboxes.
|
||||
/// </summary>
|
||||
void Fractorium::OnSequenceStaggerSpinBoxChanged(double d) { if (ui.SequenceRandomizeStaggerCheckBox->isChecked()) ConstrainLow(ui.SequenceStaggerSpinBox, ui.SequenceRandomStaggerMaxSpinBox); }
|
||||
void Fractorium::OnSequenceRandomStaggerMaxSpinBoxChanged(double d) { ConstrainHigh(ui.SequenceStaggerSpinBox, ui.SequenceRandomStaggerMaxSpinBox); }
|
||||
void Fractorium::OnSequenceStartFlameSpinBoxChanged(int d) { ConstrainLow(ui.SequenceStartFlameSpinBox, ui.SequenceStopFlameSpinBox); }
|
||||
void Fractorium::OnSequenceStopFlameSpinBoxChanged(int d) { ConstrainHigh(ui.SequenceStartFlameSpinBox, ui.SequenceStopFlameSpinBox); }
|
||||
void Fractorium::OnSequenceFramesPerRotSpinBoxChanged(int d) { if (ui.SequenceRandomizeFramesPerRotCheckBox->isChecked()) ConstrainLow(ui.SequenceFramesPerRotSpinBox, ui.SequenceRandomFramesPerRotMaxSpinBox); }
|
||||
void Fractorium::OnSequenceRandomFramesPerRotMaxSpinBoxChanged(int d) { ConstrainHigh(ui.SequenceFramesPerRotSpinBox, ui.SequenceRandomFramesPerRotMaxSpinBox); }
|
||||
void Fractorium::OnSequenceRotationsSpinBoxChanged(double d) { if (ui.SequenceRandomizeRotationsCheckBox->isChecked()) ConstrainLow(ui.SequenceRotationsSpinBox, ui.SequenceRandomRotationsMaxSpinBox); }
|
||||
void Fractorium::OnSequenceRandomRotationsMaxSpinBoxChanged(double d) { ConstrainHigh(ui.SequenceRotationsSpinBox, ui.SequenceRandomRotationsMaxSpinBox); }
|
||||
void Fractorium::OnSequenceBlendFramesSpinBoxChanged(int d) { if (ui.SequenceRandomizeBlendFramesCheckBox->isChecked()) ConstrainLow(ui.SequenceBlendFramesSpinBox, ui.SequenceRandomBlendMaxFramesSpinBox); }
|
||||
void Fractorium::OnSequenceRandomBlendMaxFramesSpinBoxChanged(int d) { ConstrainHigh(ui.SequenceBlendFramesSpinBox, ui.SequenceRandomBlendMaxFramesSpinBox); }
|
||||
void Fractorium::OnSequenceStaggerSpinBoxChanged(double d) { if (ui.SequenceRandomizeStaggerCheckBox->isChecked()) ui.SequenceRandomStaggerMaxSpinBox->setMinimum(d); }
|
||||
void Fractorium::OnSequenceRandomStaggerMaxSpinBoxChanged(double d) { if (ui.SequenceRandomStaggerMaxSpinBox->hasFocus()) ui.SequenceStaggerSpinBox->setMaximum(d); }
|
||||
void Fractorium::OnSequenceStartFlameSpinBoxChanged(int d) { ui.SequenceStopFlameSpinBox->setMinimum(d); }
|
||||
void Fractorium::OnSequenceStopFlameSpinBoxChanged(int d) { if (ui.SequenceStopFlameSpinBox->hasFocus()) ui.SequenceStartFlameSpinBox->setMaximum(d); }
|
||||
void Fractorium::OnSequenceFramesPerRotSpinBoxChanged(int d) { if (ui.SequenceRandomizeFramesPerRotCheckBox->isChecked()) ui.SequenceRandomFramesPerRotMaxSpinBox->setMinimum(d); }
|
||||
void Fractorium::OnSequenceRandomFramesPerRotMaxSpinBoxChanged(int d) { if (ui.SequenceRandomFramesPerRotMaxSpinBox->hasFocus()) ui.SequenceFramesPerRotSpinBox->setMaximum(d); }
|
||||
void Fractorium::OnSequenceRotationsSpinBoxChanged(double d) { if (ui.SequenceRandomizeRotationsCheckBox->isChecked()) ui.SequenceRandomRotationsMaxSpinBox->setMinimum(d); }
|
||||
void Fractorium::OnSequenceRandomRotationsMaxSpinBoxChanged(double d) { if (ui.SequenceRandomRotationsMaxSpinBox->hasFocus()) ui.SequenceRotationsSpinBox->setMaximum(d); }
|
||||
void Fractorium::OnSequenceBlendFramesSpinBoxChanged(int d) { if (ui.SequenceRandomizeBlendFramesCheckBox->isChecked()) ui.SequenceRandomBlendMaxFramesSpinBox->setMinimum(d); }
|
||||
void Fractorium::OnSequenceRandomBlendMaxFramesSpinBoxChanged(int d) { if (ui.SequenceRandomBlendMaxFramesSpinBox->hasFocus()) ui.SequenceBlendFramesSpinBox->setMaximum(d); }
|
||||
void Fractorium::OnSequenceRandomRotationsPerBlendSpinBoxChanged(int d) { if (ui.SequenceRandomizeRotationsPerBlendCheckBox->isChecked()) ui.SequenceRotationsPerBlendMaxSpinBox->setMinimum(d); }
|
||||
void Fractorium::OnSequenceRandomRotationsPerBlendMaxSpinBoxChanged(int d) { if (ui.SequenceRotationsPerBlendMaxSpinBox->hasFocus()) ui.SequenceRotationsPerBlendSpinBox->setMaximum(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Save all sequence settings to match the values in the controls.
|
||||
@ -863,6 +919,8 @@ void Fractorium::SyncSequenceSettings()
|
||||
m_Settings->RotationsMax(ui.SequenceRandomRotationsMaxSpinBox->value());
|
||||
m_Settings->BlendFrames(ui.SequenceBlendFramesSpinBox->value());
|
||||
m_Settings->BlendFramesMax(ui.SequenceRandomBlendMaxFramesSpinBox->value());
|
||||
m_Settings->RotationsPerBlend(ui.SequenceRotationsPerBlendSpinBox->value());
|
||||
m_Settings->RotationsPerBlendMax(ui.SequenceRotationsPerBlendMaxSpinBox->value());
|
||||
}
|
||||
|
||||
template class FractoriumEmberController<float>;
|
||||
|
@ -673,7 +673,7 @@ void FractoriumEmberController<T>::CopySelectedXforms()
|
||||
{
|
||||
m_CopiedXforms.clear();
|
||||
m_CopiedFinalXform.Clear();
|
||||
UpdateXform([&](Xform<T>* xform)
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
if (m_Ember.IsFinalXform(xform))
|
||||
m_CopiedFinalXform = *xform;
|
||||
|
@ -44,18 +44,18 @@ void Fractorium::InitParamsUI()
|
||||
//Geometry.
|
||||
row = 0;
|
||||
table = ui.GeometryTable;
|
||||
SetupSpinner<SpinBox, int> (table, this, row, 1, m_WidthSpin, spinHeight, 10, 2048, 50, SIGNAL(valueChanged(int)), SLOT(OnWidthChanged(int)), true, width(), width(), width());
|
||||
SetupSpinner<SpinBox, int> (table, this, row, 1, m_HeightSpin, spinHeight, 10, 2048, 50, SIGNAL(valueChanged(int)), SLOT(OnHeightChanged(int)), true, height(), height(), height());
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterXSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterXChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterYSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterYChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ScaleSpin, spinHeight, 10, dmax, 20, SIGNAL(valueChanged(double)), SLOT(OnScaleChanged(double)), true, 240, 240, 240);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZoomSpin, spinHeight, 0, 25, 0.2, SIGNAL(valueChanged(double)), SLOT(OnZoomChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<SpinBox, int> (table, this, row, 1, m_WidthSpin, spinHeight, 10, 2048, 50, SIGNAL(valueChanged(int)), SLOT(OnWidthChanged(int)), true, width(), width(), width());
|
||||
SetupSpinner<SpinBox, int> (table, this, row, 1, m_HeightSpin, spinHeight, 10, 2048, 50, SIGNAL(valueChanged(int)), SLOT(OnHeightChanged(int)), true, height(), height(), height());
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterXSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterXChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterYSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterYChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ScaleSpin, spinHeight, 10, dmax, 20, SIGNAL(valueChanged(double)), SLOT(OnScaleChanged(double)), true, 240, 240, 240);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZoomSpin, spinHeight, 0, 25, 0.2, SIGNAL(valueChanged(double)), SLOT(OnZoomChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_RotateSpin, spinHeight, -180, 180, 10, SIGNAL(valueChanged(double)), SLOT(OnRotateChanged(double)), true, 0, 0, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZPosSpin, spinHeight, -1000, 1000, 1, SIGNAL(valueChanged(double)), SLOT(OnZPosChanged(double)), true, 0, 1, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_PerspectiveSpin, spinHeight, -500, 500, 0.01, SIGNAL(valueChanged(double)), SLOT(OnPerspectiveChanged(double)), true, 0, 1, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_PitchSpin, spinHeight, -180, 180, 1, SIGNAL(valueChanged(double)), SLOT(OnPitchChanged(double)), true, 0, 45, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_YawSpin, spinHeight, -180, 180, 1, SIGNAL(valueChanged(double)), SLOT(OnYawChanged(double)), true, 0, 45, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DepthBlurSpin, spinHeight, -100, 100, 0.01, SIGNAL(valueChanged(double)), SLOT(OnDepthBlurChanged(double)), true, 0, 1, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZPosSpin, spinHeight, -1000, 1000, 1, SIGNAL(valueChanged(double)), SLOT(OnZPosChanged(double)), true, 0, 1, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_PerspectiveSpin, spinHeight, -500, 500, 0.01, SIGNAL(valueChanged(double)), SLOT(OnPerspectiveChanged(double)), true, 0, 1, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_PitchSpin, spinHeight, -dmax, dmax, 1, SIGNAL(valueChanged(double)), SLOT(OnPitchChanged(double)), true, 0, 45, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_YawSpin, spinHeight, -dmax, dmax, 1, SIGNAL(valueChanged(double)), SLOT(OnYawChanged(double)), true, 0, 45, 0);
|
||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_DepthBlurSpin, spinHeight, -dmax, dmax, 0.01, SIGNAL(valueChanged(double)), SLOT(OnDepthBlurChanged(double)), true, 0, 1, 0);
|
||||
//Set w/h max values.
|
||||
m_CenterXSpin->setDecimals(3);
|
||||
m_CenterYSpin->setDecimals(3);
|
||||
@ -437,38 +437,6 @@ template <typename T> void FractoriumEmberController<T>::SpatialFilterTypeChange
|
||||
|
||||
void Fractorium::OnSpatialFilterTypeComboCurrentIndexChanged(const QString& text) { m_Controller->SpatialFilterTypeChanged(text); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the temporal filter width to be used with animation.
|
||||
/// Called when the temporal filter width spinner is changed.
|
||||
/// Does not reset anything because this is only used for animation.
|
||||
/// In the future, when animation is implemented, this will have an effect.
|
||||
/// </summary>
|
||||
/// <param name="d">The temporal filter width</param>
|
||||
template <typename T> void FractoriumEmberController<T>::TemporalFilterWidthChanged(double d)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
ember.m_TemporalFilterWidth = d;
|
||||
}, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
|
||||
}
|
||||
void Fractorium::OnTemporalFilterWidthChanged(double d) { m_Controller->TemporalFilterWidthChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the temporal filter type to be used with animation.
|
||||
/// Called when the temporal filter combo box index is changed.
|
||||
/// Does not reset anything because this is only used for animation.
|
||||
/// In the future, when animation is implemented, this will have an effect.
|
||||
/// </summary>
|
||||
/// <param name="text">The name of the temporal filter</param>
|
||||
template <typename T> void FractoriumEmberController<T>::TemporalFilterTypeChanged(const QString& text)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
ember.m_TemporalFilterType = TemporalFilterCreator<T>::FromString(text.toStdString());
|
||||
}, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
|
||||
}
|
||||
void Fractorium::OnTemporalFilterTypeComboCurrentIndexChanged(const QString& text) { m_Controller->TemporalFilterTypeChanged(text); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the density estimation filter min radius value.
|
||||
/// Resets the rendering process to density filtering.
|
||||
@ -597,22 +565,6 @@ template <typename T> void FractoriumEmberController<T>::SupersampleChanged(int
|
||||
}
|
||||
void Fractorium::OnSupersampleChanged(int d) { m_Controller->SupersampleChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the temporal samples to be used with animation.
|
||||
/// Called when the temporal samples spinner is changed.
|
||||
/// Does not reset anything because this is only used for animation.
|
||||
/// In the future, when animation is implemented, this will have an effect.
|
||||
/// </summary>
|
||||
/// <param name="d">The temporal samples value</param>
|
||||
template <typename T> void FractoriumEmberController<T>::TemporalSamplesChanged(int i)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
ember.m_TemporalSamples = i;
|
||||
}, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
|
||||
}
|
||||
void Fractorium::OnTemporalSamplesChanged(int d) { m_Controller->TemporalSamplesChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the affine interpolation type.
|
||||
/// Does not reset anything because this is only used for animation.
|
||||
@ -625,13 +577,21 @@ void FractoriumEmberController<T>::AffineInterpTypeChanged(int i)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
eAffineInterp interp;
|
||||
|
||||
if (i == 0)
|
||||
ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
|
||||
interp = eAffineInterp::AFFINE_INTERP_LINEAR;
|
||||
else if (i == 1)
|
||||
ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LOG;
|
||||
interp = eAffineInterp::AFFINE_INTERP_LOG;
|
||||
else
|
||||
ember.m_AffineInterp = eAffineInterp::AFFINE_INTERP_LINEAR;
|
||||
}, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
|
||||
interp = eAffineInterp::AFFINE_INTERP_LINEAR;
|
||||
|
||||
ember.m_AffineInterp = interp;
|
||||
|
||||
if (!m_Fractorium->ApplyAll())
|
||||
if (m_EmberFilePointer)
|
||||
m_EmberFilePointer->m_AffineInterp = interp;
|
||||
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
|
||||
}
|
||||
|
||||
void Fractorium::OnAffineInterpTypeComboCurrentIndexChanged(int index) { m_Controller->AffineInterpTypeChanged(index); }
|
||||
@ -639,7 +599,6 @@ void Fractorium::OnAffineInterpTypeComboCurrentIndexChanged(int index) { m_Contr
|
||||
/// <summary>
|
||||
/// Set the interpolation type.
|
||||
/// Does not reset anything because this is only used for animation.
|
||||
/// In the future, when animation is implemented, this will have an effect.
|
||||
/// Called when the interp type combo box index is changed.
|
||||
/// </summary>
|
||||
/// <param name="i">The index</param>
|
||||
@ -648,17 +607,86 @@ void FractoriumEmberController<T>::InterpTypeChanged(int i)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
if (i == 0)
|
||||
ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
|
||||
eInterp interp;
|
||||
|
||||
if (i == 0)//Need to make this work like animate flag where it sets the value but doesn't trigger and update.//TODO
|
||||
interp = eInterp::EMBER_INTERP_LINEAR;
|
||||
else if (i == 1)
|
||||
ember.m_Interp = eInterp::EMBER_INTERP_SMOOTH;
|
||||
interp = eInterp::EMBER_INTERP_SMOOTH;
|
||||
else
|
||||
ember.m_Interp = eInterp::EMBER_INTERP_LINEAR;
|
||||
}, true, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
|
||||
interp = eInterp::EMBER_INTERP_LINEAR;
|
||||
|
||||
ember.m_Interp = interp;
|
||||
|
||||
if (!m_Fractorium->ApplyAll())
|
||||
if (m_EmberFilePointer)
|
||||
m_EmberFilePointer->m_Interp = interp;
|
||||
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
|
||||
}
|
||||
|
||||
void Fractorium::OnInterpTypeComboCurrentIndexChanged(int index) { m_Controller->InterpTypeChanged(index); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the temporal samples to be used with animation.
|
||||
/// Called when the temporal samples spinner is changed.
|
||||
/// Does not reset anything because this is only used for animation.
|
||||
/// </summary>
|
||||
/// <param name="d">The temporal samples value</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::TemporalSamplesChanged(int i)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
ember.m_TemporalSamples = i;//This will be reset on every render to trick the renderer into not thinking it's doing an animation. So setting this has no real effect. Users should set it in the final render dialog when animating.
|
||||
|
||||
if (!m_Fractorium->ApplyAll())
|
||||
if (m_EmberFilePointer)
|
||||
m_EmberFilePointer->m_TemporalSamples = i;
|
||||
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
|
||||
}
|
||||
void Fractorium::OnTemporalSamplesChanged(int d) { m_Controller->TemporalSamplesChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the temporal filter width to be used with animation.
|
||||
/// Called when the temporal filter width spinner is changed.
|
||||
/// Does not reset anything because this is only used for animation.
|
||||
/// </summary>
|
||||
/// <param name="d">The temporal filter width</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::TemporalFilterWidthChanged(double d)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
ember.m_TemporalFilterWidth = d;
|
||||
|
||||
if (!m_Fractorium->ApplyAll())
|
||||
if (m_EmberFilePointer)
|
||||
m_EmberFilePointer->m_TemporalFilterWidth = d;
|
||||
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
|
||||
}
|
||||
void Fractorium::OnTemporalFilterWidthChanged(double d) { m_Controller->TemporalFilterWidthChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the temporal filter type to be used with animation.
|
||||
/// Called when the temporal filter combo box index is changed.
|
||||
/// Does not reset anything because this is only used for animation.
|
||||
/// </summary>
|
||||
/// <param name="text">The name of the temporal filter</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::TemporalFilterTypeChanged(const QString& text)
|
||||
{
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
auto filter = TemporalFilterCreator<T>::FromString(text.toStdString());
|
||||
ember.m_TemporalFilterType = filter;
|
||||
|
||||
if (!m_Fractorium->ApplyAll())
|
||||
if (m_EmberFilePointer)
|
||||
m_EmberFilePointer->m_TemporalFilterType = filter;
|
||||
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());//Don't do anything until animation is implemented.
|
||||
}
|
||||
void Fractorium::OnTemporalFilterTypeComboCurrentIndexChanged(const QString& text) { m_Controller->TemporalFilterTypeChanged(text); }
|
||||
|
||||
/// <summary>
|
||||
/// Set the center.
|
||||
/// This updates the spinners as well as the current ember center.
|
||||
|
@ -177,29 +177,35 @@ void FractoriumSettings::LoadLast(bool b) { setValue(LOAD
|
||||
/// Sequence generation settings.
|
||||
/// </summary>
|
||||
|
||||
double FractoriumSettings::Stagger() { return value(STAGGER).toDouble(); }
|
||||
void FractoriumSettings::Stagger(double d) { setValue(STAGGER, d); }
|
||||
double FractoriumSettings::Stagger() { return value(STAGGER).toDouble(); }
|
||||
void FractoriumSettings::Stagger(double d) { setValue(STAGGER, d); }
|
||||
|
||||
double FractoriumSettings::StaggerMax() { return value(STAGGERMAX).toDouble(); }
|
||||
void FractoriumSettings::StaggerMax(double d) { setValue(STAGGERMAX, d); }
|
||||
double FractoriumSettings::StaggerMax() { return value(STAGGERMAX).toDouble(); }
|
||||
void FractoriumSettings::StaggerMax(double d) { setValue(STAGGERMAX, d); }
|
||||
|
||||
uint FractoriumSettings::FramesPerRot() { return value(FRAMESPERROT).toUInt(); }
|
||||
void FractoriumSettings::FramesPerRot(uint i) { setValue(FRAMESPERROT, i); }
|
||||
uint FractoriumSettings::FramesPerRot() { return value(FRAMESPERROT).toUInt(); }
|
||||
void FractoriumSettings::FramesPerRot(uint i) { setValue(FRAMESPERROT, i); }
|
||||
|
||||
uint FractoriumSettings::FramesPerRotMax() { return value(FRAMESPERROTMAX).toUInt(); }
|
||||
void FractoriumSettings::FramesPerRotMax(uint i) { setValue(FRAMESPERROTMAX, i); }
|
||||
uint FractoriumSettings::FramesPerRotMax() { return value(FRAMESPERROTMAX).toUInt(); }
|
||||
void FractoriumSettings::FramesPerRotMax(uint i) { setValue(FRAMESPERROTMAX, i); }
|
||||
|
||||
uint FractoriumSettings::Rotations() { return value(ROTATIONS).toDouble(); }
|
||||
void FractoriumSettings::Rotations(double d) { setValue(ROTATIONS, d); }
|
||||
uint FractoriumSettings::Rotations() { return value(ROTATIONS).toDouble(); }
|
||||
void FractoriumSettings::Rotations(double d) { setValue(ROTATIONS, d); }
|
||||
|
||||
uint FractoriumSettings::RotationsMax() { return value(ROTATIONSMAX).toDouble(); }
|
||||
void FractoriumSettings::RotationsMax(double d) { setValue(ROTATIONSMAX, d); }
|
||||
uint FractoriumSettings::RotationsMax() { return value(ROTATIONSMAX).toDouble(); }
|
||||
void FractoriumSettings::RotationsMax(double d) { setValue(ROTATIONSMAX, d); }
|
||||
|
||||
uint FractoriumSettings::BlendFrames() { return value(BLENDFRAMES).toUInt(); }
|
||||
void FractoriumSettings::BlendFrames(uint i) { setValue(BLENDFRAMES, i); }
|
||||
uint FractoriumSettings::BlendFrames() { return value(BLENDFRAMES).toUInt(); }
|
||||
void FractoriumSettings::BlendFrames(uint i) { setValue(BLENDFRAMES, i); }
|
||||
|
||||
uint FractoriumSettings::BlendFramesMax() { return value(BLENDFRAMESMAX).toUInt(); }
|
||||
void FractoriumSettings::BlendFramesMax(uint i) { setValue(BLENDFRAMESMAX, i); }
|
||||
uint FractoriumSettings::BlendFramesMax() { return value(BLENDFRAMESMAX).toUInt(); }
|
||||
void FractoriumSettings::BlendFramesMax(uint i) { setValue(BLENDFRAMESMAX, i); }
|
||||
|
||||
uint FractoriumSettings::RotationsPerBlend() { return value(ROTATIONSPERBLEND).toUInt(); }
|
||||
void FractoriumSettings::RotationsPerBlend(uint i) { setValue(ROTATIONSPERBLEND, i); }
|
||||
|
||||
uint FractoriumSettings::RotationsPerBlendMax() { return value(ROTATIONSPERBLENDMAX).toUInt(); }
|
||||
void FractoriumSettings::RotationsPerBlendMax(uint i) { setValue(ROTATIONSPERBLENDMAX, i); }
|
||||
|
||||
/// <summary>
|
||||
/// Variations filter settings.
|
||||
|
@ -37,6 +37,8 @@
|
||||
#define ROTATIONSMAX "sequence/rotationsmax"
|
||||
#define BLENDFRAMES "sequence/blendframes"
|
||||
#define BLENDFRAMESMAX "sequence/blendframesmax"
|
||||
#define ROTATIONSPERBLEND "sequence/rotationsperblend"
|
||||
#define ROTATIONSPERBLENDMAX "sequence/rotationsperblendmax"
|
||||
|
||||
#define VARFILTERSUM "varfilter/sumcheckbox"
|
||||
#define VARFILTERASSIGN "varfilter/assigncheckbox"
|
||||
@ -193,6 +195,12 @@ public:
|
||||
uint BlendFramesMax();
|
||||
void BlendFramesMax(uint i);
|
||||
|
||||
uint RotationsPerBlend();
|
||||
void RotationsPerBlend(uint i);
|
||||
|
||||
uint RotationsPerBlendMax();
|
||||
void RotationsPerBlendMax(uint i);
|
||||
|
||||
int VarFilterSum();
|
||||
void VarFilterSum(int i);
|
||||
|
||||
|
@ -139,7 +139,7 @@ void FractoriumEmberController<T>::AddLinkedXform()
|
||||
Ember<T> ember = m_Ember;
|
||||
m_Ember.Reserve(m_Ember.XformCount() + 1);//Doing this ahead of time ensures pointers remain valid.
|
||||
auto iterCount = 0;
|
||||
UpdateXform([&](Xform<T>* xform)
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
//Covers very strange case where final is selected, but initially not considered because final is excluded,
|
||||
//but after adding the new xform, it thinks its selected index is non-final.
|
||||
@ -210,7 +210,7 @@ void FractoriumEmberController<T>::DuplicateXform()
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
vector<Xform<T>> vec;
|
||||
vec.reserve(m_Ember.XformCount());
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
vec.push_back(*xform);
|
||||
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL, false);
|
||||
@ -235,7 +235,7 @@ void Fractorium::OnDuplicateXformButtonClicked(bool checked) { m_Controller->Dup
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ClearXform()
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
xform->ClearAndDeleteVariations();//Note xaos is left alone.
|
||||
}, eXformUpdate::UPDATE_SELECTED);
|
||||
@ -350,7 +350,7 @@ void Fractorium::OnAddFinalXformButtonClicked(bool checked) { m_Controller->AddF
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformWeightChanged(double d)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
xform->m_Weight = d;
|
||||
}, eXformUpdate::UPDATE_SELECTED_EXCEPT_FINAL);
|
||||
@ -363,7 +363,7 @@ void Fractorium::OnXformWeightChanged(double d) { m_Controller->XformWeightChang
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::EqualizeWeights()
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
m_Ember.EqualizeWeights();
|
||||
m_Fractorium->m_XformWeightSpin->setValue(xform->m_Weight);//Will trigger an update, so pass false to updateRender below.
|
||||
@ -381,65 +381,70 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::XformNameChanged(int row, int col)
|
||||
{
|
||||
bool forceFinal = m_Fractorium->HaveFinal();
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
int index = m_Ember.GetTotalXformIndex(xform, forceFinal);
|
||||
xform->m_Name = m_Fractorium->ui.XformWeightNameTable->item(row, col)->text().toStdString();
|
||||
XformCheckboxAt(index, [&](QCheckBox * checkbox) { checkbox->setText(MakeXformCaption(index)); });
|
||||
XformCheckboxAt(int(xfindex), [&](QCheckBox * checkbox) { checkbox->setText(MakeXformCaption(xfindex)); });
|
||||
}, eXformUpdate::UPDATE_CURRENT, false);
|
||||
FillSummary();//Manually update because this does not trigger a render, which is where this would normally be called.
|
||||
}
|
||||
void Fractorium::OnXformNameChanged(int row, int col) { m_Controller->XformNameChanged(row, col); }
|
||||
/// <summary>
|
||||
/// Set the animate field of the selected xforms.
|
||||
/// Set the animate field of the selected xforms, this allows excluding current if it's not checked, but applies only to it if none are checked.
|
||||
/// This has no effect on interactive rendering, it only sets a value
|
||||
/// that will later be saved to Xml when the user saves.
|
||||
/// This value is observed when creating sequences for animation.
|
||||
/// Applies to all embers if "Apply All" is checked.
|
||||
/// 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)
|
||||
{
|
||||
bool final = IsFinal(CurrentXform());
|
||||
auto index = m_Fractorium->ui.CurrentXformCombo->currentIndex();
|
||||
T animate = state > 0 ? 1 : 0;
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
if (final)//If the current xform was final, only apply to other embers which also have a final xform.
|
||||
bool final = IsFinal(xform);
|
||||
UpdateAll([&](Ember<T>& ember, bool isMain)
|
||||
{
|
||||
if (ember.UseFinalXform())
|
||||
if (final)//If the current xform was final, only apply to other embers which also have a final xform.
|
||||
{
|
||||
auto xform = ember.NonConstFinalXform();
|
||||
xform->m_Animate = animate;
|
||||
}
|
||||
|
||||
if (!m_Fractorium->ApplyAll())
|
||||
if (m_EmberFilePointer && m_EmberFilePointer->UseFinalXform())
|
||||
m_EmberFilePointer->NonConstFinalXform()->m_Animate = animate;
|
||||
}
|
||||
else//Current was not final, so apply to other embers which have a non-final xform at this index.
|
||||
{
|
||||
if (auto xform = ember.GetXform(index))
|
||||
xform->m_Animate = animate;
|
||||
|
||||
if (!m_Fractorium->ApplyAll() && m_EmberFilePointer)
|
||||
if (auto xform = m_EmberFilePointer->GetXform(index))
|
||||
if (ember.UseFinalXform())
|
||||
{
|
||||
auto xform = ember.NonConstFinalXform();
|
||||
xform->m_Animate = animate;
|
||||
}
|
||||
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
|
||||
}
|
||||
|
||||
if (!m_Fractorium->ApplyAll())
|
||||
if (m_EmberFilePointer && m_EmberFilePointer->UseFinalXform())
|
||||
m_EmberFilePointer->NonConstFinalXform()->m_Animate = animate;
|
||||
}
|
||||
else//Current was not final, so apply to other embers which have a non-final xform at this index.
|
||||
{
|
||||
if (auto xform = ember.GetXform(xfindex))
|
||||
xform->m_Animate = animate;
|
||||
|
||||
if (!m_Fractorium->ApplyAll() && m_EmberFilePointer)
|
||||
if (auto xform = m_EmberFilePointer->GetXform(xfindex))
|
||||
xform->m_Animate = animate;
|
||||
}
|
||||
}, false, eProcessAction::NOTHING, m_Fractorium->ApplyAll());
|
||||
}, 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>
|
||||
/// <param name="xform">The xform whose values will be used to populate the widgets</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FillWithXform(Xform<T>* xform)//Need to see where all this is called from and sync with FillXform(). Maybe rename the latter.
|
||||
void FractoriumEmberController<T>::FillWithXform(Xform<T>* xform)
|
||||
{
|
||||
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.
|
||||
m_Fractorium->ui.AnimateXformCheckBox->blockSignals(true);
|
||||
m_Fractorium->ui.AnimateXformCheckBox->setChecked(xform->m_Animate > 0 ? true : false);
|
||||
m_Fractorium->ui.AnimateXformCheckBox->blockSignals(false);
|
||||
|
||||
if (auto item = m_Fractorium->ui.XformWeightNameTable->item(0, 1))
|
||||
{
|
||||
|
@ -248,7 +248,7 @@ void Fractorium::OnPostAffineColDoubleClicked(int logicalIndex)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::AffineSetHelper(double d, int index, bool pre)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
AffineDoubleSpinBox** spinners = pre ? m_Fractorium->m_PreSpins : m_Fractorium->m_PostSpins;
|
||||
@ -330,7 +330,7 @@ void Fractorium::OnO2Changed(double d) { m_Controller->AffineSetHelper(d, 5, sen
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::FlipXforms(bool horizontal, bool vertical, bool pre)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
|
||||
@ -367,7 +367,7 @@ void Fractorium::OnFlipVerticalButtonClicked(bool checked) { m_Controller->FlipX
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::RotateXformsByAngle(double angle, bool pre)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
affine.Rotate(angle * DEG_2_RAD_T);
|
||||
@ -428,7 +428,7 @@ void Fractorium::OnRotateCcButtonClicked(bool checked)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::MoveXforms(double x, double y, bool pre)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
affine.C(affine.C() + x);
|
||||
@ -514,7 +514,7 @@ void Fractorium::OnMoveRightButtonClicked(bool checked)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ScaleXforms(double scale, bool pre)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
affine.A(affine.A() * scale);
|
||||
@ -567,7 +567,7 @@ void Fractorium::OnScaleUpButtonClicked(bool checked)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::ResetXformsAffine(bool pre)
|
||||
{
|
||||
UpdateXform([&] (Xform<T>* xform)
|
||||
UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
affine.MakeID();
|
||||
@ -585,7 +585,7 @@ void Fractorium::OnResetAffineButtonClicked(bool checked) { m_Controller->ResetX
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::RandomXformsAffine(bool pre)
|
||||
{
|
||||
UpdateXform([&](Xform<T>* xform)
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
affine.A(m_Rand.Frand11<T>());
|
||||
|
@ -51,7 +51,7 @@ void FractoriumEmberController<T>::XformColorIndexChanged(double d, bool updateR
|
||||
|
||||
if (updateRender)//False when just updating GUI in response to a change elsewhere, true when in response to a GUI change so update values and reset renderer.
|
||||
{
|
||||
UpdateXform([&](Xform<T>* xform)
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
xform->m_ColorX = Clamp<T>(d, 0, 1);
|
||||
}, update, updateRender, eProcessAction::FULL_RENDER, index);
|
||||
@ -99,7 +99,7 @@ void Fractorium::OnXformScrollColorIndexChanged(int d)
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::RandomColorIndicesButtonClicked()
|
||||
{
|
||||
UpdateXform([&](Xform<T>* xform) { xform->m_ColorX = m_Rand.Frand01<T>(); }, eXformUpdate::UPDATE_ALL, false);//Don't update renderer here...
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex) { xform->m_ColorX = m_Rand.Frand01<T>(); }, eXformUpdate::UPDATE_ALL, false);//Don't update renderer here...
|
||||
m_Fractorium->m_XformColorIndexSpin->setValue(CurrentXform()->m_ColorX);//...do it via GUI. This will set scrollbar value as well.
|
||||
}
|
||||
void Fractorium::OnRandomColorIndicesButtonClicked(bool b) { m_Controller->RandomColorIndicesButtonClicked(); }
|
||||
@ -113,7 +113,7 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::ToggleColorIndicesButtonClicked()
|
||||
{
|
||||
char ch = 1;
|
||||
UpdateXform([&](Xform<T>* xform) { xform->m_ColorX = T(ch ^= 1); }, eXformUpdate::UPDATE_ALL, false);//Don't update renderer here...
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex) { xform->m_ColorX = T(ch ^= 1); }, eXformUpdate::UPDATE_ALL, false);//Don't update renderer here...
|
||||
m_Fractorium->m_XformColorIndexSpin->setValue(CurrentXform()->m_ColorX);//...do it via GUI. This will set scrollbar value as well.
|
||||
}
|
||||
void Fractorium::OnToggleColorIndicesButtonClicked(bool b) { m_Controller->ToggleColorIndicesButtonClicked(); }
|
||||
@ -126,7 +126,7 @@ void Fractorium::OnToggleColorIndicesButtonClicked(bool b) { m_Controller->Toggl
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::RandomColorSpeedButtonClicked()
|
||||
{
|
||||
UpdateXform([&](Xform<T>* xform) { xform->m_ColorSpeed = m_Rand.Frand01<T>(); }, eXformUpdate::UPDATE_ALL);
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex) { xform->m_ColorSpeed = m_Rand.Frand01<T>(); }, eXformUpdate::UPDATE_ALL);
|
||||
m_Fractorium->m_XformColorSpeedSpin->SetValueStealth(CurrentXform()->m_ColorSpeed);
|
||||
}
|
||||
void Fractorium::OnRandomColorSpeedButtonClicked(bool b) { m_Controller->RandomColorSpeedButtonClicked(); }
|
||||
@ -140,7 +140,7 @@ template <typename T>
|
||||
void FractoriumEmberController<T>::ToggleColorSpeedButtonClicked()
|
||||
{
|
||||
char ch = 1;
|
||||
UpdateXform([&](Xform<T>* xform) { xform->m_ColorSpeed = (T(ch ^= 1) ? 0.5 : 0.0); }, eXformUpdate::UPDATE_ALL);
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex) { xform->m_ColorSpeed = (T(ch ^= 1) ? 0.5 : 0.0); }, eXformUpdate::UPDATE_ALL);
|
||||
m_Fractorium->m_XformColorSpeedSpin->SetValueStealth(CurrentXform()->m_ColorSpeed);
|
||||
}
|
||||
void Fractorium::OnToggleColorSpeedButtonClicked(bool b) { m_Controller->ToggleColorSpeedButtonClicked(); }
|
||||
@ -152,7 +152,7 @@ void Fractorium::OnToggleColorSpeedButtonClicked(bool b) { m_Controller->ToggleC
|
||||
/// </summary>
|
||||
/// <param name="d">The color speed, -1-1.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformColorSpeedChanged(double d) { UpdateXform([&] (Xform<T>* xform) { xform->m_ColorSpeed = d; }, eXformUpdate::UPDATE_SELECTED); }
|
||||
void FractoriumEmberController<T>::XformColorSpeedChanged(double d) { UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex) { xform->m_ColorSpeed = d; }, eXformUpdate::UPDATE_SELECTED); }
|
||||
void Fractorium::OnXformColorSpeedChanged(double d) { m_Controller->XformColorSpeedChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
@ -162,7 +162,7 @@ void Fractorium::OnXformColorSpeedChanged(double d) { m_Controller->XformColorSp
|
||||
/// </summary>
|
||||
/// <param name="d">The opacity, 0-1.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformOpacityChanged(double d) { UpdateXform([&] (Xform<T>* xform) { xform->m_Opacity = d; }, eXformUpdate::UPDATE_SELECTED); }
|
||||
void FractoriumEmberController<T>::XformOpacityChanged(double d) { UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex) { xform->m_Opacity = d; }, eXformUpdate::UPDATE_SELECTED); }
|
||||
void Fractorium::OnXformOpacityChanged(double d) { m_Controller->XformOpacityChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
@ -173,7 +173,7 @@ void Fractorium::OnXformOpacityChanged(double d) { m_Controller->XformOpacityCha
|
||||
/// </summary>
|
||||
/// <param name="d">The direct color percentage, 0-1.</param>
|
||||
template <typename T>
|
||||
void FractoriumEmberController<T>::XformDirectColorChanged(double d) { UpdateXform([&] (Xform<T>* xform) { xform->m_DirectColor = d; }, eXformUpdate::UPDATE_SELECTED); }
|
||||
void FractoriumEmberController<T>::XformDirectColorChanged(double d) { UpdateXform([&] (Xform<T>* xform, size_t xfindex, size_t selIndex) { xform->m_DirectColor = d; }, eXformUpdate::UPDATE_SELECTED); }
|
||||
void Fractorium::OnXformDirectColorChanged(double d) { m_Controller->XformDirectColorChanged(d); }
|
||||
|
||||
/// <summary>
|
||||
|
@ -202,7 +202,7 @@ void FractoriumEmberController<T>::VariationSpinBoxValueChanged(double d)//Would
|
||||
|
||||
if (sender)
|
||||
{
|
||||
UpdateXform([&](Xform<T>* xform)
|
||||
UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto var = m_VariationList->GetVariation(sender->GetVariationId());//The variation attached to the sender, for reference only.
|
||||
auto parVar = dynamic_cast<const ParametricVariation<T>*>(var);//The parametric cast of that variation.
|
||||
|
@ -175,9 +175,9 @@ void GLWidget::InitGL()
|
||||
|
||||
if (!b)
|
||||
{
|
||||
m_Fractorium->OnActionNewFlock(false);
|
||||
m_Fractorium->m_WidthSpin->setValue(w);
|
||||
m_Fractorium->m_HeightSpin->setValue(h);
|
||||
m_Fractorium->OnActionNewFlock(false);//This must come after the previous two lines because it uses the values of the spinners.
|
||||
}
|
||||
|
||||
m_Fractorium->m_Controller->DelayedStartRenderTimer();
|
||||
@ -839,7 +839,7 @@ void GLEmberController<T>::MousePress(QMouseEvent* e)
|
||||
//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);//Must do this first so UpdateXform() below properly grabs the current plus any selected.
|
||||
m_DragSrcTransforms.clear();
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
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.
|
||||
@ -972,7 +972,7 @@ void GLEmberController<T>::MouseMove(QMouseEvent* e)
|
||||
QRectF qrf(tl, br);
|
||||
T scale = m_FractoriumEmberController->AffineScaleCurrentToLocked();
|
||||
int i = 0;
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
QPointF cd(xform->m_Affine.C() * scale, xform->m_Affine.F() * scale);
|
||||
bool b = qrf.contains(cd);
|
||||
@ -1862,7 +1862,6 @@ bool GLEmberController<T>::CheckXformHover(Xform<T>* xform, v3T& glCoords, T& be
|
||||
template <typename T>
|
||||
void GLEmberController<T>::CalcDragXAxis()
|
||||
{
|
||||
size_t index = 0;
|
||||
auto affineToWorldScale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
|
||||
auto worldToAffineScale = m_FractoriumEmberController->AffineScaleCurrentToLocked();
|
||||
bool pre = m_AffineType == eAffineType::AffinePre;
|
||||
@ -1876,10 +1875,10 @@ void GLEmberController<T>::CalcDragXAxis()
|
||||
auto endDiff = (v2T(snapped) * affineToWorldScale) - m_DragSrcTransform.O();
|
||||
T endAngle = std::atan2(endDiff.y, endDiff.x);
|
||||
T angle = startAngle - endAngle;
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
auto srcRotated = m_DragSrcTransforms[index++];
|
||||
auto srcRotated = m_DragSrcTransforms[selIndex];
|
||||
|
||||
if (worldPivotShiftAlt)
|
||||
{
|
||||
@ -1923,10 +1922,10 @@ void GLEmberController<T>::CalcDragXAxis()
|
||||
auto endDiff = (v2T(origXPlusOff) * affineToWorldScale);
|
||||
T endAngle = std::atan2(endDiff.y, endDiff.x);
|
||||
T angle = startAngle - endAngle;
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
auto src = m_DragSrcTransforms[index++];
|
||||
auto src = m_DragSrcTransforms[selIndex];
|
||||
|
||||
if (GetAlt())
|
||||
{
|
||||
@ -1966,7 +1965,6 @@ void GLEmberController<T>::CalcDragXAxis()
|
||||
template <typename T>
|
||||
void GLEmberController<T>::CalcDragYAxis()
|
||||
{
|
||||
size_t index = 0;
|
||||
auto affineToWorldScale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
|
||||
auto worldToAffineScale = m_FractoriumEmberController->AffineScaleCurrentToLocked();
|
||||
bool pre = m_AffineType == eAffineType::AffinePre;
|
||||
@ -1980,10 +1978,10 @@ void GLEmberController<T>::CalcDragYAxis()
|
||||
auto endDiff = (v2T(snapped) * affineToWorldScale) - m_DragSrcTransform.O();
|
||||
T endAngle = std::atan2(endDiff.y, endDiff.x);
|
||||
T angle = startAngle - endAngle;
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
auto srcRotated = m_DragSrcTransforms[index++];
|
||||
auto srcRotated = m_DragSrcTransforms[selIndex];
|
||||
|
||||
if (worldPivotShiftAlt)
|
||||
{
|
||||
@ -2027,10 +2025,10 @@ void GLEmberController<T>::CalcDragYAxis()
|
||||
auto endDiff = (v2T(origYPlusOff) * affineToWorldScale);
|
||||
T endAngle = std::atan2(endDiff.y, endDiff.x);
|
||||
T angle = startAngle - endAngle;
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
auto src = m_DragSrcTransforms[index++];
|
||||
auto src = m_DragSrcTransforms[selIndex];
|
||||
|
||||
if (GetAlt())
|
||||
{
|
||||
@ -2065,7 +2063,6 @@ void GLEmberController<T>::CalcDragYAxis()
|
||||
template <typename T>
|
||||
void GLEmberController<T>::CalcDragTranslation()
|
||||
{
|
||||
size_t index = 0;
|
||||
auto affineToWorldScale = m_FractoriumEmberController->AffineScaleLockedToCurrent();
|
||||
auto worldToAffineScale = m_FractoriumEmberController->AffineScaleCurrentToLocked();
|
||||
bool worldPivotShift = !m_Fractorium->LocalPivot() && GetShift();
|
||||
@ -2077,10 +2074,10 @@ void GLEmberController<T>::CalcDragTranslation()
|
||||
T startAngle = std::atan2(m_DragSrcTransform.O().y, m_DragSrcTransform.O().x);
|
||||
T endAngle = std::atan2(snapped.y, snapped.x);
|
||||
T angle = startAngle - endAngle;
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
auto srcRotated = m_DragSrcTransforms[index++];
|
||||
auto srcRotated = m_DragSrcTransforms[selIndex];
|
||||
srcRotated.RotateTrans(angle);
|
||||
|
||||
if (worldPivotShift)
|
||||
@ -2102,10 +2099,10 @@ void GLEmberController<T>::CalcDragTranslation()
|
||||
|
||||
if (GetControl())
|
||||
{
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
auto offset = m_DragSrcTransforms[index++].O() + (affineToWorldScale * v2T(diff));
|
||||
auto offset = m_DragSrcTransforms[selIndex].O() + (affineToWorldScale * v2T(diff));
|
||||
auto snapped = SnapToGrid(offset);
|
||||
affine.O(v2T(snapped.x, snapped.y));
|
||||
|
||||
@ -2115,10 +2112,10 @@ void GLEmberController<T>::CalcDragTranslation()
|
||||
}
|
||||
else
|
||||
{
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform)
|
||||
m_FractoriumEmberController->UpdateXform([&](Xform<T>* xform, size_t xfindex, size_t selIndex)
|
||||
{
|
||||
auto& affine = pre ? xform->m_Affine : xform->m_Post;
|
||||
affine.O(m_DragSrcTransforms[index++].O() + (affineToWorldScale * v2T(diff)));
|
||||
affine.O(m_DragSrcTransforms[selIndex].O() + (affineToWorldScale * v2T(diff)));
|
||||
|
||||
if (xform == m_FractoriumEmberController->CurrentXform())
|
||||
m_DragHandlePos = v3T(affine.O(), 0) * worldToAffineScale;
|
||||
|
Loading…
Reference in New Issue
Block a user