namespace NAMESPACE
{
int GetEncoderClsID(const WCHAR* format, CLSID* pClsid) {
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if (size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for (UINT j = 0; j < num; ++j) {
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}
string CheckFileName(string name) {
if (_access("ScreenShots/" + name + ".jpg", 0) != 0)
return name;
for (uint i = 2; true; i++) {
string nextName = name + "_v" + i;
if (_access("ScreenShots/" + nextName + ".jpg", 0) != 0)
return nextName;
}
}
CLSID myClsId;
void CreateScreenShot(zCTextureConvert* texConv) {
time_t baseTime = time(Null);
tm* now = localtime(&baseTime);
string timeFormat = string::Combine(
"%u_%u_%u_%u_%u_%u",
now->tm_year + 1900,
now->tm_mon + 1,
now->tm_mday,
now->tm_hour,
now->tm_min,
now->tm_sec
);
string fileName = "ScreenShot_" + timeFormat;
fileName = CheckFileName(fileName) + ".jpg";
//cmd << "begin" << endl;
if (_access("ScreenShots", 0) != 0)
CreateDirectory("ScreenShots", 0);
zCTextureInfo info = texConv->GetTextureInfo();
info.texFormat = zRND_TEX_FORMAT_BGRA_8888;
((zCTexConGeneric*)texConv)->ConvertTextureFormat(info);
zCTextureConvert* pNewConv = zrenderer->CreateTextureConvert();
zCTextureExchange::CopyContents(texConv, pNewConv);
((zCTexConGeneric*)texConv)->SetDetailTextureMode(0);
((zCTexConGeneric*)texConv)->ConvertTextureFormat(info);
int nPitch = info.sizeX * 4;
int nImageSize = nPitch * info.sizeY;
void* pb = (void*) ::GlobalAlloc(GMEM_FIXED, nImageSize);
pNewConv->CopyTextureDataTo(0, pb, info.sizeX * 4);
delete pNewConv;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HBITMAP hBitmap = CreateBitmap(info.sizeX, info.sizeY, 1, 32, pb);
::GlobalFree(pb);
Bitmap* image = new Bitmap(hBitmap, NULL);
wstring outName = L"ScreenShots/" + fileName.AToW();
static bool once = true;
if (once) {
once = false;
int retVal = GetEncoderClsID(L"image/jpeg", &myClsId);
}
Gdiplus::Status s = image->Save(outName, &myClsId);
delete image;
GdiplusShutdown(gdiplusToken);
if (s == Gdiplus::Status::Ok) {
//cmd << "ScreenShot saved" << endl;
//ScreenShotPush( "ScreenShot saved! " + fileName );
}
else {
cmd << "ScreenShot NOT saved" << endl;
fileName = "NOT SAVED :(";
//ScreenShotPush( "ScreenShot NOT saved! " + fileName );
}
}
void CreateScreenShot(const zVEC3& cameraPos, zCTexture*& texture)
{
zMAT4& newTrafo = zCCamera::activeCam->connectedVob->trafoObjToWorld;
zMAT4 oldTrafo = newTrafo;
newTrafo.SetTranslation(cameraPos);
{
auto frameTimeFloatScope = AssignTemp(ztimer->frameTimeFloat, 0.0f);
auto frameTimeScope = AssignTemp(ztimer->frameTime, 0ul);
auto aiScope = AssignTemp(oCNpc::ai_baseEnabled, 0);
auto fileNameScope = AssignTemp(ogame->GetGameWorld()->worldFilename, Z"");
#if ENGINE >= Engine_G2
auto nameScope = AssignTemp(ogame->GetWorld()->m_strlevelName, Z"");
#endif
auto activeVobListScope = AssignTemp(ogame->GetWorld()->activeVobList, zCArray<zCVob*>{});
ogame->GetWorld()->Render(*zCCamera::activeCam);
}
zCTexConGeneric* textureConvert = dynamic_cast<zCTexConGeneric*>(zrenderer->CreateTextureConvert());
zrenderer->Vid_GetFrontBufferCopy(*textureConvert);
CreateScreenShot(textureConvert);
newTrafo = oldTrafo;
if (!texture)
texture = zrenderer->CreateTexture();
zCTextureInfo info = textureConvert->GetTextureInfo();
info.texFormat = zCTexture::CalcNextBestTexFormat(zRND_TEX_FORMAT_RGB_565);
info.numMipMap = 1;
info.sizeX = 1024;
info.sizeY = 1024;
textureConvert->ConvertTextureFormat(info);
zCTextureExchange::CopyContents(textureConvert, texture);
delete textureConvert;
}
int (*innerEvalFunc)(const zSTRING&, zSTRING&);
int ConsoleEvalFunc(const zSTRING& inpstr, zSTRING& msg)
{
if (innerEvalFunc && innerEvalFunc(inpstr, msg))
return true;
zSTRING input = inpstr;
input.Upper();
if (input.StartWith("SCREEN AT"))
{
zVEC3 cameraPos;
for (int i = 0; i < 3; i++)
{
zSTRING numString = input.GetWord(" ", 3 + i);
if (numString.IsEmpty())
{
msg = "Not enough parameters";
return true;
}
cameraPos[i] = numString.ToReal32();
}
zCTexture* shot = nullptr;
CreateScreenShot(cameraPos, shot);
static zCView* shotView = new zCView{ 1000, 1000, 3000, 3000 };
if (!shotView->ondesk)
screen->InsertItem(shotView);
shotView->InsertBack(shot);
msg = "Ok";
return true;
}
return false;
}
void RegisterEvalFunc()
{
int evalNum = 0;
for (int i = 1; i < zCON_MAX_EVAL; i++)
if (zcon->evalfunc[i])
evalNum = i;
innerEvalFunc = zcon->evalfunc[evalNum];
zcon->evalfunc[evalNum] = &ConsoleEvalFunc;
}
extern Sub<void> registerCommand;
Sub<void> registerCommand(ZSUB(GameEvent::LoadBegin), []
{
registerCommand = {};
RegisterEvalFunc();
zcon->Register("SCREEN AT", "Creates screen shot at specified position");
});
}