- work on Duke intro sequence.

Now without any Build drawing code, it goes directly to DrawTexture now. :)
This commit is contained in:
Christoph Oelckers 2020-06-28 00:32:28 +02:00
parent 4f6ab45e35
commit 67fa7f8275
10 changed files with 1077 additions and 1161 deletions

View file

@ -399,12 +399,14 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
} }
if (parms->destwidth == INT_MAX || parms->fortext) if (parms->destwidth == INT_MAX || parms->fortext)
{ {
parms->destwidth = img->GetDisplayWidth(); parms->destwidth = parms->texwidth;
} }
if (parms->destheight == INT_MAX || parms->fortext) if (parms->destheight == INT_MAX || parms->fortext)
{ {
parms->destheight = img->GetDisplayHeight(); parms->destheight = parms->texheight;
} }
parms->destwidth *= parms->patchscalex;
parms->destheight *= parms->patchscaley;
switch (parms->cleanmode) switch (parms->cleanmode)
{ {
@ -446,7 +448,7 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
case DTA_FullscreenEx: case DTA_FullscreenEx:
{ {
DoubleRect rect; DoubleRect rect;
CalcFullscreenScale(drawer, img->GetDisplayWidth(), img->GetDisplayHeight(), parms->fsscalemode, rect); CalcFullscreenScale(drawer, parms->texwidth, parms->texheight, parms->fsscalemode, rect);
parms->keepratio = true; parms->keepratio = true;
parms->x = rect.left; parms->x = rect.left;
parms->y = rect.top; parms->y = rect.top;
@ -624,6 +626,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
parms->monospace = EMonospacing::Off; parms->monospace = EMonospacing::Off;
parms->spacing = 0; parms->spacing = 0;
parms->fsscalemode = -1; parms->fsscalemode = -1;
parms->patchscalex = parms->patchscaley = 1;
// Parse the tag list for attributes. (For floating point attributes, // Parse the tag list for attributes. (For floating point attributes,
// consider that the C ABI dictates that all floats be promoted to // consider that the C ABI dictates that all floats be promoted to
@ -958,6 +961,18 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
} }
break; break;
case DTA_ScaleX:
assert(fortext == false);
if (fortext) return false;
parms->patchscalex = ListGetDouble(tags);
break;
case DTA_ScaleY:
assert(fortext == false);
if (fortext) return false;
parms->patchscaley = ListGetDouble(tags);
break;
case DTA_Masked: case DTA_Masked:
parms->masked = ListGetInt(tags); parms->masked = ListGetInt(tags);
break; break;

View file

@ -89,6 +89,8 @@ enum
DTA_FullscreenEx, DTA_FullscreenEx,
DTA_FullscreenScale, DTA_FullscreenScale,
DTA_ScaleX,
DTA_ScaleY,
}; };
@ -157,6 +159,7 @@ struct DrawParms
int8_t fsscalemode; int8_t fsscalemode;
double srcx, srcy; double srcx, srcy;
double srcwidth, srcheight; double srcwidth, srcheight;
double patchscalex, patchscaley;
}; };
struct Va_List struct Va_List

View file

@ -135,8 +135,14 @@ AnimTextures::AnimTextures()
AnimTextures::~AnimTextures() AnimTextures::~AnimTextures()
{ {
tex[0]->CleanHardwareData(true); Clean();
tex[1]->CleanHardwareData(true); }
void AnimTextures::Clean()
{
if (tex[0]) tex[0]->CleanHardwareData(true);
if (tex[1]) tex[1]->CleanHardwareData(true);
tex[0] = tex[1] = nullptr;
} }
void AnimTextures::SetSize(int format, int width, int height) void AnimTextures::SetSize(int format, int width, int height)

View file

@ -29,6 +29,7 @@ class AnimTextures
public: public:
AnimTextures(); AnimTextures();
~AnimTextures(); ~AnimTextures();
void Clean();
void SetSize(int format, int width, int height); void SetSize(int format, int width, int height);
void SetFrame(const uint8_t* palette, const void* data); void SetFrame(const uint8_t* palette, const void* data);
FGameTexture* GetFrame() FGameTexture* GetFrame()

View file

@ -38,6 +38,10 @@
#include "screenjob.h" #include "screenjob.h"
#include "i_time.h" #include "i_time.h"
#include "v_2ddrawer.h" #include "v_2ddrawer.h"
#include "animlib.h"
#include "v_draw.h"
#include "s_soundinternal.h"
#include "animtexture.h"
IMPLEMENT_CLASS(DScreenJob, true, false) IMPLEMENT_CLASS(DScreenJob, true, false)
@ -63,108 +67,166 @@ void RunScreenJob(DScreenJob *job, std::function<void(bool skipped)> completion,
while(true) while(true)
{ {
auto now = I_nsTime(); auto now = I_nsTime();
int frame = int((now - startTime) * 120 / 1'000'000'000); handleevents();
bool skiprequest = inputState.CheckAllInput(); bool skiprequest = inputState.CheckAllInput();
twod->ClearScreen(); int state = job->Frame(now - startTime, skiprequest);
int state = job->Frame(frame, skiprequest);
videoNextPage(); videoNextPage();
if (state < 1) if (state < 1)
{ {
job->Destroy();
completion(state < 0); completion(state < 0);
return; return;
} }
} }
} }
void PlayVideo(const char *filename, AnimSound *ans, int frameticks, std::function<void(bool skipped)> completion); //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
class DAnmPlayer : public DScreenJob
#if 0
void RunScreen(const char *classname, VMValue *params, int numparams, std::function<void(bool aborted)> completion)
{ {
int ticker = 0; // This doesn't need its own class type
auto ototalclock = totalclock; anim_t anim;
TArray<uint8_t> buffer;
PClass *cls = PClass::FindClass(classname); int numframes = 0;
if (cls != nullptr && cls->IsDescendantOf(NAME_GameScreen)) int curframe = 1;
{ int lastframe = -1;
auto func = dyn_cast<PFunction>(cls->FindSymbol("Init", true)); int frametime = 0;
if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protected init method. int ototalclock = 0;
{ AnimTextures animtex;
TArray<VMValue> args(numparams+1); const AnimSound* animSnd;
for(int i = 0;i<numparams;i++) args[i+1] = params[i]; const int* frameTicks;
auto item = cls->CreateNew();
if (!item)
{
completion(true);
return;
}
args[0] = item;
VMCallWithDefaults(func->Variants[0].Implementation, args, nullptr, 0);
while (true)
{
handleevents();
event_t *ev;
// This should later run off D_ProcessEvents, but currently requires a local copy here
while (eventtail != eventhead)
{
ev = &events[eventtail];
eventtail = (eventtail + 1) & (MAXEVENTS - 1);
if (ev->type == EV_None)
continue;
if (ev->type == EV_DeviceChange)
UpdateJoystickMenu(I_UpdateDeviceList());
#if 0 // this isn't safe with the current engine structure
if (C_Responder (ev))
continue; // console ate the event
if (M_Responder (ev))
continue; // menu ate the event
#endif
IFVIRTUALPTRNAME(item, NAME_GameScreen, OnEvent) public:
{ bool isvalid() { return numframes > 0; }
FInputEvent e = ev;
VMValue params[] = { (DObject*)item, &e }; DAnmPlayer(FileReader& fr, const AnimSound* ans, const int *frameticks)
int retval; : animSnd(ans), frameTicks(frameticks)
VMReturn ret(&retval); {
VMCall(func, params, 2, &ret, 1); buffer = fr.ReadPadded(1);
if (!retval) fr.Close();
{
completion(true); if (ANIM_LoadAnim(&anim, buffer.Data(), buffer.Size() - 1) < 0)
return; {
} return;
} }
} numframes = ANIM_NumFrames(&anim);
animtex.SetSize(AnimTexture::Paletted, 320, 200);
while ((int)(totalclock - ototalclock) >= 1) }
{
IFVIRTUALPTRNAME(item, NAME_GameScreen, Tick) //---------------------------------------------------------------------------
{ //
FInputEvent e = ev; //
VMValue params[] = { (DObject*)item, ticker }; //
ticker++; //---------------------------------------------------------------------------
int retval;
VMReturn ret(&retval); int Frame(uint64_t clock, bool skiprequest) override
VMCall(func, params, 2, &ret, 1); {
if (!retval) int totalclock = int(clock * 120 / 1'000'000'000);
{
completion(false); if (curframe > 4 && totalclock > frametime + 60)
return; {
} Printf("WARNING: slowdown in video playback, aborting\n");
} return -1;
} }
IFVIRTUALPTRNAME(item, NAME_GameScreen, Draw)
{ if (totalclock < ototalclock - 1)
FInputEvent e = ev; {
VMValue params[] = { (DObject*)item }; twod->ClearScreen();
ticker++; DrawTexture(twod, animtex.GetFrame(), 0, 0, DTA_FullscreenEx, 3, DTA_Masked, false, TAG_DONE);
VMCall(func, params, 1, nullptr, 0); return skiprequest? -1 : 1;
} }
videoNextPage();
animtex.SetFrame(ANIM_GetPalette(&anim), ANIM_DrawFrame(&anim, curframe));
frametime = totalclock;
twod->ClearScreen();
DrawTexture(twod, animtex.GetFrame(), 0, 0, DTA_FullscreenEx, 3, DTA_Masked, false, TAG_DONE);
int delay = 20;
if (frameTicks)
{
if (curframe == 0) delay = frameTicks[0];
else if (curframe < numframes - 1) delay = frameTicks[1];
else delay = frameTicks[2];
}
ototalclock += delay;
for (int i = 0; animSnd[i].framenum >= 0; i++)
{
if (animSnd[i].framenum == curframe)
{
int sound = animSnd[i].soundnum;
if (sound == -1)
soundEngine->StopAllChannels();
else
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, CHAN_BODY, CHANF_NONE, sound, 1.f, ATTN_NONE);
} }
} }
curframe++;
return skiprequest ? -1 : curframe < numframes? 1 : 0;
}
void OnDestroy() override
{
buffer.Reset();
animtex.Clean();
}
};
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void PlayVideo(const char* filename, const AnimSound* ans, const int* frameticks, std::function<void(bool skipped)> completion)
{
if (!filename) // this is for chaining optional videos without special case coding by the caller.
{
completion(false);
return;
}
auto fr = fileSystem.OpenFileReader(filename);
if (!fr.isOpen())
{
Printf("%s: Unable to open video\n", filename);
completion(true);
return;
}
char id[20] = {};
fr.Read(&id, 20);
fr.Seek(-20, FileReader::SeekCur);
if (!memcmp(id, "LPF ", 4))
{
auto anm = Create<DAnmPlayer>(fr, ans, frameticks);
if (!anm->isvalid())
{
Printf("%s: invalid ANM file.\n", filename);
anm->Destroy();
return;
}
RunScreenJob(anm, completion);
}
else if (!memcmp(id, "SMK2", 4))
{
// todo
}
else if (!memcmp(id, "Interplay MVE file", 18))
{
// todo
}
// add more formats here.
else
{
Printf("%s: Unknown video format\n", filename);
completion(true);
return;
} }
completion(true);
} }
#endif

View file

@ -9,11 +9,12 @@ class DScreenJob : public DObject
//std::function<void(bool skipped)> completion; //std::function<void(bool skipped)> completion;
public: public:
virtual int Frame(int clock, bool skiprequest) = 0; virtual int Frame(uint64_t clock, bool skiprequest) = 0;
}; };
void RunScreenJob(DScreenJob *job, std::function<void(bool skipped)> completion, bool clearbefore = true); void RunScreenJob(DScreenJob *job, std::function<void(bool skipped)> completion, bool clearbefore = true);
void RunScreenJob(std::function<int(uint64_t, bool)> action, std::function<void(bool)> completion, bool clearbefore = true);
struct AnimSound struct AnimSound
{ {
@ -21,10 +22,10 @@ struct AnimSound
int soundnum; int soundnum;
}; };
void PlayVideo(const char *filename, AnimSound *ans, int frameticks, std::function<void(bool skipped)> completion); void PlayVideo(const char *filename, const AnimSound *ans, const int *frameticks, std::function<void(bool)> completion);
// This one is not suitable for ANM and SMK unless a descriptor file format is implemented. // This one is not suitable for ANM and SMK unless a descriptor file format is implemented.
inline void PlayVideo(const char *filename, std::function<void(bool skipped)> completion) inline void PlayVideo(const char *filename, std::function<void(bool skipped)> completion)
{ {
PlayVideo(filename, nullptr, -1, completion); PlayVideo(filename, nullptr, nullptr , completion);
} }

File diff suppressed because it is too large Load diff

View file

@ -1069,12 +1069,13 @@ void G_DisplayExtraScreens(void)
} }
} }
void Logo(); void Logo_d();
void Logo_r();
void G_DisplayLogo(void) void G_DisplayLogo(void)
{ {
if (!isRR()) if (!isRR())
{ {
Logo(); Logo_d();
return; return;
} }
int32_t soundanm = 0; int32_t soundanm = 0;
@ -1144,159 +1145,6 @@ void G_DisplayLogo(void)
videoClearScreen(0L); videoClearScreen(0L);
return; return;
} }
if (!g_noLogo && !userConfig.nologo /* && (!g_netServer && ud.multimode < 2) */)
{
if (VOLUMEALL)
{
if (!inputState.CheckAllInput() && g_noLogoAnim == 0 && !userConfig.nologo)
{
Net_GetPackets();
Anim_Play("logo.anm");
G_FadePalette(0, 0, 0, 252);
inputState.ClearAllInput();
}
videoClearScreen(0L);
videoNextPage();
FX_StopAllSounds();
S_ClearSoundLocks();
}
S_PlaySpecialMusic(MUS_INTRO);
//g_player[myconnectindex].ps->palette = drealms;
//G_FadePalette(0,0,0,252);
if (!inputState.CheckAllInput() && g_noLogoAnim == 0 && !userConfig.nologo)
{
Net_GetPackets();
if (fileSystem.FileExists("3dr.ivf") || fileSystem.FileExists("3dr.anm"))
{
Anim_Play("3dr.anm");
G_FadePalette(0, 0, 0, 252);
inputState.ClearAllInput();
}
else
{
videoClearScreen(0);
fadepal(0, 0, 0, 0, 252, 28);
renderFlushPerms();
rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, TILE_DREALMS, 0, 0, 2 + 8 + 64 + BGSTRETCH, nullptr, DREALMSPAL);
videoNextPage();
fadepaltile(0, 0, 0, 252, 0, -28, TILE_DREALMS, DREALMSPAL);
totalclock = 0;
while (totalclock < (120 * 7) && !inputState.CheckAllInput())
{
if (G_FPSLimit())
{
videoClearScreen(0);
rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, TILE_DREALMS, 0, 0, 2 + 8 + 64 + BGSTRETCH, nullptr, DREALMSPAL);
G_HandleAsync();
videoNextPage();
}
}
fadepaltile(0, 0, 0, 0, 252, 28, TILE_DREALMS, DREALMSPAL);
}
}
videoClearScreen(0L);
videoNextPage();
inputState.ClearAllInput();
videoClearScreen(0L);
videoNextPage();
videoClearScreen(0);
//g_player[myconnectindex].ps->palette = titlepal;
renderFlushPerms();
rotatesprite_fs(160<<16, 100<<16, 65536L, 0, TILE_BETASCREEN, 0, 0, 2+8+64+BGSTRETCH, nullptr, TITLEPAL);
inputState.keyFlushChars();
fadepaltile(0, 0, 0, 252, 0, -28, TILE_BETASCREEN, TITLEPAL);
totalclock = 0;
while (
totalclock < (860+120) &&
!inputState.CheckAllInput())
{
if (G_FPSLimit())
{
videoClearScreen(0);
rotatesprite_fs(160<<16, 100<<16, 65536L, 0, TILE_BETASCREEN, 0, 0, 2+8+64+BGSTRETCH, nullptr, TITLEPAL);
if (totalclock > 120 && totalclock < (120+60))
{
if (soundanm == 0)
{
soundanm++;
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
}
rotatesprite_fs(160<<16, 104<<16, ((int32_t) totalclock-120)<<10, 0, TILE_DUKENUKEM, 0, 0, 2+8, nullptr, TITLEPAL);
}
else if (totalclock >= (120+60))
rotatesprite_fs(160<<16, (104)<<16, 60<<10, 0, TILE_DUKENUKEM, 0, 0, 2+8, nullptr, TITLEPAL);
if (totalclock > 220 && totalclock < (220+30))
{
if (soundanm == 1)
{
soundanm++;
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
}
rotatesprite_fs(160<<16, (104)<<16, 60<<10, 0, TILE_DUKENUKEM, 0, 0, 2+8, nullptr, TITLEPAL);
rotatesprite_fs(160<<16, (129)<<16, ((int32_t) totalclock - 220)<<11, 0, TILE_THREEDEE, 0, 0, 2+8, nullptr, TITLEPAL);
}
else if (totalclock >= (220+30))
rotatesprite_fs(160<<16, (129)<<16, 30<<11, 0, TILE_THREEDEE, 0, 0, 2+8, nullptr, TITLEPAL);
if (PLUTOPAK)
{
// JBF 20030804
if (totalclock >= 280 && totalclock < 395)
{
rotatesprite_fs(160<<16, (151)<<16, (410-(int32_t) totalclock)<<12, 0, TILE_PLUTOPAKSPRITE+1, (sintable[((int32_t) totalclock<<4)&2047]>>11), 0, 2+8, nullptr, TITLEPAL);
if (soundanm == 2)
{
soundanm++;
S_PlaySound(FLY_BY, CHAN_AUTO, CHANF_UI);
}
}
else if (totalclock >= 395)
{
if (soundanm == 3)
{
soundanm++;
S_PlaySound(PIPEBOMB_EXPLODE, CHAN_AUTO, CHANF_UI);
}
rotatesprite_fs(160<<16, (151)<<16, 30<<11, 0, TILE_PLUTOPAKSPRITE+1, (sintable[((int32_t) totalclock<<4)&2047]>>11), 0, 2+8, nullptr, TITLEPAL);
}
}
videoNextPage();
}
G_HandleAsync();
}
inputState.ClearAllInput();
}
renderFlushPerms();
videoClearScreen(0L);
videoNextPage();
//g_player[myconnectindex].ps->palette = palette;
P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 0); // JBF 20040308
S_PlaySound(NITEVISION_ONOFF, CHAN_AUTO, CHANF_UI);
//G_FadePalette(0,0,0,0);
videoClearScreen(0L);
} }
void G_DoOrderScreen(void) void G_DoOrderScreen(void)

View file

@ -260,7 +260,6 @@ playanm(short anim_num)
goto ENDOFANIMLOOP; goto ENDOFANIMLOOP;
} }
ANIM_LoadAnim(&anm, buffer.Data(), buffer.Size()-1);
ANIMnumframes = ANIM_NumFrames(&anm); ANIMnumframes = ANIM_NumFrames(&anm);
numframes = ANIMnumframes; numframes = ANIMnumframes;

View file

@ -155,6 +155,8 @@ enum DrawTextureTags
DTA_FullscreenEx, // advanced fullscreen control. DTA_FullscreenEx, // advanced fullscreen control.
DTA_FullscreenScale, // enable DTA_Fullscreen coordinate calculation for placed overlays. DTA_FullscreenScale, // enable DTA_Fullscreen coordinate calculation for placed overlays.
DTA_ScaleX, // scales the patch dimensions before applying any other transformation.
DTA_ScaleY,
}; };