1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-05-14 13:41:28 +00:00

Refactored video player (now a MyGUI widget)

This commit is contained in:
scrawl 2014-03-27 19:10:15 +01:00
parent 2e4ef93b28
commit 5906d795c0
19 changed files with 242 additions and 203 deletions

View file

@ -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

View file

@ -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 (...) {}
} }

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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();
}
}

View file

@ -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

View file

@ -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);
}
} }

View file

@ -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);
}; };
} }

View file

@ -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);

View file

@ -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);

View file

@ -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;
}; };
} }

View file

@ -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,14 +1105,37 @@ 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();
} }
@ -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 ()

View file

@ -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;
}; };

View file

@ -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);
} }
}; };

View file

@ -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);

View file

@ -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);

View file

@ -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>