From 62f1d5c84adff20d335bc24fefda7d35c9503b0c Mon Sep 17 00:00:00 2001 From: Lari Nieminen Date: Sat, 3 Dec 2016 02:27:34 +0200 Subject: [PATCH] Added $Subdir: .eff file property This allows animation frames of eff animations to be located in a subdirectory. This is useful for de-cluttering the effects directory in particular. --- code/bmpman/bm_internal.h | 1 + code/bmpman/bmpman.cpp | 43 +++++++++++++++++++++++++++++++++++--- code/bmpman/bmpman.h | 11 +++++----- code/cfile/cfile.cpp | 43 ++++++++++++++++++++++++++++++++++++++ code/cfile/cfile.h | 7 ++++++- code/cfile/cfilesystem.cpp | 7 +++++++ code/graphics/generic.cpp | 8 ++++++- 7 files changed, 110 insertions(+), 10 deletions(-) diff --git a/code/bmpman/bm_internal.h b/code/bmpman/bm_internal.h index b5663ec2ba5..6efd506641a 100644 --- a/code/bmpman/bm_internal.h +++ b/code/bmpman/bm_internal.h @@ -36,6 +36,7 @@ union bm_extra_info { // stuff for static animations BM_TYPE type; //!< type for individual images char filename[MAX_FILENAME_LEN]; //!< filename for individual images + bool in_subdir; //!< Whether frames are in their own subdirectory } eff; struct { bool is_apng; //!< Is this animation an APNG? diff --git a/code/bmpman/bmpman.cpp b/code/bmpman/bmpman.cpp index d75b3571164..778a3f26ccd 100644 --- a/code/bmpman/bmpman.cpp +++ b/code/bmpman/bmpman.cpp @@ -35,6 +35,7 @@ #include "pngutils/pngutils.h" #include "ship/ship.h" #include "tgautils/tgautils.h" +#include "cfile/cfilesystem.h" #include #include @@ -47,7 +48,20 @@ /** * @todo upgrade this to an inline funciton, taking bitmap_entry and const char* as arguments */ -#define EFF_FILENAME_CHECK { if ( be->type == BM_TYPE_EFF ) strcpy_s( filename, be->info.ani.eff.filename ); else strcpy_s( filename, be->filename ); } +#define EFF_FILENAME_CHECK \ +{ \ + if ( be->type == BM_TYPE_EFF ) { \ + strcpy_s( filename, be->info.ani.eff.filename ); \ + if (be->info.ani.eff.in_subdir) { \ + if (!cf_set_temp_subdir_pathtype(bm_bitmaps[be->info.ani.first_frame].filename)) { \ + mprintf(("BMPMAN: Failed to set temporary pathtype for %s: EFF_FILENAME_CHECK failed!\n", be->filename)); \ + } \ + } \ + } \ + else { \ + strcpy_s( filename, be->filename ); \ + } \ +} // -------------------------------------------------------------------------------------------------------------------- // Monitor variables MONITOR(NumBitmapPage) @@ -83,6 +97,8 @@ const int BM_ANI_NUM_TYPES = sizeof(bm_ani_type_list) / sizeof(bm_ani_type_list[ void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL; void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL; +extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES]; + // -------------------------------------------------------------------------------------------------------------------- // Declaration of protected variables (defined in cmdline.cpp). extern int Cmdline_cache_bitmaps; @@ -1311,8 +1327,9 @@ int bm_load(const SCP_string& filename) { return bm_load(filename.c_str()); } -bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, BM_TYPE *type) { +bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, BM_TYPE *type, bool *in_subdir) { int frames = 0, fps = 30, keyframe = 0; + bool subdir = false; char ext[8]; BM_TYPE c_type = BM_TYPE_NONE; char file_text[1024]; @@ -1350,6 +1367,10 @@ bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int return false; } + if (optional_string( "$Subdir:" )) { + stuff_boolean(&subdir); + } + // done with EFF so unpause parsing so whatever can continue unpause_parse(); @@ -1386,6 +1407,8 @@ bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int if (key) *key = keyframe; + *in_subdir = subdir; + return true; } @@ -1501,6 +1524,7 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke char filename[MAX_FILENAME_LEN]; int reduced = 0; int anim_fps = 0, anim_frames = 0, key = 0; + bool in_subdir = false; float anim_total_time = 0.0f; int anim_width = 0, anim_height = 0; BM_TYPE type = BM_TYPE_NONE, eff_type = BM_TYPE_NONE, c_type = BM_TYPE_NONE; @@ -1597,7 +1621,7 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke // it's an effect file, any readable image type with eff being txt if (type == BM_TYPE_EFF) { - if (!bm_load_and_parse_eff(filename, dir_type, &anim_frames, &anim_fps, &key, &eff_type)) { + if (!bm_load_and_parse_eff(filename, dir_type, &anim_frames, &anim_fps, &key, &eff_type, &in_subdir)) { mprintf(("BMPMAN: Error reading EFF\n")); if (img_cfp != nullptr) cfclose(img_cfp); @@ -1695,6 +1719,10 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke return -1; } + if (in_subdir) { + cf_set_temp_subdir_pathtype(filename); + } + int first_handle = bm_get_next_handle(); for (i = 0; i < anim_frames; i++) { @@ -1760,6 +1788,11 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke bm_bitmaps[n + i].num_mipmaps = mm_lvl; bm_bitmaps[n + i].mem_taken = (size_t)img_size; bm_bitmaps[n + i].dir_type = dir_type; + bm_bitmaps[n + i].info.ani.eff.in_subdir = in_subdir; + if (in_subdir) + bm_bitmaps[n + i].dir_type = CF_TYPE_TEMP_SUBDIR_LOOKUP; + else + bm_bitmaps[n + i].dir_type = dir_type; bm_bitmaps[n + i].load_count++; @@ -2594,6 +2627,10 @@ void bm_page_in_stop() { if ((bm_bitmaps[i].type != BM_TYPE_NONE) && (bm_bitmaps[i].type != BM_TYPE_RENDER_TARGET_DYNAMIC) && (bm_bitmaps[i].type != BM_TYPE_RENDER_TARGET_STATIC)) { if (bm_bitmaps[i].preloaded) { if (bm_preloading) { + if (bm_bitmaps[i].type == BM_TYPE_EFF && bm_bitmaps[i].info.ani.eff.in_subdir) { + cf_set_temp_subdir_pathtype(bm_bitmaps[i].filename); + } + if (!gr_preload(bm_bitmaps[i].handle, (bm_bitmaps[i].preloaded == 2))) { mprintf(("Out of VRAM. Done preloading.\n")); bm_preloading = 0; diff --git a/code/bmpman/bmpman.h b/code/bmpman/bmpman.h index 063fc5b5d2b..ac004804699 100644 --- a/code/bmpman/bmpman.h +++ b/code/bmpman/bmpman.h @@ -676,15 +676,16 @@ bool bm_set_render_target(int handle, int face = -1); * * @param[in] filename The filename of the .EFF * @param[in] dir_type - * @param[out] nframes (optional) If given, is set to the number of frames this .EFF has - * @param[out] nfps (optional) If given, is set to the fps of this .EFF - * @param[out] key (optional) If given, is set to the keyframe index of this .EFF - * @param[out] type (optional) If given, is set to the BM_TYPE of the .EFF + * @param[out] nframes (optional) If given, is set to the number of frames this .EFF has + * @param[out] nfps (optional) If given, is set to the fps of this .EFF + * @param[out] key (optional) If given, is set to the keyframe index of this .EFF + * @param[out] type (optional) If given, is set to the BM_TYPE of the .EFF + * @param[out] in_subdir (optional) If given, is set to true if the frames of this .EFF are in a subdir * * @returns true If successful * @returns false If not successful */ -bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, BM_TYPE *type); +bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int *nfps, int *key, BM_TYPE *type, bool *in_subdir); /** * @brief Calculates & returns the current frame of an animation diff --git a/code/cfile/cfile.cpp b/code/cfile/cfile.cpp index f2b9a269378..2aee86b82c6 100644 --- a/code/cfile/cfile.cpp +++ b/code/cfile/cfile.cpp @@ -88,6 +88,7 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = { { CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA }, { CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA }, { CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA }, + { CF_TYPE_TEMP_SUBDIR_LOOKUP, NULL, ".pcx .tga .jpg .png .dds", CF_TYPE_DATA }, }; @@ -135,6 +136,8 @@ void cfile_close() cf_free_secondary_filelist(); + vm_free(Pathtypes[CF_TYPE_TEMP_SUBDIR_LOOKUP].path); + cfile_inited = 0; } @@ -235,6 +238,9 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir) Cfile_block_list[i].type = CFILE_BLOCK_UNUSED; } + // Init to an empty string to avoid having to test for NULL everywhere + Pathtypes[CF_TYPE_TEMP_SUBDIR_LOOKUP].path = vm_strdup(""); + // 32 bit CRC table init cf_chksum_long_init(); @@ -1120,6 +1126,43 @@ int cf_get_dir_type(CFILE *cfile) return Cfile_block_list[cfile->id].dir_type; } +/** + * Stuffs Pathtypes with an additional path leading to a subdir of the same name as the given file (minus file extension). + * Currently used for allowing frames of .eff animations to be found in their own subdirectories. + * + * Example: if called with "debris.eff" and that file is in data/maps, then Pathtypes[CF_TYPE_TEMP_SUBDIR_LOOKUP].path + * will be stuffed with data/maps/debris, allowing data/maps/debris/debris_0000.dds (etc) to be found + */ +bool cf_set_temp_subdir_pathtype(const char *filename) { + mprintf(("CFILE: Setting temporary pathtype for %s... ", filename)); + + // Finds the relative path of where the file exists and appends the filename + // (without extension) to it, giving us a relative path that can be temporarily + // stuffed into Pathtypes + for (size_t i=CF_TYPE_ROOT; ibitmap_id = bm_create(ga->png.anim->bpp, ga->width, ga->height, ga->buffer, 0); } else { + bool in_subdir; bpp = 32; if(ga->use_hud_color) bpp = 8; - bm_load_and_parse_eff(ga->filename, CF_TYPE_ANY, &ga->num_frames, &anim_fps, &ga->keyframe, 0); + bm_load_and_parse_eff(ga->filename, CF_TYPE_ANY, &ga->num_frames, &anim_fps, &ga->keyframe, 0, &in_subdir); char *p = strrchr( ga->filename, '.' ); if ( p ) *p = 0; + + if (in_subdir) { + cf_set_temp_subdir_pathtype(ga->filename); + } + char frame_name[MAX_FILENAME_LEN]; snprintf(frame_name, MAX_FILENAME_LEN, "%s_0000", ga->filename); ga->bitmap_id = bm_load(frame_name);