Browse Source

Better Game.TakeScreenShot

The new version uses plCaptureRender, so we can take screenshots at any
size that DX can render to...
Adam Johnson 11 years ago
parent
commit
2d8d42759d
  1. 57
      Sources/Plasma/FeatureLib/pfConsole/pfConsole.cpp
  2. 64
      Sources/Plasma/FeatureLib/pfConsole/pfGameConsoleCommands.cpp

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 )
{

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 );

Loading…
Cancel
Save