- 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)
{
parms->destwidth = img->GetDisplayWidth();
parms->destwidth = parms->texwidth;
}
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)
{
@ -446,7 +448,7 @@ bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FGameTexture *img, do
case DTA_FullscreenEx:
{
DoubleRect rect;
CalcFullscreenScale(drawer, img->GetDisplayWidth(), img->GetDisplayHeight(), parms->fsscalemode, rect);
CalcFullscreenScale(drawer, parms->texwidth, parms->texheight, parms->fsscalemode, rect);
parms->keepratio = true;
parms->x = rect.left;
parms->y = rect.top;
@ -624,6 +626,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double
parms->monospace = EMonospacing::Off;
parms->spacing = 0;
parms->fsscalemode = -1;
parms->patchscalex = parms->patchscaley = 1;
// Parse the tag list for attributes. (For floating point attributes,
// 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;
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:
parms->masked = ListGetInt(tags);
break;

View file

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

View file

@ -135,8 +135,14 @@ AnimTextures::AnimTextures()
AnimTextures::~AnimTextures()
{
tex[0]->CleanHardwareData(true);
tex[1]->CleanHardwareData(true);
Clean();
}
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)

View file

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

View file

@ -38,6 +38,10 @@
#include "screenjob.h"
#include "i_time.h"
#include "v_2ddrawer.h"
#include "animlib.h"
#include "v_draw.h"
#include "s_soundinternal.h"
#include "animtexture.h"
IMPLEMENT_CLASS(DScreenJob, true, false)
@ -63,108 +67,166 @@ void RunScreenJob(DScreenJob *job, std::function<void(bool skipped)> completion,
while(true)
{
auto now = I_nsTime();
int frame = int((now - startTime) * 120 / 1'000'000'000);
handleevents();
bool skiprequest = inputState.CheckAllInput();
twod->ClearScreen();
int state = job->Frame(frame, skiprequest);
int state = job->Frame(now - startTime, skiprequest);
videoNextPage();
if (state < 1)
{
job->Destroy();
completion(state < 0);
return;
}
}
}
void PlayVideo(const char *filename, AnimSound *ans, int frameticks, std::function<void(bool skipped)> completion);
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
#if 0
void RunScreen(const char *classname, VMValue *params, int numparams, std::function<void(bool aborted)> completion)
class DAnmPlayer : public DScreenJob
{
int ticker = 0;
auto ototalclock = totalclock;
PClass *cls = PClass::FindClass(classname);
if (cls != nullptr && cls->IsDescendantOf(NAME_GameScreen))
{
auto func = dyn_cast<PFunction>(cls->FindSymbol("Init", true));
if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protected init method.
{
TArray<VMValue> args(numparams+1);
for(int i = 0;i<numparams;i++) args[i+1] = params[i];
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
// This doesn't need its own class type
anim_t anim;
TArray<uint8_t> buffer;
int numframes = 0;
int curframe = 1;
int lastframe = -1;
int frametime = 0;
int ototalclock = 0;
AnimTextures animtex;
const AnimSound* animSnd;
const int* frameTicks;
IFVIRTUALPTRNAME(item, NAME_GameScreen, OnEvent)
{
FInputEvent e = ev;
VMValue params[] = { (DObject*)item, &e };
int retval;
VMReturn ret(&retval);
VMCall(func, params, 2, &ret, 1);
if (!retval)
{
completion(true);
return;
}
}
}
while ((int)(totalclock - ototalclock) >= 1)
{
IFVIRTUALPTRNAME(item, NAME_GameScreen, Tick)
{
FInputEvent e = ev;
VMValue params[] = { (DObject*)item, ticker };
ticker++;
int retval;
VMReturn ret(&retval);
VMCall(func, params, 2, &ret, 1);
if (!retval)
{
completion(false);
return;
}
}
}
IFVIRTUALPTRNAME(item, NAME_GameScreen, Draw)
{
FInputEvent e = ev;
VMValue params[] = { (DObject*)item };
ticker++;
VMCall(func, params, 1, nullptr, 0);
}
videoNextPage();
public:
bool isvalid() { return numframes > 0; }
DAnmPlayer(FileReader& fr, const AnimSound* ans, const int *frameticks)
: animSnd(ans), frameTicks(frameticks)
{
buffer = fr.ReadPadded(1);
fr.Close();
if (ANIM_LoadAnim(&anim, buffer.Data(), buffer.Size() - 1) < 0)
{
return;
}
numframes = ANIM_NumFrames(&anim);
animtex.SetSize(AnimTexture::Paletted, 320, 200);
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int Frame(uint64_t clock, bool skiprequest) override
{
int totalclock = int(clock * 120 / 1'000'000'000);
if (curframe > 4 && totalclock > frametime + 60)
{
Printf("WARNING: slowdown in video playback, aborting\n");
return -1;
}
if (totalclock < ototalclock - 1)
{
twod->ClearScreen();
DrawTexture(twod, animtex.GetFrame(), 0, 0, DTA_FullscreenEx, 3, DTA_Masked, false, TAG_DONE);
return skiprequest? -1 : 1;
}
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;
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(std::function<int(uint64_t, bool)> action, std::function<void(bool)> completion, bool clearbefore = true);
struct AnimSound
{
@ -21,10 +22,10 @@ struct AnimSound
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.
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)
{
if (!isRR())
{
Logo();
Logo_d();
return;
}
int32_t soundanm = 0;
@ -1144,159 +1145,6 @@ void G_DisplayLogo(void)
videoClearScreen(0L);
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)

View file

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

View file

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