2006-04-13 20:47:06 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
2010-05-25 10:56:00 +00:00
|
|
|
Copyright (C) 2010 EDuke32 developers and contributors
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2010-05-25 10:56:00 +00:00
|
|
|
This file is part of EDuke32.
|
2006-04-13 20:47:06 +00:00
|
|
|
|
|
|
|
EDuke32 is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License version 2
|
|
|
|
as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
2014-07-20 08:55:56 +00:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2006-04-13 20:47:06 +00:00
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
|
2019-09-21 18:59:54 +00:00
|
|
|
#include "ns.h" // Must come before everything else!
|
|
|
|
|
2014-09-30 04:15:17 +00:00
|
|
|
#include "baselayer.h"
|
|
|
|
#include "renderlayer.h"
|
2006-04-13 20:47:06 +00:00
|
|
|
#include "duke3d.h"
|
|
|
|
#include "animlib.h"
|
2006-12-12 04:31:51 +00:00
|
|
|
#include "mouse.h"
|
2008-02-16 22:27:08 +00:00
|
|
|
#include "compat.h"
|
2012-06-03 16:11:22 +00:00
|
|
|
#include "input.h"
|
2006-04-13 20:47:06 +00:00
|
|
|
|
Possibility of specifying sounds for a VPX anim-replacement via DEF.
The syntax is as follows:
animsounds <anim> { frame1 sound1 frame2 sound2 ... }
<anim> has to be one of the tokens: cineov2, cineov3, RADLOGO, DUKETEAM,
logo, vol41a, vol42a, vol4e1, vol43a, vol4e2, or vol4e3, corresponding
to hard-coded Duke3D anims.
The frameN's (1-based frame numbers) have to be in ascending order (but not
necessarily strictly ascending, so that a frame may have more than one sound).
Example: for Duke3D's XBLA nuke logo animation (IVF extracted from nuke.webm),
the following definition overlays the video with a sound sequence similar
(identical save for timing) to the original nuke animation:
// frame 1: FLY_BY, frame 64: PIPEBOMB_EXPLODE
animsounds logo { 1 244 64 14 }
git-svn-id: https://svn.eduke32.com/eduke32@2242 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-10 23:43:54 +00:00
|
|
|
#include "anim.h"
|
|
|
|
|
2011-07-18 19:06:29 +00:00
|
|
|
#ifdef USE_LIBVPX
|
|
|
|
# include "animvpx.h"
|
|
|
|
#endif
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
#include "vfs.h"
|
|
|
|
|
2019-09-21 20:53:00 +00:00
|
|
|
BEGIN_DUKE_NS
|
|
|
|
|
|
|
|
|
2017-06-25 11:24:27 +00:00
|
|
|
// animsound_t.sound
|
|
|
|
EDUKE32_STATIC_ASSERT(INT16_MAX >= MAXSOUNDS);
|
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
hashtable_t h_dukeanim = { 8, NULL };
|
|
|
|
dukeanim_t * g_animPtr;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-02-07 02:38:28 +00:00
|
|
|
dukeanim_t *Anim_Find(const char *s)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-02-11 05:22:07 +00:00
|
|
|
intptr_t ptr = hash_findcase(&h_dukeanim, s);
|
2016-02-13 21:06:18 +00:00
|
|
|
|
|
|
|
if (ptr == -1)
|
|
|
|
{
|
|
|
|
int const siz = Bstrlen(s) + 5;
|
|
|
|
char * const str = (char *)Xcalloc(1, siz);
|
|
|
|
|
|
|
|
maybe_append_ext(str, siz, s, ".anm");
|
|
|
|
ptr = hash_findcase(&h_dukeanim, str);
|
|
|
|
|
|
|
|
if (ptr == -1)
|
|
|
|
{
|
|
|
|
maybe_append_ext(str, siz, s, ".ivf");
|
|
|
|
ptr = hash_findcase(&h_dukeanim, str);
|
|
|
|
}
|
|
|
|
|
2019-06-25 11:29:08 +00:00
|
|
|
Xfree(str);
|
2016-02-13 21:06:18 +00:00
|
|
|
}
|
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
return (dukeanim_t *)(ptr == -1 ? NULL : (dukeanim_t *)ptr);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2017-06-25 11:24:10 +00:00
|
|
|
dukeanim_t * Anim_Create(char const * fn)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2017-06-25 11:24:10 +00:00
|
|
|
dukeanim_t * anim = (dukeanim_t *)Xcalloc(1, sizeof(dukeanim_t));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
hash_add(&h_dukeanim, fn, (intptr_t)anim, 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2017-06-25 11:24:10 +00:00
|
|
|
return anim;
|
|
|
|
}
|
2015-02-11 05:22:07 +00:00
|
|
|
|
2017-10-09 07:36:40 +00:00
|
|
|
#ifndef EDUKE32_STANDALONE
|
2017-06-25 11:24:34 +00:00
|
|
|
#ifdef DYNSOUNDREMAP_ENABLE
|
|
|
|
static int32_t const StopAllSounds = -1;
|
|
|
|
#else
|
|
|
|
# define StopAllSounds -1
|
|
|
|
#endif
|
2017-10-09 07:36:40 +00:00
|
|
|
#endif
|
2017-06-25 11:24:34 +00:00
|
|
|
|
2016-02-07 02:38:28 +00:00
|
|
|
void Anim_Init(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-02-11 05:22:07 +00:00
|
|
|
hash_init(&h_dukeanim);
|
|
|
|
|
2017-06-25 11:24:34 +00:00
|
|
|
|
|
|
|
struct defaultanmsound {
|
|
|
|
#ifdef DYNSOUNDREMAP_ENABLE
|
|
|
|
int32_t const & sound;
|
|
|
|
#else
|
|
|
|
int16_t sound;
|
|
|
|
#endif
|
|
|
|
uint8_t frame;
|
|
|
|
};
|
|
|
|
|
2017-06-27 01:50:48 +00:00
|
|
|
static defaultanmsound const logo[] =
|
|
|
|
{
|
|
|
|
{ FLY_BY, 1 },
|
|
|
|
{ PIPEBOMB_EXPLODE, 19 },
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifndef EDUKE32_STANDALONE
|
2017-06-25 11:24:34 +00:00
|
|
|
static defaultanmsound const cineov2[] =
|
|
|
|
{
|
|
|
|
{ WIND_AMBIENCE, 1 },
|
|
|
|
{ ENDSEQVOL2SND1, 26 },
|
|
|
|
{ ENDSEQVOL2SND2, 36 },
|
|
|
|
{ THUD, 54 },
|
|
|
|
{ ENDSEQVOL2SND3, 62 },
|
|
|
|
{ ENDSEQVOL2SND4, 75 },
|
|
|
|
{ ENDSEQVOL2SND5, 81 },
|
|
|
|
{ ENDSEQVOL2SND6, 115 },
|
|
|
|
{ ENDSEQVOL2SND7, 124 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static defaultanmsound const cineov3[] =
|
|
|
|
{
|
|
|
|
{ WIND_REPEAT, 1 },
|
|
|
|
{ DUKE_GRUNT, 98 },
|
|
|
|
{ THUD, 82+20 },
|
|
|
|
{ SQUISHED, 82+20 },
|
|
|
|
{ ENDSEQVOL3SND3, 104+20 },
|
|
|
|
{ ENDSEQVOL3SND2, 114+20 },
|
|
|
|
{ PIPEBOMB_EXPLODE, 158 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static defaultanmsound const vol42a[] =
|
|
|
|
{
|
|
|
|
{ INTRO4_B, 1 },
|
|
|
|
{ SHORT_CIRCUIT, 12 },
|
|
|
|
{ INTRO4_5, 18 },
|
|
|
|
{ SHORT_CIRCUIT, 34 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static defaultanmsound const vol41a[] =
|
|
|
|
{
|
|
|
|
{ INTRO4_1, 1 },
|
|
|
|
{ INTRO4_3, 7 },
|
|
|
|
{ INTRO4_2, 12 },
|
|
|
|
{ INTRO4_4, 26 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static defaultanmsound const vol43a[] =
|
|
|
|
{
|
|
|
|
{ INTRO4_6, 10 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static defaultanmsound const vol4e1[] =
|
|
|
|
{
|
|
|
|
{ DUKE_UNDERWATER, 3 },
|
|
|
|
{ VOL4ENDSND1, 35 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static defaultanmsound const vol4e2[] =
|
|
|
|
{
|
|
|
|
{ DUKE_UNDERWATER, 11 },
|
|
|
|
{ VOL4ENDSND1, 20 },
|
|
|
|
{ VOL4ENDSND2, 39 },
|
|
|
|
{ StopAllSounds, 50 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static defaultanmsound const vol4e3[] =
|
|
|
|
{
|
|
|
|
{ BOSS4_DEADSPEECH, 1 },
|
|
|
|
{ VOL4ENDSND1, 40 },
|
|
|
|
{ DUKE_UNDERWATER, 40 },
|
|
|
|
{ BIGBANG, 50 },
|
|
|
|
};
|
2017-06-27 01:50:48 +00:00
|
|
|
#endif
|
2017-06-25 11:24:34 +00:00
|
|
|
|
2017-06-25 11:24:14 +00:00
|
|
|
struct defaultanm {
|
|
|
|
char const *fn;
|
2017-06-25 11:24:34 +00:00
|
|
|
defaultanmsound const *sounds;
|
|
|
|
uint8_t numsounds;
|
2017-06-25 11:24:14 +00:00
|
|
|
uint8_t fdelay;
|
|
|
|
};
|
2017-06-24 21:18:06 +00:00
|
|
|
|
2017-06-25 11:24:34 +00:00
|
|
|
#define anmsnd(x) (x), ARRAY_SIZE(x)
|
2017-06-25 11:24:14 +00:00
|
|
|
static defaultanm const anms[] =
|
|
|
|
{
|
2017-06-25 11:24:34 +00:00
|
|
|
{ "logo.anm", anmsnd(logo), 9 },
|
|
|
|
{ "3dr.anm", NULL, 0, 10 },
|
2017-06-24 21:18:06 +00:00
|
|
|
#ifndef EDUKE32_STANDALONE
|
2017-06-25 11:24:34 +00:00
|
|
|
{ "vol4e1.anm", anmsnd(vol4e1), 10 },
|
|
|
|
{ "vol4e2.anm", anmsnd(vol4e2), 14 },
|
|
|
|
{ "vol4e3.anm", anmsnd(vol4e3), 10 },
|
|
|
|
{ "vol41a.anm", anmsnd(vol41a), 14 },
|
|
|
|
{ "vol42a.anm", anmsnd(vol42a), 18 },
|
|
|
|
{ "vol43a.anm", anmsnd(vol43a), 10 },
|
|
|
|
{ "duketeam.anm", NULL, 0, 10 },
|
|
|
|
{ "radlogo.anm", NULL, 0, 10 },
|
|
|
|
{ "cineov2.anm", anmsnd(cineov2), 18 },
|
|
|
|
{ "cineov3.anm", anmsnd(cineov3), 10 },
|
2017-06-24 21:18:06 +00:00
|
|
|
#endif
|
2017-06-25 11:24:14 +00:00
|
|
|
};
|
2017-06-25 11:24:34 +00:00
|
|
|
#undef anmsnd
|
2017-06-25 11:24:14 +00:00
|
|
|
|
|
|
|
for (defaultanm const & anm : anms)
|
|
|
|
{
|
|
|
|
dukeanim_t * anim = Anim_Create(anm.fn);
|
|
|
|
anim->framedelay = anm.fdelay;
|
2017-06-25 11:24:34 +00:00
|
|
|
|
|
|
|
if (anm.numsounds)
|
|
|
|
{
|
|
|
|
anim->sounds = (animsound_t *)Xmalloc(anm.numsounds * sizeof(animsound_t));
|
2019-05-19 03:56:13 +00:00
|
|
|
int const numsounds = anm.numsounds;
|
|
|
|
for (int i = 0; i < numsounds; ++i)
|
2017-06-25 11:24:34 +00:00
|
|
|
{
|
|
|
|
defaultanmsound const & src = anm.sounds[i];
|
|
|
|
animsound_t & dst = anim->sounds[i];
|
|
|
|
|
|
|
|
dst.sound = src.sound;
|
|
|
|
dst.frame = src.frame;
|
|
|
|
}
|
|
|
|
anim->numsounds = numsounds;
|
|
|
|
}
|
2017-12-12 05:13:38 +00:00
|
|
|
|
|
|
|
anim->frameflags = 0;
|
2017-06-25 11:24:14 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2016-02-07 02:38:28 +00:00
|
|
|
int32_t Anim_Play(const char *fn)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-02-07 02:38:28 +00:00
|
|
|
dukeanim_t *anim = Anim_Find(fn);
|
2015-02-11 05:22:07 +00:00
|
|
|
|
|
|
|
if (!anim)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-02-11 05:22:07 +00:00
|
|
|
OSD_Printf("Animation %s is undefined!\n", fn);
|
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2017-06-25 11:24:19 +00:00
|
|
|
uint16_t soundidx = 0; // custom anim sounds
|
2015-02-11 05:22:07 +00:00
|
|
|
int32_t running = 1, i;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-12-27 20:39:43 +00:00
|
|
|
I_ClearAllInput();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-07-18 19:06:29 +00:00
|
|
|
#ifdef USE_LIBVPX
|
2017-06-25 11:24:19 +00:00
|
|
|
uint16_t framenum = 0;
|
2018-04-12 21:03:12 +00:00
|
|
|
while (videoGetRenderMode() >= REND_POLYMOST) // if, really
|
2011-07-18 19:06:29 +00:00
|
|
|
{
|
2017-06-27 01:50:48 +00:00
|
|
|
char const * dot = Bstrrchr(fn, '.');
|
2017-06-25 11:24:39 +00:00
|
|
|
if (!dot)
|
2011-07-18 19:06:29 +00:00
|
|
|
break;
|
|
|
|
|
2017-06-25 11:24:43 +00:00
|
|
|
dukeanim_t const * origanim = anim;
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_kfd handle = buildvfs_kfd_invalid;
|
2017-06-25 11:24:39 +00:00
|
|
|
if (!Bstrcmp(dot, ".ivf"))
|
|
|
|
{
|
|
|
|
handle = kopen4loadfrommod(fn, 0);
|
2019-03-01 08:51:50 +00:00
|
|
|
if (handle == buildvfs_kfd_invalid)
|
2017-06-25 11:24:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char vpxfn[BMAX_PATH];
|
|
|
|
Bstrncpyz(vpxfn, fn, BMAX_PATH);
|
2011-07-18 19:06:29 +00:00
|
|
|
|
2017-06-25 11:24:39 +00:00
|
|
|
ptrdiff_t dotpos = dot - fn;
|
|
|
|
if (dotpos + 4 >= BMAX_PATH)
|
|
|
|
break;
|
|
|
|
|
|
|
|
char *vpxfndot = vpxfn + dotpos;
|
|
|
|
vpxfndot[1] = 'i';
|
|
|
|
vpxfndot[2] = 'v';
|
|
|
|
vpxfndot[3] = 'f';
|
|
|
|
vpxfndot[4] = '\0';
|
|
|
|
|
|
|
|
handle = kopen4loadfrommod(vpxfn, 0);
|
2019-03-01 08:51:50 +00:00
|
|
|
if (handle == buildvfs_kfd_invalid)
|
2017-06-25 11:24:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
anim = Anim_Find(vpxfn);
|
|
|
|
}
|
2011-07-18 19:06:29 +00:00
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
animvpx_ivf_header_t info;
|
2011-07-18 19:06:29 +00:00
|
|
|
i = animvpx_read_ivf_header(handle, &info);
|
2015-02-11 05:22:07 +00:00
|
|
|
|
2011-07-18 19:06:29 +00:00
|
|
|
if (i)
|
|
|
|
{
|
2015-02-11 05:22:07 +00:00
|
|
|
OSD_Printf("Failed reading IVF file: %s\n", animvpx_read_ivf_header_errmsg[i]);
|
2011-07-18 19:06:29 +00:00
|
|
|
kclose(handle);
|
2014-01-12 14:02:30 +00:00
|
|
|
return 0;
|
2011-07-18 19:06:29 +00:00
|
|
|
}
|
|
|
|
|
2017-12-12 05:13:38 +00:00
|
|
|
if (anim)
|
|
|
|
animvpx_setup_glstate(anim->frameflags);
|
|
|
|
else
|
|
|
|
animvpx_setup_glstate(origanim->frameflags);
|
2015-02-11 05:22:07 +00:00
|
|
|
|
|
|
|
animvpx_codec_ctx codec;
|
|
|
|
|
2011-07-18 19:06:29 +00:00
|
|
|
if (animvpx_init_codec(&info, handle, &codec))
|
|
|
|
{
|
2013-03-31 18:57:59 +00:00
|
|
|
OSD_Printf("Error initializing VPX codec.\n");
|
2011-07-18 19:06:29 +00:00
|
|
|
animvpx_restore_glstate();
|
2017-12-18 23:36:05 +00:00
|
|
|
kclose(handle);
|
2014-01-12 14:02:30 +00:00
|
|
|
return 0;
|
2011-07-18 19:06:29 +00:00
|
|
|
}
|
|
|
|
|
2017-06-25 11:24:43 +00:00
|
|
|
|
|
|
|
uint32_t const convnumer = 120 * info.fpsdenom;
|
|
|
|
uint32_t const convdenom = info.fpsnumer * origanim->framedelay;
|
|
|
|
|
|
|
|
uint32_t const msecsperframe = scale(info.fpsdenom, 1000, info.fpsnumer);
|
2018-04-12 21:02:51 +00:00
|
|
|
uint32_t nextframetime = timerGetTicks();
|
2015-02-11 05:22:07 +00:00
|
|
|
uint8_t *pic;
|
2011-07-18 19:06:29 +00:00
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
// OSD_Printf("msecs per frame: %d\n", msecsperframe);
|
2011-07-18 19:06:29 +00:00
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
do
|
2011-07-18 19:06:29 +00:00
|
|
|
{
|
|
|
|
nextframetime += msecsperframe;
|
|
|
|
|
|
|
|
i = animvpx_nextpic(&codec, &pic);
|
|
|
|
if (i)
|
|
|
|
{
|
2015-02-11 05:22:07 +00:00
|
|
|
OSD_Printf("Failed getting next pic: %s\n", animvpx_nextpic_errmsg[i]);
|
2011-07-18 19:06:29 +00:00
|
|
|
if (codec.errmsg)
|
|
|
|
{
|
|
|
|
OSD_Printf(" %s\n", codec.errmsg);
|
|
|
|
if (codec.errmsg_detail)
|
|
|
|
OSD_Printf(" detail: %s\n", codec.errmsg_detail);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pic)
|
|
|
|
break; // no more pics!
|
|
|
|
|
2017-12-02 09:24:55 +00:00
|
|
|
VM_OnEventWithReturn(EVENT_PRECUTSCENE, g_player[screenpeek].ps->i, screenpeek, framenum);
|
2017-11-29 07:29:04 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoClearScreen(0);
|
2017-11-29 07:29:17 +00:00
|
|
|
|
2017-11-29 07:29:20 +00:00
|
|
|
ototalclock = totalclock + 1; // pause game like ANMs
|
|
|
|
|
2017-12-12 05:13:32 +00:00
|
|
|
if (anim)
|
|
|
|
{
|
|
|
|
if (anim->frameaspect1 == 0 || anim->frameaspect2 == 0)
|
|
|
|
animvpx_render_frame(&codec, 0);
|
|
|
|
else
|
|
|
|
animvpx_render_frame(&codec, anim->frameaspect1 / anim->frameaspect2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (origanim->frameaspect1 == 0 || origanim->frameaspect2 == 0)
|
|
|
|
animvpx_render_frame(&codec, 0);
|
|
|
|
else
|
|
|
|
animvpx_render_frame(&codec, origanim->frameaspect1 / origanim->frameaspect2);
|
|
|
|
}
|
2011-07-18 19:06:29 +00:00
|
|
|
|
2017-12-02 09:24:55 +00:00
|
|
|
VM_OnEventWithReturn(EVENT_CUTSCENE, g_player[screenpeek].ps->i, screenpeek, framenum);
|
2017-11-29 07:29:01 +00:00
|
|
|
|
Possibility of specifying sounds for a VPX anim-replacement via DEF.
The syntax is as follows:
animsounds <anim> { frame1 sound1 frame2 sound2 ... }
<anim> has to be one of the tokens: cineov2, cineov3, RADLOGO, DUKETEAM,
logo, vol41a, vol42a, vol4e1, vol43a, vol4e2, or vol4e3, corresponding
to hard-coded Duke3D anims.
The frameN's (1-based frame numbers) have to be in ascending order (but not
necessarily strictly ascending, so that a frame may have more than one sound).
Example: for Duke3D's XBLA nuke logo animation (IVF extracted from nuke.webm),
the following definition overlays the video with a sound sequence similar
(identical save for timing) to the original nuke animation:
// frame 1: FLY_BY, frame 64: PIPEBOMB_EXPLODE
animsounds logo { 1 244 64 14 }
git-svn-id: https://svn.eduke32.com/eduke32@2242 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-10 23:43:54 +00:00
|
|
|
// after rendering the frame but before displaying: maybe play sound...
|
|
|
|
framenum++;
|
2017-06-25 11:24:39 +00:00
|
|
|
if (anim)
|
Possibility of specifying sounds for a VPX anim-replacement via DEF.
The syntax is as follows:
animsounds <anim> { frame1 sound1 frame2 sound2 ... }
<anim> has to be one of the tokens: cineov2, cineov3, RADLOGO, DUKETEAM,
logo, vol41a, vol42a, vol4e1, vol43a, vol4e2, or vol4e3, corresponding
to hard-coded Duke3D anims.
The frameN's (1-based frame numbers) have to be in ascending order (but not
necessarily strictly ascending, so that a frame may have more than one sound).
Example: for Duke3D's XBLA nuke logo animation (IVF extracted from nuke.webm),
the following definition overlays the video with a sound sequence similar
(identical save for timing) to the original nuke animation:
// frame 1: FLY_BY, frame 64: PIPEBOMB_EXPLODE
animsounds logo { 1 244 64 14 }
git-svn-id: https://svn.eduke32.com/eduke32@2242 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-10 23:43:54 +00:00
|
|
|
{
|
2017-06-25 11:24:43 +00:00
|
|
|
while (soundidx < anim->numsounds && anim->sounds[soundidx].frame <= framenum)
|
2017-06-25 11:24:39 +00:00
|
|
|
{
|
|
|
|
int16_t sound = anim->sounds[soundidx].sound;
|
|
|
|
if (sound == -1)
|
|
|
|
FX_StopAllSounds();
|
|
|
|
else
|
|
|
|
S_PlaySound(sound);
|
2017-06-25 11:24:27 +00:00
|
|
|
|
2017-06-25 11:24:39 +00:00
|
|
|
soundidx++;
|
|
|
|
}
|
Possibility of specifying sounds for a VPX anim-replacement via DEF.
The syntax is as follows:
animsounds <anim> { frame1 sound1 frame2 sound2 ... }
<anim> has to be one of the tokens: cineov2, cineov3, RADLOGO, DUKETEAM,
logo, vol41a, vol42a, vol4e1, vol43a, vol4e2, or vol4e3, corresponding
to hard-coded Duke3D anims.
The frameN's (1-based frame numbers) have to be in ascending order (but not
necessarily strictly ascending, so that a frame may have more than one sound).
Example: for Duke3D's XBLA nuke logo animation (IVF extracted from nuke.webm),
the following definition overlays the video with a sound sequence similar
(identical save for timing) to the original nuke animation:
// frame 1: FLY_BY, frame 64: PIPEBOMB_EXPLODE
animsounds logo { 1 244 64 14 }
git-svn-id: https://svn.eduke32.com/eduke32@2242 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-10 23:43:54 +00:00
|
|
|
}
|
2017-06-25 11:24:43 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
uint16_t convframenum = scale(framenum, convnumer, convdenom);
|
|
|
|
while (soundidx < origanim->numsounds && origanim->sounds[soundidx].frame <= convframenum)
|
|
|
|
{
|
|
|
|
int16_t sound = origanim->sounds[soundidx].sound;
|
|
|
|
if (sound == -1)
|
|
|
|
FX_StopAllSounds();
|
|
|
|
else
|
|
|
|
S_PlaySound(sound);
|
|
|
|
|
|
|
|
soundidx++;
|
|
|
|
}
|
|
|
|
}
|
Possibility of specifying sounds for a VPX anim-replacement via DEF.
The syntax is as follows:
animsounds <anim> { frame1 sound1 frame2 sound2 ... }
<anim> has to be one of the tokens: cineov2, cineov3, RADLOGO, DUKETEAM,
logo, vol41a, vol42a, vol4e1, vol43a, vol4e2, or vol4e3, corresponding
to hard-coded Duke3D anims.
The frameN's (1-based frame numbers) have to be in ascending order (but not
necessarily strictly ascending, so that a frame may have more than one sound).
Example: for Duke3D's XBLA nuke logo animation (IVF extracted from nuke.webm),
the following definition overlays the video with a sound sequence similar
(identical save for timing) to the original nuke animation:
// frame 1: FLY_BY, frame 64: PIPEBOMB_EXPLODE
animsounds logo { 1 244 64 14 }
git-svn-id: https://svn.eduke32.com/eduke32@2242 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-10 23:43:54 +00:00
|
|
|
|
2011-07-18 19:06:29 +00:00
|
|
|
// this and showframe() instead of nextpage() are so that
|
|
|
|
// nobody tramples on our carefully set up GL state!
|
|
|
|
palfadedelta = 0;
|
2018-04-12 21:02:51 +00:00
|
|
|
videoShowFrame(0);
|
2011-07-18 19:06:29 +00:00
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
// I_ClearAllInput();
|
2012-06-03 16:11:22 +00:00
|
|
|
|
2011-12-21 18:41:03 +00:00
|
|
|
do
|
2011-07-18 19:06:29 +00:00
|
|
|
{
|
2012-09-05 17:25:34 +00:00
|
|
|
G_HandleAsync();
|
2011-07-18 19:06:29 +00:00
|
|
|
|
2019-08-07 19:12:07 +00:00
|
|
|
if (VM_OnEventWithReturn(EVENT_SKIPCUTSCENE, g_player[screenpeek].ps->i, screenpeek, I_GeneralTrigger()))
|
2011-07-18 19:06:29 +00:00
|
|
|
{
|
|
|
|
running = 0;
|
|
|
|
break;
|
|
|
|
}
|
2018-04-12 21:02:51 +00:00
|
|
|
} while (timerGetTicks() < nextframetime);
|
2015-02-11 05:22:07 +00:00
|
|
|
} while (running);
|
2011-07-18 19:06:29 +00:00
|
|
|
|
2012-07-13 18:20:55 +00:00
|
|
|
animvpx_print_stats(&codec);
|
|
|
|
|
2011-07-18 19:06:29 +00:00
|
|
|
//
|
|
|
|
kclose(handle);
|
|
|
|
animvpx_restore_glstate();
|
|
|
|
animvpx_uninit_codec(&codec);
|
|
|
|
|
2012-06-03 16:11:22 +00:00
|
|
|
I_ClearAllInput();
|
2014-01-12 14:02:30 +00:00
|
|
|
return !running; // done with playing VP8!
|
2011-07-18 19:06:29 +00:00
|
|
|
}
|
|
|
|
#endif
|
2015-02-11 05:22:07 +00:00
|
|
|
// ANM playback --- v v v ---
|
|
|
|
|
|
|
|
#ifdef USE_OPENGL
|
|
|
|
int32_t ogltexfiltermode = gltexfiltermode;
|
|
|
|
#endif
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_kfd handle = kopen4load(fn, 0);
|
2011-07-18 19:06:29 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
if (handle == buildvfs_kfd_invalid)
|
2014-01-12 14:02:30 +00:00
|
|
|
return 0;
|
2013-03-31 18:57:59 +00:00
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
int32_t length = kfilelength(handle);
|
2019-10-14 22:54:14 +00:00
|
|
|
TArray<uint8_t> buffer(length + 1, true);
|
2015-02-11 05:22:07 +00:00
|
|
|
|
2017-06-27 01:50:59 +00:00
|
|
|
if (length <= 4)
|
2013-03-31 18:57:59 +00:00
|
|
|
{
|
|
|
|
OSD_Printf("Warning: skipping playback of empty ANM file \"%s\".\n", fn);
|
|
|
|
goto end_anim;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-08-04 02:51:40 +00:00
|
|
|
anim->animlock = 255;
|
2019-10-14 22:54:14 +00:00
|
|
|
anim->animbuf = buffer.Data();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
kread(handle, anim->animbuf, length);
|
2006-04-13 20:47:06 +00:00
|
|
|
kclose(handle);
|
|
|
|
|
2017-06-27 01:50:59 +00:00
|
|
|
uint32_t firstfour;
|
|
|
|
Bmemcpy(&firstfour, anim->animbuf, 4);
|
|
|
|
|
|
|
|
// "DKIF" (.ivf)
|
|
|
|
if (firstfour == B_LITTLE32(0x46494B44))
|
|
|
|
goto end_anim;
|
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
int32_t numframes;
|
|
|
|
|
2017-06-27 01:50:59 +00:00
|
|
|
// "LPF " (.anm)
|
|
|
|
if (firstfour != B_LITTLE32(0x2046504C) ||
|
|
|
|
ANIM_LoadAnim(anim->animbuf, length) < 0 ||
|
|
|
|
(numframes = ANIM_NumFrames()) <= 0)
|
2013-03-31 18:57:59 +00:00
|
|
|
{
|
|
|
|
// XXX: ANM_LoadAnim() still checks less than the bare minimum,
|
|
|
|
// e.g. ANM file could still be too small and not contain any frames.
|
|
|
|
OSD_Printf("Error: malformed ANM file \"%s\".\n", fn);
|
|
|
|
goto end_anim;
|
|
|
|
}
|
|
|
|
|
2019-10-06 17:32:35 +00:00
|
|
|
paletteSetColorTable(ANIMPAL, ANIM_GetPalette(), true);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
// setpalette(0L,256L,tempbuf);
|
|
|
|
// setbrightness(ud.brightness>>2,tempbuf,2);
|
|
|
|
P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 8 + 2);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2017-12-12 05:13:38 +00:00
|
|
|
if ((anim->frameflags & CUTSCENE_TEXTUREFILTER && gltexfiltermode == TEXFILTER_ON) || anim->frameflags & CUTSCENE_FORCEFILTER)
|
|
|
|
gltexfiltermode = TEXFILTER_ON;
|
|
|
|
else
|
|
|
|
gltexfiltermode = TEXFILTER_OFF;
|
2007-03-04 19:52:57 +00:00
|
|
|
gltexapplyprops();
|
|
|
|
#endif
|
|
|
|
|
2018-06-12 20:28:02 +00:00
|
|
|
timerUpdate();
|
2017-06-25 11:24:06 +00:00
|
|
|
ototalclock = totalclock;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 04:15:17 +00:00
|
|
|
i = 1;
|
2015-02-11 05:22:07 +00:00
|
|
|
int32_t frametime; frametime = 0;
|
2014-09-30 04:15:17 +00:00
|
|
|
|
|
|
|
do
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2010-05-07 20:45:40 +00:00
|
|
|
if (i > 4 && totalclock > frametime + 60)
|
2008-09-28 11:00:59 +00:00
|
|
|
{
|
2013-03-31 18:57:59 +00:00
|
|
|
OSD_Printf("WARNING: slowdown in %s, skipping playback\n", fn);
|
|
|
|
goto end_anim_restore_gl;
|
2008-09-28 11:00:59 +00:00
|
|
|
}
|
2010-05-07 20:45:40 +00:00
|
|
|
|
2014-09-30 04:15:17 +00:00
|
|
|
G_HandleAsync();
|
2010-05-07 20:45:40 +00:00
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
if (totalclock < ototalclock - 1)
|
2014-09-30 04:15:17 +00:00
|
|
|
continue;
|
|
|
|
|
2017-12-02 09:24:55 +00:00
|
|
|
i = VM_OnEventWithReturn(EVENT_PRECUTSCENE, g_player[screenpeek].ps->i, screenpeek, i);
|
2017-11-29 07:29:04 +00:00
|
|
|
|
2019-10-11 21:31:59 +00:00
|
|
|
tileSetExternal(TILE_ANIM, 200, 320, ANIM_DrawFrame(i));
|
2018-04-12 21:03:47 +00:00
|
|
|
tileInvalidate(TILE_ANIM, 0, 1 << 4); // JBF 20031228
|
2010-05-07 20:45:40 +00:00
|
|
|
|
2019-08-07 19:12:07 +00:00
|
|
|
if (VM_OnEventWithReturn(EVENT_SKIPCUTSCENE, g_player[screenpeek].ps->i, screenpeek, I_GeneralTrigger()))
|
2014-09-30 04:15:17 +00:00
|
|
|
{
|
|
|
|
running = 0;
|
|
|
|
goto end_anim_restore_gl;
|
|
|
|
}
|
2012-06-03 16:11:22 +00:00
|
|
|
|
2014-09-30 04:15:17 +00:00
|
|
|
if (g_restorePalette == 1)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-09-30 04:15:17 +00:00
|
|
|
P_SetGamePalette(g_player[myconnectindex].ps, ANIMPAL, 0);
|
|
|
|
g_restorePalette = 0;
|
|
|
|
}
|
2010-05-07 20:45:40 +00:00
|
|
|
|
2019-08-27 13:39:54 +00:00
|
|
|
frametime = (int32_t) totalclock;
|
2010-05-07 20:45:40 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoClearScreen(0);
|
2010-05-07 20:45:40 +00:00
|
|
|
|
2018-01-26 04:34:46 +00:00
|
|
|
int32_t z;
|
|
|
|
if (anim->frameaspect1 > 0 && anim->frameaspect2 > 0 && ((anim->frameaspect1 / anim->frameaspect2) != (tilesiz[TILE_ANIM].y / (tilesiz[TILE_ANIM].x * 1.2))))
|
|
|
|
{
|
|
|
|
int32_t const oyxaspect = yxaspect;
|
|
|
|
if ((anim->frameaspect1 / anim->frameaspect2) >= ((decltype(anim->frameaspect1))xdim / ydim))
|
|
|
|
z = divscale16(320, tilesiz[TILE_ANIM].y);
|
|
|
|
else
|
|
|
|
z = divscale16(lrint(320 * ydim * anim->frameaspect1), lrint(tilesiz[TILE_ANIM].y * xdim * anim->frameaspect2));
|
|
|
|
int32_t aspect = divscale16(lrint(tilesiz[TILE_ANIM].y * anim->frameaspect2), lrint(tilesiz[TILE_ANIM].x * anim->frameaspect1));
|
2018-04-12 21:03:47 +00:00
|
|
|
renderSetAspect(viewingrange, aspect);
|
2018-01-26 04:34:46 +00:00
|
|
|
rotatesprite_fs(160<<16, 100<<16, z, 512, TILE_ANIM, 0, 0, 2|4|8|64|1024);
|
2018-04-12 21:03:47 +00:00
|
|
|
renderSetAspect(viewingrange, oyxaspect);
|
2018-01-26 04:34:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((tilesiz[TILE_ANIM].y / (tilesiz[TILE_ANIM].x * 1.2f)) > (1.f * xdim / ydim))
|
|
|
|
z = divscale16(320 * xdim * 3, tilesiz[TILE_ANIM].y * ydim * 4);
|
|
|
|
else
|
|
|
|
z = divscale16(200, tilesiz[TILE_ANIM].x);
|
|
|
|
rotatesprite_fs(160<<16, 100<<16, z, 512, TILE_ANIM, 0, 0, 2|4|8|64);
|
|
|
|
}
|
2015-02-11 05:22:07 +00:00
|
|
|
|
|
|
|
g_animPtr = anim;
|
2017-12-02 09:24:55 +00:00
|
|
|
i = VM_OnEventWithReturn(EVENT_CUTSCENE, g_player[screenpeek].ps->i, screenpeek, i);
|
2015-02-11 05:22:07 +00:00
|
|
|
g_animPtr = NULL;
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoNextPage();
|
2012-04-04 18:57:06 +00:00
|
|
|
|
2014-09-30 04:15:17 +00:00
|
|
|
I_ClearAllInput();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
ototalclock += anim->framedelay;
|
|
|
|
|
2017-06-25 11:24:43 +00:00
|
|
|
while (soundidx < anim->numsounds && anim->sounds[soundidx].frame <= (uint16_t)i)
|
2015-02-11 05:22:07 +00:00
|
|
|
{
|
2017-06-25 11:24:27 +00:00
|
|
|
int16_t sound = anim->sounds[soundidx].sound;
|
|
|
|
if (sound == -1)
|
|
|
|
FX_StopAllSounds();
|
|
|
|
else
|
|
|
|
S_PlaySound(sound);
|
|
|
|
|
2015-02-11 05:22:07 +00:00
|
|
|
soundidx++;
|
|
|
|
}
|
2017-06-25 11:24:19 +00:00
|
|
|
|
|
|
|
++i;
|
2014-09-30 04:15:17 +00:00
|
|
|
} while (i < numframes);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-03-31 18:57:59 +00:00
|
|
|
end_anim_restore_gl:
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2007-03-04 19:52:57 +00:00
|
|
|
gltexfiltermode = ogltexfiltermode;
|
|
|
|
gltexapplyprops();
|
2007-08-25 01:05:00 +00:00
|
|
|
#endif
|
2013-03-31 18:57:59 +00:00
|
|
|
end_anim:
|
2012-06-03 16:11:22 +00:00
|
|
|
I_ClearAllInput();
|
2019-10-14 22:54:14 +00:00
|
|
|
anim->animbuf = nullptr;
|
2006-11-14 21:35:50 +00:00
|
|
|
ANIM_FreeAnim();
|
2019-08-04 02:51:40 +00:00
|
|
|
|
2019-10-11 21:31:59 +00:00
|
|
|
tileDelete(TILE_ANIM);
|
2019-08-04 02:51:40 +00:00
|
|
|
|
|
|
|
// this is the lock for anim->animbuf
|
|
|
|
anim->animlock = 1;
|
2014-01-12 14:02:30 +00:00
|
|
|
|
|
|
|
return !running;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2019-09-21 20:53:00 +00:00
|
|
|
|
|
|
|
END_DUKE_NS
|