Refactored video player (now a MyGUI widget)

actorid
scrawl 11 years ago
parent 2e4ef93b28
commit 5906d795c0

@ -33,7 +33,7 @@ add_openmw_dir (mwgui
merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks
keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog
recharge mode recharge mode videowidget
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue

@ -456,7 +456,7 @@ void OMW::Engine::go()
// TODO: there are other intro videos, too. They need to be imported from Morrowind.ini. // TODO: there are other intro videos, too. They need to be imported from Morrowind.ini.
// Unfortunately those must play BEFORE any loading is done, which will currently not work. // Unfortunately those must play BEFORE any loading is done, which will currently not work.
// The videoplayer is created by World, so all content files must be loaded first... // The videoplayer is created by World, so all content files must be loaded first...
MWBase::Environment::get().getWorld()->playVideo("mw_logo.bik", true); MWBase::Environment::get().getWindowManager()->playVideo("mw_logo.bik", true);
} }
catch (...) {} catch (...) {}
} }

@ -96,6 +96,10 @@ namespace MWBase
*/ */
virtual void update() = 0; virtual void update() = 0;
/// @note This method will block until the video finishes playing
/// (and will continually update the window while doing so)
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
virtual void setNewGame(bool newgame) = 0; virtual void setNewGame(bool newgame) = 0;
virtual void pushGuiMode (MWGui::GuiMode mode) = 0; virtual void pushGuiMode (MWGui::GuiMode mode) = 0;

@ -420,8 +420,6 @@ namespace MWBase
virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) = 0; virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) = 0;
/// \todo this does not belong here /// \todo this does not belong here
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
virtual void stopVideo() = 0;
virtual void frameStarted (float dt, bool paused) = 0; virtual void frameStarted (float dt, bool paused) = 0;
virtual void screenshot (Ogre::Image& image, int w, int h) = 0; virtual void screenshot (Ogre::Image& image, int w, int h) = 0;

@ -90,7 +90,7 @@ namespace MWGui
else if (name == "options") else if (name == "options")
MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings); MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings);
else if (name == "credits") else if (name == "credits")
MWBase::Environment::get().getWorld()->playVideo("mw_credits.bik", true); MWBase::Environment::get().getWindowManager()->playVideo("mw_credits.bik", true);
else if (name == "exitgame") else if (name == "exitgame")
{ {
if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame) if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame)

@ -47,9 +47,7 @@ namespace MWGui
GM_Loading, GM_Loading,
GM_LoadingWallpaper, GM_LoadingWallpaper,
GM_QuickKeysMenu, GM_QuickKeysMenu
GM_Video
}; };
// Windows shown in inventory mode // Windows shown in inventory mode

@ -0,0 +1,45 @@
#include "videowidget.hpp"
namespace MWGui
{
VideoWidget::VideoWidget()
: mAllowSkipping(true)
{
eventKeyButtonPressed += MyGUI::newDelegate(this, &VideoWidget::onKeyPressed);
setNeedKeyFocus(true);
}
void VideoWidget::playVideo(const std::string &video, bool allowSkipping)
{
mAllowSkipping = allowSkipping;
mPlayer.playVideo(video);
setImageTexture(mPlayer.getTextureName());
}
int VideoWidget::getVideoWidth()
{
return mPlayer.getVideoWidth();
}
int VideoWidget::getVideoHeight()
{
return mPlayer.getVideoHeight();
}
void VideoWidget::onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
{
if (_key == MyGUI::KeyCode::Escape && mAllowSkipping)
mPlayer.stopVideo();
}
bool VideoWidget::update()
{
mPlayer.update();
return mPlayer.isPlaying();
}
}

@ -0,0 +1,39 @@
#ifndef OPENMW_MWGUI_VIDEOWIDGET_H
#define OPENMW_MWGUI_VIDEOWIDGET_H
#include <MyGUI_ImageBox.h>
#include "../mwrender/videoplayer.hpp"
namespace MWGui
{
/**
* Widget that plays a video. Can be skipped by pressing Esc.
*/
class VideoWidget : public MyGUI::ImageBox
{
public:
MYGUI_RTTI_DERIVED(VideoWidget)
VideoWidget();
void playVideo (const std::string& video, bool allowSkipping);
int getVideoWidth();
int getVideoHeight();
/// @return Is the video still playing?
bool update();
private:
bool mAllowSkipping;
MWRender::VideoPlayer mPlayer;
void onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char);
};
}
#endif

@ -4,6 +4,7 @@
#include <iterator> #include <iterator>
#include <OgreTextureManager.h> #include <OgreTextureManager.h>
#include <OgreRenderWindow.h>
#include "MyGUI_UString.h" #include "MyGUI_UString.h"
#include "MyGUI_IPointer.h" #include "MyGUI_IPointer.h"
@ -59,6 +60,7 @@
#include "bookpage.hpp" #include "bookpage.hpp"
#include "itemview.hpp" #include "itemview.hpp"
#include "fontloader.hpp" #include "fontloader.hpp"
#include "videowidget.hpp"
namespace MWGui namespace MWGui
{ {
@ -104,6 +106,8 @@ namespace MWGui
, mRecharge(NULL) , mRecharge(NULL)
, mRepair(NULL) , mRepair(NULL)
, mCompanionWindow(NULL) , mCompanionWindow(NULL)
, mVideoBackground(NULL)
, mVideoWidget(NULL)
, mTranslationDataStorage (translationDataStorage) , mTranslationDataStorage (translationDataStorage)
, mCharGen(NULL) , mCharGen(NULL)
, mInputBlocker(NULL) , mInputBlocker(NULL)
@ -155,6 +159,7 @@ namespace MWGui
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ExposedWindow>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ExposedWindow>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollView>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollView>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollBar>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollBar>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<VideoWidget>("Widget");
BookPage::registerMyGUIComponents (); BookPage::registerMyGUIComponents ();
ItemView::registerComponents(); ItemView::registerComponents();
@ -186,6 +191,13 @@ namespace MWGui
// hide mygui's pointer // hide mygui's pointer
MyGUI::PointerManager::getInstance().setVisible(false); MyGUI::PointerManager::getInstance().setVisible(false);
mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal<MyGUI::ImageBox>("ImageBox", 0,0,1,1,
MyGUI::Align::Default, "Overlay");
mVideoBackground->setImageTexture("black.png");
mVideoBackground->setVisible(false);
mVideoWidget = mVideoBackground->createWidgetReal<VideoWidget>("ImageBox", 0,0,1,1, MyGUI::Align::Default);
} }
void WindowManager::initUI() void WindowManager::initUI()
@ -391,6 +403,7 @@ namespace MWGui
mCompanionWindow->setVisible(false); mCompanionWindow->setVisible(false);
mInventoryWindow->setTrading(false); mInventoryWindow->setTrading(false);
mRecharge->setVisible(false); mRecharge->setVisible(false);
mVideoBackground->setVisible(false);
mHud->setVisible(mHudEnabled); mHud->setVisible(mHudEnabled);
@ -539,10 +552,6 @@ namespace MWGui
setCursorVisible(false); setCursorVisible(false);
break; break;
case GM_Video:
setCursorVisible(false);
mHud->setVisible(false);
break;
default: default:
// Unsupported mode, switch back to game // Unsupported mode, switch back to game
break; break;
@ -894,6 +903,7 @@ namespace MWGui
void WindowManager::windowResized(int x, int y) void WindowManager::windowResized(int x, int y)
{ {
sizeVideo(x, y);
mGuiManager->windowResized(); mGuiManager->windowResized();
mLoadingScreen->onResChange (x,y); mLoadingScreen->onResChange (x,y);
if (!mHud) if (!mHud)
@ -1401,4 +1411,57 @@ namespace MWGui
mMap->readRecord(reader, type); mMap->readRecord(reader, type);
} }
void WindowManager::playVideo(const std::string &name, bool allowSkipping)
{
mVideoWidget->playVideo("video\\" + name, allowSkipping);
// Turn off all rendering except for the GUI
mRendering->getScene()->clearSpecialCaseRenderQueues();
// SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work?
for(int i = 0;i < Ogre::RENDER_QUEUE_MAX;++i)
{
if(i > 0 && i < 96)
mRendering->getScene()->addSpecialCaseRenderQueue(i);
}
mRendering->getScene()->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize();
sizeVideo(screenSize.width, screenSize.height);
setKeyFocusWidget(mVideoWidget);
mVideoBackground->setVisible(true);
bool cursorWasVisible = mCursorVisible;
setCursorVisible(false);
while (mVideoWidget->update())
{
MWBase::Environment::get().getInputManager()->update(0, false);
mRendering->getWindow()->update();
}
setCursorVisible(cursorWasVisible);
// Restore normal rendering
mRendering->getScene()->clearSpecialCaseRenderQueues();
mRendering->getScene()->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
mVideoBackground->setVisible(false);
}
void WindowManager::sizeVideo(int screenWidth, int screenHeight)
{
// Use black bars to correct aspect ratio
mVideoBackground->setSize(screenWidth, screenHeight);
double imageaspect = static_cast<double>(mVideoWidget->getVideoWidth())/mVideoWidget->getVideoHeight();
int leftPadding = std::max(0.0, (screenWidth - screenHeight * imageaspect) / 2);
int topPadding = std::max(0.0, (screenHeight - screenWidth / imageaspect) / 2);
mVideoWidget->setCoord(leftPadding, topPadding,
screenWidth - leftPadding*2, screenHeight - topPadding*2);
}
} }

@ -18,6 +18,7 @@ namespace MyGUI
class Widget; class Widget;
class Window; class Window;
class UString; class UString;
class ImageBox;
} }
namespace Compiler namespace Compiler
@ -80,6 +81,7 @@ namespace MWGui
class SoulgemDialog; class SoulgemDialog;
class Recharge; class Recharge;
class CompanionWindow; class CompanionWindow;
class VideoWidget;
class WindowManager : public MWBase::WindowManager class WindowManager : public MWBase::WindowManager
{ {
@ -98,6 +100,10 @@ namespace MWGui
virtual Loading::Listener* getLoadingScreen(); virtual Loading::Listener* getLoadingScreen();
/// @note This method will block until the video finishes playing
/// (and will continually update the window while doing so)
virtual void playVideo(const std::string& name, bool allowSkipping);
/** /**
* Should be called each frame to update windows/gui elements. * Should be called each frame to update windows/gui elements.
* This could mean updating sizes of gui elements or opening * This could mean updating sizes of gui elements or opening
@ -332,6 +338,8 @@ namespace MWGui
Repair* mRepair; Repair* mRepair;
Recharge* mRecharge; Recharge* mRecharge;
CompanionWindow* mCompanionWindow; CompanionWindow* mCompanionWindow;
MyGUI::ImageBox* mVideoBackground;
VideoWidget* mVideoWidget;
Translation::Storage& mTranslationDataStorage; Translation::Storage& mTranslationDataStorage;
Cursor* mSoftwareCursor; Cursor* mSoftwareCursor;
@ -390,6 +398,8 @@ namespace MWGui
void onCursorChange(const std::string& name); void onCursorChange(const std::string& name);
void onKeyFocusChanged(MyGUI::Widget* widget); void onKeyFocusChanged(MyGUI::Widget* widget);
void sizeVideo(int screenWidth, int screenHeight);
}; };
} }

@ -626,9 +626,7 @@ namespace MWInput
if (MyGUI::InputManager::getInstance ().isModalAny()) if (MyGUI::InputManager::getInstance ().isModalAny())
return; return;
if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video) if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
MWBase::Environment::get().getWorld ()->stopVideo ();
else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
{ {
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx); MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx);

@ -43,7 +43,6 @@
#include "water.hpp" #include "water.hpp"
#include "npcanimation.hpp" #include "npcanimation.hpp"
#include "globalmap.hpp" #include "globalmap.hpp"
#include "videoplayer.hpp"
#include "terrainstorage.hpp" #include "terrainstorage.hpp"
#include "effectmanager.hpp" #include "effectmanager.hpp"
@ -171,9 +170,6 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode()); mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode());
mVideoPlayer = new VideoPlayer(mRendering.getScene (), mRendering.getWindow());
mVideoPlayer->setResolution (Settings::Manager::getInt ("resolution x", "Video"), Settings::Manager::getInt ("resolution y", "Video"));
mSun = 0; mSun = 0;
mDebugging = new Debugging(mRootNode, engine); mDebugging = new Debugging(mRootNode, engine);
@ -197,7 +193,6 @@ RenderingManager::~RenderingManager ()
delete mLocalMap; delete mLocalMap;
delete mOcclusionQuery; delete mOcclusionQuery;
delete mWater; delete mWater;
delete mVideoPlayer;
delete mActors; delete mActors;
delete mObjects; delete mObjects;
delete mEffectManager; delete mEffectManager;
@ -333,8 +328,6 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
void RenderingManager::update (float duration, bool paused) void RenderingManager::update (float duration, bool paused)
{ {
mVideoPlayer->update ();
if (MWBase::Environment::get().getStateManager()->getState()== if (MWBase::Environment::get().getStateManager()->getState()==
MWBase::StateManager::State_NoGame) MWBase::StateManager::State_NoGame)
return; return;
@ -884,8 +877,6 @@ void RenderingManager::windowResized(int x, int y)
Settings::Manager::setInt("resolution y", "Video", y); Settings::Manager::setInt("resolution y", "Video", y);
mRendering.adjustViewport(); mRendering.adjustViewport();
mVideoPlayer->setResolution (x, y);
MWBase::Environment::get().getWindowManager()->windowResized(x,y); MWBase::Environment::get().getWindowManager()->windowResized(x,y);
} }
@ -1001,16 +992,6 @@ void RenderingManager::screenshot(Image &image, int w, int h)
mRendering.getCamera()->setAspectRatio(oldAspect); mRendering.getCamera()->setAspectRatio(oldAspect);
} }
void RenderingManager::playVideo(const std::string& name, bool allowSkipping)
{
mVideoPlayer->playVideo ("video/" + name, allowSkipping);
}
void RenderingManager::stopVideo()
{
mVideoPlayer->stopVideo ();
}
void RenderingManager::addWaterRippleEmitter (const MWWorld::Ptr& ptr, float scale, float force) void RenderingManager::addWaterRippleEmitter (const MWWorld::Ptr& ptr, float scale, float force)
{ {
mWater->addEmitter (ptr, scale, force); mWater->addEmitter (ptr, scale, force);

@ -46,7 +46,6 @@ namespace MWRender
class LocalMap; class LocalMap;
class Water; class Water;
class GlobalMap; class GlobalMap;
class VideoPlayer;
class Animation; class Animation;
class EffectManager; class EffectManager;
@ -209,8 +208,6 @@ public:
Animation* getAnimation(const MWWorld::Ptr &ptr); Animation* getAnimation(const MWWorld::Ptr &ptr);
void playVideo(const std::string& name, bool allowSkipping);
void stopVideo();
void frameStarted(float dt, bool paused); void frameStarted(float dt, bool paused);
void screenshot(Ogre::Image& image, int w, int h); void screenshot(Ogre::Image& image, int w, int h);
@ -271,8 +268,6 @@ private:
MWRender::LocalMap* mLocalMap; MWRender::LocalMap* mLocalMap;
MWRender::Shadows* mShadows; MWRender::Shadows* mShadows;
VideoPlayer* mVideoPlayer;
}; };
} }

@ -17,7 +17,6 @@
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwsound/sound_decoder.hpp" #include "../mwsound/sound_decoder.hpp"
@ -126,7 +125,7 @@ struct VideoState {
int stream_open(int stream_index, AVFormatContext *pFormatCtx); int stream_open(int stream_index, AVFormatContext *pFormatCtx);
bool update(Ogre::MaterialPtr &mat, Ogre::Rectangle2D *rect, int screen_width, int screen_height); bool update();
static void video_thread_loop(VideoState *is); static void video_thread_loop(VideoState *is);
static void decode_thread_loop(VideoState *is); static void decode_thread_loop(VideoState *is);
@ -163,6 +162,7 @@ struct VideoState {
static int OgreResource_Write(void *user_data, uint8_t *buf, int buf_size); static int OgreResource_Write(void *user_data, uint8_t *buf, int buf_size);
static int64_t OgreResource_Seek(void *user_data, int64_t offset, int whence); static int64_t OgreResource_Seek(void *user_data, int64_t offset, int whence);
Ogre::TexturePtr mTexture;
Ogre::DataStreamPtr stream; Ogre::DataStreamPtr stream;
AVFormatContext* format_ctx; AVFormatContext* format_ctx;
@ -599,22 +599,17 @@ void VideoState::video_display()
if((*this->video_st)->codec->width != 0 && (*this->video_st)->codec->height != 0) if((*this->video_st)->codec->width != 0 && (*this->video_st)->codec->height != 0)
{ {
Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().getByName("VideoTexture");
if(texture.isNull() || static_cast<int>(texture->getWidth()) != (*this->video_st)->codec->width if(static_cast<int>(mTexture->getWidth()) != (*this->video_st)->codec->width ||
|| static_cast<int>(texture->getHeight()) != (*this->video_st)->codec->height) static_cast<int>(mTexture->getHeight()) != (*this->video_st)->codec->height)
{ {
Ogre::TextureManager::getSingleton ().remove ("VideoTexture"); mTexture->unload();
texture = Ogre::TextureManager::getSingleton().createManual( mTexture->setWidth((*this->video_st)->codec->width);
"VideoTexture", mTexture->setHeight((*this->video_st)->codec->height);
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mTexture->createInternalResources();
Ogre::TEX_TYPE_2D,
(*this->video_st)->codec->width, (*this->video_st)->codec->height,
0,
Ogre::PF_BYTE_RGBA,
Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
} }
Ogre::PixelBox pb((*this->video_st)->codec->width, (*this->video_st)->codec->height, 1, Ogre::PF_BYTE_RGBA, &vp->data[0]); Ogre::PixelBox pb((*this->video_st)->codec->width, (*this->video_st)->codec->height, 1, Ogre::PF_BYTE_RGBA, &vp->data[0]);
Ogre::HardwarePixelBufferSharedPtr buffer = texture->getBuffer(); Ogre::HardwarePixelBufferSharedPtr buffer = mTexture->getBuffer();
buffer->blitFromMemory(pb); buffer->blitFromMemory(pb);
this->display_ready = true; this->display_ready = true;
} }
@ -851,7 +846,7 @@ void VideoState::decode_thread_loop(VideoState *self)
} }
bool VideoState::update(Ogre::MaterialPtr &mat, Ogre::Rectangle2D *rect, int screen_width, int screen_height) bool VideoState::update()
{ {
if(this->quit) if(this->quit)
return false; return false;
@ -860,21 +855,6 @@ bool VideoState::update(Ogre::MaterialPtr &mat, Ogre::Rectangle2D *rect, int scr
{ {
this->refresh = false; this->refresh = false;
this->video_refresh_timer(); this->video_refresh_timer();
// Would be nice not to do this all the time...
if(this->display_ready)
mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("VideoTexture");
// Correct aspect ratio by adding black bars
double videoaspect = av_q2d((*this->video_st)->codec->sample_aspect_ratio);
if(videoaspect == 0.0)
videoaspect = 1.0;
videoaspect *= static_cast<double>((*this->video_st)->codec->width) / (*this->video_st)->codec->height;
double screenaspect = static_cast<double>(screen_width) / screen_height;
double aspect_correction = videoaspect / screenaspect;
rect->setCorners(std::max(-1.0, -1.0 * aspect_correction), std::min( 1.0, 1.0 / aspect_correction),
std::min( 1.0, 1.0 * aspect_correction), std::max(-1.0, -1.0 / aspect_correction));
} }
return true; return true;
} }
@ -1001,8 +981,29 @@ void VideoState::init(const std::string& resourceName)
if(audio_index >= 0) if(audio_index >= 0)
this->stream_open(audio_index, this->format_ctx); this->stream_open(audio_index, this->format_ctx);
if(video_index >= 0) if(video_index >= 0)
{
this->stream_open(video_index, this->format_ctx); this->stream_open(video_index, this->format_ctx);
int width = (*this->video_st)->codec->width;
int height = (*this->video_st)->codec->height;
static int i = 0;
this->mTexture = Ogre::TextureManager::getSingleton().createManual(
"OpenMW/VideoTexture" + Ogre::StringConverter::toString(++i),
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D,
width, height, // TEST
0,
Ogre::PF_BYTE_RGBA,
Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
// initialize to (0,0,0,0)
std::vector<Ogre::uint32> buffer;
buffer.resize(width * height, 0);
Ogre::PixelBox pb(width, height, 1, Ogre::PF_BYTE_RGBA, &buffer[0]);
this->mTexture->getBuffer()->blitFromMemory(pb);
}
this->parse_thread = boost::thread(decode_thread_loop, this); this->parse_thread = boost::thread(decode_thread_loop, this);
} }
@ -1073,111 +1074,26 @@ public:
#endif // defined OPENMW_USE_FFMPEG #endif // defined OPENMW_USE_FFMPEG
VideoPlayer::VideoPlayer(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* window) VideoPlayer::VideoPlayer()
: mState(NULL) : mState(NULL)
, mSceneMgr(sceneMgr)
, mRectangle(NULL)
, mNode(NULL)
, mAllowSkipping(false)
, mWindow(window)
, mWidth(0)
, mHeight(0)
{ {
mVideoMaterial = Ogre::MaterialManager::getSingleton().getByName("VideoMaterial", "General");
if (mVideoMaterial.isNull ())
{
mVideoMaterial = Ogre::MaterialManager::getSingleton().create("VideoMaterial", "General");
mVideoMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
mVideoMaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
mVideoMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
mVideoMaterial->getTechnique(0)->getPass(0)->createTextureUnitState();
mVideoMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
}
mVideoMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("black.png");
Ogre::MaterialPtr blackMaterial = Ogre::MaterialManager::getSingleton().getByName("BlackBarsMaterial", "General");
if (blackMaterial.isNull ())
{
blackMaterial = Ogre::MaterialManager::getSingleton().create("BlackBarsMaterial", "General");
blackMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
blackMaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
blackMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
blackMaterial->getTechnique(0)->getPass(0)->createTextureUnitState()->setTextureName("black.png");
}
mRectangle = new Ogre::Rectangle2D(true);
mRectangle->setCorners(-1.0, 1.0, 1.0, -1.0);
mRectangle->setMaterial("VideoMaterial");
mRectangle->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY+2);
mBackgroundRectangle = new Ogre::Rectangle2D(true);
mBackgroundRectangle->setCorners(-1.0, 1.0, 1.0, -1.0);
mBackgroundRectangle->setMaterial("BlackBarsMaterial");
mBackgroundRectangle->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY+1);
// Use infinite AAB to always stay visible
Ogre::AxisAlignedBox aabInf;
aabInf.setInfinite();
mRectangle->setBoundingBox(aabInf);
mBackgroundRectangle->setBoundingBox(aabInf);
// Attach background to the scene
mNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
mNode->attachObject(mRectangle);
mBackgroundNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
mBackgroundNode->attachObject(mBackgroundRectangle);
mRectangle->setVisible(false);
mRectangle->setVisibilityFlags(RV_Overlay);
mBackgroundRectangle->setVisible(false);
mBackgroundRectangle->setVisibilityFlags(RV_Overlay);
} }
VideoPlayer::~VideoPlayer() VideoPlayer::~VideoPlayer()
{ {
if(mState) if(mState)
close(); close();
mSceneMgr->destroySceneNode(mNode);
mSceneMgr->destroySceneNode(mBackgroundNode);
delete mRectangle;
delete mBackgroundRectangle;
} }
void VideoPlayer::playVideo(const std::string &resourceName, bool allowSkipping) void VideoPlayer::playVideo(const std::string &resourceName)
{ {
mAllowSkipping = allowSkipping;
if(mState) if(mState)
close(); close();
mRectangle->setVisible(true);
mBackgroundRectangle->setVisible(true);
mVideoMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("black.png");
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Video);
// Turn off rendering except the GUI
mSceneMgr->clearSpecialCaseRenderQueues();
// SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work.
for(int i = 0;i < Ogre::RENDER_QUEUE_MAX;++i)
{
if(i > 0 && i < 96)
mSceneMgr->addSpecialCaseRenderQueue(i);
}
mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
try { try {
mState = new VideoState; mState = new VideoState;
mState->init(resourceName); mState->init(resourceName);
while (isPlaying())
{
MWBase::Environment::get().getInputManager()->update(0, false);
update();
mWindow->update();
}
} }
catch(std::exception& e) { catch(std::exception& e) {
std::cerr<< "Failed to play video: "<<e.what() <<std::endl; std::cerr<< "Failed to play video: "<<e.what() <<std::endl;
@ -1189,15 +1105,38 @@ void VideoPlayer::update ()
{ {
if(mState) if(mState)
{ {
if(!mState->update(mVideoMaterial, mRectangle, mWidth, mHeight)) if(!mState->update())
close(); close();
} }
} }
std::string VideoPlayer::getTextureName()
{
std::string name;
if (mState)
name = mState->mTexture->getName();
return name;
}
int VideoPlayer::getVideoWidth()
{
int width=0;
if (mState)
width = mState->mTexture->getWidth();
return width;
}
int VideoPlayer::getVideoHeight()
{
int height=0;
if (mState)
height = mState->mTexture->getHeight();
return height;
}
void VideoPlayer::stopVideo () void VideoPlayer::stopVideo ()
{ {
if (mAllowSkipping) close();
close();
} }
void VideoPlayer::close() void VideoPlayer::close()
@ -1211,13 +1150,6 @@ void VideoPlayer::close()
} }
MWBase::Environment::get().getSoundManager()->resumeSounds(); MWBase::Environment::get().getSoundManager()->resumeSounds();
mRectangle->setVisible(false);
mBackgroundRectangle->setVisible(false);
MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Video);
mSceneMgr->clearSpecialCaseRenderQueues();
mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
} }
bool VideoPlayer::isPlaying () bool VideoPlayer::isPlaying ()

@ -1,27 +1,22 @@
#ifndef VIDEOPLAYER_H #ifndef VIDEOPLAYER_H
#define VIDEOPLAYER_H #define VIDEOPLAYER_H
#include <OgreMaterial.h> #include <string>
namespace Ogre
{
class SceneManager;
class SceneNode;
class Rectangle2D;
class RenderWindow;
}
namespace MWRender namespace MWRender
{ {
struct VideoState; struct VideoState;
/**
* @brief Plays a video on an Ogre texture.
*/
class VideoPlayer class VideoPlayer
{ {
public: public:
VideoPlayer(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* window); VideoPlayer();
~VideoPlayer(); ~VideoPlayer();
void playVideo (const std::string& resourceName, bool allowSkipping); void playVideo (const std::string& resourceName);
void update(); void update();
@ -30,22 +25,14 @@ namespace MWRender
bool isPlaying(); bool isPlaying();
void setResolution (int w, int h) { mWidth = w; mHeight = h; } std::string getTextureName();
int getVideoWidth();
int getVideoHeight();
private: private:
VideoState* mState; VideoState* mState;
bool mAllowSkipping;
Ogre::SceneManager* mSceneMgr;
Ogre::MaterialPtr mVideoMaterial;
Ogre::Rectangle2D* mRectangle;
Ogre::Rectangle2D* mBackgroundRectangle;
Ogre::SceneNode* mNode;
Ogre::SceneNode* mBackgroundNode;
Ogre::RenderWindow* mWindow;
int mWidth; int mWidth;
int mHeight; int mHeight;
}; };

@ -47,7 +47,7 @@ namespace MWScript
bool allowSkipping = runtime[0].mInteger; bool allowSkipping = runtime[0].mInteger;
runtime.pop(); runtime.pop();
MWBase::Environment::get().getWorld ()->playVideo (name, allowSkipping); MWBase::Environment::get().getWindowManager()->playVideo (name, allowSkipping);
} }
}; };

@ -1305,7 +1305,7 @@ namespace MWWorld
{ {
--mPlayIntro; --mPlayIntro;
if (mPlayIntro == 0) if (mPlayIntro == 0)
mRendering->playVideo(mFallback.getFallbackString("Movies_New_Game"), true); MWBase::Environment::get().getWindowManager()->playVideo(mFallback.getFallbackString("Movies_New_Game"), true);
} }
if (mGoToJail && !paused) if (mGoToJail && !paused)
@ -1776,16 +1776,6 @@ namespace MWWorld
return mRendering->getAnimation(ptr); return mRendering->getAnimation(ptr);
} }
void World::playVideo (const std::string &name, bool allowSkipping)
{
mRendering->playVideo(name, allowSkipping);
}
void World::stopVideo ()
{
mRendering->stopVideo();
}
void World::frameStarted (float dt, bool paused) void World::frameStarted (float dt, bool paused)
{ {
mRendering->frameStarted(dt, paused); mRendering->frameStarted(dt, paused);

@ -523,8 +523,6 @@ namespace MWWorld
virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr); virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr);
/// \todo this does not belong here /// \todo this does not belong here
virtual void playVideo(const std::string& name, bool allowSkipping);
virtual void stopVideo();
virtual void frameStarted (float dt, bool paused); virtual void frameStarted (float dt, bool paused);
virtual void screenshot (Ogre::Image& image, int w, int h); virtual void screenshot (Ogre::Image& image, int w, int h);

@ -9,5 +9,6 @@
<Layer name="Popup" overlapped="true" peek="true"/> <Layer name="Popup" overlapped="true" peek="true"/>
<Layer name="DragAndDrop" overlapped="false" peek="false"/> <Layer name="DragAndDrop" overlapped="false" peek="false"/>
<Layer name="LoadingScreen" overlapped="false" peek="true"/> <Layer name="LoadingScreen" overlapped="false" peek="true"/>
<Layer name="Overlay" overlapped="false" peek="false"/>
<Layer name="Pointer" overlapped="false" peek="false"/> <Layer name="Pointer" overlapped="false" peek="false"/>
</MyGUI> </MyGUI>

Loading…
Cancel
Save