From 0853b3ed8e7c4b862c4adb5f308d35bc3a2b1b79 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 27 Nov 2012 16:38:24 +0100 Subject: [PATCH] Add directory listings to VFS --- .../henrikrydgard/libnative/NativeGLView.java | 4 +- base/PCMain.cpp | 23 +++- file/file_util.cpp | 2 +- file/file_util.h | 1 + file/vfs.h | 6 +- file/zip_read.cpp | 103 ++++++++++++++++-- file/zip_read.h | 9 +- 7 files changed, 127 insertions(+), 21 deletions(-) diff --git a/android/src/com/henrikrydgard/libnative/NativeGLView.java b/android/src/com/henrikrydgard/libnative/NativeGLView.java index 6dafdc54ae..8a1f9c45d3 100644 --- a/android/src/com/henrikrydgard/libnative/NativeGLView.java +++ b/android/src/com/henrikrydgard/libnative/NativeGLView.java @@ -26,7 +26,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener { public NativeGLView(NativeActivity activity) { super(activity); setEGLContextClientVersion(2); - + /* if (Build.VERSION.SDK_INT >= 11) { try { Method method_setPreserveEGLContextOnPause = GLSurfaceView.class.getMethod( @@ -42,7 +42,7 @@ public class NativeGLView extends GLSurfaceView implements SensorEventListener { } catch (InvocationTargetException e) { e.printStackTrace(); } - } + }*/ // setEGLConfigChooser(5, 5, 5, 0, 16, 0); // setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS); diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 1a729541fd..df4529d253 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -140,23 +140,35 @@ int main(int argc, char *argv[]) { float zoom = 1.0f; bool tablet = false; + bool aspect43 = false; const char *zoomenv = getenv("ZOOM"); const char *tabletenv = getenv("TABLET"); + const char *ipad = getenv("IPAD"); + if (zoomenv) { zoom = atof(zoomenv); } if (tabletenv) { tablet = (bool)atoi(tabletenv); } - + if (ipad) aspect43 = true; + bool landscape; NativeGetAppInfo(&app_name, &app_name_nice, &landscape); + // Change these to temporarily test other resolutions. + aspect43 = false; tablet = false; + float density = 1.0f; + zoom = 1.5f; + if (landscape) { if (tablet) { pixel_xres = 1280 * zoom; pixel_yres = 800 * zoom; + } else if (aspect43) { + pixel_xres = 1024 * zoom; + pixel_yres = 768 * zoom; } else { pixel_xres = 800 * zoom; pixel_yres = 480 * zoom; @@ -168,6 +180,9 @@ int main(int argc, char *argv[]) { if (tablet) { pixel_xres = 800 * zoom; pixel_yres = 1280 * zoom; + } else if (aspect43) { + pixel_xres = 768 * zoom; + pixel_yres = 1024 * zoom; } else { pixel_xres = 480 * zoom; pixel_yres = 800 * zoom; @@ -243,7 +258,6 @@ int main(int argc, char *argv[]) { NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE"); #endif - float density = 1.0f; dp_xres = (float)pixel_xres * density / zoom; dp_yres = (float)pixel_yres * density / zoom; pixel_in_dps = (float)pixel_xres / dp_xres; @@ -344,8 +358,9 @@ int main(int argc, char *argv[]) { } // Faster exit, thanks to the OS. Remove this if you want to debug shutdown // The speed difference is only really noticable on Linux. On Windows you do notice it though - // exit(0); - +#ifdef _WIN32 + exit(0); +#endif NativeShutdownGraphics(); SDL_PauseAudio(1); SDL_CloseAudio(); diff --git a/file/file_util.cpp b/file/file_util.cpp index 5a8a557357..28dec171a0 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -191,7 +191,7 @@ size_t getFilesInDir(const char *directory, std::vector *files, const info.name = virtualName; info.fullName = std::string(directory) + "/" + virtualName; info.isDirectory = isDirectory(info.fullName); - + info.exists = true; if (!info.isDirectory) { std::string ext = getFileExtension(info.fullName); if (filter) { diff --git a/file/file_util.h b/file/file_util.h index d83172a2ae..c361c0da72 100644 --- a/file/file_util.h +++ b/file/file_util.h @@ -13,6 +13,7 @@ struct FileInfo { std::string name; std::string fullName; + bool exists; bool isDirectory; bool operator <(const FileInfo &other) const { diff --git a/file/vfs.h b/file/vfs.h index b5a5643c8e..da302a11cd 100644 --- a/file/vfs.h +++ b/file/vfs.h @@ -1,5 +1,7 @@ -#include "base/basictypes.h" +#pragma once +#include "base/basictypes.h" +#include "file/file_util.h" // Basic virtual file system. Used to manage assets on Android, where we have to // read them manually out of the APK zipfile, while being able to run on other // platforms as well with the appropriate directory set-up. @@ -13,3 +15,5 @@ void VFSShutdown(); // Always allocates an extra zero byte at the end, so that it // can be used for text like shader sources. uint8_t *VFSReadFile(const char *filename, size_t *size); +bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter = 0); +//bool VFSGetFileInfo(const char *filename, FileInfo *fileInfo); diff --git a/file/zip_read.cpp b/file/zip_read.cpp index 27d3a300e4..4631e48a65 100644 --- a/file/zip_read.cpp +++ b/file/zip_read.cpp @@ -1,6 +1,8 @@ #include +#include +#include -#ifndef _WIN32 +#ifdef ANDROID #include #endif @@ -8,7 +10,7 @@ #include "base/logging.h" #include "file/zip_read.h" -#ifndef _WIN32 +#ifdef ANDROID uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. struct zip_stat zstat; @@ -49,23 +51,24 @@ uint8_t *ReadLocalFile(const char *filename, size_t *size) { return contents; } -#ifndef _WIN32 +#ifdef ANDROID ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { + ELOG("ZIP File %s", zip_file); zip_file_ = zip_open(zip_file, 0, NULL); strcpy(in_zip_path_, in_zip_path); if (!zip_file_) { ELOG("Failed to open %s as a zip file", zip_file); } - // This is not really necessary. - int numFiles = zip_get_num_files(zip_file_); - for (int i = 0; i < numFiles; i++) { - const char* name = zip_get_name(zip_file_, i, 0); - if (name == NULL) { - ELOG("Error reading zip file name at index %i : %s", i, zip_strerror(zip_file_)); - return; + + std::vector info; + GetFileListing("assets", &info, 0); + for (int i = 0; i < info.size(); i++) { + if (info[i].isDirectory) { + ILOG("Directory: %s", info[i].name.c_str()); + } else { + ILOG("File: %s", info[i].name.c_str()); } - // ILOG("File %i : %s\n", i, name); } } @@ -80,6 +83,62 @@ uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { return ReadFromZip(zip_file_, temp_path, size); } +bool ZipAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) +{ + // We just loop through the whole ZIP file and deduce what files are in this directory, and what subdirectories there are. + std::set files; + std::set directories; + int numFiles = zip_get_num_files(zip_file_); + size_t pathlen = strlen(path); + if (path[pathlen-1] == '/') + pathlen--; + for (int i = 0; i < numFiles; i++) { + const char* name = zip_get_name(zip_file_, i, 0); + if (!name) + continue; + // ILOG("Comparing %s %s %i", name, path, pathlen); + if (!memcmp(name, path, pathlen)) { + // The prefix is right. Let's see if this is a file or path. + char *slashPos = strchr(name + pathlen + 1, '/'); + if (slashPos != 0) { + // A directory. + std::string dirName = std::string(name + pathlen + 1, slashPos - (name + pathlen + 1)); + directories.insert(dirName); + } else { + files.insert(std::string(name + pathlen + 1)); + } + } + } + + for (auto diter = directories.begin(); diter != directories.end(); ++diter) { + FileInfo info; + info.name = *diter; + info.fullName = std::string(path); + if (info.fullName[info.fullName.size()-1] == '/') + info.fullName = info.fullName.substr(0, info.fullName.size() - 1); + info.fullName += "/" + *diter; + info.exists = true; + info.isDirectory = true; + listing->push_back(info); + } + + for (auto fiter = files.begin(); fiter != files.end(); ++fiter) { + FileInfo info; + info.name = *fiter; + info.fullName = std::string(path); + if (info.fullName[info.fullName.size()-1] == '/') + info.fullName = info.fullName.substr(0, info.fullName.size() - 1); + info.fullName += "/" + *fiter; + info.exists = true; + info.isDirectory = false; + listing->push_back(info); + } + + std::sort(listing->begin(), listing->end()); + + return true; +} + #endif uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { @@ -95,6 +154,13 @@ uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { return ReadLocalFile(new_path, size); } +bool DirectoryAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = 0) +{ + getFilesInDir(path, listing, filter); + return true; +} + + struct VFSEntry { const char *prefix; AssetReader *reader; @@ -135,3 +201,18 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { ELOG("Missing filesystem for %s", filename); return 0; } + +bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter) +{ + int fn_len = strlen(path); + for (int i = 0; i < num_entries; i++) { + int prefix_len = strlen(entries[i].prefix); + if (prefix_len >= fn_len) continue; + if (0 == memcmp(path, entries[i].prefix, prefix_len)) { + entries[i].reader->GetFileListing(path + prefix_len, listing, filter); + return true; + } + } + ELOG("Missing filesystem for %s", path); + return false; +} diff --git a/file/zip_read.h b/file/zip_read.h index 2c85ec4504..e155386d4c 100644 --- a/file/zip_read.h +++ b/file/zip_read.h @@ -1,6 +1,6 @@ // TODO: Move much of this code to vfs.cpp -#ifndef _WIN32 +#ifdef ANDROID #include #endif @@ -9,6 +9,7 @@ #include "base/basictypes.h" #include "file/vfs.h" +#include "file/file_util.h" // Direct readers. deallocate using delete []. uint8_t *ReadLocalFile(const char *filename, size_t *size); @@ -18,10 +19,12 @@ public: virtual ~AssetReader() {} // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; + // Filter support is optional but nice to have + virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; virtual std::string toString() const = 0; }; -#ifndef _WIN32 +#ifdef ANDROID uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size); class ZipAssetReader : public AssetReader { public: @@ -29,6 +32,7 @@ public: ~ZipAssetReader(); // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size); + virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter); virtual std::string toString() const { return in_zip_path_; } @@ -46,6 +50,7 @@ public: } // use delete[] virtual uint8_t *ReadAsset(const char *path, size_t *size); + virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter); virtual std::string toString() const { return path_; }