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:
Valathil committed 2012-08-14 23:48:23 +00:00
1 parent 71ccf2e274
commit 48e0517e0d
17 files changed
+242 -81

No files matched your search

+40 -7
View File
@@ -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
}
+6 -2
View File
@@ -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
+1 -1
View File
@@ -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();
+2 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
}
+2 -2
View File
@@ -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
+2
View File
@@ -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.
// *****************************************************************************
+3 -3
View File
@@ -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));
}
+1 -1
View File
@@ -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);
+64
View File
@@ -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)
//
+6 -2
View File
@@ -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;
}
+5 -9
View File
@@ -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;
+3 -1
View File
@@ -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();
+22 -32
View File
@@ -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;
}
}
+3 -2
View File
@@ -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
+5
View File
@@ -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");