diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 980afdfae..ab8d93a87 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -1,18 +1,21 @@ #include "savegamedialog.hpp" -#include "widgets.hpp" - -#include -#include #include #include #include #include +#include +#include + +#include + #include #include +#include + #include "../mwbase/statemanager.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -22,6 +25,7 @@ #include "../mwstate/character.hpp" #include "confirmationdialog.hpp" +#include "widgets.hpp" namespace MWGui { @@ -358,30 +362,38 @@ namespace MWGui << " " << hour << " " << (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}"); mInfoText->setCaptionWithReplacing(text.str()); -#if 0 + + // Decode screenshot - std::vector data = mCurrentSlot->mProfile.mScreenshot; // MemoryDataStream doesn't work with const data :( - Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size())); - Ogre::Image image; - image.load(stream, "jpg"); - - const std::string textureName = "@savegame_screenshot"; - Ogre::TexturePtr texture; - texture = Ogre::TextureManager::getSingleton().getByName(textureName); - mScreenshot->setImageTexture(""); - if (texture.isNull()) + const std::vector& data = mCurrentSlot->mProfile.mScreenshot; + Files::IMemStream instream (&data[0], data.size()); + + osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("jpg"); + if (!readerwriter) + { + std::cerr << "Can't open savegame screenshot, no jpg readerwriter found" << std::endl; + return; + } + + osgDB::ReaderWriter::ReadResult result = readerwriter->readImage(instream); + if (!result.success()) { - texture = Ogre::TextureManager::getSingleton().createManual(textureName, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - image.getWidth(), image.getHeight(), 0, Ogre::PF_BYTE_RGBA, Ogre::TU_DYNAMIC_WRITE_ONLY); + std::cerr << "Failed to read savegame screenshot: " << result.message() << std::endl; + return; } - texture->unload(); - texture->setWidth(image.getWidth()); - texture->setHeight(image.getHeight()); - texture->loadImage(image); - mScreenshot->setImageTexture(textureName); -#endif + osg::ref_ptr texture (new osg::Texture2D); + texture->setImage(result.getImage()); + texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + texture->setResizeNonPowerOfTwoHint(false); + texture->setUnRefImageDataAfterApply(true); + + mScreenshotTexture.reset(new osgMyGUI::OSGTexture(texture)); + + mScreenshot->setRenderItemTexture(mScreenshotTexture.get()); + mScreenshot->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); } } diff --git a/apps/openmw/mwgui/savegamedialog.hpp b/apps/openmw/mwgui/savegamedialog.hpp index 2192adbde..6a9e59cc6 100644 --- a/apps/openmw/mwgui/savegamedialog.hpp +++ b/apps/openmw/mwgui/savegamedialog.hpp @@ -48,6 +48,7 @@ namespace MWGui void fillSaveList(); + std::auto_ptr mScreenshotTexture; MyGUI::ImageBox* mScreenshot; bool mSaving; diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index b800da701..6a5b7f59a 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -85,7 +85,7 @@ IF(NOT WIN32 AND NOT APPLE) ENDIF() add_component_dir (files linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager - lowlevelfile constrainedfilestream + lowlevelfile constrainedfilestream memorystream ) add_component_dir (compiler diff --git a/components/files/memorystream.hpp b/components/files/memorystream.hpp new file mode 100644 index 000000000..9a3510044 --- /dev/null +++ b/components/files/memorystream.hpp @@ -0,0 +1,31 @@ +#ifndef OPENMW_COMPONENTS_FILES_MEMORYSTREAM_H +#define OPENMW_COMPONENTS_FILES_MEMORYSTREAM_H + +#include + +namespace Files +{ + + struct MemBuf : std::streambuf + { + MemBuf(char const* buffer, size_t size) + { + // a streambuf isn't specific to istreams, so we need a non-const pointer :/ + char* nonconstBuffer = (const_cast(buffer)); + this->setg(nonconstBuffer, nonconstBuffer, nonconstBuffer + size); + } + }; + + /// @brief A variant of std::istream that reads from a constant in-memory buffer. + struct IMemStream: virtual MemBuf, std::istream + { + IMemStream(char const* buffer, size_t size) + : MemBuf(buffer, size) + , std::istream(static_cast(this)) + { + } + }; + +} + +#endif