mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 22:56:30 -10:00
Allow generic_anim's to reuse bmpman and texture_cache slots and implement eff streaming. Changed talking heads to use generic_anim. Fixes Mantis 2417
This commit is contained in:
1 parent
71ccf2e274
commit
48e0517e0d
17 files changed
+242
-81
No files matched your search
+40
-7
@@ -635,6 +635,37 @@ int bm_load_duplicate(char *filename)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to reload a different bitmap into an existing slot.
|
||||
* This should only be used if you are certain the new picture has the same type, dimensions etc.
|
||||
*
|
||||
* @return negative if the given handle doesn't exist, the filename was empty or the slot is still locked
|
||||
* @return the bitmap_handle on success
|
||||
*/
|
||||
int bm_reload(int bitmap_handle, char* filename)
|
||||
{
|
||||
if ( !bm_inited )
|
||||
bm_init();
|
||||
|
||||
// if no file was passed then get out now
|
||||
if ( (filename == NULL) || (strlen(filename) <= 0) )
|
||||
return -1;
|
||||
|
||||
int bitmapnum = bitmap_handle % MAX_BITMAPS;
|
||||
|
||||
if ( bm_bitmaps[bitmapnum].type == BM_TYPE_NONE )
|
||||
return -1;
|
||||
|
||||
if ( bm_bitmaps[bitmapnum].ref_count )
|
||||
{
|
||||
nprintf(("BmpMan", "Trying to reload a bitmap that is still locked. Filename: %s, ref_count: %d", bm_bitmaps[bitmapnum].filename, bm_bitmaps[bitmapnum].ref_count));
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(bm_bitmaps[bitmapnum].filename, filename, MAX_FILENAME_LEN);
|
||||
return bitmap_handle;
|
||||
}
|
||||
|
||||
DCF(bm_frag,"Shows BmpMan fragmentation")
|
||||
{
|
||||
if ( Dc_command ) {
|
||||
@@ -1617,7 +1648,7 @@ MONITOR( SizeBitmapPage )
|
||||
*
|
||||
* Only lock a bitmap when you need it! This will convert it into the appropriate format also.
|
||||
*/
|
||||
bitmap * bm_lock( int handle, ubyte bpp, ubyte flags )
|
||||
bitmap * bm_lock( int handle, ubyte bpp, ubyte flags, bool nodebug)
|
||||
{
|
||||
bitmap *bmp;
|
||||
bitmap_entry *be;
|
||||
@@ -1677,7 +1708,7 @@ bitmap * bm_lock( int handle, ubyte bpp, ubyte flags )
|
||||
#endif
|
||||
|
||||
// read the file data
|
||||
if ( gr_bm_lock( be->filename, handle, bitmapnum, bpp, flags ) == -1 ) {
|
||||
if ( gr_bm_lock( be->filename, handle, bitmapnum, bpp, flags, nodebug ) == -1 ) {
|
||||
// oops, this isn't good - reset and return NULL
|
||||
bm_unlock( bitmapnum );
|
||||
bm_unload( bitmapnum );
|
||||
@@ -1891,7 +1922,7 @@ int bm_release(int handle, int clear_render_targets)
|
||||
*
|
||||
* @return 1 on successful release, 0 otherwise
|
||||
*/
|
||||
int bm_unload( int handle, int clear_render_targets )
|
||||
int bm_unload( int handle, int clear_render_targets, bool nodebug )
|
||||
{
|
||||
bitmap_entry *be;
|
||||
bitmap *bmp;
|
||||
@@ -1913,7 +1944,7 @@ int bm_unload( int handle, int clear_render_targets )
|
||||
Assert( be->handle == handle ); // INVALID BITMAP HANDLE!
|
||||
|
||||
// If it is locked, cannot free it.
|
||||
if (be->ref_count != 0) {
|
||||
if (be->ref_count != 0 && !nodebug) {
|
||||
nprintf(("BmpMan", "Tried to unload %s that has a lock count of %d.. not unloading\n", be->filename, be->ref_count));
|
||||
return 0;
|
||||
}
|
||||
@@ -1925,7 +1956,7 @@ int bm_unload( int handle, int clear_render_targets )
|
||||
if ( be->load_count > 0 )
|
||||
be->load_count--;
|
||||
|
||||
if ( be->load_count != 0 ) {
|
||||
if ( be->load_count != 0 && !nodebug) {
|
||||
nprintf(("BmpMan", "Tried to unload %s that has a load count of %d.. not unloading\n", be->filename, be->load_count + 1));
|
||||
return 0;
|
||||
}
|
||||
@@ -1941,11 +1972,13 @@ int bm_unload( int handle, int clear_render_targets )
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < bm_bitmaps[first].info.ani.num_frames; i++) {
|
||||
nprintf(("BmpMan", "Unloading %s frame %d. %dx%dx%d\n", be->filename, i, bmp->w, bmp->h, bmp->bpp));
|
||||
if(!nodebug)
|
||||
nprintf(("BmpMan", "Unloading %s frame %d. %dx%dx%d\n", be->filename, i, bmp->w, bmp->h, bmp->bpp));
|
||||
bm_free_data(first+i); // clears flags, bbp, data, etc
|
||||
}
|
||||
} else {
|
||||
nprintf(("BmpMan", "Unloading %s. %dx%dx%d\n", be->filename, bmp->w, bmp->h, bmp->bpp));
|
||||
if(!nodebug)
|
||||
nprintf(("BmpMan", "Unloading %s. %dx%dx%d\n", be->filename, bmp->w, bmp->h, bmp->bpp));
|
||||
bm_free_data(n); // clears flags, bbp, data, etc
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ int bm_create( int bpp, int w, int h, void *data = NULL, int flags = 0);
|
||||
// Frees up a bitmap's data, but bitmap number 'n' can
|
||||
// still be used, it will just have to be paged in next
|
||||
// time it is locked.
|
||||
int bm_unload( int n, int clear_render_targets = 0 );
|
||||
int bm_unload( int n, int clear_render_targets = 0, bool nodebug = false);
|
||||
|
||||
// like bm_unload() except that it's safe to use to free data without worrying about
|
||||
// load_count so it's safe to use in relation to bm_release() and in gr_*_texture functions
|
||||
@@ -133,7 +133,7 @@ extern int bm_load_either(char *filename, int *nframes = NULL, int *fps = NULL,
|
||||
// that can be accessed until you call bm_unlock. Only lock
|
||||
// a bitmap when you need it! This will convert it into the
|
||||
// appropriate format also.
|
||||
extern bitmap * bm_lock( int bitmapnum, ubyte bpp, ubyte flags );
|
||||
extern bitmap * bm_lock( int bitmapnum, ubyte bpp, ubyte flags, bool nodebug = false);
|
||||
|
||||
// The signature is a field that gets filled in with
|
||||
// a unique signature for each bitmap. The signature for each bitmap
|
||||
@@ -172,6 +172,9 @@ void bm_gfx_get_pixel( int bitmap, float u, float v, ubyte *r, ubyte *g, ubyte *
|
||||
// nnew = number of bytes of bitmaps locked this frame that weren't locked last frame
|
||||
void bm_get_frame_usage(int *ntotal, int *nnew);
|
||||
|
||||
// Reload a different image into an existing bmpman slot
|
||||
int bm_reload(int bitmap_handle, char* filename);
|
||||
|
||||
/*
|
||||
* Example on using bm_create
|
||||
*
|
||||
@@ -281,4 +284,5 @@ int bm_make_render_target( int width, int height, int flags );
|
||||
int bm_is_render_target(int bitmap_id);
|
||||
int bm_set_render_target(int handle, int face = -1);
|
||||
|
||||
int bm_load_and_parse_eff(char *filename, int dir_type, int *nframes, int *nfps, int *key, ubyte *type);
|
||||
#endif
|
||||
@@ -1254,7 +1254,7 @@ void event_editor::OnBrowseAvi()
|
||||
|
||||
z = cfile_push_chdir(CF_TYPE_INTERFACE);
|
||||
CFileDialog dlg(TRUE, "ani", m_avi_filename, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
|
||||
"Ani Files (*.ani)|*.ani|Avi Files (*.avi)|*.avi|Both (*.ani, *.avi)|*.ani;*.avi||");
|
||||
"Ani Files (*.ani)|*.ani|Eff Files (*.eff)|*.eff|Avi Files (*.avi)|*.avi|Both (*.ani, *.avi)|*.ani;*.avi||");
|
||||
|
||||
if (dlg.DoModal() == IDOK) {
|
||||
m_avi_filename = dlg.GetFileName();
|
||||
|
||||
@@ -118,6 +118,8 @@ $Directive Wait Time: 3000 \n\
|
||||
;; Turns off the HUD when in-game cutscenes are playing \n\
|
||||
$Cutscene camera disables HUD: YES \n\
|
||||
\n\
|
||||
;; Set to NO when you want to have full color .eff head animations \n\
|
||||
$Color head animations with hud colors: YES \n\
|
||||
\n\
|
||||
#SEXP SETTINGS \n\
|
||||
\n\
|
||||
@@ -152,7 +154,6 @@ $Default ship select effect: FS2 \n\
|
||||
;; used when no ani is specified or weapon_select_3d is active \n\
|
||||
$Default weapon select effect: FS2 \n\
|
||||
\n\
|
||||
\n\
|
||||
#END \n\
|
||||
";
|
||||
|
||||
|
||||
+9
-1
@@ -407,7 +407,7 @@ typedef struct screen {
|
||||
int (*gf_bm_load)(ubyte type, int n, char *filename, CFILE *img_cfp, int *w, int *h, int *bpp, ubyte *c_type, int *mm_lvl, int *size);
|
||||
void (*gf_bm_init)(int n);
|
||||
void (*gf_bm_page_in_start)();
|
||||
int (*gf_bm_lock)(char *filename, int handle, int bitmapnum, ubyte bpp, ubyte flags);
|
||||
int (*gf_bm_lock)(char *filename, int handle, int bitmapnum, ubyte bpp, ubyte flags, bool nodebug);
|
||||
|
||||
int (*gf_bm_make_render_target)(int n, int *width, int *height, ubyte *bpp, int *mm_lvl, int flags );
|
||||
int (*gf_bm_set_render_target)(int n, int face);
|
||||
@@ -493,6 +493,8 @@ typedef struct screen {
|
||||
void (*gf_set_team_color)(SCP_string team);
|
||||
void (*gf_enable_team_color)();
|
||||
void (*gf_disable_team_color)();
|
||||
|
||||
void (*gf_update_texture)(int bitmap_handle, int bpp, ubyte* data);
|
||||
} screen;
|
||||
|
||||
// handy macro
|
||||
@@ -789,6 +791,8 @@ __inline void gr_render_buffer(int start, const vertex_buffer *bufferp, int texi
|
||||
#define gr_enable_team_color GR_CALL(*gr_screen.gf_enable_team_color)
|
||||
#define gr_disable_team_color GR_CALL(*gr_screen.gf_disable_team_color)
|
||||
|
||||
#define gr_update_texture GR_CALL(*gr_screen.gf_update_texture)
|
||||
|
||||
// color functions
|
||||
void gr_get_color( int *r, int *g, int b );
|
||||
void gr_init_color(color *c, int r, int g, int b);
|
||||
@@ -806,6 +810,10 @@ void gr_bitmap_uv(int _x, int _y, int _w, int _h, float _u0, float _v0, float _u
|
||||
void gr_bitmap_list(bitmap_2d_list* list, int n_bm, bool allow_scaling);
|
||||
void gr_bitmap_list(bitmap_rect_list* list, int n_bm, bool allow_scaling);
|
||||
|
||||
// texture update functions
|
||||
ubyte* gr_opengl_get_texture_update_pointer(int bitmap_handle);
|
||||
void gr_opengl_update_texture(int bitmap_handle, int bpp, ubyte* data);
|
||||
|
||||
// special function for drawing polylines. this function is specifically intended for
|
||||
// polylines where each section is no more than 90 degrees away from a previous section.
|
||||
// Moreover, it is _really_ intended for use with 45 degree angles.
|
||||
|
||||
+68
-17
@@ -102,6 +102,7 @@ void generic_anim_init(generic_anim *ga, const char *filename)
|
||||
ga->height = 0;
|
||||
ga->width = 0;
|
||||
ga->bitmap_id = -1;
|
||||
ga->colored = false;
|
||||
}
|
||||
|
||||
// CommanderDJ - same as generic_anim_init, just with an SCP_string
|
||||
@@ -184,6 +185,8 @@ int generic_anim_stream(generic_anim *ga)
|
||||
//TODO: add streaming EFF
|
||||
if(ga->type == BM_TYPE_ANI) {
|
||||
bpp = ANI_BPP_CHECK;
|
||||
if(ga->colored)
|
||||
bpp = 8;
|
||||
ga->ani.animation = anim_load(ga->filename, CF_TYPE_ANY, 0);
|
||||
ga->ani.instance = init_anim_instance(ga->ani.animation, bpp);
|
||||
|
||||
@@ -197,7 +200,7 @@ int generic_anim_stream(generic_anim *ga)
|
||||
ga->height = ga->ani.animation->height;
|
||||
ga->width = ga->ani.animation->width;
|
||||
ga->buffer = ga->ani.instance->frame;
|
||||
ga->bitmap_id = bm_create(bpp, ga->width, ga->height, ga->buffer, 0);
|
||||
ga->bitmap_id = bm_create(bpp, ga->width, ga->height, ga->buffer, (bpp==8)?BMP_AABITMAP:0);
|
||||
ga->ani.instance->last_bitmap = -1;
|
||||
|
||||
ga->ani.instance->file_offset = ga->ani.animation->file_offset;
|
||||
@@ -206,8 +209,19 @@ int generic_anim_stream(generic_anim *ga)
|
||||
ga->previous_frame = -1;
|
||||
}
|
||||
else {
|
||||
//placeholder until we get eff streaming working
|
||||
return generic_anim_load(ga);
|
||||
bpp = 32;
|
||||
if(ga->colored)
|
||||
bpp = 8;
|
||||
bm_load_and_parse_eff(ga->filename, CF_TYPE_ANY, &ga->num_frames, &anim_fps, &ga->keyframe, 0);
|
||||
char *p = strrchr( ga->filename, '.' );
|
||||
if ( p )
|
||||
*p = 0;
|
||||
char frame_name[32];
|
||||
snprintf(frame_name, 32, "%s_0000", ga->filename);
|
||||
ga->bitmap_id = bm_load(frame_name);
|
||||
snprintf(frame_name, 32, "%s_0001", ga->filename);
|
||||
ga->eff.next_frame = bm_load(frame_name);
|
||||
bm_get_info(ga->bitmap_id, &ga->width, &ga->height);
|
||||
}
|
||||
|
||||
// keyframe info
|
||||
@@ -234,9 +248,6 @@ int generic_anim_stream(generic_anim *ga)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// EFF not handled yet; code shouldn't get here anyway per above block
|
||||
}
|
||||
|
||||
ga->streaming = 1;
|
||||
|
||||
@@ -269,6 +280,10 @@ void generic_anim_unload(generic_anim *ga)
|
||||
anim_free(ga->ani.animation);
|
||||
free_anim_instance(ga->ani.instance);
|
||||
}
|
||||
if(ga->type == BM_TYPE_EFF) {
|
||||
bm_release(ga->eff.next_frame);
|
||||
bm_release(ga->bitmap_id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//trying to release the first frame will release ALL frames
|
||||
@@ -282,11 +297,44 @@ void generic_anim_unload(generic_anim *ga)
|
||||
}
|
||||
|
||||
//for timer debug, #define TIMER
|
||||
void generic_render_eff_stream(generic_anim *ga)
|
||||
{
|
||||
if(ga->current_frame == ga->previous_frame)
|
||||
return;
|
||||
int i;
|
||||
int bpp = 32;
|
||||
if(ga->colored)
|
||||
bpp = 8;
|
||||
#ifdef TIMER
|
||||
int start_time = timer_get_fixed_seconds();
|
||||
#endif
|
||||
|
||||
#ifdef TIMER
|
||||
mprintf(("=========================\n"));
|
||||
mprintf(("frame: %d\n", ga->current_frame));
|
||||
#endif
|
||||
char frame_name[32];
|
||||
snprintf(frame_name, 32, "%s_%.4d", ga->filename, ga->current_frame);
|
||||
if(bm_reload(ga->eff.next_frame, frame_name) == ga->eff.next_frame)
|
||||
{
|
||||
bitmap* next_frame_bmp = bm_lock(ga->eff.next_frame, bpp, (bpp==8)?BMP_AABITMAP:BMP_TEX_NONCOMP, true);
|
||||
if(next_frame_bmp->data)
|
||||
gr_update_texture(ga->bitmap_id, bpp, (ubyte*)next_frame_bmp->data);
|
||||
bm_unlock(ga->eff.next_frame);
|
||||
bm_unload(ga->eff.next_frame, 0, true);
|
||||
}
|
||||
#ifdef TIMER
|
||||
mprintf(("end: %d\n", timer_get_fixed_seconds() - start_time));
|
||||
mprintf(("=========================\n"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void generic_render_ani_stream(generic_anim *ga)
|
||||
{
|
||||
int i;
|
||||
int bpp = ANI_BPP_CHECK;
|
||||
|
||||
if(ga->colored)
|
||||
bpp = 8;
|
||||
#ifdef TIMER
|
||||
int start_time = timer_get_fixed_seconds();
|
||||
#endif
|
||||
@@ -310,10 +358,10 @@ void generic_render_ani_stream(generic_anim *ga)
|
||||
ga->ani.instance->data = ga->ani.animation->data + ga->ani.animation->keys[ga->current_frame].offset;
|
||||
}
|
||||
if(ga->ani.animation->flags & ANF_STREAMED) {
|
||||
ga->ani.instance->file_offset = unpack_frame_from_file(ga->ani.instance, ga->buffer, ga->width * ga->height, (ga->ani.instance->xlate_pal) ? ga->ani.animation->palette_translation : NULL, 0, bpp);
|
||||
ga->ani.instance->file_offset = unpack_frame_from_file(ga->ani.instance, ga->buffer, ga->width * ga->height, (ga->ani.instance->xlate_pal) ? ga->ani.animation->palette_translation : NULL, (bpp==8)?1:0, bpp);
|
||||
}
|
||||
else {
|
||||
ga->ani.instance->data = unpack_frame(ga->ani.instance, ga->ani.instance->data, ga->buffer, ga->width * ga->height, (ga->ani.instance->xlate_pal) ? ga->ani.animation->palette_translation : NULL, 0, bpp);
|
||||
ga->ani.instance->data = unpack_frame(ga->ani.instance, ga->ani.instance->data, ga->buffer, ga->width * ga->height, (ga->ani.instance->xlate_pal) ? ga->ani.animation->palette_translation : NULL, (bpp==8)?1:0, bpp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -341,20 +389,18 @@ void generic_render_ani_stream(generic_anim *ga)
|
||||
#endif
|
||||
for(i = ga->previous_frame + 1; i <= ga->current_frame; i++) {
|
||||
if(ga->ani.animation->flags & ANF_STREAMED) {
|
||||
ga->ani.instance->file_offset = unpack_frame_from_file(ga->ani.instance, ga->buffer, ga->width * ga->height, (ga->ani.instance->xlate_pal) ? ga->ani.animation->palette_translation : NULL, 0, bpp);
|
||||
ga->ani.instance->file_offset = unpack_frame_from_file(ga->ani.instance, ga->buffer, ga->width * ga->height, (ga->ani.instance->xlate_pal) ? ga->ani.animation->palette_translation : NULL, (bpp==8)?1:0, bpp);
|
||||
}
|
||||
else {
|
||||
ga->ani.instance->data = unpack_frame(ga->ani.instance, ga->ani.instance->data, ga->buffer, ga->width * ga->height, (ga->ani.instance->xlate_pal) ? ga->ani.animation->palette_translation : NULL, 0, bpp);
|
||||
ga->ani.instance->data = unpack_frame(ga->ani.instance, ga->ani.instance->data, ga->buffer, ga->width * ga->height, (ga->ani.instance->xlate_pal) ? ga->ani.animation->palette_translation : NULL, (bpp==8)?1:0, bpp);
|
||||
}
|
||||
}
|
||||
}
|
||||
// always go back to screen format
|
||||
BM_SELECT_SCREEN_FORMAT();
|
||||
//we need to use this because performance is worse if we flush the gfx card buffer
|
||||
if ( ga->ani.instance->last_bitmap != -1 ){
|
||||
bm_release(ga->ani.instance->last_bitmap);
|
||||
}
|
||||
ga->bitmap_id = bm_create(bpp, ga->width, ga->height, ga->buffer, 0);
|
||||
|
||||
gr_update_texture(ga->bitmap_id, bpp, ga->buffer);
|
||||
|
||||
//in case we want to check that the frame is actually changing
|
||||
//mprintf(("frame crc = %08X\n", cf_add_chksum_long(0, ga->buffer, ga->width * ga->height * (bpp >> 3))));
|
||||
@@ -401,7 +447,7 @@ void generic_anim_render(generic_anim *ga, float frametime, int x, int y)
|
||||
if(ga->direction & GENERIC_ANIM_DIRECTION_NOLOOP) {
|
||||
ga->anim_time = ga->total_time - 0.001f; //stop on last frame when playing - if it's equal we jump to the first frame
|
||||
}
|
||||
else if(!ga->done_playing){
|
||||
if(!ga->done_playing){
|
||||
//we've played this at least once
|
||||
ga->done_playing = 1;
|
||||
}
|
||||
@@ -425,6 +471,8 @@ void generic_anim_render(generic_anim *ga, float frametime, int x, int y)
|
||||
//TODO: add EFF streaming
|
||||
if(ga->type == BM_TYPE_ANI) {
|
||||
generic_render_ani_stream(ga);
|
||||
} else {
|
||||
generic_render_eff_stream(ga);
|
||||
}
|
||||
gr_set_bitmap(ga->bitmap_id);
|
||||
}
|
||||
@@ -432,6 +480,9 @@ void generic_anim_render(generic_anim *ga, float frametime, int x, int y)
|
||||
gr_set_bitmap(ga->first_frame + ga->current_frame);
|
||||
}
|
||||
ga->previous_frame = ga->current_frame;
|
||||
gr_bitmap(x, y);
|
||||
if(ga->colored)
|
||||
gr_aabitmap(x,y);
|
||||
else
|
||||
gr_bitmap(x,y);
|
||||
}
|
||||
}
|
||||
@@ -33,9 +33,8 @@ typedef struct generic_anim {
|
||||
anim_instance *instance;
|
||||
unsigned char bg_type; //to store background type to avoid messed up colours
|
||||
} ani;
|
||||
//reserved for eff streaming
|
||||
struct {
|
||||
//
|
||||
int next_frame;
|
||||
} eff;
|
||||
};
|
||||
ubyte type;
|
||||
@@ -44,6 +43,7 @@ typedef struct generic_anim {
|
||||
int height;
|
||||
int width;
|
||||
int bitmap_id;
|
||||
bool colored;
|
||||
} generic_anim;
|
||||
|
||||
// Goober5000
|
||||
|
||||
@@ -1846,6 +1846,8 @@ void opengl_setup_function_pointers()
|
||||
gr_screen.gf_set_team_color = gr_opengl_set_team_color;
|
||||
gr_screen.gf_enable_team_color = gr_opengl_enable_team_color;
|
||||
gr_screen.gf_disable_team_color = gr_opengl_disable_team_color;
|
||||
|
||||
gr_screen.gf_update_texture = gr_opengl_update_texture;
|
||||
// NOTE: All function pointers here should have a Cmdline_nohtl check at the top
|
||||
// if they shouldn't be run in non-HTL mode, Don't keep separate entries.
|
||||
// *****************************************************************************
|
||||
|
||||
@@ -418,7 +418,7 @@ extern bool opengl_texture_slot_valid(int n, int handle);
|
||||
/**
|
||||
* Lock an image files data into memory
|
||||
*/
|
||||
int gr_opengl_bm_lock( char *filename, int handle, int bitmapnum, ubyte bpp, ubyte flags )
|
||||
int gr_opengl_bm_lock( char *filename, int handle, int bitmapnum, ubyte bpp, ubyte flags, bool nodebug)
|
||||
{
|
||||
ubyte c_type = BM_TYPE_NONE;
|
||||
ubyte true_bpp;
|
||||
@@ -438,13 +438,13 @@ int gr_opengl_bm_lock( char *filename, int handle, int bitmapnum, ubyte bpp, uby
|
||||
if ( (bmp->data == 0) && !opengl_texture_slot_valid(bitmapnum, handle) ) {
|
||||
Assert(be->ref_count == 1);
|
||||
|
||||
if (be->type != BM_TYPE_USER) {
|
||||
if (be->type != BM_TYPE_USER && !nodebug) {
|
||||
if (bmp->data == 0)
|
||||
nprintf (("BmpMan", "Loading %s for the first time.\n", be->filename));
|
||||
}
|
||||
|
||||
if ( !Bm_paging ) {
|
||||
if (be->type != BM_TYPE_USER)
|
||||
if (be->type != BM_TYPE_USER && !nodebug)
|
||||
nprintf(("Paging", "Loading %s (%dx%dx%d)\n", be->filename, bmp->w, bmp->h, true_bpp));
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ void gr_opengl_bm_init(int n);
|
||||
void gr_opengl_bm_page_in_start();
|
||||
|
||||
// Lock an image files data into memory
|
||||
int gr_opengl_bm_lock(char *filename, int handle, int bitmapnum, ubyte bpp, ubyte flags);
|
||||
int gr_opengl_bm_lock(char *filename, int handle, int bitmapnum, ubyte bpp, ubyte flags, bool nodebug);
|
||||
|
||||
void gr_opengl_bm_save_render_target(int slot);
|
||||
int gr_opengl_bm_make_render_target(int n, int *width, int *height, ubyte *bpp, int *mm_lvl, int flags);
|
||||
|
||||
@@ -1388,6 +1388,70 @@ int opengl_export_image( int slot, int width, int height, int alpha, int num_mip
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
void gr_opengl_update_texture(int bitmap_handle, int bpp, ubyte* data)
|
||||
{
|
||||
GLenum texFormat, glFormat;
|
||||
int n = bm_get_cache_slot (bitmap_handle, 1);
|
||||
tcache_slot_opengl *t = &Textures[n];
|
||||
if(!t->texture_id)
|
||||
return;
|
||||
int byte_mult = (bpp >> 3);
|
||||
int true_byte_mult = (t->bpp >> 3);
|
||||
ubyte* texmem = NULL;
|
||||
// GL_BGRA_EXT is *much* faster with some hardware/drivers
|
||||
if (true_byte_mult == 4) {
|
||||
texFormat = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
glFormat = GL_BGRA;
|
||||
} else if (true_byte_mult == 3) {
|
||||
texFormat = GL_UNSIGNED_BYTE;
|
||||
glFormat = GL_BGR;
|
||||
} else {
|
||||
texFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV;
|
||||
glFormat = GL_BGRA;
|
||||
}
|
||||
if (byte_mult == 1) {
|
||||
texFormat = GL_UNSIGNED_BYTE;
|
||||
glFormat = GL_ALPHA;
|
||||
texmem = (ubyte *) vm_malloc (t->w*t->h*byte_mult);
|
||||
ubyte* texmemp = texmem;
|
||||
|
||||
Assert( texmem != NULL );
|
||||
|
||||
int luminance = 0;
|
||||
for (int i = 0; i < t->h; i++) {
|
||||
for (int j = 0; j < t->w; j++) {
|
||||
if ( (i < t->h) && (j < t->w) ) {
|
||||
if ( true_byte_mult > 1 ) {
|
||||
luminance = 0;
|
||||
|
||||
if ( true_byte_mult > 3 ) {
|
||||
for (int k = 0; k < 3; k++) {
|
||||
luminance += data[(i*t->w+j)*true_byte_mult+k];
|
||||
}
|
||||
|
||||
*texmemp++ = (ubyte)((luminance / 3) * (data[(i*t->w+j)*true_byte_mult+3]/255.0f));
|
||||
} else {
|
||||
for (int k = 0; k < true_byte_mult; k++) {
|
||||
luminance += data[(i*t->w+j)*true_byte_mult+k];
|
||||
}
|
||||
|
||||
*texmemp++ = (ubyte)(luminance / true_byte_mult);
|
||||
}
|
||||
} else {
|
||||
*texmemp++ = GL_xlat[data[i*t->w+j]];
|
||||
}
|
||||
} else {
|
||||
*texmemp++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, t->texture_id);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, t->w, t->h, glFormat, texFormat, (texmem)?texmem:data);
|
||||
if (texmem != NULL)
|
||||
vm_free(texmem);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// GL_EXT_framebuffer_object stuff (ie, render-to-texture)
|
||||
//
|
||||
|
||||
@@ -459,6 +459,10 @@ void gr_stub_flush_data_states()
|
||||
{
|
||||
}
|
||||
|
||||
void gr_stub_update_texture(int bitmap_handle, int bpp, ubyte* data)
|
||||
{
|
||||
}
|
||||
|
||||
// bitmap functions
|
||||
int gr_stub_bm_load(ubyte type, int n, char *filename, CFILE *img_cfp, int *w, int *h, int *bpp, ubyte *c_type, int *mm_lvl, int *size)
|
||||
{
|
||||
@@ -549,7 +553,7 @@ int gr_stub_bm_load(ubyte type, int n, char *filename, CFILE *img_cfp, int *w, i
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gr_stub_bm_lock(char *filename, int handle, int bitmapnum, ubyte bpp, ubyte flags)
|
||||
int gr_stub_bm_lock(char *filename, int handle, int bitmapnum, ubyte bpp, ubyte flags, bool nodebug)
|
||||
{
|
||||
ubyte c_type = BM_TYPE_NONE;
|
||||
ubyte true_bpp;
|
||||
@@ -862,6 +866,6 @@ bool gr_stub_init()
|
||||
gr_screen.gf_enable_team_color = gr_stub_enable_team_color;
|
||||
gr_screen.gf_disable_team_color = gr_stub_disable_team_color;
|
||||
|
||||
|
||||
gr_screen.gf_update_texture = gr_stub_update_texture;
|
||||
return true;
|
||||
}
|
||||
@@ -1237,7 +1237,7 @@ void HudGaugeTalkingHead::render(float frametime)
|
||||
}
|
||||
|
||||
if(msg_id != -1 && head_anim != NULL) {
|
||||
if(anim_playing(head_anim)) {
|
||||
if(!head_anim->done_playing) {
|
||||
// draw frame
|
||||
// hud_set_default_color();
|
||||
setGaugeColor();
|
||||
@@ -1248,11 +1248,12 @@ void HudGaugeTalkingHead::render(float frametime)
|
||||
resetClip();
|
||||
|
||||
renderBitmap(Head_frame.first_frame, position[0], position[1]); // head ani border
|
||||
|
||||
gr_set_screen_scale(base_w, base_h);
|
||||
setGaugeColor();
|
||||
generic_anim_render(head_anim,frametime, position[0] + Anim_offsets[0] + fl2i(HUD_offset_x), position[1] + Anim_offsets[1] + fl2i(HUD_offset_y));
|
||||
// draw title
|
||||
renderString(position[0] + Header_offsets[0], position[1] + Header_offsets[1], XSTR("message", 217));
|
||||
} else {
|
||||
anim_stop_playing(head_anim);
|
||||
for (int j = 0; j < Num_messages_playing; ++j) {
|
||||
if (Playing_messages[j].id == msg_id) {
|
||||
Playing_messages[j].play_anim = false;
|
||||
@@ -1267,13 +1268,8 @@ void HudGaugeTalkingHead::render(float frametime)
|
||||
for (int i = 0; i < Num_messages_playing; i++ ) {
|
||||
if(Playing_messages[i].play_anim && Playing_messages[i].id != msg_id ) {
|
||||
msg_id = Playing_messages[i].id;
|
||||
if(head_anim) {
|
||||
if(anim_playing(head_anim)) {
|
||||
anim_stop_playing(head_anim);
|
||||
}
|
||||
}
|
||||
if (Playing_messages[i].anim_data)
|
||||
head_anim = createAnim(Playing_messages[i].start_frame, Playing_messages[i].anim_data);
|
||||
head_anim = Playing_messages[i].anim_data;
|
||||
else
|
||||
head_anim = NULL;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "hud/hud.h"
|
||||
#include "anim/packunpack.h"
|
||||
#include "graphics/generic.h"
|
||||
|
||||
#define MAX_HUD_LINE_LEN 256 // maximum number of characters for a HUD message
|
||||
|
||||
@@ -124,7 +125,8 @@ class HudGaugeTalkingHead: public HudGauge // HUD_TALKING_HEAD
|
||||
int Anim_offsets[2];
|
||||
int Anim_size[2];
|
||||
|
||||
anim_instance *head_anim;
|
||||
generic_anim *head_anim;
|
||||
|
||||
int msg_id;
|
||||
public:
|
||||
HudGaugeTalkingHead();
|
||||
|
||||
@@ -309,7 +309,7 @@ int add_avi( char *avi_name )
|
||||
// would have returned if a slot existed.
|
||||
strcpy_s( extra.name, avi_name );
|
||||
extra.num = -1;
|
||||
extra.anim_data = NULL;
|
||||
generic_anim_unload(&extra.anim_data);
|
||||
Message_avis.push_back(extra);
|
||||
Num_message_avis++;
|
||||
return ((int)Message_avis.size() - 1);
|
||||
@@ -622,7 +622,7 @@ void messages_init()
|
||||
// this forces a reload of the AVI's and waves for builtin messages. Needed because the flic and
|
||||
// sound system also get reset between missions!
|
||||
for (i = 0; i < Num_builtin_avis; i++ ) {
|
||||
Message_avis[i].anim_data = NULL;
|
||||
generic_anim_unload(&Message_avis[i].anim_data);
|
||||
}
|
||||
|
||||
for (i = 0; i < Num_builtin_waves; i++ ){
|
||||
@@ -663,8 +663,6 @@ void messages_init()
|
||||
// free a loaded avi
|
||||
void message_mission_free_avi(int m_index)
|
||||
{
|
||||
int rc = 0, try_count = 0;
|
||||
|
||||
// check for bogus index
|
||||
if ( (m_index < 0) || (m_index >= Num_message_avis) )
|
||||
return;
|
||||
@@ -674,21 +672,7 @@ void message_mission_free_avi(int m_index)
|
||||
if ( !hud_gauge_active(HUD_TALKING_HEAD) )
|
||||
return;
|
||||
|
||||
if (Message_avis[m_index].anim_data != NULL) {
|
||||
do {
|
||||
rc = anim_free( Message_avis[m_index].anim_data );
|
||||
try_count++;
|
||||
|
||||
// -2 is to catch a point where the data isn't valid and we want
|
||||
// to just abort right now rather than to keep trying
|
||||
if (rc == -2)
|
||||
break;
|
||||
|
||||
// stop at 25 tries to avoid a possible endless loop
|
||||
} while ( rc && (try_count < 25) );
|
||||
|
||||
Message_avis[m_index].anim_data = NULL;
|
||||
}
|
||||
generic_anim_unload(&Message_avis[m_index].anim_data);
|
||||
}
|
||||
|
||||
// called to do cleanup when leaving a mission
|
||||
@@ -1045,7 +1029,7 @@ bool message_play_wave( message_q *q )
|
||||
// input: time => time of voice clip, in ms
|
||||
// ani => pointer to anim data
|
||||
// reverse => flag to indicate that the start should be time ms from the end (used for death screams)
|
||||
int message_calc_anim_start_frame(int time, anim *ani, int reverse)
|
||||
void message_calc_anim_start_frame(int time, generic_anim *ani, int reverse)
|
||||
{
|
||||
float wave_time, anim_time;
|
||||
int start_frame;
|
||||
@@ -1054,23 +1038,24 @@ int message_calc_anim_start_frame(int time, anim *ani, int reverse)
|
||||
|
||||
// If no voice clip exists, start from beginning of anim
|
||||
if ( time <= 0 ) {
|
||||
return start_frame;
|
||||
return;
|
||||
}
|
||||
|
||||
// convert time to seconds
|
||||
wave_time = time/1000.0f;
|
||||
anim_time = ani->time;
|
||||
anim_time = ani->total_time;
|
||||
|
||||
// If voice clip is longer than anim, start from beginning of anim
|
||||
if ( wave_time >= (anim_time) ) {
|
||||
return start_frame;
|
||||
return;
|
||||
}
|
||||
|
||||
float fps = ani->num_frames / ani->total_time;
|
||||
if ( reverse ) {
|
||||
start_frame = (ani->total_frames-1) - fl2i(ani->fps * wave_time + 0.5f);
|
||||
start_frame = (ani->num_frames-1) - fl2i(fps * wave_time + 0.5f);
|
||||
} else {
|
||||
int num_frames_extra;
|
||||
num_frames_extra = fl2i(ani->fps * (anim_time - wave_time) + 0.5f);
|
||||
num_frames_extra = fl2i(fps * (anim_time - wave_time) + 0.5f);
|
||||
if ( num_frames_extra > 0 ) {
|
||||
start_frame=rand()%num_frames_extra;
|
||||
}
|
||||
@@ -1081,7 +1066,8 @@ int message_calc_anim_start_frame(int time, anim *ani, int reverse)
|
||||
start_frame=0;
|
||||
}
|
||||
|
||||
return start_frame;
|
||||
ani->current_frame = start_frame;
|
||||
ani->anim_time = fps / start_frame;
|
||||
}
|
||||
|
||||
// Play animation associated with message
|
||||
@@ -1089,6 +1075,7 @@ int message_calc_anim_start_frame(int time, anim *ani, int reverse)
|
||||
// q => message queue data
|
||||
//
|
||||
// note: changes Messave_wave_duration, Playing_messages[].wave, and Message_waves[].num
|
||||
extern bool Headani_color;
|
||||
void message_play_anim( message_q *q )
|
||||
{
|
||||
message_extra *anim_info;
|
||||
@@ -1182,13 +1169,15 @@ void message_play_anim( message_q *q )
|
||||
// the avi, set the top level index to -1 to avoid multiple tries at loading the flick.
|
||||
|
||||
// if there is something already here that's not this same file then go ahead a let go of it - taylor
|
||||
if ( (anim_info->anim_data != NULL) && !strstr(anim_info->anim_data->name, ani_name) ) {
|
||||
if ( !strstr(anim_info->anim_data.filename, ani_name) ) {
|
||||
message_mission_free_avi( m->avi_info.index );
|
||||
}
|
||||
|
||||
anim_info->anim_data = anim_load( ani_name, CF_TYPE_ANY, 0 );
|
||||
generic_anim_init(&anim_info->anim_data, ani_name);
|
||||
if(Headani_color)
|
||||
anim_info->anim_data.colored = true;
|
||||
|
||||
if ( anim_info->anim_data == NULL ) {
|
||||
if ( generic_anim_stream(&anim_info->anim_data) < 0 ) {
|
||||
nprintf (("messaging", "Cannot load message avi %s. Will not play.\n", ani_name));
|
||||
m->avi_info.index = -1; // if cannot load the avi -- set this index to -1 to avoid trying to load multiple times
|
||||
}
|
||||
@@ -1205,9 +1194,10 @@ void message_play_anim( message_q *q )
|
||||
if ( hud_disabled() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Playing_messages[Num_messages_playing].anim_data = anim_info->anim_data;
|
||||
Playing_messages[Num_messages_playing].start_frame = message_calc_anim_start_frame(Message_wave_duration, anim_info->anim_data, is_death_scream);
|
||||
|
||||
anim_info->anim_data.direction = GENERIC_ANIM_DIRECTION_NOLOOP;
|
||||
Playing_messages[Num_messages_playing].anim_data = &anim_info->anim_data;
|
||||
message_calc_anim_start_frame(Message_wave_duration, &anim_info->anim_data, is_death_scream);
|
||||
Playing_messages[Num_messages_playing].play_anim = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "globalincs/globals.h" // include so that we can gets defs for lengths of tokens
|
||||
#include "anim/packunpack.h"
|
||||
#include "graphics/generic.h"
|
||||
|
||||
struct ship;
|
||||
|
||||
@@ -26,7 +27,7 @@ struct ship;
|
||||
typedef struct message_extra {
|
||||
char name[MAX_FILENAME_LEN];
|
||||
int num;
|
||||
anim *anim_data;
|
||||
generic_anim anim_data;
|
||||
} message_extra;
|
||||
|
||||
extern SCP_vector<message_extra> Message_avis;
|
||||
@@ -139,7 +140,7 @@ extern SCP_vector<MMessage> Messages;
|
||||
|
||||
typedef struct pmessage {
|
||||
//anim_instance *anim; // handle of anim currently playing
|
||||
anim *anim_data; // animation data to be used by the talking head HUD gauge handler
|
||||
generic_anim *anim_data; // animation data to be used by the talking head HUD gauge handler
|
||||
int start_frame; // the start frame needed to play the animation
|
||||
bool play_anim; // used to tell HUD gauges if they should be playing or not
|
||||
int wave; // handle of wave currently playing
|
||||
|
||||
@@ -21,6 +21,7 @@ bool Alternate_chaining_behavior;
|
||||
int Default_ship_select_effect;
|
||||
int Default_weapon_select_effect;
|
||||
bool Enable_external_shaders = false;
|
||||
bool Headani_color = true;
|
||||
|
||||
|
||||
void parse_mod_table(char *filename)
|
||||
@@ -80,6 +81,10 @@ void parse_mod_table(char *filename)
|
||||
if (optional_string("$Cutscene camera disables HUD:")) {
|
||||
stuff_boolean(&Cutscene_camera_disables_hud);
|
||||
}
|
||||
|
||||
if (optional_string("$Color head animations with hud colors:")) {
|
||||
stuff_boolean(&Headani_color);
|
||||
}
|
||||
|
||||
optional_string("#SEXP SETTINGS");
|
||||
|
||||
|
||||
Reference in new issue
Block a user