mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:53:52 +00:00
Write savegame screenshot
This commit is contained in:
parent
24551c7bab
commit
2a85a22dba
7 changed files with 101 additions and 13 deletions
|
@ -23,6 +23,7 @@ namespace osg
|
||||||
{
|
{
|
||||||
class Vec3f;
|
class Vec3f;
|
||||||
class Quat;
|
class Quat;
|
||||||
|
class Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Loading
|
namespace Loading
|
||||||
|
@ -438,7 +439,7 @@ namespace MWBase
|
||||||
virtual void reattachPlayerCamera() = 0;
|
virtual void reattachPlayerCamera() = 0;
|
||||||
|
|
||||||
/// \todo this does not belong here
|
/// \todo this does not belong here
|
||||||
virtual void screenshot (Ogre::Image& image, int w, int h) = 0;
|
virtual void screenshot (osg::Image* image, int w, int h) = 0;
|
||||||
|
|
||||||
/// Find default position inside exterior cell specified by name
|
/// Find default position inside exterior cell specified by name
|
||||||
/// \return false if exterior with given name not exists, true otherwise
|
/// \return false if exterior with given name not exists, true otherwise
|
||||||
|
|
|
@ -379,6 +379,65 @@ namespace MWRender
|
||||||
mWater->setHeight(height);
|
mWater->setHeight(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NotifyDrawCompletedCallback : public osg::Camera::DrawCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void operator () (osg::RenderInfo& renderInfo) const
|
||||||
|
{
|
||||||
|
mCondition.signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
mutable OpenThreads::Condition mCondition;
|
||||||
|
};
|
||||||
|
|
||||||
|
void RenderingManager::screenshot(osg::Image *image, int w, int h)
|
||||||
|
{
|
||||||
|
int oldCullMask = mViewer->getCamera()->getCullMask();
|
||||||
|
mViewer->getCamera()->setCullMask(oldCullMask & (~Mask_GUI));
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Camera> rttCamera (new osg::Camera);
|
||||||
|
rttCamera->setNodeMask(Mask_RenderToTexture);
|
||||||
|
rttCamera->attach(osg::Camera::COLOR_BUFFER, image);
|
||||||
|
rttCamera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||||
|
rttCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
|
||||||
|
rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT);
|
||||||
|
rttCamera->setClearColor(mViewer->getCamera()->getClearColor());
|
||||||
|
rttCamera->setClearMask(mViewer->getCamera()->getClearMask());
|
||||||
|
rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mViewDistance);
|
||||||
|
rttCamera->setViewMatrix(mViewer->getCamera()->getViewMatrix());
|
||||||
|
rttCamera->setViewport(0, 0, w, h);
|
||||||
|
rttCamera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D);
|
||||||
|
texture->setInternalFormat(GL_RGB);
|
||||||
|
texture->setTextureSize(w, h);
|
||||||
|
texture->setResizeNonPowerOfTwoHint(false);
|
||||||
|
rttCamera->attach(osg::Camera::COLOR_BUFFER, texture);
|
||||||
|
|
||||||
|
image->setDataType(GL_UNSIGNED_BYTE);
|
||||||
|
image->setPixelFormat(texture->getInternalFormat());
|
||||||
|
|
||||||
|
rttCamera->addChild(mLightRoot);
|
||||||
|
|
||||||
|
mRootNode->addChild(rttCamera);
|
||||||
|
|
||||||
|
mViewer->frame();
|
||||||
|
|
||||||
|
// The draw needs to complete before we can copy back our image.
|
||||||
|
osg::ref_ptr<NotifyDrawCompletedCallback> callback (new NotifyDrawCompletedCallback);
|
||||||
|
rttCamera->setFinalDrawCallback(callback);
|
||||||
|
OpenThreads::Mutex m;
|
||||||
|
m.lock();
|
||||||
|
callback->mCondition.wait(&m);
|
||||||
|
m.unlock();
|
||||||
|
|
||||||
|
rttCamera->removeChildren(0, rttCamera->getNumChildren());
|
||||||
|
rttCamera->setGraphicsContext(NULL);
|
||||||
|
mRootNode->removeChild(rttCamera);
|
||||||
|
|
||||||
|
mViewer->getCamera()->setCullMask(oldCullMask);
|
||||||
|
}
|
||||||
|
|
||||||
void RenderingManager::getCameraToViewportRay(float nX, float nY, osg::Vec3f &origin, osg::Vec3f &dest)
|
void RenderingManager::getCameraToViewportRay(float nX, float nY, osg::Vec3f &origin, osg::Vec3f &dest)
|
||||||
{
|
{
|
||||||
osg::Matrix viewProj = mViewer->getCamera()->getViewMatrix() * mViewer->getCamera()->getProjectionMatrix();
|
osg::Matrix viewProj = mViewer->getCamera()->getViewMatrix() * mViewer->getCamera()->getProjectionMatrix();
|
||||||
|
|
|
@ -82,6 +82,9 @@ namespace MWRender
|
||||||
void setWaterEnabled(bool enabled);
|
void setWaterEnabled(bool enabled);
|
||||||
void setWaterHeight(float level);
|
void setWaterHeight(float level);
|
||||||
|
|
||||||
|
/// Take a screenshot of w*h onto the given image, not including the GUI.
|
||||||
|
void screenshot(osg::Image* image, int w, int h);
|
||||||
|
|
||||||
/// Return the object under the mouse cursor / crosshair position, given by nX and nY normalized screen coordinates,
|
/// Return the object under the mouse cursor / crosshair position, given by nX and nY normalized screen coordinates,
|
||||||
/// where (0,0) is the top left corner.
|
/// where (0,0) is the top left corner.
|
||||||
MWWorld::Ptr getFacedObject(const float nX, const float nY, float maxDistance, bool ignorePlayer);
|
MWWorld::Ptr getFacedObject(const float nX, const float nY, float maxDistance, bool ignorePlayer);
|
||||||
|
|
|
@ -10,7 +10,9 @@
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include <OgreImage.h>
|
#include <osg/Image>
|
||||||
|
|
||||||
|
#include <osgDB/Registry>
|
||||||
|
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/filesystem/operations.hpp>
|
#include <boost/filesystem/operations.hpp>
|
||||||
|
@ -179,14 +181,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
|
||||||
profile.mTimePlayed = mTimePlayed;
|
profile.mTimePlayed = mTimePlayed;
|
||||||
profile.mDescription = description;
|
profile.mDescription = description;
|
||||||
|
|
||||||
/*
|
writeScreenshot(profile.mScreenshot);
|
||||||
int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
|
|
||||||
Ogre::Image screenshot;
|
|
||||||
world.screenshot(screenshot, screenshotW, screenshotH);
|
|
||||||
Ogre::DataStreamPtr encoded = screenshot.encode("jpg");
|
|
||||||
profile.mScreenshot.resize(encoded->size());
|
|
||||||
encoded->read(&profile.mScreenshot[0], encoded->size());
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!slot)
|
if (!slot)
|
||||||
slot = getCurrentCharacter()->createSlot (profile);
|
slot = getCurrentCharacter()->createSlot (profile);
|
||||||
|
@ -572,3 +567,31 @@ bool MWState::StateManager::verifyProfile(const ESM::SavedGame& profile) const
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MWState::StateManager::writeScreenshot(std::vector<char> &imageData) const
|
||||||
|
{
|
||||||
|
int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Image> screenshot (new osg::Image);
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->screenshot(screenshot.get(), screenshotW, screenshotH);
|
||||||
|
|
||||||
|
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("jpg");
|
||||||
|
if (!readerwriter)
|
||||||
|
{
|
||||||
|
std::cerr << "Unable to write screenshot, can't find a jpg ReaderWriter" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream ostream;
|
||||||
|
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*screenshot, ostream);
|
||||||
|
if (!result.success())
|
||||||
|
{
|
||||||
|
std::cerr << "Unable to write screenshot: " << result.message() << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string data = ostream.str();
|
||||||
|
imageData = std::vector<char>(data.begin(), data.end());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ namespace MWState
|
||||||
|
|
||||||
bool verifyProfile (const ESM::SavedGame& profile) const;
|
bool verifyProfile (const ESM::SavedGame& profile) const;
|
||||||
|
|
||||||
|
void writeScreenshot (std::vector<char>& imageData) const;
|
||||||
|
|
||||||
std::map<int, int> buildContentFileIndexMap (const ESM::ESMReader& reader) const;
|
std::map<int, int> buildContentFileIndexMap (const ESM::ESMReader& reader) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -2128,9 +2128,9 @@ namespace MWWorld
|
||||||
return mRendering->getAnimation(ptr);
|
return mRendering->getAnimation(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::screenshot(Ogre::Image &image, int w, int h)
|
void World::screenshot(osg::Image* image, int w, int h)
|
||||||
{
|
{
|
||||||
//mRendering->screenshot(image, w, h);
|
mRendering->screenshot(image, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::activateDoor(const MWWorld::Ptr& door)
|
void World::activateDoor(const MWWorld::Ptr& door)
|
||||||
|
|
|
@ -524,7 +524,7 @@ namespace MWWorld
|
||||||
virtual void reattachPlayerCamera();
|
virtual void reattachPlayerCamera();
|
||||||
|
|
||||||
/// \todo this does not belong here
|
/// \todo this does not belong here
|
||||||
virtual void screenshot (Ogre::Image& image, int w, int h);
|
virtual void screenshot (osg::Image* image, int w, int h);
|
||||||
|
|
||||||
/// Find center of exterior cell above land surface
|
/// Find center of exterior cell above land surface
|
||||||
/// \return false if exterior with given name not exists, true otherwise
|
/// \return false if exterior with given name not exists, true otherwise
|
||||||
|
|
Loading…
Reference in a new issue