diff --git a/src/lol/sys/file.h b/src/lol/sys/file.h index 97f3f390..a6ec3e9b 100644 --- a/src/lol/sys/file.h +++ b/src/lol/sys/file.h @@ -54,7 +54,7 @@ class File { public: File(); - File(File const &that); + File(File const &directory); File &operator =(File const &that); ~File(); @@ -72,6 +72,34 @@ private: class FileData *m_data; }; +class Directory +{ +public: + Directory(String const &name); + Directory(Directory const &that); + Directory &operator =(Directory const &that); + ~Directory(); + + void Open(FileAccess mode); + bool IsValid() const; + void Close(); + +private: + bool GetContent(Array* files, Array* directories); +public: + bool GetContent(Array& files, Array& directories); + bool GetContent(Array& directories); + bool GetContent(Array& files); + String GetName(); + + static String GetCurrent(); + static bool SetCurrent(String directory); + +private: + class DirectoryData* m_data; + String m_name; +}; + } /* namespace lol */ #endif // __LOL_SYS_FILE_H__ diff --git a/src/scene.cpp b/src/scene.cpp index d9f21eea..6d5d0cd7 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -70,6 +70,7 @@ private: Shader *m_line_shader; VertexDeclaration *m_line_vdecl; + int m_tile_cam; Array m_tiles; Array m_lights; @@ -94,6 +95,7 @@ Scene::Scene(ivec2 size) data->m_default_cam->SetProjection(proj); PushCamera(data->m_default_cam); + data->m_tile_cam = -1; data->m_tile_shader = 0; data->m_tile_vdecl = new VertexDeclaration(VertexStream(VertexUsage::Position), VertexStream(VertexUsage::TexCoord)); @@ -124,12 +126,13 @@ Scene::~Scene() delete data; } -void Scene::PushCamera(Camera *cam) +int Scene::PushCamera(Camera *cam) { ASSERT(this, "trying to push a camera before g_scene is ready"); Ticker::Ref(cam); data->m_camera_stack.Push(cam); + return data->m_camera_stack.Count() - 1; } void Scene::PopCamera(Camera *cam) @@ -151,9 +154,16 @@ void Scene::PopCamera(Camera *cam) ASSERT(false, "trying to pop a nonexistent camera from the scene"); } -Camera *Scene::GetCamera() +void Scene::SetTileCam(int cam_idx) { - return data->m_camera_stack.Last(); + data->m_tile_cam = cam_idx; +} + +Camera *Scene::GetCamera(int cam_idx) +{ + return (0 <= cam_idx && cam_idx < data->m_camera_stack.Count()) ? + data->m_camera_stack[cam_idx] : + data->m_camera_stack.Last(); } void Scene::Reset() @@ -282,9 +292,9 @@ void Scene::RenderTiles() // XXX: rename to Blit() data->m_tile_shader->Bind(); uni_mat = data->m_tile_shader->GetUniformLocation("u_projection"); - data->m_tile_shader->SetUniform(uni_mat, GetCamera()->GetProjection()); + data->m_tile_shader->SetUniform(uni_mat, GetCamera(data->m_tile_cam)->GetProjection()); uni_mat = data->m_tile_shader->GetUniformLocation("u_view"); - data->m_tile_shader->SetUniform(uni_mat, GetCamera()->GetView()); + data->m_tile_shader->SetUniform(uni_mat, GetCamera(data->m_tile_cam)->GetView()); uni_mat = data->m_tile_shader->GetUniformLocation("u_model"); data->m_tile_shader->SetUniform(uni_mat, mat4(1.f)); diff --git a/src/scene.h b/src/scene.h index 44134870..4bbe51c3 100644 --- a/src/scene.h +++ b/src/scene.h @@ -37,9 +37,10 @@ private: ~Scene(); public: - Camera *GetCamera(); - void PushCamera(Camera *cam); + Camera *GetCamera(int cam_idx=-1); + int PushCamera(Camera *cam); void PopCamera(Camera *cam); + void SetTileCam(int cam_idx); void Reset(); diff --git a/src/sys/file.cpp b/src/sys/file.cpp index 72dd0ad6..99f91fec 100644 --- a/src/sys/file.cpp +++ b/src/sys/file.cpp @@ -20,6 +20,13 @@ # include #endif +#if WIN32 +# define WIN32_LEAN_AND_MEAN 1 +# include +#else +# include +#endif + #include "core.h" namespace lol @@ -29,6 +36,7 @@ namespace lol extern AAssetManager *g_assets; #endif +//--------------- class FileData { friend class File; @@ -191,18 +199,21 @@ class FileData StreamType m_type; }; +//-- FILE -- File::File() : m_data(new FileData) { ++m_data->m_refcount; } +//-- File::File(File const &that) : m_data(that.m_data) { ++m_data->m_refcount; } +//-- File &File::operator =(File const &that) { if (this == &that) @@ -222,6 +233,7 @@ File &File::operator =(File const &that) return *this; } +//-- File::~File() { int refcount = --m_data->m_refcount; @@ -232,45 +244,310 @@ File::~File() } } +//-- void File::Open(StreamType stream) { return m_data->Open(stream); } +//-- void File::Open(String const &file, FileAccess mode) { return m_data->Open(file, mode); } +//-- bool File::IsValid() const { return m_data->IsValid(); } +//-- int File::Read(uint8_t *buf, int count) { return m_data->Read(buf, count); } +//-- String File::ReadString() { return m_data->ReadString(); } +//-- int File::Write(uint8_t const *buf, int count) { return m_data->Write(buf, count); } +//-- int File::WriteString(const String &buf) { return m_data->WriteString(buf); } +//-- void File::Close() { m_data->Close(); } +//--------------- +class DirectoryData +{ + friend class Directory; + + DirectoryData() : m_type(StreamType::File) + { +#if WIN32 + m_handle = INVALID_HANDLE_VALUE; +#elif HAVE_STDIO_H + m_dd = nullptr; +#endif WIN32 + } + + void Open(String const &directory, FileAccess mode) + { + m_type = StreamType::File; +#if __CELLOS_LV2__ || __ANDROID__ + //NO IMPLEMENTATION +#elif WIN32 + m_directory = directory; + String filter = m_directory + String("*"); + filter.Replace('/', '\\', true); + WIN32_FIND_DATA FindFileData; + m_handle = FindFirstFile(filter.C(), &FindFileData); +#elif HAVE_STDIO_H + m_dd = opendir(directory.C()); +#endif + } + + void Close() + { + if (m_type != StreamType::File) + return; + + if (IsValid()) + { +#if __CELLOS_LV2__ || __ANDROID__ + //NO IMPLEMENTATION +#elif WIN32 + FindClose(m_handle); +#elif HAVE_STDIO_H + closedir(m_dd); +#endif + } +#if __CELLOS_LV2__ || __ANDROID__ + //NO IMPLEMENTATION +#elif WIN32 + m_handle = INVALID_HANDLE_VALUE; +#elif HAVE_STDIO_H + m_dd = nullptr; +#endif + } + + bool GetContentList(Array* files, Array* directories) + { + if (!IsValid()) + return false; + +#if __CELLOS_LV2__ || __ANDROID__ + //NO IMPLEMENTATION +#elif WIN32 + String filter = m_directory + String("*"); + filter.Replace('/', '\\', true); + WIN32_FIND_DATA find_data; + HANDLE handle = FindFirstFile(filter.C(), &find_data); + bool file_valid = (handle != INVALID_HANDLE_VALUE); + + while (file_valid) + { + if (find_data.cFileName[0] != '.') + { + //We have a directory + if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (directories) + *directories << String(std::string(find_data.cFileName).c_str()); + } + else + { + if (files) + *files << String(find_data.cFileName); + } + } + //Go for next one + file_valid = FindNextFile(m_handle, &find_data); + } +#elif HAVE_STDIO_H + //NO IMPLEMENTATION +#endif + return ((files && files->Count()) || (directories && directories->Count())); + } + + inline bool IsValid() const + { +#if __CELLOS_LV2__ || __ANDROID__ + //NO IMPLEMENTATION +#elif WIN32 + return (m_handle != INVALID_HANDLE_VALUE); +#elif HAVE_STDIO_H + return !!m_dd; +#else + return false; +#endif + } + +#if __CELLOS_LV2__ || __ANDROID__ + //NO IMPLEMENTATION +#elif WIN32 + HANDLE m_handle; + String m_directory; +#elif HAVE_STDIO_H + DIR *m_dd; +#endif + Atomic m_refcount; + StreamType m_type; +}; + +//-- DIRECTORY -- +Directory::Directory(String const &name) + : m_data(new DirectoryData), + m_name(name + String("/")) +{ + ++m_data->m_refcount; +} + +//-- +Directory::Directory(Directory const &that) + : m_data(that.m_data), + m_name(that.m_name) +{ + ++m_data->m_refcount; +} + +//-- +Directory &Directory::operator =(Directory const &that) +{ + if (this == &that) + return *this; + + /* FIXME: this needs auditing */ + int refcount = --m_data->m_refcount; + if (refcount == 0) + { + m_data->Close(); + delete m_data; + } + + m_data = that.m_data; + m_name = that.m_name; + ++m_data->m_refcount; + + return *this; +} + +//-- +Directory::~Directory() +{ + int refcount = --m_data->m_refcount; + if (refcount == 0) + { + m_data->Close(); + delete m_data; + } +} + +//-- +void Directory::Open(FileAccess mode) +{ + return m_data->Open(m_name, mode); +} + +//-- +bool Directory::IsValid() const +{ + return m_data->IsValid(); +} + +//-- +void Directory::Close() +{ + m_data->Close(); +} + +//-- +bool Directory::GetContent(Array* files, Array* directories) +{ + Array sfiles, sdirectories; + bool found_some = m_data->GetContentList(&sfiles, &sdirectories); + + if (directories) + for (int i = 0; i < sdirectories.Count(); i++) + directories->Push(Directory(m_name + sdirectories[i])); + + if (files) + for (int i = 0; i < sfiles.Count(); i++) + files->Push(m_name + sfiles[i]); + + return (files && files->Count()) || (directories || directories->Count()); +} + +//-- +bool Directory::GetContent(Array& files, Array& directories) +{ + return GetContent(&files, &directories); +} + +//-- +bool Directory::GetContent(Array& directories) +{ + return GetContent(nullptr, &directories); +} + +//-- +bool Directory::GetContent(Array& files) +{ + return GetContent(&files, nullptr); +} + +//-- +String Directory::GetName() +{ + return m_name; +} + +//-- +String Directory::GetCurrent() +{ + String result; +#if __CELLOS_LV2__ || __ANDROID__ + //NO IMPLEMENTATION +#elif WIN32 + TCHAR buff[MAX_PATH * 2]; + GetCurrentDirectory(MAX_PATH, buff); + result = buff; + result.Replace('\\', '/', true); +#elif HAVE_STDIO_H + //NO IMPLEMENTATION +#endif + return result; +} + +//-- +bool Directory::SetCurrent(String directory) +{ +#if __CELLOS_LV2__ || __ANDROID__ + //NO IMPLEMENTATION +#elif WIN32 + String result = directory; + result.Replace('/', '\\', true); + return SetCurrentDirectory(result.C()); +#elif HAVE_STDIO_H + //NO IMPLEMENTATION +#endif + return false; +} + } /* namespace lol */ diff --git a/src/tiler.cpp b/src/tiler.cpp index 509422e2..14b22808 100644 --- a/src/tiler.cpp +++ b/src/tiler.cpp @@ -40,6 +40,10 @@ static TilerData * const data = &tilerdata; * Public Tiler class */ +TileSet *Tiler::Register(String const &path, ivec2 size, ivec2 count) +{ + return Tiler::Register(path.C(), size, count); +} TileSet *Tiler::Register(char const *path, ivec2 size, ivec2 count) { int id = data->tilesets.MakeSlot(path); @@ -54,6 +58,10 @@ TileSet *Tiler::Register(char const *path, ivec2 size, ivec2 count) return tileset; } +TileSet *Tiler::Register(String const &path) +{ + return Tiler::Register(path.C()); +} TileSet *Tiler::Register(char const *path) { int id = data->tilesets.MakeSlot(path); diff --git a/src/tiler.h b/src/tiler.h index 76cc2f5a..5381747c 100644 --- a/src/tiler.h +++ b/src/tiler.h @@ -27,7 +27,9 @@ namespace lol class Tiler { public: + static TileSet *Register(String const &path, ivec2 size, ivec2 count); static TileSet *Register(char const *path, ivec2 size, ivec2 count); + static TileSet *Register(String const &path); static TileSet *Register(char const *path); static void Deregister(TileSet *);