path improvements/fixes:

- replace more std::wstring with Native or VfsPath; wstring_from_utf8 ->
NativePathFromString
- replace sequences of Join(Path(), Basename+extension) with
ChangeExtension in wsdl, CacheLoader
- add Path::IsDirectory to replace .empty() / path_is_dir_sep(.back()).
also changed behavior to reflect the fact that "" is the VFS root
_directory_
- Path::Join now allows 2 identical path types (e.g. VfsPath) or one
char* literal (prevents inadvertently introducing non-safe characters).
to convert from wstring or wchar_t, use an explicit ctor (e.g.
VfsPath(wchar_t_string))

This was SVN commit r9091.
This commit is contained in:
janwas 2011-03-21 19:54:08 +00:00
parent 6d25329412
commit c3405e6f50
57 changed files with 179 additions and 165 deletions

View File

@ -248,7 +248,7 @@ VfsPath CColladaManager::GetLoadableFilename(const VfsPath& pathnameNoExtension,
const wchar_t* realDaePath = wcsstr(realDaeBuf, L"mods/");
// cachedPmdVfsPath is "cache/mods/whatever/art/meshes/whatever_{hash}.pmd"
VfsPath cachedPmdVfsPath = Path::Join(L"cache/", realDaePath);
VfsPath cachedPmdVfsPath = Path::Join("cache", VfsPath(realDaePath));
cachedPmdVfsPath = Path::ChangeExtension(cachedPmdVfsPath, extension);
// If it's not in the cache, we'll have to create it first

View File

@ -142,11 +142,11 @@ bool CObjectBase::Load(const VfsPath& pathname)
if (option_name == el_mesh)
{
currentVariant->m_ModelFilename = Path::Join(L"art/meshes", option.GetText().FromUTF8());
currentVariant->m_ModelFilename = Path::Join("art/meshes", option.GetText().FromUTF8());
}
else if (option_name == el_texture)
{
currentVariant->m_TextureFilename = Path::Join(L"art/textures/skins", option.GetText().FromUTF8());
currentVariant->m_TextureFilename = Path::Join("art/textures/skins", option.GetText().FromUTF8());
}
else if (option_name == el_decal)
{
@ -178,7 +178,7 @@ bool CObjectBase::Load(const VfsPath& pathname)
}
else if (ae.Name == at_file)
{
anim.m_FileName = Path::Join(L"art/animation", ae.Value.FromUTF8());
anim.m_FileName = Path::Join("art/animation", ae.Value.FromUTF8());
}
else if (ae.Name == at_speed)
{
@ -239,7 +239,7 @@ bool CObjectBase::Load(const VfsPath& pathname)
}
else if (child_name == el_material)
{
m_Material = Path::Join(L"art/materials", child.GetText().FromUTF8());
m_Material = Path::Join("art/materials", child.GetText().FromUTF8());
}
}

View File

@ -85,7 +85,7 @@ CObjectBase* CObjectManager::FindObjectBase(const CStrW& objectname)
CObjectBase* obj = new CObjectBase(*this);
VfsPath pathname = Path::Join(L"art/actors/", objectname);
VfsPath pathname = Path::Join("art/actors/", objectname);
if (obj->Load(pathname))
{

View File

@ -168,7 +168,7 @@ void CTerrainTextureManager::RecurseDirectory(const CTerrainPropertiesPtr& paren
CTerrainPropertiesPtr props;
// Load terrains.xml first, if it exists
VfsPath pathname = Path::Join(path, L"terrains.xml");
VfsPath pathname = Path::Join(path, "terrains.xml");
if (VfsFileExists(pathname))
props = GetPropertiesFromFile(parentProps, pathname);

View File

@ -302,7 +302,7 @@ public:
CTexturePtr texture = CreateTexture(textureProps);
CTextureConverter::Settings settings = GetConverterSettings(texture);
if (!m_TextureConverter.ConvertTexture(texture, sourcePath, Path::Join(L"cache", archiveCachePath), settings))
if (!m_TextureConverter.ConvertTexture(texture, sourcePath, Path::Join("cache", archiveCachePath), settings))
return false;
while (true)
@ -409,7 +409,7 @@ public:
VfsPath p;
for (fs::wpath::iterator it = srcPath.begin(); it != srcPath.end(); ++it)
{
VfsPath settingsPath = Path::Join(p, L"textures.xml");
VfsPath settingsPath = Path::Join(p, "textures.xml");
m_HotloadFiles[settingsPath].insert(texture);
CTextureConverter::SettingsFile* f = GetSettingsFile(settingsPath);
if (f)

View File

@ -27,8 +27,8 @@
#include "ps/CLogger.h"
#include "ps/XML/RelaxNG.h"
static NativePath MOD_PATH(Path::Join(DataDir(), L"mods/_test.mesh"));
static NativePath CACHE_PATH(Path::Join(DataDir(), L"_testcache"));
static NativePath MOD_PATH(Path::Join(DataDir(), "mods/_test.mesh"));
static NativePath CACHE_PATH(Path::Join(DataDir(), "_testcache"));
const wchar_t* srcDAE = L"collada/sphere.dae";
const wchar_t* srcPMD = L"collada/sphere.pmd";
@ -59,7 +59,7 @@ class TestMeshManager : public CxxTest::TestSuite
g_VFS = CreateVfs(20*MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", MOD_PATH));
TS_ASSERT_OK(g_VFS->Mount(L"collada/", Path::Join(DataDir(), L"tests/collada"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"collada/", Path::Join(DataDir(), "tests/collada"), VFS_MOUNT_MUST_EXIST));
// Mount _testcache onto virtual /cache - don't use the normal cache
// directory because that's full of loads of cached files from the

View File

@ -32,11 +32,11 @@ public:
void setUp()
{
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); // clean up in case the last test run failed
DeleteDirectory(Path::Join(DataDir(), "_testcache")); // clean up in case the last test run failed
m_VFS = CreateVfs(20*MiB);
TS_ASSERT_OK(m_VFS->Mount(L"", Path::Join(DataDir(), L"mods/_test.tex"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(m_VFS->Mount(L"cache/", Path::Join(DataDir(), L"_testcache")));
TS_ASSERT_OK(m_VFS->Mount(L"", Path::Join(DataDir(), "mods/_test.tex"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(m_VFS->Mount(L"cache/", Path::Join(DataDir(), "_testcache")));
tex_codec_register_all();
}
@ -46,7 +46,7 @@ public:
tex_codec_unregister_all();
m_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache"));
DeleteDirectory(Path::Join(DataDir(), "_testcache"));
}
void test_convert_quality()

View File

@ -34,11 +34,11 @@ public:
void setUp()
{
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); // clean up in case the last test run failed
DeleteDirectory(Path::Join(DataDir(), "_testcache")); // clean up in case the last test run failed
m_VFS = CreateVfs(20*MiB);
TS_ASSERT_OK(m_VFS->Mount(L"", Path::Join(DataDir(), L"mods/_test.tex"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(m_VFS->Mount(L"cache/", Path::Join(DataDir(), L"_testcache")));
TS_ASSERT_OK(m_VFS->Mount(L"", Path::Join(DataDir(), "mods/_test.tex"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(m_VFS->Mount(L"cache/", Path::Join(DataDir(), "_testcache")));
h_mgr_init();
tex_codec_register_all();
@ -54,7 +54,7 @@ public:
h_mgr_shutdown();
m_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache"));
DeleteDirectory(Path::Join(DataDir(), "_testcache"));
}
void test_load_basic()

View File

@ -1578,7 +1578,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
if (attr_name == "texture")
{
image.m_TextureName = Path::Join(L"art/textures/ui", attr_value);
image.m_TextureName = Path::Join("art/textures/ui", attr_value);
}
else
if (attr_name == "size")

View File

@ -115,7 +115,7 @@ void CGUIManager::LoadPage(SGUIPage& page)
page.gui.reset(new CGUI());
page.gui->Initialize();
VfsPath path = Path::Join(L"gui", page.name.c_str());
VfsPath path = Path::Join("gui", VfsPath(page.name.c_str()));
page.inputs.insert(path);
CXeromyces xero;
@ -144,7 +144,7 @@ void CGUIManager::LoadPage(SGUIPage& page)
CStrW name (node.GetText().FromUTF8());
TIMER(name.c_str());
VfsPath path = Path::Join(L"gui", name.c_str());
VfsPath path = Path::Join("gui", VfsPath(name.c_str()));
page.gui->LoadXmlFile(path, page.inputs);
}

View File

@ -384,7 +384,7 @@ void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, const CStr& SpriteName,
// TODO: Should check (nicely) that this is a valid file?
SGUIImage Image;
Image.m_TextureName = Path::Join(L"art/textures/ui", wstring_from_utf8(SpriteName.substr(10)));
Image.m_TextureName = Path::Join("art/textures/ui", NativePathFromString(SpriteName.substr(10)));
CClientArea ca(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100));
Image.m_Size = ca;

View File

@ -433,7 +433,7 @@ void ForceGC(void* cbdata)
void DumpSimState(void* UNUSED(cbdata))
{
NativePath path = Path::Join(psLogDir(), L"sim_dump.txt");
NativePath path = Path::Join(psLogDir(), "sim_dump.txt");
std::ofstream file (StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc);
g_Game->GetSimulation2()->DumpDebugState(file);
}

View File

@ -174,7 +174,7 @@ LibError debug_WriteCrashlog(const wchar_t* text)
return ERR::REENTERED; // NOWARN
FILE* f;
NativePath pathname = Path::Join(ah_get_log_dir(), L"crashlog.txt");
NativePath pathname = Path::Join(ah_get_log_dir(), "crashlog.txt");
errno_t err = _wfopen_s(&f, pathname.c_str(), L"w");
if(err != 0)
{

View File

@ -43,7 +43,7 @@ void dbghelp_ImportFunctions()
// application loaded.") and then the system directory, whose
// dbghelp.dll is too old. we therefore specify the full path
// to our executable directory, which contains a newer dbghelp.dll.
const NativePath pathname = Path::Join(wutil_DetectExecutablePath(), L"dbghelp.dll");
const NativePath pathname = Path::Join(wutil_DetectExecutablePath(), "dbghelp.dll");
HMODULE hDbghelp = LoadLibraryW(pathname.c_str());
debug_assert(hDbghelp);
#define FUNC(ret, name, params) p##name = (ret (__stdcall*) params)GetProcAddress(hDbghelp, #name);

View File

@ -30,9 +30,9 @@
#include <time.h>
#include <limits>
#include "lib/utf8.h"
#include "lib/bits.h"
#include "lib/byte_order.h"
#include "lib/utf8.h" // wstring_from_utf8
#include "lib/fat_time.h"
#include "lib/path_util.h"
#include "lib/allocators/pool.h"
@ -412,7 +412,7 @@ public:
WARN_RETURN(ERR::CORRUPTED);
const VfsPath relativePathname(cdfh->Pathname());
if(relativePathname.empty() || !path_is_dir_sep(relativePathname[relativePathname.length()-1])) // ignore directories
if(!Path::IsDirectory(relativePathname))
{
const NativePath name = Path::Filename(relativePathname);
FileInfo fileInfo(name, cdfh->USize(), cdfh->MTime());

View File

@ -28,7 +28,6 @@
#include <string>
#include "lib/path_util.h"
#include "lib/utf8.h" // wstring_from_utf8
#include "lib/posix/posix_filesystem.h"
@ -122,7 +121,7 @@ LibError CreateDirectories(const NativePath& path, mode_t mode)
// If we were passed a path ending with '/', strip the '/' now so that
// we can consistently use Path to find parent directory names
if(path_is_dir_sep(path[path.length()-1]))
if(Path::IsDirectory(path))
return CreateDirectories(Path::Path(path), mode);
RETURN_ERR(CreateDirectories(Path::Path(path), mode));

View File

@ -38,21 +38,13 @@ ERROR_ASSOCIATE(ERR::PATH_COMPONENT_SEPARATOR, L"path component contains dir sep
ERROR_ASSOCIATE(ERR::PATH_NOT_FOUND, L"path not found", -1);
bool path_is_dir_sep(wchar_t c)
static bool path_is_dir_sep(wchar_t c)
{
// note: ideally path strings would only contain '/' or even SYS_DIR_SEP.
// however, windows-specific code (e.g. the sound driver detection)
// uses these routines with '\\' strings. converting them all to
// '/' and then back before passing to WinAPI would be annoying.
// also, the self-tests verify correct operation of such strings.
// it would be error-prone to only test the platform's separator
// strings there. hence, we allow all separators here.
if(c == '/' || c == '\\')
return true;
return false;
}
// is s2 a subpath of s1, or vice versa?
// (equal counts as subpath)
bool path_is_subpath(const wchar_t* s1, const wchar_t* s2)

View File

@ -54,14 +54,6 @@ namespace ERR
**/
LIB_API LibError path_component_validate(const wchar_t* name);
/**
* is the given character a path separator character?
*
* @param c character to test
* @return bool
**/
LIB_API bool path_is_dir_sep(wchar_t c);
/**
* is s2 a subpath of s1, or vice versa? (equal counts as subpath)
*
@ -79,72 +71,106 @@ LIB_API bool path_is_subpath(const wchar_t* s1, const wchar_t* s2);
**/
LIB_API const wchar_t* path_name_only(const wchar_t* path);
namespace Path {
static inline NativePath Path(const NativePath& pathname)
template<class Path_t>
static inline bool IsDirectory(const Path_t& pathname)
{
if(pathname.empty()) // (ensure back() is safe)
return false; // (the VFS root directory is represented as an empty string)
// note: ideally, path strings would only contain '/' or even SYS_DIR_SEP.
// however, windows-specific code (e.g. the sound driver detection)
// uses these routines with '\\' strings. converting them all to
// '/' and then back before passing to OS functions would be annoying.
// also, the self-tests verify correct operation of such strings.
// it would be error-prone to only test the platform's separator
// strings there. hence, we allow all separators here.
return pathname.back() == '/' || pathname.back() == '\\';
}
template<class Path_t>
static inline Path_t Path(const Path_t& pathname)
{
size_t n = pathname.find_last_of('/');
if(n == NativePath::npos)
if(n == Path_t::npos)
{
n = pathname.find_last_of('\\');
if(n == NativePath::npos)
if(n == Path_t::npos)
return L"";
}
return pathname.substr(0, n);
}
static inline NativePath Filename(const NativePath& pathname)
template<class Path_t>
static inline Path_t Filename(const Path_t& pathname)
{
size_t n = pathname.find_last_of('/');
if(n == NativePath::npos)
if(n == Path_t::npos)
{
n = pathname.find_last_of('\\');
if(n == NativePath::npos)
if(n == Path_t::npos)
return pathname;
}
return pathname.substr(n+1);
}
static inline NativePath Basename(const NativePath& pathname)
template<class Path_t>
static inline Path_t Basename(const Path_t& pathname)
{
const NativePath filename = Filename(pathname);
const Path_t filename = Filename(pathname);
const size_t idxDot = filename.find_last_of('.');
if(idxDot == NativePath::npos)
if(idxDot == Path_t::npos)
return filename;
return filename.substr(0, idxDot);
}
static inline NativePath Extension(const NativePath& pathname)
template<class Path_t>
static inline std::wstring Extension(const Path_t& pathname)
{
const size_t idxDot = pathname.find_last_of('.');
if(idxDot == NativePath::npos)
return NativePath();
if(idxDot == Path_t::npos)
return Path_t();
return pathname.substr(idxDot);
}
static inline NativePath Join(const NativePath& path1, const NativePath& path2)
static inline std::wstring JoinPathStrings(const std::wstring& path1, const std::wstring& path2)
{
NativePath ret = path1;
if(!path1.empty() && path1[path1.length()-1] != '/' && path1[path1.length()-1] != '\\')
std::wstring ret = path1;
if(!IsDirectory(path1))
ret += '/';
ret += path2;
return ret;
}
static inline NativePath Join(const NativePath& path1, const NativePath& path2, const NativePath& path3)
template<class Path_t>
static inline Path_t Join(const Path_t& path1, const Path_t& path2)
{
return Join(Join(path1, path2), path3);
return JoinPathStrings(path1, path2);
}
static inline NativePath AddSlash(const NativePath& path)
template<class Path_t>
static inline Path_t Join(const Path_t& path1, const char* literal)
{
return (!path.empty() && path_is_dir_sep(path[path.length()-1]))? path : path+L'/';
return JoinPathStrings(path1, NativePathFromString(literal));
}
static inline NativePath ChangeExtension(const NativePath& pathname, const NativePath& extension)
template<class Path_t>
static inline Path_t Join(const char* literal, const Path_t& path2)
{
return Join(Path(pathname), Basename(Filename(pathname))+extension);
return JoinPathStrings(NativePathFromString(literal), path2);
}
template<class Path_t>
static inline Path_t AddSlash(const Path_t& path)
{
return IsDirectory(path)? path : path+L'/';
}
template<class Path_t>
static inline Path_t ChangeExtension(const Path_t& pathname, const std::wstring& extension)
{
return Join(Path(pathname), Basename(pathname)+extension);
}
} // namespace Path

View File

@ -237,7 +237,7 @@ LibError dir_watch_Poll(DirWatchNotifications& notifications)
continue;
}
DirWatch* dirWatch = (DirWatch*)polled_notifications[i].userdata;
NativePath pathname = Path::Join(dirWatch->path, NativePathFromString(polled_notifications[i].filename));
NativePath pathname = Path::Join(dirWatch->path, polled_notifications[i].filename);
notifications.push_back(DirWatchNotification(pathname, type));
}

View File

@ -31,7 +31,7 @@
#include <cstdio>
LibError sys_get_executable_name(std::wstring& pathname)
LibError sys_get_executable_name(NativePath& pathname)
{
const char* path;
Dl_info dl_info;
@ -53,7 +53,7 @@ LibError sys_get_executable_name(std::wstring& pathname)
char* resolved = realpath(path, resolvedBuf);
if (!resolved)
return ERR::FAIL;
pathname = wstring_from_utf8(resolved);
pathname = NativePathFromString(resolved);
return INFO::OK;
}
@ -72,7 +72,7 @@ LibError sys_get_executable_name(std::wstring& pathname)
char* resolved = realpath(absolute, resolvedBuf);
if (!resolved)
return ERR::NO_SYS;
pathname = wstring_from_utf8(resolved);
pathname = NativePathFromString(resolved);
return INFO::OK;
}

View File

@ -78,7 +78,7 @@ LibError gfx_get_video_mode(int* xres, int* yres, int* bpp, int* freq)
}
LibError sys_get_executable_name(std::wstring& pathname)
LibError sys_get_executable_name(NativePath& pathname)
{
static char name[PATH_MAX];
static bool init = false;
@ -102,7 +102,7 @@ LibError sys_get_executable_name(std::wstring& pathname)
debug_printf(L"app bundle name: %hs\n", name);
}
pathname = wstring_from_utf8(name);
pathname = NativePathFromString(name);
return INFO::OK;
}

View File

@ -57,7 +57,7 @@ struct wdirent* wreaddir(WDIR* wd)
dirent* ent = readdir(wd->d);
if(!ent)
return 0;
std::wstring name = wstring_from_utf8(ent->d_name);
NativePath name = NativePathFromString(ent->d_name);
wcscpy_s(wd->name, ARRAY_SIZE(wd->name), name.c_str());
return &wd->ent;
}

View File

@ -333,7 +333,7 @@ static NativePath DriverPathname()
#endif
char filename[PATH_MAX];
sprintf_s(filename, ARRAY_SIZE(filename), "aken%s%s.sys", bits, debug);
return Path::Join(wutil_ExecutablePath(), NativePathFromString(filename));
return Path::Join(wutil_ExecutablePath(), filename);
}

View File

@ -1871,7 +1871,7 @@ void wdbg_sym_WriteMinidump(EXCEPTION_POINTERS* exception_pointers)
WinScopedLock lock(WDBG_SYM_CS);
NativePath path = Path::Join(ah_get_log_dir(), L"crashlog.dmp");
NativePath path = Path::Join(ah_get_log_dir(), "crashlog.dmp");
HANDLE hFile = CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
if(hFile == INVALID_HANDLE_VALUE)
{

View File

@ -370,7 +370,7 @@ class DirWatchManager
public:
LibError Add(const NativePath& path, PDirWatch& dirWatch)
{
debug_assert(path_is_dir_sep(path.back())); // must be a directory path
debug_assert(Path::IsDirectory(path));
// check if this is a subdirectory of a tree that's already being
// watched (this is much faster than issuing a new watch; it also

View File

@ -57,7 +57,7 @@ void* dlopen(const char* so_name, int flags)
{
debug_assert(!(flags & RTLD_GLOBAL));
NativePath pathname = Path::ChangeExtension(wstring_from_utf8(so_name), L".dll");
NativePath pathname = Path::ChangeExtension(NativePathFromString(so_name), L".dll");
HMODULE hModule = LoadLibraryW(pathname.c_str());
return void_from_HMODULE(hModule);
}

View File

@ -1485,14 +1485,11 @@ static NativePath GetStdoutPathname()
wchar_t pathnameEXE[MAX_PATH];
const DWORD charsWritten = GetModuleFileNameW(0, pathnameEXE, ARRAY_SIZE(pathnameEXE));
debug_assert(charsWritten);
const NativePath path = Path::Path(pathnameEXE);
// add the EXE name to the filename to allow multiple executables
// with their own redirections. (we can't use wutil_ExecutablePath
// because it doesn't return the basename)
NativePath name = Path::Basename(pathnameEXE);
NativePath pathname = Path::Join(path, (name+L"_stdout.txt"));
NativePath pathname = Path::ChangeExtension(NativePath(pathnameEXE), L"_stdout.txt");
return pathname;
}

View File

@ -99,7 +99,7 @@ static BOOL CALLBACK DirectSoundCallback(void* guid, const wchar_t* UNUSED(descr
// note: $system\\drivers is not in LoadLibrary's search list,
// so we have to give the full pathname.
directSoundDriverPath = Path::Join(wutil_SystemPath(), L"drivers", module);
directSoundDriverPath = Path::Join(Path::Join(wutil_SystemPath(), "drivers"), NativePath(module));
// we assume the first "driver name" (sound card) is the one we want;
// stick with that and stop calling.

View File

@ -272,7 +272,7 @@ NativePath wutil_DetectExecutablePath()
wchar_t modulePathname[MAX_PATH+1] = {0};
const DWORD len = GetModuleFileNameW(GetModuleHandle(0), modulePathname, MAX_PATH);
debug_assert(len != 0);
return Path::Path(modulePathname);
return Path::Path(NativePath(modulePathname));
}
// (NB: wutil_Init is called before static ctors => use placement new)

View File

@ -438,7 +438,7 @@ static void RunGameOrAtlas(int argc, const char* argv[])
Paths paths(args);
g_VFS = CreateVfs(20 * MiB);
g_VFS->Mount(L"cache/", paths.Cache(), VFS_MOUNT_ARCHIVABLE);
g_VFS->Mount(L"", Path::Join(paths.RData(), L"mods/public"), VFS_MOUNT_MUST_EXIST);
g_VFS->Mount(L"", Path::Join(paths.RData(), "mods/public"), VFS_MOUNT_MUST_EXIST);
{
CReplayPlayer replay;

View File

@ -182,7 +182,7 @@ void CNetTurnManager::OnSyncError(u32 turn, const std::string& expectedHash)
bool ok = m_Simulation2.ComputeStateHash(hash, quick);
debug_assert(ok);
NativePath path = Path::Join(psLogDir(), L"oos_dump.txt");
NativePath path = Path::Join(psLogDir(), "oos_dump.txt");
std::ofstream file (StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc);
m_Simulation2.DumpDebugState(file);
file.close();

View File

@ -38,8 +38,8 @@ public:
void setUp()
{
g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), L"_testcache")));
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), "_testcache")));
CXeromyces::Startup();
// Need some stuff for terrain movement costs:
@ -60,7 +60,7 @@ public:
CXeromyces::Terminate();
g_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache"));
DeleteDirectory(Path::Join(DataDir(), "_testcache"));
}
bool clients_are_all(const std::vector<CNetClient*>& clients, uint state)

View File

@ -39,9 +39,9 @@ CArchiveBuilder::CArchiveBuilder(const std::wstring& mod, const std::wstring& te
m_VFS = CreateVfs(20*MiB);
DeleteDirectory(Path::Join(m_TempDir, L"_archivecache")); // clean up in case the last run failed
DeleteDirectory(Path::Join(m_TempDir, "_archivecache")); // clean up in case the last run failed
m_VFS->Mount(L"cache/", Path::Join(m_TempDir, L"_archivecache/"));
m_VFS->Mount(L"cache/", Path::Join(m_TempDir, "_archivecache/"));
m_VFS->Mount(L"", Path::AddSlash(mod), VFS_MOUNT_MUST_EXIST);
@ -53,7 +53,7 @@ CArchiveBuilder::~CArchiveBuilder()
{
m_VFS.reset();
DeleteDirectory(Path::Join(m_TempDir, L"_archivecache"));
DeleteDirectory(Path::Join(m_TempDir, "_archivecache"));
tex_codec_unregister_all();
}
@ -102,7 +102,7 @@ void CArchiveBuilder::Build(const std::wstring& archive)
debug_assert(ok);
std::wstring cachedRealPath;
ret = m_VFS->GetRealPath(Path::Join(L"cache", cachedPath), cachedRealPath);
ret = m_VFS->GetRealPath(Path::Join("cache", cachedPath), cachedRealPath);
debug_assert(ret == INFO::OK);
writer->AddFile(cachedRealPath, cachedPath);
@ -126,7 +126,7 @@ void CArchiveBuilder::Build(const std::wstring& archive)
debug_assert(ok);
std::wstring cachedRealPath;
ret = m_VFS->GetRealPath(Path::Join(L"cache", cachedPath), cachedRealPath);
ret = m_VFS->GetRealPath(Path::Join("cache", cachedPath), cachedRealPath);
debug_assert(ret == INFO::OK);
writer->AddFile(cachedRealPath, cachedPath);

View File

@ -75,10 +75,10 @@ const char* html_header1 = "</h2>\n";
CLogger::CLogger()
{
std::wstring mainlogPath(Path::Join(psLogDir(), L"mainlog.html"));
NativePath mainlogPath(Path::Join(psLogDir(), "mainlog.html"));
m_MainLog = new std::ofstream(utf8_from_wstring(mainlogPath).c_str(), std::ofstream::out | std::ofstream::trunc);
std::wstring interestinglogPath(Path::Join(psLogDir(), L"interestinglog.html"));
NativePath interestinglogPath(Path::Join(psLogDir(), "interestinglog.html"));
m_InterestingLog = new std::ofstream(utf8_from_wstring(interestinglogPath).c_str(), std::ofstream::out | std::ofstream::trunc);
m_OwnsStreams = true;

View File

@ -109,10 +109,7 @@ bool CCacheLoader::CanUseArchiveCache(const VfsPath& sourcePath, const VfsPath&
VfsPath CCacheLoader::ArchiveCachePath(const VfsPath& sourcePath)
{
VfsPath sourceDir = Path::Path(sourcePath);
std::wstring sourceName = Path::Filename(sourcePath);
return Path::Join(sourceDir, sourceName + L".cached" + m_FileExtension);
return Path::ChangeExtension(sourcePath, Path::Extension(sourcePath) + L".cached" + m_FileExtension);
}
VfsPath CCacheLoader::LooseCachePath(const VfsPath& sourcePath, const MD5& initialHash, u32 version)
@ -145,9 +142,7 @@ VfsPath CCacheLoader::LooseCachePath(const VfsPath& sourcePath, const MD5& initi
digestPrefix << std::setfill(L'0') << std::setw(2) << (int)digest[i];
// Construct the final path
VfsPath sourceDir = Path::Path(sourcePath);
std::wstring sourceName = Path::Filename(sourcePath);
return Path::Join(L"cache", sourceDir, sourceName + L"." + digestPrefix.str() + m_FileExtension);
return Path::Join("cache", Path::ChangeExtension(sourcePath, std::wstring(L".") + digestPrefix.str() + m_FileExtension));
// TODO: we should probably include the mod name, once that's possible (http://trac.wildfiregames.com/ticket/564)
}

View File

@ -454,8 +454,8 @@ static void InitVfs(const CmdLineArgs& args)
const size_t cacheSize = ChooseCacheSize();
g_VFS = CreateVfs(cacheSize);
g_VFS->Mount(L"screenshots/", Path::Join(paths.Data(), L"screenshots/"));
const NativePath readonlyConfig = Path::Join(paths.RData(), L"config/");
g_VFS->Mount(L"screenshots/", Path::Join(paths.Data(), "screenshots/"));
const NativePath readonlyConfig = Path::Join(paths.RData(), "config/");
g_VFS->Mount(L"config/", readonlyConfig);
if(readonlyConfig != paths.Config())
g_VFS->Mount(L"config/", paths.Config());
@ -466,8 +466,8 @@ static void InitVfs(const CmdLineArgs& args)
if(!args.Has("onlyPublicFiles"))
mods.push_back("internal");
NativePath modArchivePath = Path::Join(paths.Cache(), L"mods");
NativePath modLoosePath = Path::Join(paths.RData(), L"mods");
NativePath modArchivePath = Path::Join(paths.Cache(), "mods");
NativePath modLoosePath = Path::Join(paths.RData(), "mods");
for (size_t i = 0; i < mods.size(); ++i)
{
size_t priority = i;

View File

@ -34,7 +34,7 @@ Paths::Paths(const CmdLineArgs& args)
#ifdef INSTALLED_DATADIR
m_rdata = WIDEN(STRINGIZE(INSTALLED_DATADIR)) L"/";
#else
m_rdata = Path::Join(m_root, L"data/");
m_rdata = Path::Join(m_root, "data/");
#endif
const wchar_t* subdirectoryName = args.Has("writableRoot")? 0 : L"0ad";
@ -43,29 +43,29 @@ Paths::Paths(const CmdLineArgs& args)
if(!subdirectoryName)
{
m_data = m_rdata;
m_config = Path::Join(m_data, L"config/");
m_cache = Path::Join(m_data, L"cache/");
m_logs = Path::Join(m_root, L"logs/");
m_config = Path::Join(m_data, "config/");
m_cache = Path::Join(m_data, "cache/");
m_logs = Path::Join(m_root, "logs/");
}
else
{
#if OS_WIN
const NativePath appdata = Path::AddSlash(Path::Join(wutil_AppdataPath(), subdirectoryName));
m_data = Path::Join(appdata, L"data/");
m_config = Path::Join(appdata, L"config/");
m_cache = Path::Join(appdata, L"cache/");
m_logs = Path::Join(appdata, L"logs/");
const NativePath appdata = Path::AddSlash(Path::Join(wutil_AppdataPath(), NativePath(subdirectoryName)));
m_data = Path::Join(appdata, "data/");
m_config = Path::Join(appdata, "config/");
m_cache = Path::Join(appdata, "cache/");
m_logs = Path::Join(appdata, "logs/");
#else
const char* envHome = getenv("HOME");
debug_assert(envHome);
const NativePath home(wstring_from_utf8(envHome));
const NativePath xdgData = XDG_Path("XDG_DATA_HOME", home, Path::Join(home, L".local/share/", subdirectoryName));
const NativePath xdgConfig = XDG_Path("XDG_CONFIG_HOME", home, Path::Join(home, L".config/", subdirectoryName));
const NativePath xdgCache = XDG_Path("XDG_CACHE_HOME", home, Path::Join(home, L".cache/", subdirectoryName));
const NativePath xdgData = XDG_Path("XDG_DATA_HOME", home, Path::Join(home, ".local/share/"), subdirectoryName));
const NativePath xdgConfig = XDG_Path("XDG_CONFIG_HOME", home, Path::Join(home, ".config/"), subdirectoryName));
const NativePath xdgCache = XDG_Path("XDG_CACHE_HOME", home, Path::Join(home, ".cache/"), subdirectoryName));
m_data = Path::AddSlash(xdgData);
m_cache = Path::AddSlash(xdgCache);
m_config = Path::AddSlash(Path::Join(xdgConfig, L"config"));
m_logs = Path::AddSlash(Path::Join(xdgConfig, L"logs"));
m_config = Path::AddSlash(Path::Join(xdgConfig, "config"));
m_logs = Path::AddSlash(Path::Join(xdgConfig, "logs"));
#endif
}
}
@ -103,8 +103,8 @@ Paths::Paths(const CmdLineArgs& args)
if(path)
{
if(path[0] != '/') // relative to $HOME
return Path::AddSlash(Path::Join(home, wstring_from_utf8(path)));
return Path::AddSlash(wstring_from_utf8(path));
return Path::AddSlash(Path::Join(home, path));
return Path::AddSlash(NativePathFromString(path));
}
return Path::AddSlash(defaultPath);
}

View File

@ -526,7 +526,7 @@ void CProfileViewer::SaveToFile()
{
// Open the file. (It will be closed when the CProfileViewer
// destructor is called.)
NativePath path = Path::Join(psLogDir(), L"profile.txt");
NativePath path = Path::Join(psLogDir(), "profile.txt");
m->outputStream.open(utf8_from_wstring(path).c_str(), std::ofstream::out | std::ofstream::trunc);
if (m->outputStream.fail())

View File

@ -77,12 +77,12 @@ void psBundleLogs(FILE* f)
fwprintf(f, L"SVN Revision: %ls\n\n", svn_revision);
fwprintf(f, L"System info:\n\n");
NativePath path1 = Path::Join(psLogDir(), L"system_info.txt");
NativePath path1 = Path::Join(psLogDir(), "system_info.txt");
AppendAsciiFile(f, path1);
fwprintf(f, L"\n\n====================================\n\n");
fwprintf(f, L"Main log:\n\n");
NativePath path2 = Path::Join(psLogDir(), L"mainlog.html");
NativePath path2 = Path::Join(psLogDir(), "mainlog.html");
AppendAsciiFile(f, path2);
fwprintf(f, L"\n\n====================================\n\n");
}

View File

@ -68,7 +68,7 @@ CReplayLogger::CReplayLogger(ScriptInterface& scriptInterface) :
name << L"/commands.txt";
NativePath path = Path::Join(psLogDir(), name.str());
NativePath path = Path::Join(psLogDir(), NativePath(name.str()));
CreateDirectories(Path::Path(path), 0700);
m_Stream = new std::ofstream(StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc);
}

View File

@ -78,7 +78,7 @@ void WriteSystemInfo()
struct utsname un;
uname(&un);
NativePath pathname = Path::Join(psLogDir(), L"system_info.txt");
NativePath pathname = Path::Join(psLogDir(), "system_info.txt");
FILE* f;
errno_t err = _wfopen_s(&f, pathname.c_str(), L"w");
if(err != 0)

View File

@ -70,7 +70,7 @@ void CWorld::RegisterInit(const CStrW& mapFile, int playerID)
// Load the map, if one was specified
if (mapFile.length())
{
VfsPath mapfilename(Path::Join(L"maps/scenarios/", mapFile + L".pmp"));
VfsPath mapfilename(Path::Join("maps/scenarios", NativePath(mapFile + L".pmp")));
CMapReader* reader = 0;
try

View File

@ -118,7 +118,7 @@ bool CXeromyces::GenerateCachedXMB(const PIVFS& vfs, const VfsPath& sourcePath,
archiveCachePath = cacheLoader.ArchiveCachePath(sourcePath);
return (ConvertFile(vfs, sourcePath, Path::Join(L"cache", archiveCachePath)) == PSRETURN_OK);
return (ConvertFile(vfs, sourcePath, Path::Join("cache", archiveCachePath)) == PSRETURN_OK);
}
PSRETURN CXeromyces::ConvertFile(const PIVFS& vfs, const VfsPath& filename, const VfsPath& xmbPath)

View File

@ -1624,7 +1624,7 @@ int CRenderer::LoadAlphaMaps()
{
// note: these individual textures can be discarded afterwards;
// we cache the composite.
textures[i] = ogl_tex_load(g_VFS, Path::Join(path, fnames[i]));
textures[i] = ogl_tex_load(g_VFS, Path::Join(path, VfsPath(fnames[i])));
RETURN_ERR(textures[i]);
// get its size and make sure they are all equal.

View File

@ -75,7 +75,7 @@ void SkyManager::LoadSkyTextures()
{
for (size_t i = 0; i < ARRAY_SIZE(m_SkyTexture); ++i)
{
VfsPath path = Path::Join(L"art/textures/skies", m_SkySet, std::wstring(s_imageNames[i])+L".dds");
VfsPath path = Path::Join("art/textures/skies", Path::Join(NativePath(m_SkySet), NativePath(s_imageNames[i])+L".dds"));
CTextureProperties textureProps(path);
textureProps.SetWrap(GL_CLAMP_TO_EDGE);

View File

@ -275,12 +275,17 @@ JSBool GetBuildTimestamp(JSContext* cx, uintN argc, jsval* vp)
}
#ifdef DEBUG
void DumpHeap(const char* name, int idx, JSContext* cx)
void DumpHeap(const char* basename, int idx, JSContext* cx)
{
wchar_t buf[64];
swprintf_s(buf, ARRAY_SIZE(buf), L"%hs.%03d.txt", name, idx);
NativePath path = Path::Join(psLogDir(), buf);
FILE* f = fopen(utf8_from_wstring(path).c_str(), "w");
char filename[64];
sprintf_s(filename, ARRAY_SIZE(filename), "%hs.%03d.txt", basename, idx);
NativePath pathname = Path::Join(psLogDir(), filename);
#if OS_WIN
FILE* f = _wfopen(pathname.c_str(), L"w");
#else
std::string pathname8 = StringFromNativePath(pathname);
FILE* f = fopen(pathname8.c_str(), "w");
#endif
debug_assert(f);
JS_DumpHeap(cx, f, NULL, 0, NULL, (size_t)-1, NULL);
fclose(f);

View File

@ -289,7 +289,7 @@ void CSimulation2Impl::DumpState()
std::wstringstream name;
name << L"sim_log/" << getpid() << L"/" << std::setw(5) << std::setfill(L'0') << m_TurnNumber << L".txt";
NativePath path = Path::Join(psLogDir(), name.str());
NativePath path = Path::Join(psLogDir(), NativePath(name.str()));
CreateDirectories(Path::Path(path), 0700);
std::ofstream file (StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc);

View File

@ -320,7 +320,7 @@ bool CCmpTemplateManager::LoadTemplateFile(const std::string& templateName, int
// Normal case: templateName is an XML file:
VfsPath path = Path::Join(TEMPLATE_ROOT, wstring_from_utf8(templateName + ".xml"));
VfsPath path = Path::Join(VfsPath(TEMPLATE_ROOT), NativePathFromString(templateName + ".xml"));
CXeromyces xero;
PSRETURN ok = xero.Load(g_VFS, path);
if (ok != PSRETURN_OK)

View File

@ -36,8 +36,8 @@ public:
CXeromyces::Startup();
g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache/", Path::Join(DataDir(), L"cache")));
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache/", Path::Join(DataDir(), "cache")));
// Need some stuff for terrain movement costs:
// (TODO: this ought to be independent of any graphics code)

View File

@ -25,7 +25,7 @@ public:
void setUp()
{
g_VFS = CreateVfs(20 * MiB);
g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/public"), VFS_MOUNT_MUST_EXIST); // ignore directory-not-found errors
g_VFS->Mount(L"", Path::Join(DataDir(), "mods/public"), VFS_MOUNT_MUST_EXIST); // ignore directory-not-found errors
CXeromyces::Startup();
}

View File

@ -940,7 +940,7 @@ CScriptVal CComponentManager::Script_ReadJSONFile(void* cbdata, std::string file
{
CComponentManager* componentManager = static_cast<CComponentManager*> (cbdata);
NativePath path = L"simulation/data/" + wstring_from_utf8(fileName);
NativePath path = Path::Join("simulation/data", NativePathFromString(fileName));
return componentManager->GetScriptInterface().ReadJSONFile(path).get();
}

View File

@ -37,8 +37,8 @@ public:
void setUp()
{
g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/_test.sim"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), L"_testcache")));
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/_test.sim"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), "_testcache")));
CXeromyces::Startup();
}
@ -46,7 +46,7 @@ public:
{
CXeromyces::Terminate();
g_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache"));
DeleteDirectory(Path::Join(DataDir(), "_testcache"));
}
void test_LoadTemplate()
@ -223,8 +223,8 @@ public:
void setUp()
{
g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), L"_testcache")));
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), "_testcache")));
CXeromyces::Startup();
}
@ -232,7 +232,7 @@ public:
{
CXeromyces::Terminate();
g_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache"));
DeleteDirectory(Path::Join(DataDir(), "_testcache"));
}
// This just attempts loading every public entity, to check there's no validation errors

View File

@ -44,8 +44,8 @@ public:
void setUp()
{
g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/_test.sim"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), L"_testcache")));
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/_test.sim"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), "_testcache")));
CXeromyces::Startup();
}
@ -53,7 +53,7 @@ public:
{
CXeromyces::Terminate();
g_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache"));
DeleteDirectory(Path::Join(DataDir(), "_testcache"));
}
void test_Load()

View File

@ -487,8 +487,8 @@ public:
CXeromyces::Startup();
g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache/", Path::Join(DataDir(), L"cache")));
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache/", Path::Join(DataDir(), "cache")));
CTerrain terrain;

View File

@ -42,8 +42,8 @@ public:
void setUp()
{
g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/_test.sim"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), L"_testcache")));
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/_test.sim"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), "_testcache")));
CXeromyces::Startup();
}
@ -51,7 +51,7 @@ public:
{
CXeromyces::Terminate();
g_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache"));
DeleteDirectory(Path::Join(DataDir(), "_testcache"));
}
void test_AddEntity()
@ -130,7 +130,7 @@ public:
{
CSimulation2 sim(NULL, &m_Terrain);
TS_ASSERT_OK(CreateDirectories(Path::Join(DataDir(), L"mods/_test.sim/simulation/components/hotload/"), 0700));
TS_ASSERT_OK(CreateDirectories(Path::Join(DataDir(), "mods/_test.sim/simulation/components/hotload/"), 0700));
copyFile(L"simulation/components/test-hotload1.js", L"simulation/components/hotload/hotload.js");
TS_ASSERT_OK(g_VFS->Invalidate(L"simulation/components/hotload/hotload.js"));
@ -155,7 +155,7 @@ public:
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (sim.QueryInterface(ent, IID_Test1))->GetX(), 1000);
TS_ASSERT_OK(DeleteDirectory(Path::Join(DataDir(), L"mods/_test.sim/simulation/components/hotload/")));
TS_ASSERT_OK(DeleteDirectory(Path::Join(DataDir(), "mods/_test.sim/simulation/components/hotload/")));
TS_ASSERT_OK(g_VFS->Invalidate(L"simulation/components/hotload/hotload.js"));
TS_ASSERT_OK(sim.ReloadChangedFile(L"simulation/components/hotload/hotload.js"));

View File

@ -96,7 +96,7 @@ NativePath DataDir()
{
NativePath path;
TS_ASSERT_OK(sys_get_executable_name(path));
return Path::Join(Path::Path(path), L"../data");
return Path::Join(Path::Path(path), "../data");
}
// Script-based testing setup:
@ -115,7 +115,7 @@ void ScriptTestSetup(ScriptInterface& ifc)
// Load the TS_* function definitions
// (We don't use VFS because tests might not have the normal VFS paths loaded)
NativePath path = Path::Join(DataDir(), L"tests/test_setup.js");
NativePath path = Path::Join(DataDir(), "tests/test_setup.js");
std::ifstream ifs(StringFromNativePath(path).c_str());
debug_assert(ifs.good());
std::string content((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

View File

@ -100,7 +100,7 @@ MESSAGEHANDLER(LoadMap)
MESSAGEHANDLER(SaveMap)
{
CMapWriter writer;
const VfsPath pathname = Path::Join(L"maps/scenarios/", *msg->filename);
const VfsPath pathname = Path::Join("maps/scenarios", *msg->filename);
writer.SaveMap(pathname,
g_Game->GetWorld()->GetTerrain(),
g_Renderer.GetWaterManager(), g_Renderer.GetSkyManager(),