diff --git a/shader/cell.as b/assets/shader/cell.as similarity index 100% rename from shader/cell.as rename to assets/shader/cell.as diff --git a/shader/cell.pipeline b/assets/shader/cell.pipeline similarity index 100% rename from shader/cell.pipeline rename to assets/shader/cell.pipeline diff --git a/shader/cell_frag.as b/assets/shader/cell_frag.as similarity index 100% rename from shader/cell_frag.as rename to assets/shader/cell_frag.as diff --git a/shader/cell_frag.glsl b/assets/shader/cell_frag.glsl similarity index 100% rename from shader/cell_frag.glsl rename to assets/shader/cell_frag.glsl diff --git a/shader/cell_vert.as b/assets/shader/cell_vert.as similarity index 100% rename from shader/cell_vert.as rename to assets/shader/cell_vert.as diff --git a/shader/cell_vert.glsl b/assets/shader/cell_vert.glsl similarity index 100% rename from shader/cell_vert.glsl rename to assets/shader/cell_vert.glsl diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 2e8b03a..dd0d23e 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -58,6 +58,11 @@ enum { * VY_INSUFFICIENT_BUFFER if the provided output buffer is too small */ VY_DLLEXPORT vy_result vyUTF8ToWStr(const char *utf8, wchar_t *wstr, size_t len); +/* Returns VY_SUCCESS if the string was successfully converted, + * VY_INVALID_UNICODE if invalid unicode characters were encountered or + * VY_INSUFFICIENT_BUFFER if the provided output buffer is too small */ +VY_DLLEXPORT vy_result vyWStrToUTF8(const wchar_t *wstr, char *utf8, size_t len); + /* Relative pointer */ typedef struct { int32_t off; diff --git a/src/runtime/text.c b/src/runtime/text.c index 4929a96..c46e9ad 100644 --- a/src/runtime/text.c +++ b/src/runtime/text.c @@ -35,4 +35,24 @@ VY_DLLEXPORT vy_result vyUTF8ToWStr(const char *utf8, wchar_t *wstr, size_t len) } } #endif +} + + +VY_DLLEXPORT vy_result vyWStrToUTF8(const wchar_t *wstr, char *utf8, size_t len) { +#ifdef _WIN32 + int res = WideCharToMultiByte(CP_UTF8, WC_COMPOSITECHECK, wstr, -1, utf8, (int)len, NULL, NULL); + if (res > 0) { + return VY_SUCCESS; + } else { + DWORD err = GetLastError(); + if (err == ERROR_INSUFFICIENT_BUFFER) + return VY_INSUFFICIENT_BUFFER; + else if (err == ERROR_NO_UNICODE_TRANSLATION) + return VY_INVALID_UNICODE; + else { + vyReportError("CORE", "Unexpected error in vyWStrToUTF8(): %u", err); + return VY_UNKNOWN_ERROR; + } + } +#endif } \ No newline at end of file diff --git a/src/tools/assetc/assetc.c b/src/tools/assetc/assetc.c index 69408cd..631a117 100644 --- a/src/tools/assetc/assetc.c +++ b/src/tools/assetc/assetc.c @@ -25,6 +25,8 @@ extern vy_result vyProcessShaderFile(vy_file_id file, uint32_t flags, vy_processor_output *output); +extern void vyDiscoverAssets(void); + vy_assetc_options g_assetc_options = { .root_directory = ".", .optimization = VY_ASSET_OPTIMIZATION_NONE, @@ -121,12 +123,11 @@ int main(int argc, char **argv) { return 1; } - vyAddFileToProcessingQueue(vyAddFile("shader\\cell.pipeline"), 0); + vyDiscoverAssets(); vyWaitUntilProcessingIsFinished(); vyStopProcessing(); - vySaveAssetMeta(); vyShutdownBufferManager(); diff --git a/src/tools/assetc/discovery.c b/src/tools/assetc/discovery.c index 637a281..8beb381 100644 --- a/src/tools/assetc/discovery.c +++ b/src/tools/assetc/discovery.c @@ -1,5 +1,78 @@ +#include "utils.h" +#include "assetmeta.h" +#include "processing.h" -void DiscoverAssets(void) { - +#include +typedef struct { + char path_scratch[1024]; + unsigned int path_end; +} vy_discovery_data; + +static vy_result DirectoryHandler(const char *name, vyIterateDirElementType type, void *user) { + vy_discovery_data *data = user; + + size_t name_len = strlen(name); + + if (type == VY_DIR_ELEMENT_TYPE_FILE) { + /* Don't parse .as files */ + if (name_len >= 3) { + if (memcmp(&name[name_len - 3], ".as", 3) == 0) { + /* Skip */ + return VY_SUCCESS; + } + } + + /* Check if we know that file */ + data->path_scratch[data->path_end] = '/'; + memcpy(data->path_scratch + data->path_end + 1, name, name_len); + data->path_scratch[data->path_end + 1 + name_len] = '\0'; + + vy_file_id fid = vyAddFile(data->path_scratch); + if (vyLookupUID(fid) != VY_INVALID_UID) { + vy_assetmeta meta; + if (!vyGetAssetMeta(fid, &meta) || (meta.last_changed >= meta.compiled_ts)) { + /* The file (may have) changed */ + vy_result res = vyAddFileToProcessingQueue(fid, 0); + if (res != VY_SUCCESS) + return res; + } + else { + /* The file is unchanged, we just need to add it to the output again. */ + vyLog("ASSETC", "File %s is unchanged.", data->path_scratch); + } + } else { + /* Process it */ + vy_result res = vyAddFileToProcessingQueue(fid, 0); + if (res != VY_SUCCESS) + return res; + } + } else if (type == VY_DIR_ELEMENT_TYPE_DIRECTORY) { + if (strcmp(name, ".") == 0) + return VY_SUCCESS; + if (strcmp(name, "..") == 0) + return VY_SUCCESS; + + unsigned int path_end_before = data->path_end; + data->path_scratch[data->path_end++] = '/'; + memcpy(data->path_scratch + data->path_end, name, name_len); + data->path_scratch[data->path_end + name_len] = '\0'; + data->path_end += name_len; + + vy_result res = vyIterateDirectory(data->path_scratch, user, DirectoryHandler); + if (res != VY_SUCCESS) + return res; + + data->path_end = path_end_before; + } + return VY_SUCCESS; +} + +void vyDiscoverAssets(void) { + vy_discovery_data data; + data.path_scratch[0] = '.'; + data.path_scratch[1] = '\0'; + data.path_end = 1; + + vyIterateDirectory(".", &data, DirectoryHandler); } \ No newline at end of file diff --git a/src/tools/assetc/utils.c b/src/tools/assetc/utils.c index 97e1d06..d9502bb 100644 --- a/src/tools/assetc/utils.c +++ b/src/tools/assetc/utils.c @@ -50,4 +50,40 @@ uint64_t vyGetFileModificationTimestamp(vy_file_id fid) { ts |= (uint64_t)attribs.ftLastWriteTime.dwHighDateTime << 32; return ts; #endif +} + +vy_result vyIterateDirectory(const char *path, void *user, vy_iterate_directory_cb_func iterate_cb) { +#ifdef _WIN32 + vy_result res; + WCHAR wpath[MAX_PATH]; + char wildcard_path[MAX_PATH]; + strncpy(wildcard_path, path, MAX_PATH); + strncat(wildcard_path, "\\*", MAX_PATH - strlen(path)); + + res = vyUTF8ToWStr(wildcard_path, wpath, MAX_PATH); + if (res != VY_SUCCESS) + return res; + + WIN32_FIND_DATAW find; + HANDLE h = FindFirstFileW(wpath, &find); + if (h == INVALID_HANDLE_VALUE) + return VY_UNKNOWN_ERROR; + do { + char utf8_file[MAX_PATH]; + res = vyWStrToUTF8(find.cFileName, utf8_file, MAX_PATH); + if (res != VY_SUCCESS) + break; + vyIterateDirElementType type; + if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + type = VY_DIR_ELEMENT_TYPE_DIRECTORY; + else + type = VY_DIR_ELEMENT_TYPE_FILE; + res = iterate_cb(utf8_file, type, user); + if (res != VY_SUCCESS) + break; + } while (FindNextFileW(h, &find) != 0); + + FindClose(h); + return res; +#endif } \ No newline at end of file diff --git a/src/tools/assetc/utils.h b/src/tools/assetc/utils.h index 02e5158..8b3b79d 100644 --- a/src/tools/assetc/utils.h +++ b/src/tools/assetc/utils.h @@ -13,4 +13,13 @@ uint64_t vyGetCurrentTimestamp(void); uint64_t vyGetFileModificationTimestamp(vy_file_id fid); +typedef enum { + VY_DIR_ELEMENT_TYPE_FILE, + VY_DIR_ELEMENT_TYPE_DIRECTORY, +} vyIterateDirElementType; + +typedef vy_result vy_iterate_directory_cb_func(const char *name, vyIterateDirElementType type, void *user); + +vy_result vyIterateDirectory(const char *path, void *user, vy_iterate_directory_cb_func iterate_cb); + #endif