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 "pfConsole.h"
#include "pfConsoleCore/pfConsoleEngine.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/plInputDevice.h"
#include "plInputCore/plInputInterface.h" #include "plInputCore/plInputInterface.h"
#include "plInputCore/plInputInterfaceMgr.h" #include "plInputCore/plInputInterfaceMgr.h"
#include "pnInputCore/plKeyMap.h"
#include "pnInputCore/plKeyDef.h" #include "pnInputCore/plKeyDef.h"
#include "pnInputCore/plKeyMap.h"
#include "pnKeyedObject/plFixedKey.h"
#include "plMessage/plInputEventMsg.h" #include "plMessage/plInputEventMsg.h"
#include "plMessage/plCaptureRenderMsg.h"
#include "plMessage/plConsoleMsg.h" #include "plMessage/plConsoleMsg.h"
#include "plMessage/plInputIfaceMgrMsg.h" #include "plMessage/plInputIfaceMgrMsg.h"
#include "pnKeyedObject/plFixedKey.h"
#include "hsTimer.h"
#include "plgDispatch.h"
#include "plPipeline.h"
#include "plNetClient/plNetClientMgr.h" #include "plNetClient/plNetClientMgr.h"
#include "plPipeline/plDebugText.h"
#include "pfPython/cyPythonInterface.h"
#ifndef PLASMA_EXTERNAL_RELEASE #ifndef PLASMA_EXTERNAL_RELEASE
#include "pfGameMgr/pfGameMgr.h" #include "pfGameMgr/pfGameMgr.h"
@ -265,8 +268,42 @@ void pfConsole::ISetMode( uint8_t mode )
//// MsgReceive ////////////////////////////////////////////////////////////// //// MsgReceive //////////////////////////////////////////////////////////////
#include <algorithm>
bool pfConsole::MsgReceive( plMessage *msg ) 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 ); plControlEventMsg *ctrlMsg = plControlEventMsg::ConvertNoRef( msg );
if( ctrlMsg != nil ) 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 "pfConsoleCore/pfConsoleCmd.h"
#include "pfConsole.h" #include "pfConsole.h"
#include "plPipeline.h"
#include "plgDispatch.h" #include "plgDispatch.h"
#include "plGImage/plMipmap.h" #include "plPipeline.h"
#include "plGImage/plTGAWriter.h"
#include "pfMessage/pfGameGUIMsg.h"
#include "hsResMgr.h" #include "hsResMgr.h"
#include "pfGameGUIMgr/pfGUICtrlGenerator.h"
#include "plAvatar/plAvatarMgr.h"
#include "plAvatar/plAnimStage.h" #include "plAvatar/plAnimStage.h"
#include "plAvatar/plAvBrainGeneric.h" #include "plAvatar/plAvBrainGeneric.h"
#include "plAvatar/plAvBrainHuman.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 "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; } } #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 ) PF_CONSOLE_GROUP( Game )
#ifndef LIMIT_CONSOLE_COMMANDS PF_CONSOLE_CMD( Game, TakeScreenshot, "int width, int height", "Captures a screenshot" )
PF_CONSOLE_CMD( Game, 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" ); hsAssert(pfConsole::GetPipeline(), "Game.TakeScreenShot needs a plPipeline!");
plMipmap myMipmap;
char fileName[ 512 ];
uint32_t uniqueNumber;
int width = params[0];
int height = params[1];
if( numParams > 1 ) // Let's use plCaptureRender so that we have a really nice image.
{ // We'll take care of saving in pfConsole::MsgReceive
PrintString( "Too many parameters to TakeScreenshot" ); plCaptureRender::Capture(pfConsole::GetInstance()->GetKey(), width, height);
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 ];
plTGAWriter::Instance().WriteMipmap( fileName, &myMipmap );
sprintf( str, "Screenshot written to '%s'.", fileName );
PrintString( str );
}
} }
#ifndef LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_CMD( Game, LoadDialog, "string dlgName", "Loads the given GUI dialog into memory" ) PF_CONSOLE_CMD( Game, LoadDialog, "string dlgName", "Loads the given GUI dialog into memory" )
{ {
plUoid lu( kGameGUIMgr_KEY ); plUoid lu( kGameGUIMgr_KEY );

Loading…
Cancel
Save