Browse Source

Merge pull request #361 from Hoikas/capture

Revamp Game.TakeScreenShot

Fixes #358.
Joseph Davies 11 years ago
parent
commit
57854640e7
  1. 27
      Sources/Plasma/FeatureLib/pfCamera/plVirtualCamNeu.cpp
  2. 3
      Sources/Plasma/FeatureLib/pfCamera/plVirtualCamNeu.h
  3. 57
      Sources/Plasma/FeatureLib/pfConsole/pfConsole.cpp
  4. 89
      Sources/Plasma/FeatureLib/pfConsole/pfConsoleCommands.cpp
  5. 64
      Sources/Plasma/FeatureLib/pfConsole/pfGameConsoleCommands.cpp
  6. 2
      Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp
  7. 3
      Sources/Plasma/PubUtilLib/plPipeline/plCaptureRender.cpp

27
Sources/Plasma/FeatureLib/pfCamera/plVirtualCamNeu.cpp

@ -309,6 +309,7 @@ void plVirtualCam1::Refresh()
{
plPipeline* pipe = plVirtualCam1::Instance()->fPipe;
SetAspectRatio((float)pipe->Width() / (float)pipe->Height());
plVirtualCam1::Instance()->SetOutputFOV();
}
void plVirtualCam1::SetAspectRatio(float ratio)
@ -845,18 +846,7 @@ void plVirtualCam1::Output()
targetMatrix.GetInverse(&inverse);
fPipe->SetWorldToCamera( targetMatrix, inverse );
if (HasFlags(kSetFOV)) // are we changing the field of view?
{
ClearFlags(kSetFOV);
fPipe->SetFOV(fFOVw,fFOVh);
fPipe->RefreshMatrices();
if (foutLog)
{
fprintf(foutLog, "****************************************************************\n");
fprintf(foutLog, "FOV changed to %f %f\n",fFOVh, fFOVw);
fprintf(foutLog, "****************************************************************\n");
}
}
SetOutputFOV();
/* if (foutLog)
{
fprintf(foutLog, "output pos %f %f %f\n", fOutputPos.fX,fOutputPos.fY,fOutputPos.fZ);
@ -865,6 +855,19 @@ void plVirtualCam1::Output()
} */
}
void plVirtualCam1::SetOutputFOV()
{
ClearFlags(kSetFOV);
fPipe->SetFOV(fFOVw, fFOVh);
fPipe->RefreshMatrices();
if (foutLog)
{
fprintf(foutLog, "****************************************************************\n");
fprintf(foutLog, "FOV changed to %f %f\n", fFOVh, fFOVw);
fprintf(foutLog, "****************************************************************\n");
}
}
void plVirtualCam1::Init()
{
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());

3
Sources/Plasma/FeatureLib/pfCamera/plVirtualCamNeu.h

@ -81,9 +81,10 @@ protected:
void Output();
void SetOutputFOV();
void IUpdate();
void INext();
public:
enum flags
{

57
Sources/Plasma/FeatureLib/pfConsole/pfConsole.cpp

@ -45,26 +45,29 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
// //
//////////////////////////////////////////////////////////////////////////////
#include "pfPython/cyPythonInterface.h"
#include "HeadSpin.h"
#include "pfConsole.h"
#include "pfConsoleCore/pfConsoleEngine.h"
#include "plPipeline/plDebugText.h"
#include "HeadSpin.h"
#include "plFileSystem.h"
#include "plgDispatch.h"
#include "plPipeline.h"
#include "hsTimer.h"
#include "plGImage/plPNG.h"
#include "plInputCore/plInputDevice.h"
#include "plInputCore/plInputInterface.h"
#include "plInputCore/plInputInterfaceMgr.h"
#include "pnInputCore/plKeyMap.h"
#include "pnInputCore/plKeyDef.h"
#include "pnInputCore/plKeyMap.h"
#include "pnKeyedObject/plFixedKey.h"
#include "plMessage/plInputEventMsg.h"
#include "plMessage/plCaptureRenderMsg.h"
#include "plMessage/plConsoleMsg.h"
#include "plMessage/plInputIfaceMgrMsg.h"
#include "pnKeyedObject/plFixedKey.h"
#include "hsTimer.h"
#include "plgDispatch.h"
#include "plPipeline.h"
#include "plNetClient/plNetClientMgr.h"
#include "plPipeline/plDebugText.h"
#include "pfPython/cyPythonInterface.h"
#ifndef PLASMA_EXTERNAL_RELEASE
#include "pfGameMgr/pfGameMgr.h"
@ -265,8 +268,42 @@ void pfConsole::ISetMode( uint8_t mode )
//// MsgReceive //////////////////////////////////////////////////////////////
#include <algorithm>
bool pfConsole::MsgReceive( plMessage *msg )
{
// Handle screenshot saving...
plCaptureRenderMsg* capMsg = plCaptureRenderMsg::ConvertNoRef(msg);
if (capMsg) {
plFileName screenshots = plFileName::Join(plFileSystem::GetUserDataPath(), "Screenshots");
plFileSystem::CreateDir(screenshots, false); // just in case...
plString prefix = plProduct::ShortName();
// List all of the PNG indices we have taken up already...
plString pattern = plString::Format("%s*.png", prefix.c_str());
std::vector<plFileName> images = plFileSystem::ListDir(screenshots, pattern.c_str());
std::set<uint32_t> indices;
std::for_each(images.begin(), images.end(),
[&] (const plFileName& fn) {
plString idx = fn.GetFileNameNoExt().Substr(prefix.GetSize());
indices.insert(idx.ToUInt(10));
}
);
// Now that we have an ordered set of indices, save this screenshot to the first one we don't have.
uint32_t num = 0;
for (auto it = indices.begin(); it != indices.end(); ++it, ++num) {
if (*it != num)
break;
}
// Got our num, save the screenshot.
plFileName fn = plString::Format("%s%04d.png", prefix.c_str(), num);
plPNG::Instance().WriteToFile(plFileName::Join(screenshots, fn), capMsg->GetMipmap());
AddLineF("Saved screenshot as '%s'", fn.AsString().c_str());
return true;
}
plControlEventMsg *ctrlMsg = plControlEventMsg::ConvertNoRef( msg );
if( ctrlMsg != nil )
{

89
Sources/Plasma/FeatureLib/pfConsole/pfConsoleCommands.cpp

@ -144,7 +144,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plDrawable/plDynaBulletMgr.h"
#include "plGImage/plMipmap.h"
#include "plGImage/plTGAWriter.h"
#include "plGLight/plShadowCaster.h"
#include "plGLight/plShadowMaster.h"
@ -1533,44 +1532,6 @@ static bool MakeUniqueFileName(const char* prefix, const char* ext, char* fileNa
#ifndef LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_CMD( Graphics_Renderer, TakeScreenshot, "...", "Takes a shot of the current frame and saves it to the given file" )
{
hsAssert( pfConsole::GetPipeline() != nil, "Cannot use this command before pipeline initialization" );
plMipmap myMipmap;
char fileName[ 512 ];
if( numParams > 1 )
{
PrintString( "Too many parameters to TakeScreenshot" );
return;
}
else if( numParams == 1 )
strcpy( fileName, (char *)params[ 0 ] );
else
{
// Think up a filename
if (!MakeUniqueFileName("screen", "tga", fileName))
{
PrintString( "Out of filenames for TakeScreenshot" );
return;
}
}
if( !pfConsole::GetPipeline()->CaptureScreen( &myMipmap ) )
PrintString( "Error capturing screenshot" );
else
{
char str[ 512 ];
plTGAWriter::Instance().WriteMipmap( fileName, &myMipmap );
sprintf( str, "Screenshot written to '%s'.", fileName );
PrintString( str );
}
}
#include "pfSurface/plGrabCubeMap.h"
PF_CONSOLE_CMD( Graphics_Renderer, GrabCubeMap,
@ -1605,56 +1566,6 @@ PF_CONSOLE_CMD( Graphics_Renderer, GrabCubeCam,
grabCube.GrabCube(pfConsole::GetPipeline(), pos, pref, clearColor);
}
#include "plGImage/plJPEG.h"
PF_CONSOLE_CMD( Graphics_Renderer, TakeJPEGScreenshot, "...", "Takes a shot of the current frame and saves it to the given file" )
{
hsAssert( pfConsole::GetPipeline() != nil, "Cannot use this command before pipeline initialization" );
plMipmap myMipmap;
char fileName[ 512 ];
if( numParams > 2 )
{
PrintString( "Too many parameters to TakeScreenshot" );
return;
}
else if( numParams > 0 )
strcpy( fileName, (char *)params[ 0 ] );
else
{
// Think up a filename
if (!MakeUniqueFileName("screen", "jpg", fileName))
{
PrintString( "Out of filenames for TakeScreenshot" );
return;
}
}
if( !pfConsole::GetPipeline()->CaptureScreen( &myMipmap ) )
PrintString( "Error capturing screenshot" );
else
{
char str[ 512 ];
uint8_t quality = 75;
if( numParams == 2 )
quality = (int)params[ 1 ];
plJPEG::Instance().SetWriteQuality( quality );
if( !plJPEG::Instance().WriteToFile( fileName, &myMipmap ) )
{
sprintf( str, "JPEG write failed (%s).", plJPEG::Instance().GetLastError() );
}
else
sprintf( str, "Screenshot written to '%s', quality of %d%%.", fileName, quality );
PrintString( str );
}
}
#include "plGImage/plAVIWriter.h"
PF_CONSOLE_CMD( Graphics_Renderer, AVIWrite, "...", "Saves each frame to an AVI file" )

64
Sources/Plasma/FeatureLib/pfConsole/pfGameConsoleCommands.cpp

@ -72,19 +72,20 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "pfConsoleCore/pfConsoleCmd.h"
#include "pfConsole.h"
#include "plPipeline.h"
#include "plgDispatch.h"
#include "plGImage/plMipmap.h"
#include "plGImage/plTGAWriter.h"
#include "pfMessage/pfGameGUIMsg.h"
#include "plPipeline.h"
#include "hsResMgr.h"
#include "pfGameGUIMgr/pfGUICtrlGenerator.h"
#include "plAvatar/plAvatarMgr.h"
#include "plAvatar/plAnimStage.h"
#include "plAvatar/plAvBrainGeneric.h"
#include "plAvatar/plAvBrainHuman.h"
#include "plMessage/plAvatarMsg.h"
#include "plAvatar/plAvatarMgr.h"
#include "plGImage/plMipmap.h"
#include "pfGameGUIMgr/pfGUICtrlGenerator.h"
#include "pnKeyedObject/plFixedKey.h"
#include "plMessage/plAvatarMsg.h"
#include "pfMessage/pfGameGUIMsg.h"
#include "plPipeline/plCaptureRender.h"
#define PF_SANITY_CHECK( cond, msg ) { if( !( cond ) ) { PrintString( msg ); return; } }
@ -115,52 +116,19 @@ static bool plDoesFileExist( const char *path )
PF_CONSOLE_GROUP( Game )
#ifndef LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_CMD( Game, TakeScreenshot, "...", "Takes a shot of the current frame and saves it to the given file" )
PF_CONSOLE_CMD( Game, TakeScreenshot, "int width, int height", "Captures a screenshot" )
{
hsAssert( pfConsole::GetPipeline() != nil, "Cannot use this command before pipeline initialization" );
plMipmap myMipmap;
char fileName[ 512 ];
uint32_t uniqueNumber;
if( numParams > 1 )
{
PrintString( "Too many parameters to TakeScreenshot" );
return;
}
else if( numParams == 1 )
strcpy( fileName, (char *)params[ 0 ] );
else
{
// Think up a filename
for( uniqueNumber = 1; uniqueNumber < 1000; uniqueNumber++ )
{
sprintf( fileName, "screen%03d.tga", uniqueNumber );
if( !plDoesFileExist( fileName ) )
break;
}
if( uniqueNumber == 1000 )
{
PrintString( "Out of filenames for TakeScreenshot" );
return;
}
}
if( !pfConsole::GetPipeline()->CaptureScreen( &myMipmap ) )
PrintString( "Error capturing screenshot" );
else
{
char str[ 512 ];
hsAssert(pfConsole::GetPipeline(), "Game.TakeScreenShot needs a plPipeline!");
int width = params[0];
int height = params[1];
plTGAWriter::Instance().WriteMipmap( fileName, &myMipmap );
sprintf( str, "Screenshot written to '%s'.", fileName );
PrintString( str );
}
// Let's use plCaptureRender so that we have a really nice image.
// We'll take care of saving in pfConsole::MsgReceive
plCaptureRender::Capture(pfConsole::GetInstance()->GetKey(), width, height);
}
#ifndef LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_CMD( Game, LoadDialog, "string dlgName", "Loads the given GUI dialog into memory" )
{
plUoid lu( kGameGUIMgr_KEY );

2
Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp

@ -5186,14 +5186,12 @@ void plDXPipeline::ISetRenderTarget( plRenderTarget *target )
/// Set to main screen
main = fD3DMainSurface;
depth = fD3DDepthSurface;
ISetAnisotropy(true);
}
else
{
/// Set to this target
main = ref->GetColorSurface();
depth = ref->fD3DDepthSurface;
ISetAnisotropy(false);
}
if( main != fSettings.fCurrD3DMainSurface || depth != fSettings.fCurrD3DDepthSurface )

3
Sources/Plasma/PubUtilLib/plPipeline/plCaptureRender.cpp

@ -54,6 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsResMgr.h"
#include "pnKeyedObject/plUoid.h"
#include "pfCamera/plVirtualCamNeu.h"
#include "pfGameGUIMgr/pfGameGUIMgr.h"
#else // MF_FRONTBUFF_CAPTURE
@ -89,12 +90,14 @@ void plCaptureRenderRequest::Render(plPipeline* pipe, plPageTreeMgr* pageMgr)
// Clear our render target
// Render the scene
pipe->PushRenderRequest(this);
plVirtualCam1::Refresh();
pipe->ClearRenderTarget();
pageMgr->Render(pipe);
pipe->PopRenderRequest(this);
plVirtualCam1::Refresh();
// set up state so we can clear the z-buffer for every gui dialog (and therefore not have it
// be obscured by other geometry)

Loading…
Cancel
Save