Add demo to "movie" conversion.

It currently writes a series of png files (QF/qfmvNNNNNN.png), at a fixed
rate of 30fps, with no sound recording.
This commit is contained in:
Bill Currie 2012-01-05 19:19:37 +09:00
parent b13a2b6dbd
commit 423e08ce21
12 changed files with 186 additions and 38 deletions

View file

@ -56,6 +56,7 @@ void SCR_DrawTurtle (void);
void SCR_DrawPause (void);
struct tex_s *SCR_ScreenShot (int width, int height);
struct tex_s *SCR_CaptureBGR (void);
void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y);
int MipColor (int r, int g, int b);
int SCR_ModalMessage (const char *text);

View file

@ -28,8 +28,7 @@
# include "config.h"
#endif
static __attribute__ ((used)) const char rcsid[] =
"$Id$";
static __attribute__ ((used)) const char rcsid[] = "$Id$";
#ifdef HAVE_STRING_H
# include <string.h>
@ -66,6 +65,24 @@ static __attribute__ ((used)) const char rcsid[] =
/* SCREEN SHOTS */
VISIBLE tex_t *
SCR_CaptureBGR (void)
{
int count;
tex_t *tex;
count = vid.width * vid.height;
tex = malloc (field_offset (tex_t, data[count * 3]));
SYS_CHECKMEM (tex);
tex->width = vid.width;
tex->height = vid.height;
tex->format = tex_rgb;
tex->palette = 0;
qfglReadPixels (0, 0, tex->width, tex->height, GL_BGR_EXT,
GL_UNSIGNED_BYTE, tex->data);
return tex;
}
VISIBLE tex_t *
SCR_ScreenShot (int width, int height)
{
@ -133,20 +150,18 @@ SCR_ScreenShot (int width, int height)
void
SCR_ScreenShot_f (void)
{
byte *buffer;
dstring_t *pcxname = dstring_new ();
// find a file name to save it to
// find a file name to save it to
if (!QFS_NextFilename (pcxname,
va ("%s/qf", qfs_gamedir->dir.shots), ".tga")) {
Sys_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n");
} else {
buffer = malloc (vid.width * vid.height * 3);
SYS_CHECKMEM (buffer);
qfglReadPixels (0, 0, vid.width, vid.height, GL_BGR_EXT,
GL_UNSIGNED_BYTE, buffer);
WriteTGAfile (pcxname->str, buffer, vid.width, vid.height);
free (buffer);
tex_t *tex;
tex = SCR_CaptureBGR ();
WriteTGAfile (pcxname->str, tex->data, tex->width, tex->height);
free (tex);
Sys_Printf ("Wrote %s/%s\n", qfs_userpath, pcxname->str);
}
dstring_delete (pcxname);

View file

@ -203,6 +203,31 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs)
qfglFlush ();
}
VISIBLE tex_t *
SCR_CaptureBGR (void)
{
byte *r, *b;
int count, i;
tex_t *tex;
count = vid.width * vid.height;
tex = malloc (field_offset (tex_t, data[count * 3]));
SYS_CHECKMEM (tex);
tex->width = vid.width;
tex->height = vid.height;
tex->format = tex_rgb;
tex->palette = 0;
qfglReadPixels (0, 0, vid.width, vid.height, GL_RGB,
GL_UNSIGNED_BYTE, tex->data);
for (i = 0, r = tex->data, b = tex->data + 2; i < count;
i++, r += 3, b += 3) {
byte t = *b;
*b = *r;
*r = t;
}
return tex;
}
VISIBLE tex_t *
SCR_ScreenShot (int width, int height)
{
@ -212,28 +237,18 @@ SCR_ScreenShot (int width, int height)
VISIBLE void
SCR_ScreenShot_f (void)
{
byte *buffer, *r, *b;
dstring_t *name = dstring_new ();
int size, i;
// find a file name to save it to
if (!QFS_NextFilename (name,
va ("%s/qf", qfs_gamedir->dir.shots), ".png")) {
Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PNG file\n");
} else {
size = vid.width * vid.height;
buffer = malloc (size * 3);
SYS_CHECKMEM (buffer);
qfglReadPixels (0, 0, vid.width, vid.height, GL_RGB,
GL_UNSIGNED_BYTE, buffer);
// FIXME have to swap rgb (WritePNG bug?)
for (i = 0, r = buffer, b = buffer + 2; i < size; i++, r+=3, b+=3) {
byte t = *b;
*b = *r;
*r = t;
}
WritePNGqfs (name->str, buffer, vid.width, vid.height);
free (buffer);
tex_t *tex;
tex = SCR_CaptureBGR ();
WritePNGqfs (name->str, tex->data, tex->width, tex->height);
free (tex);
Sys_Printf ("Wrote %s/%s\n", qfs_userpath, name->str);
}
dstring_delete (name);

View file

@ -28,8 +28,7 @@
# include "config.h"
#endif
static __attribute__ ((used)) const char rcsid[] =
"$Id$";
static __attribute__ ((used)) const char rcsid[] = "$Id$";
#ifdef HAVE_STRING_H
# include <string.h>
@ -87,6 +86,36 @@ SCR_ApplyBlend (void) // Used to be V_UpdatePalette
/* SCREEN SHOTS */
VISIBLE tex_t *
SCR_CaptureBGR (void)
{
int count, x, y;
tex_t *tex;
const byte *src;
byte *dst;
count = vid.width * vid.height;
tex = malloc (field_offset (tex_t, data[count * 3]));
SYS_CHECKMEM (tex);
tex->width = vid.width;
tex->height = vid.height;
tex->format = tex_rgb;
tex->palette = 0;
D_EnableBackBufferAccess ();
src = vid.buffer;
for (y = 0; y < tex->height; y++) {
dst = tex->data + (tex->height - 1 - y) * tex->width * 3;
for (x = 0; x < tex->width; x++) {
*dst++ = vid.basepal[*src * 3 + 2]; // blue
*dst++ = vid.basepal[*src * 3 + 1]; // green
*dst++ = vid.basepal[*src * 3 + 0]; // red
src++;
}
}
D_DisableBackBufferAccess ();
return tex;
}
tex_t *
SCR_ScreenShot (int width, int height)
{
@ -159,7 +188,7 @@ SCR_ScreenShot_f (void)
pcx_t *pcx;
int pcx_len;
// find a file name to save it to
// find a file name to save it to
if (!QFS_NextFilename (pcxname,
va ("%s/qf", qfs_gamedir->dir.shots), ".pcx")) {
Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PCX");

View file

@ -28,8 +28,7 @@
# include "config.h"
#endif
static __attribute__ ((used)) const char rcsid[] =
"$Id$";
static __attribute__ ((used)) const char rcsid[] = "$Id$";
#ifdef HAVE_STRING_H
# include <string.h>
@ -155,6 +154,36 @@ SCR_ApplyBlend (void) // Used to be V_UpdatePalette
/* SCREEN SHOTS */
VISIBLE tex_t *
SCR_CaptureBGR (void)
{
int count, x, y;
tex_t *tex;
const byte *src;
byte *dst;
count = vid.width * vid.height;
tex = malloc (field_offset (tex_t, data[count * 3]));
SYS_CHECKMEM (tex);
tex->width = vid.width;
tex->height = vid.height;
tex->format = tex_rgb;
tex->palette = 0;
D_EnableBackBufferAccess ();
src = vid.buffer;
for (y = 0; y < tex->height; y++) {
dst = tex->data + (tex->height - 1 - y) * tex->width * 3;
for (x = 0; x < tex->width; x++) {
*dst++ = vid.basepal[*src * 3 + 2]; // blue
*dst++ = vid.basepal[*src * 3 + 1]; // green
*dst++ = vid.basepal[*src * 3 + 0]; // red
src++;
}
}
D_DisableBackBufferAccess ();
return tex;
}
VISIBLE tex_t *
SCR_ScreenShot (int width, int height)
{
@ -168,7 +197,7 @@ SCR_ScreenShot_f (void)
pcx_t *pcx = 0;
int pcx_len;
// find a file name to save it to
// find a file name to save it to
if (!QFS_NextFilename (pcxname,
va ("%s/qf", qfs_gamedir->dir.shots), ".pcx")) {
Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PCX");

View file

@ -119,6 +119,7 @@ typedef struct
// demo recording info must be here, because record is started before
// entering a map (and clearing client_state_t)
qboolean demorecording;
qboolean demo_capture;
qboolean demoplayback;
qboolean timedemo;
int forcetrack; // -1 = use normal cd track

View file

@ -126,6 +126,7 @@ CL_StopPlayback (void)
Qclose (cls.demofile);
cls.demofile = NULL;
CL_SetState (ca_disconnected);
cls.demo_capture = 0;
cls.demoplayback = 0;
key_game_target = IMT_0;
Key_SetKeyDest (key_game);
@ -384,9 +385,19 @@ CL_PlayDemo_f (void)
if (cmd_source != src_command)
return;
if (Cmd_Argc () != 2) {
Sys_Printf ("play <demoname> : plays a demo\n");
return;
switch (Cmd_Argc ()) {
case 2:
cls.demo_capture = 0;
break;
case 3:
if (!strcmp (Cmd_Argv (2), "rec")) {
cls.demo_capture = 1;
break;
}
// fall through
default:
Sys_Printf ("play <demoname> : plays a demo\n");
return;
}
timedemo_runs = timedemo_count = 1; // make sure looped timedemos stop
strncpy (demoname, Cmd_Argv (1), sizeof (demoname));

View file

@ -41,12 +41,15 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$";
#include "QF/cmd.h"
#include "QF/console.h"
#include "QF/cvar.h"
#include "QF/image.h"
#include "QF/input.h"
#include "QF/keys.h"
#include "QF/msg.h"
#include "QF/plugin.h"
#include "QF/png.h"
#include "QF/progs.h"
#include "QF/qargs.h"
#include "QF/screen.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/vid.h"
@ -638,6 +641,9 @@ _Host_Frame (float time)
rand (); // keep the random time dependent
if (cls.demo_capture)
time = 1.0 / 30; //FIXME fixed 30fps atm
// decide the simulation time
if ((sleeptime = Host_FilterTime (time)) != 0) {
// don't run too fast, or packet will flood outs
@ -685,6 +691,14 @@ _Host_Frame (float time)
else
host_time += host_frametime; //FIXME is this needed? vcr stuff
if (cls.demo_capture) {
tex_t *tex = SCR_CaptureBGR ();
WritePNGqfs (va ("%s/qfmv%06d.png", qfs_gamedir->dir.shots,
cls.demo_capture++),
tex->data, tex->width, tex->height);
free (tex);
}
host_framecount++;
fps_count++;
}

View file

@ -33,6 +33,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$";
#include "QF/cdaudio.h"
#include "QF/cvar.h"
#include "QF/plugin.h"
#include "QF/screen.h"
#include "host.h"
#include "server.h"
@ -70,6 +71,13 @@ CL_UpdateScreen (double realtime)
{
}
struct tex_s *
SCR_CaptureBGR (void)
{
return 0;
}
void
CL_Cmd_ForwardToServer (void)
{

View file

@ -167,6 +167,7 @@ typedef struct
// demo recording info must be here, because record is started before
// entering a map (and clearing client_state_t)
qboolean demorecording;
qboolean demo_capture;
qboolean demoplayback;
qboolean demoplayback2;
qboolean findtrack;

View file

@ -144,6 +144,7 @@ CL_StopPlayback (void)
Qclose (cls.demofile);
cls.demofile = NULL;
CL_SetState (ca_disconnected);
cls.demo_capture = 0;
cls.demoplayback = 0;
cls.demoplayback2 = 0;
demotime_cached = 0;
@ -933,9 +934,19 @@ CL_StartDemo (void)
static void
CL_PlayDemo_f (void)
{
if (Cmd_Argc () != 2) {
Sys_Printf ("play <demoname> : plays a demo\n");
return;
switch (Cmd_Argc ()) {
case 2:
cls.demo_capture = 0;
break;
case 3:
if (!strcmp (Cmd_Argv (2), "rec")) {
cls.demo_capture = 1;
break;
}
// fall through
default:
Sys_Printf ("play <demoname> : plays a demo\n");
return;
}
timedemo_runs = timedemo_count = 1; // make sure looped timedemos stop
// disconnect from server

View file

@ -71,11 +71,13 @@ static __attribute__ ((used)) const char rcsid[] =
#include "QF/console.h"
#include "QF/cvar.h"
#include "QF/draw.h"
#include "QF/image.h"
#include "QF/input.h"
#include "QF/keys.h"
#include "QF/model.h"
#include "QF/msg.h"
#include "QF/plugin.h"
#include "QF/png.h"
#include "QF/progs.h"
#include "QF/qargs.h"
#include "QF/qendian.h"
@ -1488,7 +1490,7 @@ Host_SimulationTime (float time)
if (oldrealtime > realtime)
oldrealtime = 0;
if (cls.timedemo)
if (cls.demoplayback)
return 0;
if (cl_maxfps->value <= 0)
@ -1523,6 +1525,9 @@ Host_Frame (float time)
// something bad happened, or the server disconnected
return;
if (cls.demo_capture)
time = 1.0 / 30; //FIXME fixed 30fps atm
// decide the simulation time
if ((sleeptime = Host_SimulationTime (time)) != 0) {
#ifdef HAVE_USLEEP
@ -1623,6 +1628,14 @@ Host_Frame (float time)
pass1 + pass2 + pass3, pass1, pass2, pass3);
}
if (cls.demo_capture) {
tex_t *tex = SCR_CaptureBGR ();
WritePNGqfs (va ("%s/qfmv%06d.png", qfs_gamedir->dir.shots,
cls.demo_capture++),
tex->data, tex->width, tex->height);
free (tex);
}
host_framecount++;
fps_count++;
}