diff --git a/Source/EmberAnimate/EmberAnimate.cpp b/Source/EmberAnimate/EmberAnimate.cpp
index 282ad6e..1ce4a6a 100644
--- a/Source/EmberAnimate/EmberAnimate.cpp
+++ b/Source/EmberAnimate/EmberAnimate.cpp
@@ -11,7 +11,7 @@ using namespace EmberCommon;
/// A populated EmberOptions object which specifies all program options to be used
/// True if success, else false.
template
-bool EmberAnimate(EmberOptions& opt)
+bool EmberAnimate(int argc, _TCHAR* argv[], EmberOptions& opt)
{
auto info = OpenCLInfo::Instance();
std::cout.imbue(std::locale(""));
@@ -45,6 +45,7 @@ bool EmberAnimate(EmberOptions& opt)
vector>> renderers;
vector errorReport;
std::recursive_mutex verboseCs;
+ auto fullpath = GetExePath(argv[0]);
if (opt.EmberCL())
{
@@ -130,7 +131,7 @@ bool EmberAnimate(EmberOptions& opt)
renderers.push_back(std::move(tempRenderer));
}
- if (!InitPaletteList(opt.PalettePath()))//For any modern flames, the palette isn't used. This is for legacy purposes and should be removed.
+ if (!InitPaletteList(fullpath, opt.PalettePath())) //For any modern flames, the palette isn't used. This is for legacy purposes and should be removed.
return false;
cout << "Parsing ember file " << opt.Input() << "\n";
@@ -554,10 +555,10 @@ int _tmain(int argc, _TCHAR* argv[])
#ifdef DO_DOUBLE
if (!opt.Sp())
- b = EmberAnimate(opt);
+ b = EmberAnimate(argc, argv, opt);
else
#endif
- b = EmberAnimate(opt);
+ b = EmberAnimate(argc, argv, opt);
}
return b ? 0 : 1;
diff --git a/Source/EmberCommon/EmberCommon.h b/Source/EmberCommon/EmberCommon.h
index 9faba60..b3f8064 100644
--- a/Source/EmberCommon/EmberCommon.h
+++ b/Source/EmberCommon/EmberCommon.h
@@ -100,41 +100,63 @@ static bool ParseEmberFile(XmlToEmber& parser, const string& filename, vector
{
if (!parser.Parse(filename.c_str(), embers, useDefaults))
{
- cout << "Error parsing flame file " << filename << ", returning without executing.\n";
+ cerr << "Error parsing flame file " << filename << ", returning without executing.\n";
return false;
}
if (embers.empty())
{
- cout << "Error: No data present in file " << filename << ". Aborting.\n";
+ cerr << "Error: No data present in file " << filename << ". Aborting.\n";
return false;
}
return true;
}
+///
+/// Cross platform wrapper for getting the full path of the current executable.
+///
+/// The value of argv[0] passed into main()
+/// The full path of the executable as a string
+static string GetExePath(const char* argv0)
+{
+ string fullpath;
+#ifdef _WIN32
+ fullpath = argv0;
+#else
+ vector v;
+ v.resize(2048);
+#if __APPLE__
+ uint32_t vs = uint32_t(v.size());
+
+ if (_NSGetExecutablePath(v.data(), &vs) == 0)
+ fullpath = string(v.data());
+ else
+ cerr << "Could not discern full path from executable.\n";
+
+#else
+ auto fullsize = readlink("/proc/self/exe", v.data(), v.size());
+ fullpath = string(v.data());
+#endif
+#endif
+ return GetPath(fullpath);
+}
+
///
/// Wrapper for parsing palette Xml file and initializing it's private static members,
/// and printing any errors that occurred.
/// Template argument expected to be float or double.
///
+/// The full path of the folder the program is running in
/// The full path and name of the file
/// True if success, else false.
template
-static bool InitPaletteList(const string& filename)
+static bool InitPaletteList(const string& programPath, const string& filename)
{
auto paletteList = PaletteList::Instance();
-#ifdef _WIN32
- vector fullpath;
- fullpath.resize(2048);
- GetModuleFileName(nullptr, fullpath.data(), fullpath.size());
- string s = GetPath(string(fullpath.data()));
-#else
- string s = "./";
-#endif
static vector paths =
{
- s
+ programPath
#ifndef _WIN32
, "~/",
"~/.config/fractorium/",
@@ -146,15 +168,21 @@ static bool InitPaletteList(const string& filename)
for (auto& p : paths)
{
+ auto fullpath = p + filename;
+ //cout << "Trying: " << fullpath << endl;
+
if (!added)
- added |= paletteList->Add(p + filename);
+ {
+ if (std::ifstream(fullpath))
+ added |= paletteList->Add(fullpath);
+ }
else
break;
}
if (!added || !paletteList->Size())
{
- cout << "Error parsing palette file " << filename << ". Reason: \n"
+ cerr << "Error parsing palette file " << filename << ". Reason: \n"
<< paletteList->ErrorReportString() << "\nReturning without executing.\n";
return false;
}
diff --git a/Source/EmberCommon/EmberCommonPch.h b/Source/EmberCommon/EmberCommonPch.h
index 1c4872e..6186a3c 100644
--- a/Source/EmberCommon/EmberCommonPch.h
+++ b/Source/EmberCommon/EmberCommonPch.h
@@ -20,6 +20,7 @@
#include
#else
#include
+ #include
#define _TCHAR char
#define _tmain main
#define _T
diff --git a/Source/EmberGenome/EmberGenome.cpp b/Source/EmberGenome/EmberGenome.cpp
index 4e228ee..b1d9707 100644
--- a/Source/EmberGenome/EmberGenome.cpp
+++ b/Source/EmberGenome/EmberGenome.cpp
@@ -43,7 +43,7 @@ void SetDefaultTestValues(Ember& ember)
/// A populated EmberOptions object which specifies all program options to be used
/// True if success, else false.
template
-bool EmberGenome(EmberOptions& opt)
+bool EmberGenome(int argc, _TCHAR* argv[], EmberOptions& opt)
{
auto info = OpenCLInfo::Instance();
std::cout.imbue(std::locale(""));
@@ -193,6 +193,7 @@ bool EmberGenome(EmberOptions& opt)
unique_ptr> renderer(CreateRenderer(opt.EmberCL() ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, devices, false, 0, emberReport));
QTIsaac rand(ISAAC_INT(t.Tic()), ISAAC_INT(t.Tic() * 2), ISAAC_INT(t.Tic() * 3));
vector errorReport = emberReport.ErrorReport();
+ auto fullpath = GetExePath(argv[0]);
os.imbue(std::locale(""));
os2.imbue(std::locale(""));
@@ -205,7 +206,7 @@ bool EmberGenome(EmberOptions& opt)
return false;
}
- if (!InitPaletteList(opt.PalettePath()))
+ if (!InitPaletteList(fullpath, opt.PalettePath()))
return false;
if (!opt.EmberCL())
@@ -870,10 +871,10 @@ int _tmain(int argc, _TCHAR* argv[])
#ifdef DO_DOUBLE
if (!opt.Sp())
- b = EmberGenome(opt);
+ b = EmberGenome(argc, argv, opt);
else
#endif
- b = EmberGenome(opt);
+ b = EmberGenome(argc, argv, opt);
}
return b ? 0 : 1;
diff --git a/Source/EmberRender/EmberRender.cpp b/Source/EmberRender/EmberRender.cpp
index 6dea6a1..6d920f7 100644
--- a/Source/EmberRender/EmberRender.cpp
+++ b/Source/EmberRender/EmberRender.cpp
@@ -11,7 +11,7 @@ using namespace EmberCommon;
/// A populated EmberOptions object which specifies all program options to be used
/// True if success, else false.
template
-bool EmberRender(EmberOptions& opt)
+bool EmberRender(int argc, _TCHAR* argv[], EmberOptions& opt)
{
auto info = EmberCLns::OpenCLInfo::Instance();
std::cout.imbue(std::locale(""));
@@ -47,6 +47,7 @@ bool EmberRender(EmberOptions& opt)
auto progress = make_unique>();
unique_ptr> renderer(CreateRenderer(opt.EmberCL() ? eRendererType::OPENCL_RENDERER : eRendererType::CPU_RENDERER, devices, false, 0, emberReport));
vector errorReport = emberReport.ErrorReport();
+ auto fullpath = GetExePath(argv[0]);
if (!errorReport.empty())
emberReport.DumpErrorReport();
@@ -60,7 +61,7 @@ bool EmberRender(EmberOptions& opt)
if (opt.EmberCL() && renderer->RendererType() != eRendererType::OPENCL_RENDERER)//OpenCL init failed, so fall back to CPU.
opt.EmberCL(false);
- if (!InitPaletteList(opt.PalettePath()))//For any modern flames, the palette isn't used. This is for legacy purposes and should be removed.
+ if (!InitPaletteList(fullpath, opt.PalettePath()))//For any modern flames, the palette isn't used. This is for legacy purposes and should be removed.
return false;
if (!ParseEmberFile(parser, opt.Input(), embers))
@@ -432,10 +433,10 @@ int _tmain(int argc, _TCHAR* argv[])
#ifdef DO_DOUBLE
if (!opt.Sp())
- b = EmberRender(opt);
+ b = EmberRender(argc, argv, opt);
else
#endif
- b = EmberRender(opt);
+ b = EmberRender(argc, argv, opt);
}
return b ? 0 : 1;