From f29c4086cd575a83c1ef29b078c64e052bde3468 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sun, 12 Oct 2014 15:18:37 +0200 Subject: [PATCH 01/23] Fixes #1982: Long class names are cut off in the UI Increased length of text filed for race, class name in stats window, and class name cation in chargen create class window. Signed-off-by: Lukasz Gromanowski --- files/mygui/openmw_chargen_create_class.layout | 2 +- files/mygui/openmw_stats_window.layout | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/files/mygui/openmw_chargen_create_class.layout b/files/mygui/openmw_chargen_create_class.layout index dee2f4fcf..1d071e621 100644 --- a/files/mygui/openmw_chargen_create_class.layout +++ b/files/mygui/openmw_chargen_create_class.layout @@ -3,7 +3,7 @@ - + diff --git a/files/mygui/openmw_stats_window.layout b/files/mygui/openmw_stats_window.layout index 6cdd4c02a..0b8dee5c8 100644 --- a/files/mygui/openmw_stats_window.layout +++ b/files/mygui/openmw_stats_window.layout @@ -89,11 +89,11 @@ - + - + From 02f0b7caa38a7d2342c9dcf0fa6798b3fc507244 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Thu, 16 Oct 2014 23:22:22 +0200 Subject: [PATCH 02/23] Fixes #1982: Long class names are cut off in the UI Added HBox widget with AutoSizedTextBox, spacer, and TextBox for level, race, class caption and text pairs. Signed-off-by: Lukasz Gromanowski --- files/mygui/openmw_stats_window.layout | 66 ++++++++++++++++---------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/files/mygui/openmw_stats_window.layout b/files/mygui/openmw_stats_window.layout index 0b8dee5c8..df0a3f39f 100644 --- a/files/mygui/openmw_stats_window.layout +++ b/files/mygui/openmw_stats_window.layout @@ -70,32 +70,50 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + From e2bad395e573b62ac1c836b97e37e44f1da59fca Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 24 Oct 2014 18:07:17 +0200 Subject: [PATCH 03/23] Leak fix --- apps/openmw/mwgui/windowmanagerimp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index f431bc8f1..6ab8b94c5 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -377,6 +377,7 @@ namespace MWGui delete mHitFader; delete mWerewolfFader; delete mScreenFader; + delete mBlindnessFader; delete mDebugWindow; cleanupGarbage(); From 925fa8d1931b909d688e95246e96c056fd82b46e Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Fri, 24 Oct 2014 12:46:14 +0200 Subject: [PATCH 04/23] Reset ownership of items dropped via 'drop' instruction (Fixes #2053) --- apps/openmw/mwscript/miscextensions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 0de8f3b91..c7d221139 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -454,7 +454,8 @@ namespace MWScript if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item)) { int removed = store.remove(*iter, toRemove, ptr); - MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter, removed); + MWWorld::Ptr dropped = MWBase::Environment::get().getWorld()->dropObjectOnGround(ptr, *iter, removed); + dropped.getCellRef().setOwner(""); toRemove -= removed; From fa746b8e54a54c3ba9fb9399d21795791dc28f3c Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Fri, 24 Oct 2014 13:05:39 +0200 Subject: [PATCH 05/23] Do not display weight or value in tooltip for zero-weight items (Fixes #2047) --- apps/openmw/mwclass/light.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 7b2d7e132..e6d266de2 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -191,8 +191,11 @@ namespace MWClass std::string text; - text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); - text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); + if (ref->mBase->mData.mWeight != 0) + { + text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); + text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}"); + } if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { text += MWGui::ToolTips::getCellRefString(ptr.getCellRef()); From ed3a3f717f3387fdf8978862d78d50a0e0cc5dbd Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Fri, 24 Oct 2014 18:49:38 +0200 Subject: [PATCH 06/23] Handle getdistance on objects inside a container (Fixes #2046) --- apps/openmw/mwbase/world.hpp | 4 ++ apps/openmw/mwscript/interpretercontext.cpp | 11 ++++++ apps/openmw/mwworld/cellstore.hpp | 11 ++++++ apps/openmw/mwworld/containerstore.cpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 41 +++++++++++++++++++++ apps/openmw/mwworld/worldimp.hpp | 4 ++ 6 files changed, 72 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 71a45a92c..c1a889913 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -199,6 +199,10 @@ namespace MWBase virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0; ///< Search is limited to the active cells. + virtual MWWorld::Ptr findContainer (const MWWorld::Ptr& ptr) = 0; + ///< Return a pointer to a liveCellRef which contains \a ptr. + /// \note Search is limited to the active cells. + /// \todo enable reference in the OGRE scene virtual void enable (const MWWorld::Ptr& ptr) = 0; diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index cb02a6c97..52021839d 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -21,6 +21,7 @@ #include "../mwworld/class.hpp" #include "../mwworld/cellstore.hpp" +#include "../mwworld/containerstore.hpp" #include "../mwmechanics/npcstats.hpp" @@ -434,6 +435,16 @@ namespace MWScript else ref2 = MWBase::Environment::get().getWorld()->getPtr(id, false); + if (ref2.getContainerStore()) // is the object contained? + { + MWWorld::Ptr container = MWBase::Environment::get().getWorld()->findContainer(ref2); + + if (!container.isEmpty()) + ref2 = container; + else + throw std::runtime_error("failed to find container ptr"); + } + const MWWorld::Ptr ref = MWBase::Environment::get().getWorld()->getPtr(name, false); // If the objects are in different worldspaces, return a large value (just like vanilla) diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index ba6fad7ba..e322ef4a4 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -149,6 +149,17 @@ namespace MWWorld forEachImp (functor, mCreatureLists); } + template + bool forEachContainer (Functor& functor) + { + mHasState = true; + + return + forEachImp (functor, mContainers) && + forEachImp (functor, mCreatures) && + forEachImp (functor, mNpcs); + } + bool isExterior() const; Ptr searchInContainer (const std::string& id); diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 085b079d9..45728371b 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -272,7 +272,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr item.mCell = actorPtr.getCell(); } - item.mContainerStore = 0; + item.mContainerStore = this; MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index d8e0d52b8..5d07a26a0 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -657,6 +657,47 @@ namespace MWWorld return mWorldScene->searchPtrViaActorId (actorId); } + struct FindContainerFunctor + { + Ptr mContainedPtr; + Ptr mResult; + + FindContainerFunctor(const Ptr& containedPtr) : mContainedPtr(containedPtr) {} + + bool operator() (Ptr ptr) + { + if (mContainedPtr.getContainerStore() == &ptr.getClass().getContainerStore(ptr)) + { + mResult = ptr; + return false; + } + + return true; + } + }; + + Ptr World::findContainer(const Ptr& ptr) + { + if (ptr.isInCell()) + return Ptr(); + + Ptr player = getPlayerPtr(); + if (ptr.getContainerStore() == &player.getClass().getContainerStore(player)) + return player; + + const Scene::CellStoreCollection& collection = mWorldScene->getActiveCells(); + for (Scene::CellStoreCollection::const_iterator cellIt = collection.begin(); cellIt != collection.end(); ++cellIt) + { + FindContainerFunctor functor(ptr); + (*cellIt)->forEachContainer(functor); + + if (!functor.mResult.isEmpty()) + return functor.mResult; + } + + return Ptr(); + } + void World::addContainerScripts(const Ptr& reference, CellStore * cell) { if( reference.getTypeName()==typeid (ESM::Container).name() || diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 334e799f2..fef279705 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -260,6 +260,10 @@ namespace MWWorld virtual Ptr searchPtrViaActorId (int actorId); ///< Search is limited to the active cells. + virtual MWWorld::Ptr findContainer (const MWWorld::Ptr& ptr); + ///< Return a pointer to a liveCellRef which contains \a ptr. + /// \note Search is limited to the active cells. + virtual void adjustPosition (const Ptr& ptr, bool force); ///< Adjust position after load to be on ground. Must be called after model load. /// @param force do this even if the ptr is flying From b39d69e98c859a78b813abc70099372763a07bc8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 24 Oct 2014 21:19:17 +0200 Subject: [PATCH 07/23] Videoplayer fixes, play/pause & seeking - Fix rindex overflow - Fix audio sample size bugs (was using sample_fmt and channel count of the decoder, instead of the resampled settings). We didn't notice this bug before, because the OpenAL MovieAudioFactory tries to resample to a format of the same byte size. - Add support for play/pause and seeking controls (not used by cutscenes in OpenMW) - Closing the video when arriving at the stream end is now handled by the user (we may also want to keep the video open and seek back) The video player now has a standalone demo, at https://github.com/scrawl/ogre-ffmpeg-videoplayer --- apps/openmw/mwgui/videowidget.cpp | 3 +- apps/openmw/mwsound/ffmpeg_decoder.cpp | 6 +- apps/openmw/mwsound/movieaudiofactory.cpp | 4 +- extern/ogre-ffmpeg-videoplayer/CMakeLists.txt | 15 +- .../ogre-ffmpeg-videoplayer/audiodecoder.cpp | 40 +++- .../ogre-ffmpeg-videoplayer/audiodecoder.hpp | 5 +- .../ogre-ffmpeg-videoplayer/videoplayer.cpp | 56 ++++- .../ogre-ffmpeg-videoplayer/videoplayer.hpp | 19 +- extern/ogre-ffmpeg-videoplayer/videostate.cpp | 216 +++++++++++++++--- extern/ogre-ffmpeg-videoplayer/videostate.hpp | 33 ++- 10 files changed, 318 insertions(+), 79 deletions(-) diff --git a/apps/openmw/mwgui/videowidget.cpp b/apps/openmw/mwgui/videowidget.cpp index 76fdd5287..f8054925b 100644 --- a/apps/openmw/mwgui/videowidget.cpp +++ b/apps/openmw/mwgui/videowidget.cpp @@ -30,8 +30,7 @@ int VideoWidget::getVideoHeight() bool VideoWidget::update() { - mPlayer.update(); - return mPlayer.isPlaying(); + return mPlayer.update(); } void VideoWidget::stop() diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index a2998ad03..b086d4aed 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -148,7 +148,7 @@ size_t FFmpeg_Decoder::readAVAudioData(void *data, size_t length) break; mFramePos = 0; mFrameSize = mFrame->nb_samples * (*mStream)->codec->channels * - av_get_bytes_per_sample((*mStream)->codec->sample_fmt); + av_get_bytes_per_sample(mOutputSampleFormat); } /* Get the amount of bytes remaining to be written, and clamp to @@ -384,7 +384,7 @@ void FFmpeg_Decoder::readAll(std::vector &output) while(getAVAudioData()) { size_t got = mFrame->nb_samples * (*mStream)->codec->channels * - av_get_bytes_per_sample((*mStream)->codec->sample_fmt); + av_get_bytes_per_sample(mOutputSampleFormat); const char *inbuf = reinterpret_cast(mFrameData[0]); output.insert(output.end(), inbuf, inbuf+got); } @@ -403,7 +403,7 @@ void FFmpeg_Decoder::rewind() size_t FFmpeg_Decoder::getSampleOffset() { int delay = (mFrameSize-mFramePos) / (*mStream)->codec->channels / - av_get_bytes_per_sample((*mStream)->codec->sample_fmt); + av_get_bytes_per_sample(mOutputSampleFormat); return (int)(mNextPts*(*mStream)->codec->sample_rate) - delay; } diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index bc7bb8023..97925c7c5 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -44,8 +44,8 @@ namespace MWSound size_t getSampleOffset() { - ssize_t clock_delay = (mFrameSize-mFramePos) / mAVStream->codec->channels / - av_get_bytes_per_sample(mAVStream->codec->sample_fmt); + ssize_t clock_delay = (mFrameSize-mFramePos) / av_get_channel_layout_nb_channels(mOutputChannelLayout) / + av_get_bytes_per_sample(mOutputSampleFormat); return (size_t)(mAudioClock*mAVStream->codec->sample_rate) - clock_delay; } diff --git a/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt b/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt index f34ffa64b..299a57799 100644 --- a/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt +++ b/extern/ogre-ffmpeg-videoplayer/CMakeLists.txt @@ -3,15 +3,14 @@ set(OGRE_FFMPEG_VIDEOPLAYER_LIBRARY "ogre-ffmpeg-videoplayer") # Sources set(OGRE_FFMPEG_VIDEOPLAYER_SOURCE_FILES - videoplayer.cpp - videostate.cpp - videodefs.hpp + videoplayer.cpp + videostate.cpp + videodefs.hpp libavwrapper.cpp audiodecoder.cpp audiofactory.hpp ) - # Find FFMPEG set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE) unset(FFMPEG_LIBRARIES CACHE) @@ -30,10 +29,14 @@ else() message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).") endif() endif() - include_directories(${FFMPEG_INCLUDE_DIRS}) +# Find Boost +set(BOOST_COMPONENTS thread) +find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) +include_directories(${Boost_INCLUDE_DIRS}) + add_library(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} STATIC ${OGRE_FFMPEG_VIDEOPLAYER_SOURCE_FILES}) -target_link_libraries(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} ${VIDEO_FFMPEG_LIBRARIES}) +target_link_libraries(${OGRE_FFMPEG_VIDEOPLAYER_LIBRARY} ${VIDEO_FFMPEG_LIBRARIES} ${Boost_LIBRARIES}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp b/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp index 54fe2b24f..41313d5d5 100644 --- a/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp +++ b/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp @@ -152,8 +152,8 @@ int MovieAudioDecoder::synchronize_audio() double avg_diff = mAudioDiffAccum * (1.0 - mAudioDiffAvgCoef); if(fabs(avg_diff) >= mAudioDiffThreshold) { - int n = av_get_bytes_per_sample(mAVStream->codec->sample_fmt) * - mAVStream->codec->channels; + int n = av_get_bytes_per_sample(mOutputSampleFormat) * + av_get_channel_layout_nb_channels(mOutputChannelLayout); sample_skip = ((int)(diff * mAVStream->codec->sample_rate) * n); } } @@ -161,7 +161,7 @@ int MovieAudioDecoder::synchronize_audio() return sample_skip; } -int MovieAudioDecoder::audio_decode_frame(AVFrame *frame) +int MovieAudioDecoder::audio_decode_frame(AVFrame *frame, int &sample_skip) { AVPacket *pkt = &mPacket; @@ -191,7 +191,7 @@ int MovieAudioDecoder::audio_decode_frame(AVFrame *frame) if(!mDataBuf || mDataBufLen < frame->nb_samples) { av_freep(&mDataBuf); - if(av_samples_alloc(&mDataBuf, NULL, mAVStream->codec->channels, + if(av_samples_alloc(&mDataBuf, NULL, av_get_channel_layout_nb_channels(mOutputChannelLayout), frame->nb_samples, mOutputSampleFormat, 0) < 0) break; else @@ -212,8 +212,8 @@ int MovieAudioDecoder::audio_decode_frame(AVFrame *frame) (double)mAVStream->codec->sample_rate; /* We have data, return it and come back for more later */ - return frame->nb_samples * mAVStream->codec->channels * - av_get_bytes_per_sample(mAVStream->codec->sample_fmt); + return frame->nb_samples * av_get_channel_layout_nb_channels(mOutputChannelLayout) * + av_get_bytes_per_sample(mOutputSampleFormat); } av_free_packet(pkt); @@ -221,6 +221,18 @@ int MovieAudioDecoder::audio_decode_frame(AVFrame *frame) if(mVideoState->audioq.get(pkt, mVideoState) < 0) return -1; + if(pkt->data == mVideoState->mFlushPktData) + { + avcodec_flush_buffers(mAVStream->codec); + mAudioDiffAccum = 0.0; + mAudioDiffAvgCount = 0; + mAudioClock = av_q2d(mAVStream->time_base)*pkt->pts; + sample_skip = 0; + + if(mVideoState->audioq.get(pkt, mVideoState) < 0) + return -1; + } + /* if update, update the audio clock w/pts */ if((uint64_t)pkt->pts != AV_NOPTS_VALUE) mAudioClock = av_q2d(mAVStream->time_base)*pkt->pts; @@ -229,6 +241,16 @@ int MovieAudioDecoder::audio_decode_frame(AVFrame *frame) size_t MovieAudioDecoder::read(char *stream, size_t len) { + if (mVideoState->mPaused) + { + // fill the buffer with silence + size_t sampleSize = av_get_bytes_per_sample(mOutputSampleFormat); + char* data[1]; + data[0] = stream; + av_samples_set_silence((uint8_t**)data, 0, len/sampleSize, 1, mOutputSampleFormat); + return len; + } + int sample_skip = synchronize_audio(); size_t total = 0; @@ -237,7 +259,7 @@ size_t MovieAudioDecoder::read(char *stream, size_t len) if(mFramePos >= mFrameSize) { /* We have already sent all our data; get more */ - mFrameSize = audio_decode_frame(mFrame); + mFrameSize = audio_decode_frame(mFrame, sample_skip); if(mFrameSize < 0) { /* If error, we're done */ @@ -260,8 +282,8 @@ size_t MovieAudioDecoder::read(char *stream, size_t len) { len1 = std::min(len1, -mFramePos); - int n = av_get_bytes_per_sample(mAVStream->codec->sample_fmt) * - mAVStream->codec->channels; + int n = av_get_bytes_per_sample(mOutputSampleFormat) + * av_get_channel_layout_nb_channels(mOutputChannelLayout); /* add samples by copying the first sample*/ if(n == 1) diff --git a/extern/ogre-ffmpeg-videoplayer/audiodecoder.hpp b/extern/ogre-ffmpeg-videoplayer/audiodecoder.hpp index 88406d51d..b05b16d42 100644 --- a/extern/ogre-ffmpeg-videoplayer/audiodecoder.hpp +++ b/extern/ogre-ffmpeg-videoplayer/audiodecoder.hpp @@ -77,7 +77,8 @@ private: * skip (negative means to duplicate). */ int synchronize_audio(); - int audio_decode_frame(AVFrame *frame); + /// @param sample_skip If seeking happened, the sample_skip variable will be reset to 0. + int audio_decode_frame(AVFrame *frame, int &sample_skip); public: MovieAudioDecoder(VideoState *is); @@ -101,6 +102,8 @@ public: virtual double getAudioClock(); /// This is the main interface to be used by the user's audio library. + /// @par Request filling the \a stream with \a len number of bytes. + /// @return The number of bytes read (may not be the requested number if we arrived at the end of the audio stream) size_t read(char *stream, size_t len); }; diff --git a/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp b/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp index 434b676ee..d80449199 100644 --- a/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp +++ b/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp @@ -38,19 +38,17 @@ void VideoPlayer::playVideo(const std::string &resourceName) } } -void VideoPlayer::update () +bool VideoPlayer::update () { if(mState) - { - if(!mState->update()) - close(); - } + return mState->update(); + return false; } std::string VideoPlayer::getTextureName() { std::string name; - if (mState) + if (mState && !mState->mTexture.isNull()) name = mState->mTexture->getName(); return name; } @@ -58,7 +56,7 @@ std::string VideoPlayer::getTextureName() int VideoPlayer::getVideoWidth() { int width=0; - if (mState) + if (mState && !mState->mTexture.isNull()) width = mState->mTexture->getWidth(); return width; } @@ -66,7 +64,7 @@ int VideoPlayer::getVideoWidth() int VideoPlayer::getVideoHeight() { int height=0; - if (mState) + if (mState && !mState->mTexture.isNull()) height = mState->mTexture->getHeight(); return height; } @@ -82,14 +80,48 @@ void VideoPlayer::close() } } -bool VideoPlayer::isPlaying () +bool VideoPlayer::hasAudioStream() { - return mState != NULL; + return mState && mState->audio_st != NULL; } -bool VideoPlayer::hasAudioStream() +void VideoPlayer::play() { - return mState && mState->audio_st != NULL; + if (mState) + mState->setPaused(false); +} + +void VideoPlayer::pause() +{ + if (mState) + mState->setPaused(true); +} + +bool VideoPlayer::isPaused() +{ + if (mState) + return mState->mPaused; + return true; +} + +double VideoPlayer::getCurrentTime() +{ + if (mState) + return mState->get_master_clock(); + return 0.0; +} + +void VideoPlayer::seek(double time) +{ + if (mState) + mState->seekTo(time); +} + +double VideoPlayer::getDuration() +{ + if (mState) + return mState->getDuration(); + return 0.0; } } diff --git a/extern/ogre-ffmpeg-videoplayer/videoplayer.hpp b/extern/ogre-ffmpeg-videoplayer/videoplayer.hpp index 750ad02e5..2727ac6f0 100644 --- a/extern/ogre-ffmpeg-videoplayer/videoplayer.hpp +++ b/extern/ogre-ffmpeg-videoplayer/videoplayer.hpp @@ -29,16 +29,29 @@ namespace Video bool hasAudioStream(); /// Play the given video. If a video is already playing, the old video is closed first. + /// @note The video will be unpaused by default. Use the pause() and play() methods to control pausing. void playVideo (const std::string& resourceName); + /// Get the current playback time position in the video, in seconds + double getCurrentTime(); + + /// Get the duration of the video in seconds + double getDuration(); + + /// Seek to the specified time position in the video + void seek(double time); + + void play(); + void pause(); + bool isPaused(); + /// This should be called every frame by the user to update the video texture. - void update(); + /// @return Returns true if the video is still playing, false if we have reached the end of the video stream. + bool update(); /// Stop the currently playing video, if a video is playing. void close(); - bool isPlaying(); - /// Return the texture name of the currently playing video, or "" if no video is playing. std::string getTextureName(); /// Return the width of the currently playing video, or 0 if no video is playing. diff --git a/extern/ogre-ffmpeg-videoplayer/videostate.cpp b/extern/ogre-ffmpeg-videoplayer/videostate.cpp index c77723421..7ac7a122c 100644 --- a/extern/ogre-ffmpeg-videoplayer/videostate.cpp +++ b/extern/ogre-ffmpeg-videoplayer/videostate.cpp @@ -31,6 +31,18 @@ extern "C" } +static const char* flushString = "FLUSH"; +struct FlushPacket : AVPacket +{ + FlushPacket() + : AVPacket() + { + data = ( (uint8_t*)flushString); + } +}; + +static FlushPacket flush_pkt; + #include "videoplayer.hpp" #include "audiodecoder.hpp" #include "audiofactory.hpp" @@ -46,14 +58,18 @@ namespace Video VideoState::VideoState() : format_ctx(NULL), av_sync_type(AV_SYNC_DEFAULT) - , external_clock_base(0.0) , audio_st(NULL) , video_st(NULL), frame_last_pts(0.0) , video_clock(0.0), sws_context(NULL), rgbaFrame(NULL), pictq_size(0) , pictq_rindex(0), pictq_windex(0) - , quit(false) + , mQuit(false), mPaused(false) , mAudioFactory(NULL) + , mSeekRequested(false) + , mSeekPos(0) + , mVideoEnded(false) { + mFlushPktData = flush_pkt.data; + // Register all formats and codecs av_register_all(); } @@ -77,7 +93,7 @@ void PacketQueue::put(AVPacket *pkt) pkt1->pkt = *pkt; pkt1->next = NULL; - if(pkt1->pkt.destruct == NULL) + if(pkt->data != flush_pkt.data && pkt1->pkt.destruct == NULL) { if(av_dup_packet(&pkt1->pkt) < 0) { @@ -104,7 +120,7 @@ void PacketQueue::put(AVPacket *pkt) int PacketQueue::get(AVPacket *pkt, VideoState *is) { boost::unique_lock lock(this->mutex); - while(!is->quit) + while(!is->mQuit) { AVPacketList *pkt1 = this->first_pkt; if(pkt1) @@ -143,7 +159,8 @@ void PacketQueue::clear() for(pkt = this->first_pkt; pkt != NULL; pkt = pkt1) { pkt1 = pkt->next; - av_free_packet(&pkt->pkt); + if (pkt->pkt.data != flush_pkt.data) + av_free_packet(&pkt->pkt); av_freep(&pkt); } this->last_pkt = NULL; @@ -205,6 +222,7 @@ void VideoState::video_display(VideoPicture *vp) void VideoState::video_refresh() { + boost::mutex::scoped_lock lock(this->pictq_mutex); if(this->pictq_size == 0) return; @@ -212,12 +230,11 @@ void VideoState::video_refresh() { VideoPicture* vp = &this->pictq[this->pictq_rindex]; this->video_display(vp); + this->pictq_rindex = (pictq_rindex+1) % VIDEO_PICTURE_QUEUE_SIZE; this->frame_last_pts = vp->pts; - this->pictq_mutex.lock(); this->pictq_size--; this->pictq_cond.notify_one(); - this->pictq_mutex.unlock(); } else { @@ -236,19 +253,18 @@ void VideoState::video_refresh() break; } + assert (this->pictq_rindex < VIDEO_PICTURE_QUEUE_SIZE); VideoPicture* vp = &this->pictq[this->pictq_rindex]; this->video_display(vp); this->frame_last_pts = vp->pts; - this->pictq_mutex.lock(); this->pictq_size -= i; // update queue for next picture this->pictq_size--; - this->pictq_rindex++; + this->pictq_rindex = (this->pictq_rindex+1) % VIDEO_PICTURE_QUEUE_SIZE; this->pictq_cond.notify_one(); - this->pictq_mutex.unlock(); } } @@ -260,12 +276,14 @@ int VideoState::queue_picture(AVFrame *pFrame, double pts) /* wait until we have a new pic */ { boost::unique_lock lock(this->pictq_mutex); - while(this->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !this->quit) + while(this->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !this->mQuit) this->pictq_cond.timed_wait(lock, boost::posix_time::milliseconds(1)); } - if(this->quit) + if(this->mQuit) return -1; + this->pictq_mutex.lock(); + // windex is set to 0 initially vp = &this->pictq[this->pictq_windex]; @@ -292,7 +310,6 @@ int VideoState::queue_picture(AVFrame *pFrame, double pts) // now we inform our display thread that we have a pic ready this->pictq_windex = (this->pictq_windex+1) % VIDEO_PICTURE_QUEUE_SIZE; - this->pictq_mutex.lock(); this->pictq_size++; this->pictq_mutex.unlock(); @@ -353,6 +370,21 @@ void VideoState::video_thread_loop(VideoState *self) while(self->videoq.get(packet, self) >= 0) { + if(packet->data == flush_pkt.data) + { + avcodec_flush_buffers((*self->video_st)->codec); + + self->pictq_mutex.lock(); + self->pictq_size = 0; + self->pictq_rindex = 0; + self->pictq_windex = 0; + self->pictq_mutex.unlock(); + + self->frame_last_pts = packet->pts * av_q2d((*self->video_st)->time_base); + global_video_pkt_pts = self->frame_last_pts; + continue; + } + // Save global pts to be stored in pFrame global_video_pkt_pts = packet->pts; // Decode video frame @@ -394,8 +426,67 @@ void VideoState::decode_thread_loop(VideoState *self) throw std::runtime_error("No streams to decode"); // main decode loop - while(!self->quit) + while(!self->mQuit) { + if(self->mSeekRequested) + { + uint64_t seek_target = self->mSeekPos; + int streamIndex = -1; + + int videoStreamIndex = -1;; + int audioStreamIndex = -1; + if (self->video_st) + videoStreamIndex = self->video_st - self->format_ctx->streams; + if (self->audio_st) + audioStreamIndex = self->audio_st - self->format_ctx->streams; + + if(videoStreamIndex >= 0) + streamIndex = videoStreamIndex; + else if(audioStreamIndex >= 0) + streamIndex = audioStreamIndex; + + uint64_t timestamp = seek_target; + + // QtCreator's highlighter doesn't like AV_TIME_BASE_Q's {} initializer for some reason + AVRational avTimeBaseQ = AVRational(); // = AV_TIME_BASE_Q; + avTimeBaseQ.num = 1; + avTimeBaseQ.den = AV_TIME_BASE; + + if(streamIndex >= 0) + timestamp = av_rescale_q(seek_target, avTimeBaseQ, self->format_ctx->streams[streamIndex]->time_base); + + // AVSEEK_FLAG_BACKWARD appears to be needed, otherwise ffmpeg may seek to a keyframe *after* the given time + // we want to seek to any keyframe *before* the given time, so we can continue decoding as normal from there on + if(av_seek_frame(self->format_ctx, streamIndex, timestamp, AVSEEK_FLAG_BACKWARD) < 0) + std::cerr << "Error seeking " << self->format_ctx->filename << std::endl; + else + { + // Clear the packet queues and put a special packet with the new clock time + if(audioStreamIndex >= 0) + { + self->audioq.clear(); + flush_pkt.pts = av_rescale_q(seek_target, avTimeBaseQ, + self->format_ctx->streams[audioStreamIndex]->time_base); + self->audioq.put(&flush_pkt); + } + if(videoStreamIndex >= 0) + { + self->videoq.clear(); + flush_pkt.pts = av_rescale_q(seek_target, avTimeBaseQ, + self->format_ctx->streams[videoStreamIndex]->time_base); + self->videoq.put(&flush_pkt); + } + self->pictq_mutex.lock(); + self->pictq_size = 0; + self->pictq_rindex = 0; + self->pictq_windex = 0; + self->pictq_mutex.unlock(); + self->mExternalClock.set(seek_target); + } + self->mSeekRequested = false; + } + + if((self->audio_st && self->audioq.size > MAX_AUDIOQ_SIZE) || (self->video_st && self->videoq.size > MAX_VIDEOQ_SIZE)) { @@ -404,7 +495,13 @@ void VideoState::decode_thread_loop(VideoState *self) } if(av_read_frame(pFormatCtx, packet) < 0) - break; + { + if (self->audioq.nb_packets == 0 && self->videoq.nb_packets == 0 && self->pictq_size == 0) + self->mVideoEnded = true; + continue; + } + else + self->mVideoEnded = false; // Is this a packet from the video stream? if(self->video_st && packet->stream_index == self->video_st-pFormatCtx->streams) @@ -414,17 +511,6 @@ void VideoState::decode_thread_loop(VideoState *self) else av_free_packet(packet); } - - /* all done - wait for it */ - self->videoq.flush(); - self->audioq.flush(); - while(!self->quit) - { - // EOF reached, all packets processed, we can exit now - if(self->audioq.nb_packets == 0 && self->videoq.nb_packets == 0 && self->pictq_size == 0) - break; - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - } } catch(std::runtime_error& e) { std::cerr << "An error occured playing the video: " << e.what () << std::endl; @@ -433,17 +519,14 @@ void VideoState::decode_thread_loop(VideoState *self) std::cerr << "An error occured playing the video: " << e.getFullDescription () << std::endl; } - self->quit = true; + self->mQuit = true; } bool VideoState::update() { - if(this->quit) - return false; - this->video_refresh(); - return true; + return !this->mVideoEnded; } @@ -510,7 +593,7 @@ void VideoState::init(const std::string& resourceName) unsigned int i; this->av_sync_type = AV_SYNC_DEFAULT; - this->quit = false; + this->mQuit = false; this->stream = Ogre::ResourceGroupManager::getSingleton().openResource(resourceName); if(this->stream.isNull()) @@ -564,7 +647,7 @@ void VideoState::init(const std::string& resourceName) audio_index = i; } - this->external_clock_base = av_gettime(); + mExternalClock.set(0); if(audio_index >= 0) this->stream_open(audio_index, this->format_ctx); @@ -598,12 +681,12 @@ void VideoState::init(const std::string& resourceName) void VideoState::deinit() { - this->quit = true; + this->mQuit = true; - mAudioDecoder.reset(); + this->audioq.flush(); + this->videoq.flush(); - this->audioq.cond.notify_one(); - this->videoq.cond.notify_one(); + mAudioDecoder.reset(); if (this->parse_thread.joinable()) this->parse_thread.join(); @@ -643,7 +726,7 @@ void VideoState::deinit() double VideoState::get_external_clock() { - return ((uint64_t)av_gettime()-this->external_clock_base) / 1000000.0; + return mExternalClock.get() / 1000000.0; } double VideoState::get_master_clock() @@ -667,5 +750,62 @@ double VideoState::get_audio_clock() return mAudioDecoder->getAudioClock(); } +void VideoState::setPaused(bool isPaused) +{ + this->mPaused = isPaused; + mExternalClock.setPaused(isPaused); +} + +void VideoState::seekTo(double time) +{ + time = std::max(0.0, time); + time = std::min(getDuration(), time); + mSeekPos = (uint64_t) (time * AV_TIME_BASE); + mSeekRequested = true; +} + +double VideoState::getDuration() +{ + return this->format_ctx->duration / 1000000.0; +} + + +ExternalClock::ExternalClock() + : mTimeBase(av_gettime()) + , mPausedAt(0) + , mPaused(false) +{ +} + +void ExternalClock::setPaused(bool paused) +{ + boost::mutex::scoped_lock lock(mMutex); + if (mPaused == paused) + return; + if (paused) + { + mPausedAt = av_gettime() - mTimeBase; + } + else + mTimeBase = av_gettime() - mPausedAt; + mPaused = paused; +} + +uint64_t ExternalClock::get() +{ + boost::mutex::scoped_lock lock(mMutex); + if (mPaused) + return mPausedAt; + else + return av_gettime() - mTimeBase; +} + +void ExternalClock::set(uint64_t time) +{ + boost::mutex::scoped_lock lock(mMutex); + mTimeBase = av_gettime() - time; + mPausedAt = time; +} + } diff --git a/extern/ogre-ffmpeg-videoplayer/videostate.hpp b/extern/ogre-ffmpeg-videoplayer/videostate.hpp index 90ebec0a3..cdeb2d0e3 100644 --- a/extern/ogre-ffmpeg-videoplayer/videostate.hpp +++ b/extern/ogre-ffmpeg-videoplayer/videostate.hpp @@ -27,6 +27,21 @@ struct VideoState; class MovieAudioFactory; class MovieAudioDecoder; +struct ExternalClock +{ + ExternalClock(); + + uint64_t mTimeBase; + uint64_t mPausedAt; + bool mPaused; + + boost::mutex mMutex; + + void setPaused(bool paused); + uint64_t get(); + void set(uint64_t time); +}; + struct PacketQueue { PacketQueue() : first_pkt(NULL), last_pkt(NULL), flushing(false), nb_packets(0), size(0) @@ -66,6 +81,11 @@ struct VideoState { void init(const std::string& resourceName); void deinit(); + void setPaused(bool isPaused); + void seekTo(double time); + + double getDuration(); + int stream_open(int stream_index, AVFormatContext *pFormatCtx); bool update(); @@ -93,15 +113,18 @@ struct VideoState { MovieAudioFactory* mAudioFactory; boost::shared_ptr mAudioDecoder; + ExternalClock mExternalClock; + Ogre::DataStreamPtr stream; AVFormatContext* format_ctx; int av_sync_type; - uint64_t external_clock_base; AVStream** audio_st; PacketQueue audioq; + uint8_t* mFlushPktData; + AVStream** video_st; double frame_last_pts; double video_clock; /// Date: Sat, 25 Oct 2014 00:14:51 +0200 Subject: [PATCH 08/23] Add possibly missing include for av_rescale_q --- extern/ogre-ffmpeg-videoplayer/videostate.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extern/ogre-ffmpeg-videoplayer/videostate.cpp b/extern/ogre-ffmpeg-videoplayer/videostate.cpp index 7ac7a122c..cc6308b14 100644 --- a/extern/ogre-ffmpeg-videoplayer/videostate.cpp +++ b/extern/ogre-ffmpeg-videoplayer/videostate.cpp @@ -25,6 +25,8 @@ extern "C" #include #endif + #include + #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1) #define av_frame_alloc avcodec_alloc_frame #endif From dbe30e31b935dbdf60136e3121b7b67cd17d93fb Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 25 Oct 2014 00:56:43 +0200 Subject: [PATCH 09/23] Make creature's model take priority over base_anim.nif (Fixes #2055) --- apps/openmw/mwrender/creatureanimation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/creatureanimation.cpp b/apps/openmw/mwrender/creatureanimation.cpp index 247a0ba14..fef9fa644 100644 --- a/apps/openmw/mwrender/creatureanimation.cpp +++ b/apps/openmw/mwrender/creatureanimation.cpp @@ -27,9 +27,9 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) setObjectRoot(model, false); setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha); - addAnimSource(model); if((ref->mBase->mFlags&ESM::Creature::Bipedal)) addAnimSource("meshes\\base_anim.nif"); + addAnimSource(model); } } @@ -47,9 +47,9 @@ CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr) setObjectRoot(model, false); setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha); - addAnimSource(model); if((ref->mBase->mFlags&ESM::Creature::Bipedal)) addAnimSource("meshes\\base_anim.nif"); + addAnimSource(model); mPtr.getClass().getInventoryStore(mPtr).setListener(this, mPtr); From e01795556f3a04b4e5ff202e7c154df09b85080d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 25 Oct 2014 10:37:57 +1100 Subject: [PATCH 10/23] Suppress some warnings for MSVC. --- apps/openmw/mwgui/formatting.hpp | 1 + extern/ogre-ffmpeg-videoplayer/audiofactory.hpp | 1 + extern/ogre-ffmpeg-videoplayer/videostate.cpp | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/formatting.hpp b/apps/openmw/mwgui/formatting.hpp index 3e21b62e2..5b7925057 100644 --- a/apps/openmw/mwgui/formatting.hpp +++ b/apps/openmw/mwgui/formatting.hpp @@ -132,6 +132,7 @@ namespace MWGui virtual int pageSplit(); protected: + virtual ~GraphicElement() {} MyGUI::Widget * mParent; Paginator & mPaginator; BlockStyle mBlockStyle; diff --git a/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp b/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp index cf1ff46a8..06abd6a74 100644 --- a/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp +++ b/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp @@ -12,6 +12,7 @@ class MovieAudioFactory { public: virtual boost::shared_ptr createDecoder(VideoState* videoState) = 0; + virtual ~MovieAudioFactory() {} }; } diff --git a/extern/ogre-ffmpeg-videoplayer/videostate.cpp b/extern/ogre-ffmpeg-videoplayer/videostate.cpp index c77723421..ece491edc 100644 --- a/extern/ogre-ffmpeg-videoplayer/videostate.cpp +++ b/extern/ogre-ffmpeg-videoplayer/videostate.cpp @@ -221,7 +221,7 @@ void VideoState::video_refresh() } else { - const float threshold = 0.03; + const float threshold = 0.03f; if (this->pictq[pictq_rindex].pts > this->get_master_clock() + threshold) return; // not ready yet to show this picture From 69d0c7fd7090b84729fbd3ca48870b0501f1ffb4 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 25 Oct 2014 10:40:33 +1100 Subject: [PATCH 11/23] Cleanup leftover from previous osx support attempts. --- cmake/FindOGRE.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/FindOGRE.cmake b/cmake/FindOGRE.cmake index 51589698f..f2acf9d33 100644 --- a/cmake/FindOGRE.cmake +++ b/cmake/FindOGRE.cmake @@ -382,7 +382,6 @@ endmacro() ogre_find_component(Paging OgrePaging.h) # look for Overlay component ogre_find_component(Overlay OgreOverlaySystem.h) -ogre_find_component(Overlay OgreOverlay.h) # look for Terrain component ogre_find_component(Terrain OgreTerrain.h) # look for Property component From ea67cf0ebeb87e29db96c555c2be217bdd91bba0 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 25 Oct 2014 15:37:09 +1100 Subject: [PATCH 12/23] Try the fix again. --- extern/ogre-ffmpeg-videoplayer/audiofactory.hpp | 1 - extern/ogre-ffmpeg-videoplayer/videoplayer.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp b/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp index 06abd6a74..cf1ff46a8 100644 --- a/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp +++ b/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp @@ -12,7 +12,6 @@ class MovieAudioFactory { public: virtual boost::shared_ptr createDecoder(VideoState* videoState) = 0; - virtual ~MovieAudioFactory() {} }; } diff --git a/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp b/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp index 434b676ee..5487e916a 100644 --- a/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp +++ b/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp @@ -1,5 +1,6 @@ #include "videoplayer.hpp" +#include "audiofactory.hpp" #include "videostate.hpp" namespace Video From d7716e7314a4054038a5c7119d1c1f128608fa57 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 25 Oct 2014 09:37:51 +0200 Subject: [PATCH 13/23] Fixes #1982: Long class names are cut off in the UI Corrected HBox, AutoSizedTextBox and TextBox positions and alignment. Signed-off-by: Lukasz Gromanowski --- files/mygui/openmw_stats_window.layout | 30 ++++++++++---------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/files/mygui/openmw_stats_window.layout b/files/mygui/openmw_stats_window.layout index df0a3f39f..ef6db8323 100644 --- a/files/mygui/openmw_stats_window.layout +++ b/files/mygui/openmw_stats_window.layout @@ -69,47 +69,39 @@ - - - + + + - - - - + + - - + + - - - - + - - + + - - - - + From c9750dc7c69fc9d792a020a5c08c7d8abaff8d1c Mon Sep 17 00:00:00 2001 From: sylar Date: Sat, 25 Oct 2014 19:00:23 +0400 Subject: [PATCH 14/23] fixes shadows on glsles --- files/materials/objects.shader | 8 ++++---- files/materials/shadows.h | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 87330e34e..2368d9961 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -499,7 +499,7 @@ #if SHADOWS || SHADOWS_PSSM float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y; - float fade = 1-((depthPassthrough - shadowFar_fadeStart.y) / fadeRange); + float fade = 1.0-((depthPassthrough - shadowFar_fadeStart.y) / fadeRange); shadow = (depthPassthrough > shadowFar_fadeStart.x) ? 1.0 : ((depthPassthrough > shadowFar_fadeStart.y) ? 1.0-((1.0-shadow)*fade) : shadow); #endif @@ -514,11 +514,11 @@ #endif #if UNDERWATER - float3 waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0,0,1), waterLevel); + float3 waterEyePos = intercept(worldPos, cameraPos.xyz - worldPos, float3(0.0,0.0,1.0), waterLevel); #endif #if SHADOWS || SHADOWS_PSSM - shOutputColour(0) *= (lightResult - float4(directionalResult * (1.0-shadow),0)); + shOutputColour(0) *= (lightResult - float4(directionalResult * (1.0-shadow),0.0)); #else shOutputColour(0) *= lightResult; #endif @@ -574,7 +574,7 @@ #endif // prevent negative colour output (for example with negative lights) - shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0,0,0)); + shOutputColour(0).xyz = max(shOutputColour(0).xyz, float3(0.0,0.0,0.0)); } #endif diff --git a/files/materials/shadows.h b/files/materials/shadows.h index 65dffe492..eba3a3ea7 100644 --- a/files/materials/shadows.h +++ b/files/materials/shadows.h @@ -6,11 +6,11 @@ float depthShadowPCF (shTexture2D shadowMap, float4 shadowMapPos, float2 offset) shadowMapPos /= shadowMapPos.w; float3 o = float3(offset.xy, -offset.x) * 0.3; //float3 o = float3(0,0,0); - float c = (shadowMapPos.z <= FIXED_BIAS + shSample(shadowMap, shadowMapPos.xy - o.xy).r) ? 1 : 0; // top left - c += (shadowMapPos.z <= FIXED_BIAS + shSample(shadowMap, shadowMapPos.xy + o.xy).r) ? 1 : 0; // bottom right - c += (shadowMapPos.z <= FIXED_BIAS + shSample(shadowMap, shadowMapPos.xy + o.zy).r) ? 1 : 0; // bottom left - c += (shadowMapPos.z <= FIXED_BIAS + shSample(shadowMap, shadowMapPos.xy - o.zy).r) ? 1 : 0; // top right - return c / 4; + float c = (shadowMapPos.z <= FIXED_BIAS + shSample(shadowMap, shadowMapPos.xy - o.xy).r) ? 1.0 : 0.0; // top left + c += (shadowMapPos.z <= FIXED_BIAS + shSample(shadowMap, shadowMapPos.xy + o.xy).r) ? 1.0 : 0.0; // bottom right + c += (shadowMapPos.z <= FIXED_BIAS + shSample(shadowMap, shadowMapPos.xy + o.zy).r) ? 1.0 : 0.0; // bottom left + c += (shadowMapPos.z <= FIXED_BIAS + shSample(shadowMap, shadowMapPos.xy - o.zy).r) ? 1.0 : 0.0; // top right + return c / 4.0; } From 55c9c0a26634d0e4742eb562197ab2d1d39aee29 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 25 Oct 2014 17:17:57 +0200 Subject: [PATCH 15/23] Audio resampling fixes - Don't try to use float audio or extended channel layouts if the hardware does not support them - Add channel layout resampling support to ffmpeg_decoder --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 83 ++++++++++++----------- apps/openmw/mwsound/ffmpeg_decoder.hpp | 1 + apps/openmw/mwsound/movieaudiofactory.cpp | 21 +++--- 3 files changed, 55 insertions(+), 50 deletions(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index b086d4aed..b4307e395 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -5,6 +5,8 @@ #include +#include "al.h" + extern "C" { #ifndef HAVE_LIBSWRESAMPLE // FIXME: remove this section once libswresample is packaged for Debian @@ -112,7 +114,7 @@ bool FFmpeg_Decoder::getAVAudioData() if(!mDataBuf || mDataBufLen < mFrame->nb_samples) { av_freep(&mDataBuf); - if(av_samples_alloc(&mDataBuf, NULL, (*mStream)->codec->channels, + if(av_samples_alloc(&mDataBuf, NULL, av_get_channel_layout_nb_channels(mOutputChannelLayout), mFrame->nb_samples, mOutputSampleFormat, 0) < 0) break; else @@ -147,7 +149,7 @@ size_t FFmpeg_Decoder::readAVAudioData(void *data, size_t length) if(!getAVAudioData()) break; mFramePos = 0; - mFrameSize = mFrame->nb_samples * (*mStream)->codec->channels * + mFrameSize = mFrame->nb_samples * av_get_channel_layout_nb_channels(mOutputChannelLayout) * av_get_bytes_per_sample(mOutputSampleFormat); } @@ -285,47 +287,32 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * if(!mStream) fail("No audio stream info"); - if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8) - *type = SampleType_UInt8; - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16) - *type = SampleType_Int16; - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT) - *type = SampleType_Float32; + if(((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) + && alIsExtensionPresent("AL_EXT_FLOAT32")) + mOutputSampleFormat = AV_SAMPLE_FMT_FLT; else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P) - *type = SampleType_UInt8; + mOutputSampleFormat = AV_SAMPLE_FMT_U8; else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P) + mOutputSampleFormat = AV_SAMPLE_FMT_S16; + else + mOutputSampleFormat = AV_SAMPLE_FMT_S16; + + if(mOutputSampleFormat == AV_SAMPLE_FMT_U8) + *type = SampleType_UInt8; + else if(mOutputSampleFormat == AV_SAMPLE_FMT_S16) *type = SampleType_Int16; - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) + else if(mOutputSampleFormat == AV_SAMPLE_FMT_FLT) *type = SampleType_Float32; - else - fail(std::string("Unsupported sample format: ")+ - av_get_sample_fmt_name((*mStream)->codec->sample_fmt)); int64_t ch_layout = (*mStream)->codec->channel_layout; - if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_MONO) - *chans = ChannelConfig_Mono; - else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_STEREO) - *chans = ChannelConfig_Stereo; - else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_QUAD) - *chans = ChannelConfig_Quad; - else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_5POINT1) - *chans = ChannelConfig_5point1; - else if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_7POINT1) - *chans = ChannelConfig_7point1; - else if((*mStream)->codec->channel_layout == 0) + if(ch_layout == 0) { /* Unknown channel layout. Try to guess. */ if((*mStream)->codec->channels == 1) - { - *chans = ChannelConfig_Mono; ch_layout = AV_CH_LAYOUT_MONO; - } else if((*mStream)->codec->channels == 2) - { - *chans = ChannelConfig_Stereo; ch_layout = AV_CH_LAYOUT_STEREO; - } else { std::stringstream sstr("Unsupported raw channel count: "); @@ -333,6 +320,25 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * fail(sstr.str()); } } + + mOutputChannelLayout = ch_layout; + if ((ch_layout == AV_CH_LAYOUT_5POINT1 || ch_layout == AV_CH_LAYOUT_7POINT1 + || ch_layout == AV_CH_LAYOUT_QUAD) && !alIsExtensionPresent("AL_EXT_MCFORMATS")) + mOutputChannelLayout = AV_CH_LAYOUT_STEREO; + else if (ch_layout != AV_CH_LAYOUT_MONO + && ch_layout != AV_CH_LAYOUT_STEREO) + mOutputChannelLayout = AV_CH_LAYOUT_STEREO; + + if(mOutputChannelLayout == AV_CH_LAYOUT_MONO) + *chans = ChannelConfig_Mono; + else if(mOutputChannelLayout == AV_CH_LAYOUT_STEREO) + *chans = ChannelConfig_Stereo; + else if(mOutputChannelLayout == AV_CH_LAYOUT_QUAD) + *chans = ChannelConfig_Quad; + else if(mOutputChannelLayout == AV_CH_LAYOUT_5POINT1) + *chans = ChannelConfig_5point1; + else if(mOutputChannelLayout == AV_CH_LAYOUT_7POINT1) + *chans = ChannelConfig_7point1; else { char str[1024]; @@ -343,17 +349,11 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * *samplerate = (*mStream)->codec->sample_rate; - if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P) - mOutputSampleFormat = AV_SAMPLE_FMT_U8; - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P) - mOutputSampleFormat = AV_SAMPLE_FMT_S16; - else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) - mOutputSampleFormat = AV_SAMPLE_FMT_FLT; - - if(mOutputSampleFormat != AV_SAMPLE_FMT_NONE) + if(mOutputSampleFormat != (*mStream)->codec->sample_fmt + || mOutputChannelLayout != ch_layout) { mSwr = swr_alloc_set_opts(mSwr, // SwrContext - ch_layout, // output ch layout + mOutputChannelLayout, // output ch layout mOutputSampleFormat, // output sample format (*mStream)->codec->sample_rate, // output sample rate ch_layout, // input ch layout @@ -383,7 +383,7 @@ void FFmpeg_Decoder::readAll(std::vector &output) while(getAVAudioData()) { - size_t got = mFrame->nb_samples * (*mStream)->codec->channels * + size_t got = mFrame->nb_samples * av_get_channel_layout_nb_channels(mOutputChannelLayout) * av_get_bytes_per_sample(mOutputSampleFormat); const char *inbuf = reinterpret_cast(mFrameData[0]); output.insert(output.end(), inbuf, inbuf+got); @@ -402,7 +402,7 @@ void FFmpeg_Decoder::rewind() size_t FFmpeg_Decoder::getSampleOffset() { - int delay = (mFrameSize-mFramePos) / (*mStream)->codec->channels / + int delay = (mFrameSize-mFramePos) / av_get_channel_layout_nb_channels(mOutputChannelLayout) / av_get_bytes_per_sample(mOutputSampleFormat); return (int)(mNextPts*(*mStream)->codec->sample_rate) - delay; } @@ -416,6 +416,7 @@ FFmpeg_Decoder::FFmpeg_Decoder() , mNextPts(0.0) , mSwr(0) , mOutputSampleFormat(AV_SAMPLE_FMT_NONE) + , mOutputChannelLayout(0) , mDataBuf(NULL) , mFrameData(NULL) , mDataBufLen(0) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.hpp b/apps/openmw/mwsound/ffmpeg_decoder.hpp index 796f17350..2cdbbf363 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.hpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.hpp @@ -59,6 +59,7 @@ namespace MWSound SwrContext *mSwr; enum AVSampleFormat mOutputSampleFormat; + int64_t mOutputChannelLayout; uint8_t *mDataBuf; uint8_t **mFrameData; int mDataBufLen; diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index 97925c7c5..2a978b115 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -6,6 +6,8 @@ #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" +#include "al.h" + #include "sound_decoder.hpp" #include "sound.hpp" @@ -64,20 +66,21 @@ namespace MWSound virtual void adjustAudioSettings(AVSampleFormat& sampleFormat, uint64_t& channelLayout, int& sampleRate) { - if (sampleFormat == AV_SAMPLE_FMT_U8P) + if (sampleFormat == AV_SAMPLE_FMT_U8P || sampleFormat == AV_SAMPLE_FMT_U8) sampleFormat = AV_SAMPLE_FMT_U8; - else if (sampleFormat == AV_SAMPLE_FMT_S16P) + else if (sampleFormat == AV_SAMPLE_FMT_S16P || sampleFormat == AV_SAMPLE_FMT_S16) sampleFormat = AV_SAMPLE_FMT_S16; - else if (sampleFormat == AV_SAMPLE_FMT_FLTP) + else if ((sampleFormat == AV_SAMPLE_FMT_FLTP || sampleFormat == AV_SAMPLE_FMT_FLT) + && alIsExtensionPresent("AL_EXT_FLOAT32")) sampleFormat = AV_SAMPLE_FMT_FLT; else - sampleFormat = AV_SAMPLE_FMT_FLT; + sampleFormat = AV_SAMPLE_FMT_S16; - if (channelLayout != AV_CH_LAYOUT_MONO - && channelLayout != AV_CH_LAYOUT_5POINT1 - && channelLayout != AV_CH_LAYOUT_7POINT1 - && channelLayout != AV_CH_LAYOUT_STEREO - && channelLayout != AV_CH_LAYOUT_QUAD) + if ((channelLayout == AV_CH_LAYOUT_5POINT1 || channelLayout == AV_CH_LAYOUT_7POINT1 + || channelLayout == AV_CH_LAYOUT_QUAD) && !alIsExtensionPresent("AL_EXT_MCFORMATS")) + channelLayout = AV_CH_LAYOUT_STEREO; + else if (channelLayout != AV_CH_LAYOUT_MONO + && channelLayout != AV_CH_LAYOUT_STEREO) channelLayout = AV_CH_LAYOUT_STEREO; } From 6126b3b84a33186ebe3d7230c71bb3ffc963878a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 25 Oct 2014 17:26:20 +0200 Subject: [PATCH 16/23] Videoplayer: wait until we have the first picture before returning from playVideo() --- .../ogre-ffmpeg-videoplayer/videoplayer.cpp | 7 ++++ extern/ogre-ffmpeg-videoplayer/videostate.cpp | 41 ++++++++----------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp b/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp index d80449199..ac759804b 100644 --- a/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp +++ b/extern/ogre-ffmpeg-videoplayer/videoplayer.cpp @@ -31,6 +31,13 @@ void VideoPlayer::playVideo(const std::string &resourceName) mState = new VideoState; mState->setAudioFactory(mAudioFactory.get()); mState->init(resourceName); + + // wait until we have the first picture + while (mState->video_st && mState->mTexture.isNull()) + { + if (!mState->update()) + break; + } } catch(std::exception& e) { std::cerr<< "Failed to play video: "<video_st)->codec->width != 0 && (*this->video_st)->codec->height != 0) { - - if(static_cast(mTexture->getWidth()) != (*this->video_st)->codec->width || - static_cast(mTexture->getHeight()) != (*this->video_st)->codec->height) + if (mTexture.isNull()) { - mTexture->unload(); - mTexture->setWidth((*this->video_st)->codec->width); - mTexture->setHeight((*this->video_st)->codec->height); - mTexture->createInternalResources(); + static int i = 0; + mTexture = Ogre::TextureManager::getSingleton().createManual( + "ffmpeg/VideoTexture" + Ogre::StringConverter::toString(++i), + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + 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::HardwarePixelBufferSharedPtr buffer = mTexture->getBuffer(); @@ -657,24 +660,6 @@ void VideoState::init(const std::string& resourceName) if(video_index >= 0) { 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( - "ffmpeg/VideoTexture" + Ogre::StringConverter::toString(++i), - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - width, height, - 0, - Ogre::PF_BYTE_RGBA, - Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); - - // initialize to (0,0,0,0) - std::vector buffer; - buffer.resize(width * height, 0); - Ogre::PixelBox pb(width, height, 1, Ogre::PF_BYTE_RGBA, &buffer[0]); - this->mTexture->getBuffer()->blitFromMemory(pb); } @@ -724,6 +709,12 @@ void VideoState::deinit() } avformat_close_input(&this->format_ctx); } + + if (!mTexture.isNull()) + { + Ogre::TextureManager::getSingleton().remove(mTexture->getName()); + mTexture.setNull(); + } } double VideoState::get_external_clock() From c8a273f5527fc654cf43ba3bf14e191a3fcf4d95 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 25 Oct 2014 19:57:01 +0200 Subject: [PATCH 17/23] Stats window layout fix --- files/mygui/openmw_stats_window.layout | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/files/mygui/openmw_stats_window.layout b/files/mygui/openmw_stats_window.layout index ef6db8323..11119c404 100644 --- a/files/mygui/openmw_stats_window.layout +++ b/files/mygui/openmw_stats_window.layout @@ -70,8 +70,8 @@ - - + + @@ -80,10 +80,11 @@ + - + @@ -93,9 +94,10 @@ + - + @@ -105,6 +107,7 @@ + From dc6a99d32a86dc25cf8b891c2770b093e804d807 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 25 Oct 2014 20:00:10 +0200 Subject: [PATCH 18/23] Add missing virtual destructor --- extern/ogre-ffmpeg-videoplayer/audiofactory.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp b/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp index cf1ff46a8..06abd6a74 100644 --- a/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp +++ b/extern/ogre-ffmpeg-videoplayer/audiofactory.hpp @@ -12,6 +12,7 @@ class MovieAudioFactory { public: virtual boost::shared_ptr createDecoder(VideoState* videoState) = 0; + virtual ~MovieAudioFactory() {} }; } From ac067564eabc654a8f8c1abfc46b4d46e86e9cfc Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 25 Oct 2014 20:50:41 +0200 Subject: [PATCH 19/23] Don't include al.h in decoder classes, format support check will need to be redone later. For now, resample all formats that might not be supported on any hardware. --- apps/openmw/mwsound/ffmpeg_decoder.cpp | 11 ++++------- apps/openmw/mwsound/movieaudiofactory.cpp | 11 ++++------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp index b4307e395..2002bded7 100644 --- a/apps/openmw/mwsound/ffmpeg_decoder.cpp +++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp @@ -5,8 +5,6 @@ #include -#include "al.h" - extern "C" { #ifndef HAVE_LIBSWRESAMPLE // FIXME: remove this section once libswresample is packaged for Debian @@ -287,9 +285,8 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * if(!mStream) fail("No audio stream info"); - if(((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) - && alIsExtensionPresent("AL_EXT_FLOAT32")) - mOutputSampleFormat = AV_SAMPLE_FMT_FLT; + if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) + mOutputSampleFormat = AV_SAMPLE_FMT_S16; // FIXME: Check for AL_EXT_FLOAT32 support else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P) mOutputSampleFormat = AV_SAMPLE_FMT_U8; else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P) @@ -322,8 +319,8 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType * } mOutputChannelLayout = ch_layout; - if ((ch_layout == AV_CH_LAYOUT_5POINT1 || ch_layout == AV_CH_LAYOUT_7POINT1 - || ch_layout == AV_CH_LAYOUT_QUAD) && !alIsExtensionPresent("AL_EXT_MCFORMATS")) + if (ch_layout == AV_CH_LAYOUT_5POINT1 || ch_layout == AV_CH_LAYOUT_7POINT1 + || ch_layout == AV_CH_LAYOUT_QUAD) // FIXME: check for AL_EXT_MCFORMATS support mOutputChannelLayout = AV_CH_LAYOUT_STEREO; else if (ch_layout != AV_CH_LAYOUT_MONO && ch_layout != AV_CH_LAYOUT_STEREO) diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp index 2a978b115..468f8c82c 100644 --- a/apps/openmw/mwsound/movieaudiofactory.cpp +++ b/apps/openmw/mwsound/movieaudiofactory.cpp @@ -6,8 +6,6 @@ #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" -#include "al.h" - #include "sound_decoder.hpp" #include "sound.hpp" @@ -70,14 +68,13 @@ namespace MWSound sampleFormat = AV_SAMPLE_FMT_U8; else if (sampleFormat == AV_SAMPLE_FMT_S16P || sampleFormat == AV_SAMPLE_FMT_S16) sampleFormat = AV_SAMPLE_FMT_S16; - else if ((sampleFormat == AV_SAMPLE_FMT_FLTP || sampleFormat == AV_SAMPLE_FMT_FLT) - && alIsExtensionPresent("AL_EXT_FLOAT32")) - sampleFormat = AV_SAMPLE_FMT_FLT; + else if (sampleFormat == AV_SAMPLE_FMT_FLTP || sampleFormat == AV_SAMPLE_FMT_FLT) + sampleFormat = AV_SAMPLE_FMT_S16; // FIXME: check for AL_EXT_FLOAT32 support else sampleFormat = AV_SAMPLE_FMT_S16; - if ((channelLayout == AV_CH_LAYOUT_5POINT1 || channelLayout == AV_CH_LAYOUT_7POINT1 - || channelLayout == AV_CH_LAYOUT_QUAD) && !alIsExtensionPresent("AL_EXT_MCFORMATS")) + if (channelLayout == AV_CH_LAYOUT_5POINT1 || channelLayout == AV_CH_LAYOUT_7POINT1 + || channelLayout == AV_CH_LAYOUT_QUAD) // FIXME: check for AL_EXT_MCFORMATS support channelLayout = AV_CH_LAYOUT_STEREO; else if (channelLayout != AV_CH_LAYOUT_MONO && channelLayout != AV_CH_LAYOUT_STEREO) From dab05471be3fb1408116ec2e68516140b4e6b340 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 25 Oct 2014 21:09:37 +0200 Subject: [PATCH 20/23] Reset crime when bounty is reset to 0 by a script (Fixes #2057) --- apps/openmw/mwscript/statsextensions.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 170c5fe94..befb8d82e 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -20,6 +20,7 @@ #include "../mwbase/windowmanager.hpp" #include "../mwworld/class.hpp" +#include "../mwworld/player.hpp" #include "../mwmechanics/creaturestats.hpp" #include "../mwmechanics/npcstats.hpp" @@ -416,8 +417,12 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); - player.getClass().getNpcStats (player).setBounty(runtime[0].mFloat); + int bounty = runtime[0].mFloat; runtime.pop(); + player.getClass().getNpcStats (player).setBounty(bounty); + + if (bounty == 0) + MWBase::Environment::get().getWorld()->getPlayer().recordCrimeId(); } }; From 450e951b2dad4dd70d904b49fc14648d19dae757 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sun, 26 Oct 2014 01:54:25 +0200 Subject: [PATCH 21/23] Adjusted book layout to better match vanilla --- files/mygui/openmw_book.layout | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/files/mygui/openmw_book.layout b/files/mygui/openmw_book.layout index 3b1cfea64..2336d5b2c 100644 --- a/files/mygui/openmw_book.layout +++ b/files/mygui/openmw_book.layout @@ -2,47 +2,51 @@ - + - + - + - - + + - - + + - + - + - + + + - + + + - - + + From 95683bc8c33b5496d83e86ec3f79c47a191ef2d8 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 26 Oct 2014 15:04:52 +1000 Subject: [PATCH 22/23] Add user interface for top level window status-bar setting (implementation already existed). For feature #854. --- apps/opencs/model/settings/usersettings.cpp | 5 +++++ apps/opencs/view/doc/view.cpp | 2 +- apps/opencs/view/doc/viewmanager.cpp | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 1813a97ff..7d277f814 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -120,6 +120,11 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() reuse->setToolTip ("When a new subview is requested and a matching subview already " " exist, do not open a new subview and use the existing one instead."); + Setting *statusBar = createSetting (Type_CheckBox, "show-statusbar", "Show Status Bar"); + statusBar->setDefaultValue ("true"); + statusBar->setToolTip ("If a newly open top level window is showing status bars or not. " + " Note that this does not affect existing windows."); + Setting *maxSubView = createSetting (Type_SpinBox, "max-subviews", "Maximum number of subviews per top-level window"); maxSubView->setDefaultValue (256); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index d36e01901..bef0c170d 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -105,7 +105,7 @@ void CSVDoc::View::setupViewMenu() mShowStatusBar->setCheckable (true); connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool))); std::string showStatusBar = - CSMSettings::UserSettings::instance().settingValue("Display/show statusbar").toStdString(); + CSMSettings::UserSettings::instance().settingValue("window/show-statusbar").toStdString(); if(showStatusBar == "true") mShowStatusBar->setChecked(true); view->addAction (mShowStatusBar); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 4229ab531..5f6b6b46a 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -144,7 +144,7 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) mViews.push_back (view); std::string showStatusBar = - CSMSettings::UserSettings::instance().settingValue("Display/show statusbar").toStdString(); + CSMSettings::UserSettings::instance().settingValue("window/show-statusbar").toStdString(); view->toggleStatusBar (showStatusBar == "true"); view->show(); From 925f1487b0cbf6fc90dbce7bd03cd033a7f7baee Mon Sep 17 00:00:00 2001 From: sylar Date: Wed, 26 Nov 2014 06:55:41 +0400 Subject: [PATCH 23/23] fix for world_matrix error --- files/materials/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/materials/core.h b/files/materials/core.h index a912e2356..e6cde4bda 100644 --- a/files/materials/core.h +++ b/files/materials/core.h @@ -68,7 +68,7 @@ @version 120 #endif -#if SH_GLSLES == 1 && SH_FRAGMENT_SHADER +#if SH_GLSLES == 1 precision mediump int; precision mediump float; #endif