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;