mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-04 03:40:14 +00:00
Merge branch 'master' into mouse-picking
Conflicts: apps/opencs/model/settings/usersettings.cpp
This commit is contained in:
commit
6ca88dc541
@ -120,6 +120,11 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||||||
reuse->setToolTip ("When a new subview is requested and a matching subview already "
|
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.");
|
" 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",
|
Setting *maxSubView = createSetting (Type_SpinBox, "max-subviews",
|
||||||
"Maximum number of subviews per top-level window");
|
"Maximum number of subviews per top-level window");
|
||||||
maxSubView->setDefaultValue (256);
|
maxSubView->setDefaultValue (256);
|
||||||
@ -127,6 +132,12 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||||||
maxSubView->setToolTip ("If the maximum number is reached and a new subview is opened "
|
maxSubView->setToolTip ("If the maximum number is reached and a new subview is opened "
|
||||||
"it will be placed into a new top-level window.");
|
"it will be placed into a new top-level window.");
|
||||||
|
|
||||||
|
Setting *hide = createSetting (Type_CheckBox, "hide-subview", "Hide single subview");
|
||||||
|
hide->setDefaultValue ("false");
|
||||||
|
hide->setToolTip ("When a view contains only a single subview, hide the subview title "
|
||||||
|
"bar and if this subview is closed also close the view (unless it is the last "
|
||||||
|
"view for this document)");
|
||||||
|
|
||||||
Setting *minWidth = createSetting (Type_SpinBox, "minimum-width",
|
Setting *minWidth = createSetting (Type_SpinBox, "minimum-width",
|
||||||
"Minimum subview width");
|
"Minimum subview width");
|
||||||
minWidth->setDefaultValue (325);
|
minWidth->setDefaultValue (325);
|
||||||
@ -158,6 +169,53 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||||||
"This option may be removed in future once the mouse picking feature is completed.");
|
"This option may be removed in future once the mouse picking feature is completed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declareSection ("table-input", "Table Input");
|
||||||
|
{
|
||||||
|
QString inPlaceEdit ("Edit in Place");
|
||||||
|
QString editRecord ("Edit Record");
|
||||||
|
QString view ("View");
|
||||||
|
QString editRecordAndClose ("Edit Record and Close");
|
||||||
|
|
||||||
|
QStringList values;
|
||||||
|
values
|
||||||
|
<< "None" << inPlaceEdit << editRecord << view << "Revert" << "Delete"
|
||||||
|
<< editRecordAndClose << "View and Close";
|
||||||
|
|
||||||
|
QString toolTip = "<ul>"
|
||||||
|
"<li>None</li>"
|
||||||
|
"<li>Edit in Place: Edit the clicked cell</li>"
|
||||||
|
"<li>Edit Record: Open a dialogue subview for the clicked record</li>"
|
||||||
|
"<li>View: Open a scene subview for the clicked record (not available everywhere)</li>"
|
||||||
|
"<li>Revert: Revert record</li>"
|
||||||
|
"<li>Delete: Delete recordy</li>"
|
||||||
|
"<li>Edit Record and Close: Open a dialogue subview for the clicked record and close the table subview</li>"
|
||||||
|
"<li>View And Close: Open a scene subview for the clicked record and close the table subview</li>"
|
||||||
|
"</ul>";
|
||||||
|
|
||||||
|
Setting *doubleClick = createSetting (Type_ComboBox, "double", "Double Click");
|
||||||
|
doubleClick->setDeclaredValues (values);
|
||||||
|
doubleClick->setDefaultValue (inPlaceEdit);
|
||||||
|
doubleClick->setToolTip ("Action on double click in table:<p>" + toolTip);
|
||||||
|
|
||||||
|
Setting *shiftDoubleClick = createSetting (Type_ComboBox, "double-s",
|
||||||
|
"Shift Double Click");
|
||||||
|
shiftDoubleClick->setDeclaredValues (values);
|
||||||
|
shiftDoubleClick->setDefaultValue (editRecord);
|
||||||
|
shiftDoubleClick->setToolTip ("Action on shift double click in table:<p>" + toolTip);
|
||||||
|
|
||||||
|
Setting *ctrlDoubleClick = createSetting (Type_ComboBox, "double-c",
|
||||||
|
"Control Double Click");
|
||||||
|
ctrlDoubleClick->setDeclaredValues (values);
|
||||||
|
ctrlDoubleClick->setDefaultValue (view);
|
||||||
|
ctrlDoubleClick->setToolTip ("Action on control double click in table:<p>" + toolTip);
|
||||||
|
|
||||||
|
Setting *shiftCtrlDoubleClick = createSetting (Type_ComboBox, "double-sc",
|
||||||
|
"Shift Control Double Click");
|
||||||
|
shiftCtrlDoubleClick->setDeclaredValues (values);
|
||||||
|
shiftCtrlDoubleClick->setDefaultValue (editRecordAndClose);
|
||||||
|
shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in table:<p>" + toolTip);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* There are three types of values:
|
* There are three types of values:
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "view.hpp"
|
#include "view.hpp"
|
||||||
|
|
||||||
CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id)
|
CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id)
|
||||||
: mUniversalId (id), mParent (NULL)
|
: mUniversalId (id)
|
||||||
{
|
{
|
||||||
/// \todo add a button to the title bar that clones this sub view
|
/// \todo add a button to the title bar that clones this sub view
|
||||||
|
|
||||||
@ -31,7 +31,15 @@ void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
|
|||||||
|
|
||||||
void CSVDoc::SubView::closeEvent (QCloseEvent *event)
|
void CSVDoc::SubView::closeEvent (QCloseEvent *event)
|
||||||
{
|
{
|
||||||
// update title bars of view and subviews
|
emit updateSubViewIndicies (this);
|
||||||
if(mParent)
|
|
||||||
mParent->updateSubViewIndicies(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CSVDoc::SubView::getTitle() const
|
||||||
|
{
|
||||||
|
return mUniversalId.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::SubView::closeRequest()
|
||||||
|
{
|
||||||
|
emit closeRequest (this);
|
||||||
|
}
|
@ -25,12 +25,13 @@ namespace CSVDoc
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
CSMWorld::UniversalId mUniversalId;
|
CSMWorld::UniversalId mUniversalId;
|
||||||
View *mParent;
|
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
SubView (const SubView&);
|
SubView (const SubView&);
|
||||||
SubView& operator= (SubView&);
|
SubView& operator= (SubView&);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void setUniversalId(const CSMWorld::UniversalId& id);
|
void setUniversalId(const CSMWorld::UniversalId& id);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -47,7 +48,9 @@ namespace CSVDoc
|
|||||||
virtual void useHint (const std::string& hint);
|
virtual void useHint (const std::string& hint);
|
||||||
///< Default implementation: ignored
|
///< Default implementation: ignored
|
||||||
|
|
||||||
void setParent(View *parent) { mParent = parent; }
|
virtual std::string getTitle() const;
|
||||||
|
|
||||||
|
virtual void updateUserSetting (const QString& name, const QStringList& value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -57,9 +60,15 @@ namespace CSVDoc
|
|||||||
|
|
||||||
void focusId (const CSMWorld::UniversalId& universalId, const std::string& hint);
|
void focusId (const CSMWorld::UniversalId& universalId, const std::string& hint);
|
||||||
|
|
||||||
public slots:
|
void closeRequest (SubView *subView);
|
||||||
virtual void updateUserSetting
|
|
||||||
(const QString &, const QStringList &);
|
void updateTitle();
|
||||||
|
|
||||||
|
void updateSubViewIndicies (SubView *view = 0);
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
|
||||||
|
void closeRequest();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ void CSVDoc::View::setupViewMenu()
|
|||||||
mShowStatusBar->setCheckable (true);
|
mShowStatusBar->setCheckable (true);
|
||||||
connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool)));
|
connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool)));
|
||||||
std::string showStatusBar =
|
std::string showStatusBar =
|
||||||
CSMSettings::UserSettings::instance().settingValue("Display/show statusbar").toStdString();
|
CSMSettings::UserSettings::instance().settingValue("window/show-statusbar").toStdString();
|
||||||
if(showStatusBar == "true")
|
if(showStatusBar == "true")
|
||||||
mShowStatusBar->setChecked(true);
|
mShowStatusBar->setChecked(true);
|
||||||
view->addAction (mShowStatusBar);
|
view->addAction (mShowStatusBar);
|
||||||
@ -300,7 +300,7 @@ void CSVDoc::View::setupUi()
|
|||||||
setupDebugMenu();
|
setupDebugMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::View::updateTitle(const std::string subview)
|
void CSVDoc::View::updateTitle()
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
|
|
||||||
@ -312,8 +312,13 @@ void CSVDoc::View::updateTitle(const std::string subview)
|
|||||||
if (mViewTotal>1)
|
if (mViewTotal>1)
|
||||||
stream << " [" << (mViewIndex+1) << "/" << mViewTotal << "]";
|
stream << " [" << (mViewIndex+1) << "/" << mViewTotal << "]";
|
||||||
|
|
||||||
if (subview != "")
|
CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance();
|
||||||
stream << " - " << subview;
|
|
||||||
|
bool hideTitle = userSettings.setting ("window/hide-subview", QString ("false"))=="true" &&
|
||||||
|
mSubViews.size()==1 && !mSubViews.at (0)->isFloating();
|
||||||
|
|
||||||
|
if (hideTitle)
|
||||||
|
stream << " - " << mSubViews.at (0)->getTitle();
|
||||||
|
|
||||||
setWindowTitle (stream.str().c_str());
|
setWindowTitle (stream.str().c_str());
|
||||||
}
|
}
|
||||||
@ -323,24 +328,26 @@ void CSVDoc::View::updateSubViewIndicies(SubView *view)
|
|||||||
if(view && mSubViews.contains(view))
|
if(view && mSubViews.contains(view))
|
||||||
mSubViews.removeOne(view);
|
mSubViews.removeOne(view);
|
||||||
|
|
||||||
if(mSubViews.size() == 1)
|
CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance();
|
||||||
|
|
||||||
|
bool hideTitle = userSettings.setting ("window/hide-subview", QString ("false"))=="true" &&
|
||||||
|
mSubViews.size()==1 && !mSubViews.at (0)->isFloating();
|
||||||
|
|
||||||
|
updateTitle();
|
||||||
|
|
||||||
|
foreach (SubView *subView, mSubViews)
|
||||||
{
|
{
|
||||||
if(!mSubViews.at(0)->isFloating())
|
if (!subView->isFloating())
|
||||||
{
|
{
|
||||||
mSubViews.at(0)->setTitleBarWidget(new QWidget(this));
|
if (hideTitle)
|
||||||
updateTitle(mSubViews.at(0)->getUniversalId().getTypeName().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
updateTitle();
|
|
||||||
if(mSubViews.size() > 1)
|
|
||||||
{
|
|
||||||
foreach(SubView * sb, mSubViews)
|
|
||||||
{
|
{
|
||||||
QWidget * tb = sb->titleBarWidget();
|
subView->setTitleBarWidget (new QWidget (this));
|
||||||
if(tb) delete tb;
|
subView->setWindowTitle (QString::fromUtf8 (subView->getTitle().c_str()));
|
||||||
sb->setTitleBarWidget(0);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete subView->titleBarWidget();
|
||||||
|
subView->setTitleBarWidget (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,10 +520,12 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
|
|||||||
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)), this,
|
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)), this,
|
||||||
SLOT (addSubView (const CSMWorld::UniversalId&, const std::string&)));
|
SLOT (addSubView (const CSMWorld::UniversalId&, const std::string&)));
|
||||||
|
|
||||||
connect (&CSMSettings::UserSettings::instance(),
|
connect (view, SIGNAL (closeRequest (SubView *)), this, SLOT (closeRequest (SubView *)));
|
||||||
SIGNAL (userSettingUpdated (const QString &, const QStringList &)),
|
|
||||||
view,
|
connect (view, SIGNAL (updateTitle()), this, SLOT (updateTitle()));
|
||||||
SLOT (updateUserSetting (const QString &, const QStringList &)));
|
|
||||||
|
connect (view, SIGNAL (updateSubViewIndicies (SubView *)),
|
||||||
|
this, SLOT (updateSubViewIndicies (SubView *)));
|
||||||
|
|
||||||
view->show();
|
view->show();
|
||||||
}
|
}
|
||||||
@ -729,9 +738,16 @@ void CSVDoc::View::resizeViewHeight (int height)
|
|||||||
resize (geometry().width(), height);
|
resize (geometry().width(), height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::View::updateUserSetting
|
void CSVDoc::View::updateUserSetting (const QString &name, const QStringList &list)
|
||||||
(const QString &name, const QStringList &list)
|
{
|
||||||
{}
|
if (name=="window/hide-subview")
|
||||||
|
updateSubViewIndicies (0);
|
||||||
|
|
||||||
|
foreach (SubView *subView, mSubViews)
|
||||||
|
{
|
||||||
|
subView->updateUserSetting (name, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CSVDoc::View::toggleShowStatusBar (bool show)
|
void CSVDoc::View::toggleShowStatusBar (bool show)
|
||||||
{
|
{
|
||||||
@ -761,3 +777,14 @@ void CSVDoc::View::stop()
|
|||||||
{
|
{
|
||||||
mDocument->stopRunning();
|
mDocument->stopRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::closeRequest (SubView *subView)
|
||||||
|
{
|
||||||
|
CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance();
|
||||||
|
|
||||||
|
if (mSubViews.size()>1 || mViewTotal<=1 ||
|
||||||
|
userSettings.setting ("window/hide-subview", QString ("false"))!="true")
|
||||||
|
subView->deleteLater();
|
||||||
|
else if (mViewManager.closeRequest (this))
|
||||||
|
mViewManager.removeDocAndView (mDocument);
|
||||||
|
}
|
||||||
|
@ -75,8 +75,6 @@ namespace CSVDoc
|
|||||||
|
|
||||||
void setupUi();
|
void setupUi();
|
||||||
|
|
||||||
void updateTitle(const std::string subview = "");
|
|
||||||
|
|
||||||
void updateActions();
|
void updateActions();
|
||||||
|
|
||||||
void exitApplication();
|
void exitApplication();
|
||||||
@ -114,9 +112,6 @@ namespace CSVDoc
|
|||||||
/// Function called by view manager when user preferences are updated
|
/// Function called by view manager when user preferences are updated
|
||||||
void updateEditorSetting (const QString &, const QString &);
|
void updateEditorSetting (const QString &, const QString &);
|
||||||
|
|
||||||
// called when subviews are added or removed
|
|
||||||
void updateSubViewIndicies(SubView *view = 0);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void newGameRequest();
|
void newGameRequest();
|
||||||
@ -139,6 +134,11 @@ namespace CSVDoc
|
|||||||
|
|
||||||
void updateUserSetting (const QString &, const QStringList &);
|
void updateUserSetting (const QString &, const QStringList &);
|
||||||
|
|
||||||
|
void updateTitle();
|
||||||
|
|
||||||
|
// called when subviews are added or removed
|
||||||
|
void updateSubViewIndicies (SubView *view = 0);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void newView();
|
void newView();
|
||||||
@ -222,6 +222,8 @@ namespace CSVDoc
|
|||||||
void run (const std::string& profile, const std::string& startupInstruction = "");
|
void run (const std::string& profile, const std::string& startupInstruction = "");
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
void closeRequest (SubView *subView);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
|
|||||||
mViews.push_back (view);
|
mViews.push_back (view);
|
||||||
|
|
||||||
std::string showStatusBar =
|
std::string showStatusBar =
|
||||||
CSMSettings::UserSettings::instance().settingValue("Display/show statusbar").toStdString();
|
CSMSettings::UserSettings::instance().settingValue("window/show-statusbar").toStdString();
|
||||||
|
|
||||||
view->toggleStatusBar (showStatusBar == "true");
|
view->toggleStatusBar (showStatusBar == "true");
|
||||||
view->show();
|
view->show();
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "../widget/scenetoolmode.hpp"
|
#include "../widget/scenetoolmode.hpp"
|
||||||
|
|
||||||
CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
|
CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
|
||||||
: SubView (id)
|
: SubView (id), mTitle (id.toString().c_str())
|
||||||
{
|
{
|
||||||
QHBoxLayout *layout = new QHBoxLayout;
|
QHBoxLayout *layout = new QHBoxLayout;
|
||||||
|
|
||||||
@ -52,15 +52,19 @@ CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDo
|
|||||||
|
|
||||||
void CSVWorld::PreviewSubView::setEditLock (bool locked) {}
|
void CSVWorld::PreviewSubView::setEditLock (bool locked) {}
|
||||||
|
|
||||||
void CSVWorld::PreviewSubView::closeRequest()
|
std::string CSVWorld::PreviewSubView::getTitle() const
|
||||||
{
|
{
|
||||||
deleteLater();
|
return mTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::PreviewSubView::referenceableIdChanged (const std::string& id)
|
void CSVWorld::PreviewSubView::referenceableIdChanged (const std::string& id)
|
||||||
{
|
{
|
||||||
if (id.empty())
|
if (id.empty())
|
||||||
setWindowTitle ("Preview: Reference to <nothing>");
|
mTitle = "Preview: Reference to <nothing>";
|
||||||
else
|
else
|
||||||
setWindowTitle (("Preview: Reference to " + id).c_str());
|
mTitle = "Preview: Reference to " + id;
|
||||||
|
|
||||||
|
setWindowTitle (QString::fromUtf8 (mTitle.c_str()));
|
||||||
|
|
||||||
|
emit updateTitle();
|
||||||
}
|
}
|
@ -20,6 +20,7 @@ namespace CSVWorld
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
CSVRender::PreviewWidget *mScene;
|
CSVRender::PreviewWidget *mScene;
|
||||||
|
std::string mTitle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -27,9 +28,9 @@ namespace CSVWorld
|
|||||||
|
|
||||||
virtual void setEditLock (bool locked);
|
virtual void setEditLock (bool locked);
|
||||||
|
|
||||||
private slots:
|
virtual std::string getTitle() const;
|
||||||
|
|
||||||
void closeRequest();
|
private slots:
|
||||||
|
|
||||||
void referenceableIdChanged (const std::string& id);
|
void referenceableIdChanged (const std::string& id);
|
||||||
};
|
};
|
||||||
|
@ -150,9 +150,9 @@ void CSVWorld::SceneSubView::useHint (const std::string& hint)
|
|||||||
mScene->useViewHint (hint);
|
mScene->useViewHint (hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::SceneSubView::closeRequest()
|
std::string CSVWorld::SceneSubView::getTitle() const
|
||||||
{
|
{
|
||||||
deleteLater();
|
return mTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::UniversalId& id)
|
void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::UniversalId& id)
|
||||||
@ -161,10 +161,11 @@ void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::UniversalId&
|
|||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << "Scene: " << getUniversalId().getId();
|
stream << "Scene: " << getUniversalId().getId();
|
||||||
|
|
||||||
setWindowTitle (QString::fromUtf8 (stream.str().c_str()));
|
mTitle = stream.str();
|
||||||
|
setWindowTitle (QString::fromUtf8 (mTitle.c_str()));
|
||||||
|
emit updateTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection& selection)
|
void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection& selection)
|
||||||
{
|
{
|
||||||
setUniversalId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Scene, "sys::default"));
|
setUniversalId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Scene, "sys::default"));
|
||||||
@ -189,7 +190,9 @@ void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection
|
|||||||
stream << "cell around it)";
|
stream << "cell around it)";
|
||||||
}
|
}
|
||||||
|
|
||||||
setWindowTitle (QString::fromUtf8 (stream.str().c_str()));
|
mTitle = stream.str();
|
||||||
|
setWindowTitle (QString::fromUtf8 (mTitle.c_str()));
|
||||||
|
emit updateTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
|
void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
|
||||||
|
@ -44,6 +44,7 @@ namespace CSVWorld
|
|||||||
QHBoxLayout* mLayout;
|
QHBoxLayout* mLayout;
|
||||||
CSMDoc::Document& mDocument;
|
CSMDoc::Document& mDocument;
|
||||||
CSVWidget::SceneToolbar* mToolbar;
|
CSVWidget::SceneToolbar* mToolbar;
|
||||||
|
std::string mTitle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -57,6 +58,8 @@ namespace CSVWorld
|
|||||||
|
|
||||||
virtual void useHint (const std::string& hint);
|
virtual void useHint (const std::string& hint);
|
||||||
|
|
||||||
|
virtual std::string getTitle() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void makeConnections(CSVRender::PagedWorldspaceWidget* widget);
|
void makeConnections(CSVRender::PagedWorldspaceWidget* widget);
|
||||||
@ -75,8 +78,6 @@ namespace CSVWorld
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void closeRequest();
|
|
||||||
|
|
||||||
void cellSelectionChanged (const CSMWorld::CellSelection& selection);
|
void cellSelectionChanged (const CSMWorld::CellSelection& selection);
|
||||||
|
|
||||||
void cellSelectionChanged (const CSMWorld::UniversalId& id);
|
void cellSelectionChanged (const CSMWorld::UniversalId& id);
|
||||||
|
@ -81,6 +81,6 @@ void CSVWorld::ScriptSubView::rowsAboutToBeRemoved (const QModelIndex& parent, i
|
|||||||
QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn);
|
QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn);
|
||||||
|
|
||||||
if (!parent.isValid() && index.row()>=start && index.row()<=end)
|
if (!parent.isValid() && index.row()>=start && index.row()<=end)
|
||||||
deleteLater();
|
emit closeRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +177,79 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||||||
menu.exec (event->globalPos());
|
menu.exec (event->globalPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::Table::mouseDoubleClickEvent (QMouseEvent *event)
|
||||||
|
{
|
||||||
|
Qt::KeyboardModifiers modifiers =
|
||||||
|
event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier);
|
||||||
|
|
||||||
|
QModelIndex index = currentIndex();
|
||||||
|
|
||||||
|
selectionModel()->select (index,
|
||||||
|
QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||||
|
|
||||||
|
std::map<Qt::KeyboardModifiers, DoubleClickAction>::iterator iter =
|
||||||
|
mDoubleClickActions.find (modifiers);
|
||||||
|
|
||||||
|
if (iter==mDoubleClickActions.end())
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (iter->second)
|
||||||
|
{
|
||||||
|
case Action_None:
|
||||||
|
|
||||||
|
event->accept();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Action_InPlaceEdit:
|
||||||
|
|
||||||
|
DragRecordTable::mouseDoubleClickEvent (event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Action_EditRecord:
|
||||||
|
|
||||||
|
event->accept();
|
||||||
|
editRecord();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Action_View:
|
||||||
|
|
||||||
|
event->accept();
|
||||||
|
viewRecord();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Action_Revert:
|
||||||
|
|
||||||
|
event->accept();
|
||||||
|
if (mDispatcher->canRevert())
|
||||||
|
mDispatcher->executeRevert();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Action_Delete:
|
||||||
|
|
||||||
|
event->accept();
|
||||||
|
if (mDispatcher->canDelete())
|
||||||
|
mDispatcher->executeDelete();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Action_EditRecordAndClose:
|
||||||
|
|
||||||
|
event->accept();
|
||||||
|
editRecord();
|
||||||
|
emit closeRequest();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Action_ViewAndClose:
|
||||||
|
|
||||||
|
event->accept();
|
||||||
|
viewRecord();
|
||||||
|
emit closeRequest();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
||||||
bool createAndDelete, bool sorting, CSMDoc::Document& document)
|
bool createAndDelete, bool sorting, CSMDoc::Document& document)
|
||||||
: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0),
|
: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0),
|
||||||
@ -284,6 +357,11 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
|||||||
this, SLOT (selectionSizeUpdate ()));
|
this, SLOT (selectionSizeUpdate ()));
|
||||||
|
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
|
|
||||||
|
mDoubleClickActions.insert (std::make_pair (0, Action_InPlaceEdit));
|
||||||
|
mDoubleClickActions.insert (std::make_pair (Qt::ShiftModifier, Action_EditRecord));
|
||||||
|
mDoubleClickActions.insert (std::make_pair (Qt::ControlModifier, Action_View));
|
||||||
|
mDoubleClickActions.insert (std::make_pair (Qt::ShiftModifier | Qt::ControlModifier, Action_EditRecordAndClose));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::Table::setEditLock (bool locked)
|
void CSVWorld::Table::setEditLock (bool locked)
|
||||||
@ -404,6 +482,9 @@ void CSVWorld::Table::editCell()
|
|||||||
|
|
||||||
void CSVWorld::Table::viewRecord()
|
void CSVWorld::Table::viewRecord()
|
||||||
{
|
{
|
||||||
|
if (!(mModel->getFeatures() & CSMWorld::IdTableBase::Feature_View))
|
||||||
|
return;
|
||||||
|
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
|
|
||||||
if (selectedRows.size()==1)
|
if (selectedRows.size()==1)
|
||||||
@ -439,18 +520,59 @@ void CSVWorld::Table::previewRecord()
|
|||||||
void CSVWorld::Table::updateUserSetting
|
void CSVWorld::Table::updateUserSetting
|
||||||
(const QString &name, const QStringList &list)
|
(const QString &name, const QStringList &list)
|
||||||
{
|
{
|
||||||
int columns = mModel->columnCount();
|
if (name=="records/type-format" || name=="records/status-format")
|
||||||
|
{
|
||||||
|
int columns = mModel->columnCount();
|
||||||
|
|
||||||
for (int i=0; i<columns; ++i)
|
for (int i=0; i<columns; ++i)
|
||||||
if (QAbstractItemDelegate *delegate = itemDelegateForColumn (i))
|
if (QAbstractItemDelegate *delegate = itemDelegateForColumn (i))
|
||||||
{
|
|
||||||
dynamic_cast<CommandDelegate&>
|
|
||||||
(*delegate).updateUserSetting (name, list);
|
|
||||||
{
|
{
|
||||||
emit dataChanged (mModel->index (0, i),
|
dynamic_cast<CommandDelegate&>
|
||||||
mModel->index (mModel->rowCount()-1, i));
|
(*delegate).updateUserSetting (name, list);
|
||||||
|
{
|
||||||
|
emit dataChanged (mModel->index (0, i),
|
||||||
|
mModel->index (mModel->rowCount()-1, i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString base ("table-input/double");
|
||||||
|
if (name.startsWith (base))
|
||||||
|
{
|
||||||
|
QString modifierString = name.mid (base.size());
|
||||||
|
Qt::KeyboardModifiers modifiers = 0;
|
||||||
|
|
||||||
|
if (modifierString=="-s")
|
||||||
|
modifiers = Qt::ShiftModifier;
|
||||||
|
else if (modifierString=="-c")
|
||||||
|
modifiers = Qt::ControlModifier;
|
||||||
|
else if (modifierString=="-sc")
|
||||||
|
modifiers = Qt::ShiftModifier | Qt::ControlModifier;
|
||||||
|
|
||||||
|
DoubleClickAction action = Action_None;
|
||||||
|
|
||||||
|
QString value = list.at (0);
|
||||||
|
|
||||||
|
if (value=="Edit in Place")
|
||||||
|
action = Action_InPlaceEdit;
|
||||||
|
else if (value=="Edit Record")
|
||||||
|
action = Action_EditRecord;
|
||||||
|
else if (value=="View")
|
||||||
|
action = Action_View;
|
||||||
|
else if (value=="Revert")
|
||||||
|
action = Action_Revert;
|
||||||
|
else if (value=="Delete")
|
||||||
|
action = Action_Delete;
|
||||||
|
else if (value=="Edit Record and Close")
|
||||||
|
action = Action_EditRecordAndClose;
|
||||||
|
else if (value=="View and Close")
|
||||||
|
action = Action_ViewAndClose;
|
||||||
|
|
||||||
|
mDoubleClickActions[modifiers] = action;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::Table::tableSizeUpdate()
|
void CSVWorld::Table::tableSizeUpdate()
|
||||||
@ -567,7 +689,6 @@ std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column
|
|||||||
|
|
||||||
std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const
|
std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const
|
||||||
{
|
{
|
||||||
|
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
std::vector<CSMWorld::UniversalId> idToDrag;
|
std::vector<CSMWorld::UniversalId> idToDrag;
|
||||||
|
|
||||||
|
@ -36,6 +36,18 @@ namespace CSVWorld
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
enum DoubleClickAction
|
||||||
|
{
|
||||||
|
Action_None,
|
||||||
|
Action_InPlaceEdit,
|
||||||
|
Action_EditRecord,
|
||||||
|
Action_View,
|
||||||
|
Action_Revert,
|
||||||
|
Action_Delete,
|
||||||
|
Action_EditRecordAndClose,
|
||||||
|
Action_ViewAndClose
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<CommandDelegate *> mDelegates;
|
std::vector<CommandDelegate *> mDelegates;
|
||||||
QAction *mEditAction;
|
QAction *mEditAction;
|
||||||
QAction *mCreateAction;
|
QAction *mCreateAction;
|
||||||
@ -53,8 +65,8 @@ namespace CSVWorld
|
|||||||
CSMWorld::IdTableBase *mModel;
|
CSMWorld::IdTableBase *mModel;
|
||||||
int mRecordStatusDisplay;
|
int mRecordStatusDisplay;
|
||||||
CSMWorld::CommandDispatcher *mDispatcher;
|
CSMWorld::CommandDispatcher *mDispatcher;
|
||||||
|
|
||||||
CSMWorld::UniversalId mEditCellId;
|
CSMWorld::UniversalId mEditCellId;
|
||||||
|
std::map<Qt::KeyboardModifiers, DoubleClickAction> mDoubleClickActions;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -64,6 +76,10 @@ namespace CSVWorld
|
|||||||
|
|
||||||
void dropEvent(QDropEvent *event);
|
void dropEvent(QDropEvent *event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void mouseDoubleClickEvent (QMouseEvent *event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Table (const CSMWorld::UniversalId& id, bool createAndDelete,
|
Table (const CSMWorld::UniversalId& id, bool createAndDelete,
|
||||||
@ -94,6 +110,8 @@ namespace CSVWorld
|
|||||||
|
|
||||||
void cloneRequest(const CSMWorld::UniversalId&);
|
void cloneRequest(const CSMWorld::UniversalId&);
|
||||||
|
|
||||||
|
void closeRequest();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void editCell();
|
void editCell();
|
||||||
|
@ -69,6 +69,8 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
|||||||
|
|
||||||
connect(mFilterBox, SIGNAL(recordDropped(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)),
|
connect(mFilterBox, SIGNAL(recordDropped(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)),
|
||||||
this, SLOT(createFilterRequest(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)));
|
this, SLOT(createFilterRequest(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)));
|
||||||
|
|
||||||
|
connect (mTable, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::TableSubView::setEditLock (bool locked)
|
void CSVWorld::TableSubView::setEditLock (bool locked)
|
||||||
@ -150,3 +152,4 @@ bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +199,10 @@ namespace MWBase
|
|||||||
virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0;
|
virtual MWWorld::Ptr searchPtrViaActorId (int actorId) = 0;
|
||||||
///< Search is limited to the active cells.
|
///< 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
|
/// \todo enable reference in the OGRE scene
|
||||||
virtual void enable (const MWWorld::Ptr& ptr) = 0;
|
virtual void enable (const MWWorld::Ptr& ptr) = 0;
|
||||||
|
|
||||||
|
@ -191,8 +191,11 @@ namespace MWClass
|
|||||||
|
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight);
|
if (ref->mBase->mData.mWeight != 0)
|
||||||
text += MWGui::ToolTips::getValueString(ref->mBase->mData.mValue, "#{sValue}");
|
{
|
||||||
|
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()) {
|
if (MWBase::Environment::get().getWindowManager()->getFullHelp()) {
|
||||||
text += MWGui::ToolTips::getCellRefString(ptr.getCellRef());
|
text += MWGui::ToolTips::getCellRefString(ptr.getCellRef());
|
||||||
|
@ -132,6 +132,7 @@ namespace MWGui
|
|||||||
virtual int pageSplit();
|
virtual int pageSplit();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual ~GraphicElement() {}
|
||||||
MyGUI::Widget * mParent;
|
MyGUI::Widget * mParent;
|
||||||
Paginator & mPaginator;
|
Paginator & mPaginator;
|
||||||
BlockStyle mBlockStyle;
|
BlockStyle mBlockStyle;
|
||||||
|
@ -30,8 +30,7 @@ int VideoWidget::getVideoHeight()
|
|||||||
|
|
||||||
bool VideoWidget::update()
|
bool VideoWidget::update()
|
||||||
{
|
{
|
||||||
mPlayer.update();
|
return mPlayer.update();
|
||||||
return mPlayer.isPlaying();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoWidget::stop()
|
void VideoWidget::stop()
|
||||||
|
@ -377,6 +377,7 @@ namespace MWGui
|
|||||||
delete mHitFader;
|
delete mHitFader;
|
||||||
delete mWerewolfFader;
|
delete mWerewolfFader;
|
||||||
delete mScreenFader;
|
delete mScreenFader;
|
||||||
|
delete mBlindnessFader;
|
||||||
delete mDebugWindow;
|
delete mDebugWindow;
|
||||||
|
|
||||||
cleanupGarbage();
|
cleanupGarbage();
|
||||||
|
@ -27,9 +27,9 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr)
|
|||||||
setObjectRoot(model, false);
|
setObjectRoot(model, false);
|
||||||
setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha);
|
setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha);
|
||||||
|
|
||||||
addAnimSource(model);
|
|
||||||
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
||||||
addAnimSource("meshes\\base_anim.nif");
|
addAnimSource("meshes\\base_anim.nif");
|
||||||
|
addAnimSource(model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,9 +47,9 @@ CreatureWeaponAnimation::CreatureWeaponAnimation(const MWWorld::Ptr &ptr)
|
|||||||
setObjectRoot(model, false);
|
setObjectRoot(model, false);
|
||||||
setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha);
|
setRenderProperties(mObjectRoot, RV_Actors, RQG_Main, RQG_Alpha);
|
||||||
|
|
||||||
addAnimSource(model);
|
|
||||||
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
if((ref->mBase->mFlags&ESM::Creature::Bipedal))
|
||||||
addAnimSource("meshes\\base_anim.nif");
|
addAnimSource("meshes\\base_anim.nif");
|
||||||
|
addAnimSource(model);
|
||||||
|
|
||||||
mPtr.getClass().getInventoryStore(mPtr).setListener(this, mPtr);
|
mPtr.getClass().getInventoryStore(mPtr).setListener(this, mPtr);
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
|
||||||
@ -434,6 +435,16 @@ namespace MWScript
|
|||||||
else
|
else
|
||||||
ref2 = MWBase::Environment::get().getWorld()->getPtr(id, false);
|
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);
|
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)
|
// If the objects are in different worldspaces, return a large value (just like vanilla)
|
||||||
|
@ -454,7 +454,8 @@ namespace MWScript
|
|||||||
if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item))
|
if (::Misc::StringUtils::ciEqual(iter->getCellRef().getRefId(), item))
|
||||||
{
|
{
|
||||||
int removed = store.remove(*iter, toRemove, ptr);
|
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;
|
toRemove -= removed;
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
#include "../mwworld/player.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/creaturestats.hpp"
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
@ -416,8 +417,12 @@ namespace MWScript
|
|||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
MWWorld::Ptr player = world->getPlayerPtr();
|
MWWorld::Ptr player = world->getPlayerPtr();
|
||||||
|
|
||||||
player.getClass().getNpcStats (player).setBounty(runtime[0].mFloat);
|
int bounty = runtime[0].mFloat;
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
player.getClass().getNpcStats (player).setBounty(bounty);
|
||||||
|
|
||||||
|
if (bounty == 0)
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().recordCrimeId();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ bool FFmpeg_Decoder::getAVAudioData()
|
|||||||
if(!mDataBuf || mDataBufLen < mFrame->nb_samples)
|
if(!mDataBuf || mDataBufLen < mFrame->nb_samples)
|
||||||
{
|
{
|
||||||
av_freep(&mDataBuf);
|
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)
|
mFrame->nb_samples, mOutputSampleFormat, 0) < 0)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
@ -147,8 +147,8 @@ size_t FFmpeg_Decoder::readAVAudioData(void *data, size_t length)
|
|||||||
if(!getAVAudioData())
|
if(!getAVAudioData())
|
||||||
break;
|
break;
|
||||||
mFramePos = 0;
|
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((*mStream)->codec->sample_fmt);
|
av_get_bytes_per_sample(mOutputSampleFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the amount of bytes remaining to be written, and clamp to
|
/* Get the amount of bytes remaining to be written, and clamp to
|
||||||
@ -285,47 +285,31 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
|
|||||||
if(!mStream)
|
if(!mStream)
|
||||||
fail("No audio stream info");
|
fail("No audio stream info");
|
||||||
|
|
||||||
if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8)
|
if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLT || (*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP)
|
||||||
*type = SampleType_UInt8;
|
mOutputSampleFormat = AV_SAMPLE_FMT_S16; // FIXME: Check for AL_EXT_FLOAT32 support
|
||||||
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;
|
|
||||||
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P)
|
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)
|
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_S16P)
|
||||||
*type = SampleType_Int16;
|
mOutputSampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
else if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_FLTP)
|
|
||||||
*type = SampleType_Float32;
|
|
||||||
else
|
else
|
||||||
fail(std::string("Unsupported sample format: ")+
|
mOutputSampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
av_get_sample_fmt_name((*mStream)->codec->sample_fmt));
|
|
||||||
|
if(mOutputSampleFormat == AV_SAMPLE_FMT_U8)
|
||||||
|
*type = SampleType_UInt8;
|
||||||
|
else if(mOutputSampleFormat == AV_SAMPLE_FMT_S16)
|
||||||
|
*type = SampleType_Int16;
|
||||||
|
else if(mOutputSampleFormat == AV_SAMPLE_FMT_FLT)
|
||||||
|
*type = SampleType_Float32;
|
||||||
|
|
||||||
int64_t ch_layout = (*mStream)->codec->channel_layout;
|
int64_t ch_layout = (*mStream)->codec->channel_layout;
|
||||||
|
|
||||||
if((*mStream)->codec->channel_layout == AV_CH_LAYOUT_MONO)
|
if(ch_layout == 0)
|
||||||
*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)
|
|
||||||
{
|
{
|
||||||
/* Unknown channel layout. Try to guess. */
|
/* Unknown channel layout. Try to guess. */
|
||||||
if((*mStream)->codec->channels == 1)
|
if((*mStream)->codec->channels == 1)
|
||||||
{
|
|
||||||
*chans = ChannelConfig_Mono;
|
|
||||||
ch_layout = AV_CH_LAYOUT_MONO;
|
ch_layout = AV_CH_LAYOUT_MONO;
|
||||||
}
|
|
||||||
else if((*mStream)->codec->channels == 2)
|
else if((*mStream)->codec->channels == 2)
|
||||||
{
|
|
||||||
*chans = ChannelConfig_Stereo;
|
|
||||||
ch_layout = AV_CH_LAYOUT_STEREO;
|
ch_layout = AV_CH_LAYOUT_STEREO;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::stringstream sstr("Unsupported raw channel count: ");
|
std::stringstream sstr("Unsupported raw channel count: ");
|
||||||
@ -333,6 +317,25 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
|
|||||||
fail(sstr.str());
|
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) // 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)
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
char str[1024];
|
char str[1024];
|
||||||
@ -343,17 +346,11 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
|
|||||||
|
|
||||||
*samplerate = (*mStream)->codec->sample_rate;
|
*samplerate = (*mStream)->codec->sample_rate;
|
||||||
|
|
||||||
if((*mStream)->codec->sample_fmt == AV_SAMPLE_FMT_U8P)
|
if(mOutputSampleFormat != (*mStream)->codec->sample_fmt
|
||||||
mOutputSampleFormat = AV_SAMPLE_FMT_U8;
|
|| mOutputChannelLayout != ch_layout)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
mSwr = swr_alloc_set_opts(mSwr, // SwrContext
|
mSwr = swr_alloc_set_opts(mSwr, // SwrContext
|
||||||
ch_layout, // output ch layout
|
mOutputChannelLayout, // output ch layout
|
||||||
mOutputSampleFormat, // output sample format
|
mOutputSampleFormat, // output sample format
|
||||||
(*mStream)->codec->sample_rate, // output sample rate
|
(*mStream)->codec->sample_rate, // output sample rate
|
||||||
ch_layout, // input ch layout
|
ch_layout, // input ch layout
|
||||||
@ -383,8 +380,8 @@ void FFmpeg_Decoder::readAll(std::vector<char> &output)
|
|||||||
|
|
||||||
while(getAVAudioData())
|
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((*mStream)->codec->sample_fmt);
|
av_get_bytes_per_sample(mOutputSampleFormat);
|
||||||
const char *inbuf = reinterpret_cast<char*>(mFrameData[0]);
|
const char *inbuf = reinterpret_cast<char*>(mFrameData[0]);
|
||||||
output.insert(output.end(), inbuf, inbuf+got);
|
output.insert(output.end(), inbuf, inbuf+got);
|
||||||
}
|
}
|
||||||
@ -402,8 +399,8 @@ void FFmpeg_Decoder::rewind()
|
|||||||
|
|
||||||
size_t FFmpeg_Decoder::getSampleOffset()
|
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((*mStream)->codec->sample_fmt);
|
av_get_bytes_per_sample(mOutputSampleFormat);
|
||||||
return (int)(mNextPts*(*mStream)->codec->sample_rate) - delay;
|
return (int)(mNextPts*(*mStream)->codec->sample_rate) - delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,6 +413,7 @@ FFmpeg_Decoder::FFmpeg_Decoder()
|
|||||||
, mNextPts(0.0)
|
, mNextPts(0.0)
|
||||||
, mSwr(0)
|
, mSwr(0)
|
||||||
, mOutputSampleFormat(AV_SAMPLE_FMT_NONE)
|
, mOutputSampleFormat(AV_SAMPLE_FMT_NONE)
|
||||||
|
, mOutputChannelLayout(0)
|
||||||
, mDataBuf(NULL)
|
, mDataBuf(NULL)
|
||||||
, mFrameData(NULL)
|
, mFrameData(NULL)
|
||||||
, mDataBufLen(0)
|
, mDataBufLen(0)
|
||||||
|
@ -59,6 +59,7 @@ namespace MWSound
|
|||||||
|
|
||||||
SwrContext *mSwr;
|
SwrContext *mSwr;
|
||||||
enum AVSampleFormat mOutputSampleFormat;
|
enum AVSampleFormat mOutputSampleFormat;
|
||||||
|
int64_t mOutputChannelLayout;
|
||||||
uint8_t *mDataBuf;
|
uint8_t *mDataBuf;
|
||||||
uint8_t **mFrameData;
|
uint8_t **mFrameData;
|
||||||
int mDataBufLen;
|
int mDataBufLen;
|
||||||
|
@ -44,8 +44,8 @@ namespace MWSound
|
|||||||
|
|
||||||
size_t getSampleOffset()
|
size_t getSampleOffset()
|
||||||
{
|
{
|
||||||
ssize_t clock_delay = (mFrameSize-mFramePos) / mAVStream->codec->channels /
|
ssize_t clock_delay = (mFrameSize-mFramePos) / av_get_channel_layout_nb_channels(mOutputChannelLayout) /
|
||||||
av_get_bytes_per_sample(mAVStream->codec->sample_fmt);
|
av_get_bytes_per_sample(mOutputSampleFormat);
|
||||||
return (size_t)(mAudioClock*mAVStream->codec->sample_rate) - clock_delay;
|
return (size_t)(mAudioClock*mAVStream->codec->sample_rate) - clock_delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,20 +64,20 @@ namespace MWSound
|
|||||||
|
|
||||||
virtual void adjustAudioSettings(AVSampleFormat& sampleFormat, uint64_t& channelLayout, int& sampleRate)
|
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;
|
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;
|
sampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
else if (sampleFormat == AV_SAMPLE_FMT_FLTP)
|
else if (sampleFormat == AV_SAMPLE_FMT_FLTP || sampleFormat == AV_SAMPLE_FMT_FLT)
|
||||||
sampleFormat = AV_SAMPLE_FMT_FLT;
|
sampleFormat = AV_SAMPLE_FMT_S16; // FIXME: check for AL_EXT_FLOAT32 support
|
||||||
else
|
else
|
||||||
sampleFormat = AV_SAMPLE_FMT_FLT;
|
sampleFormat = AV_SAMPLE_FMT_S16;
|
||||||
|
|
||||||
if (channelLayout != AV_CH_LAYOUT_MONO
|
if (channelLayout == AV_CH_LAYOUT_5POINT1 || channelLayout == AV_CH_LAYOUT_7POINT1
|
||||||
&& channelLayout != AV_CH_LAYOUT_5POINT1
|
|| channelLayout == AV_CH_LAYOUT_QUAD) // FIXME: check for AL_EXT_MCFORMATS support
|
||||||
&& channelLayout != AV_CH_LAYOUT_7POINT1
|
channelLayout = AV_CH_LAYOUT_STEREO;
|
||||||
&& channelLayout != AV_CH_LAYOUT_STEREO
|
else if (channelLayout != AV_CH_LAYOUT_MONO
|
||||||
&& channelLayout != AV_CH_LAYOUT_QUAD)
|
&& channelLayout != AV_CH_LAYOUT_STEREO)
|
||||||
channelLayout = AV_CH_LAYOUT_STEREO;
|
channelLayout = AV_CH_LAYOUT_STEREO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +149,17 @@ namespace MWWorld
|
|||||||
forEachImp (functor, mCreatureLists);
|
forEachImp (functor, mCreatureLists);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Functor>
|
||||||
|
bool forEachContainer (Functor& functor)
|
||||||
|
{
|
||||||
|
mHasState = true;
|
||||||
|
|
||||||
|
return
|
||||||
|
forEachImp (functor, mContainers) &&
|
||||||
|
forEachImp (functor, mCreatures) &&
|
||||||
|
forEachImp (functor, mNpcs);
|
||||||
|
}
|
||||||
|
|
||||||
bool isExterior() const;
|
bool isExterior() const;
|
||||||
|
|
||||||
Ptr searchInContainer (const std::string& id);
|
Ptr searchInContainer (const std::string& id);
|
||||||
|
@ -272,7 +272,7 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
|
|||||||
item.mCell = actorPtr.getCell();
|
item.mCell = actorPtr.getCell();
|
||||||
}
|
}
|
||||||
|
|
||||||
item.mContainerStore = 0;
|
item.mContainerStore = this;
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item);
|
MWBase::Environment::get().getWorld()->getLocalScripts().add(script, item);
|
||||||
|
|
||||||
|
@ -657,6 +657,47 @@ namespace MWWorld
|
|||||||
return mWorldScene->searchPtrViaActorId (actorId);
|
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)
|
void World::addContainerScripts(const Ptr& reference, CellStore * cell)
|
||||||
{
|
{
|
||||||
if( reference.getTypeName()==typeid (ESM::Container).name() ||
|
if( reference.getTypeName()==typeid (ESM::Container).name() ||
|
||||||
|
@ -260,6 +260,10 @@ namespace MWWorld
|
|||||||
virtual Ptr searchPtrViaActorId (int actorId);
|
virtual Ptr searchPtrViaActorId (int actorId);
|
||||||
///< Search is limited to the active cells.
|
///< 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);
|
virtual void adjustPosition (const Ptr& ptr, bool force);
|
||||||
///< Adjust position after load to be on ground. Must be called after model load.
|
///< Adjust position after load to be on ground. Must be called after model load.
|
||||||
/// @param force do this even if the ptr is flying
|
/// @param force do this even if the ptr is flying
|
||||||
|
@ -382,7 +382,6 @@ endmacro()
|
|||||||
ogre_find_component(Paging OgrePaging.h)
|
ogre_find_component(Paging OgrePaging.h)
|
||||||
# look for Overlay component
|
# look for Overlay component
|
||||||
ogre_find_component(Overlay OgreOverlaySystem.h)
|
ogre_find_component(Overlay OgreOverlaySystem.h)
|
||||||
ogre_find_component(Overlay OgreOverlay.h)
|
|
||||||
# look for Terrain component
|
# look for Terrain component
|
||||||
ogre_find_component(Terrain OgreTerrain.h)
|
ogre_find_component(Terrain OgreTerrain.h)
|
||||||
# look for Property component
|
# look for Property component
|
||||||
|
15
extern/ogre-ffmpeg-videoplayer/CMakeLists.txt
vendored
15
extern/ogre-ffmpeg-videoplayer/CMakeLists.txt
vendored
@ -3,15 +3,14 @@ set(OGRE_FFMPEG_VIDEOPLAYER_LIBRARY "ogre-ffmpeg-videoplayer")
|
|||||||
# Sources
|
# Sources
|
||||||
|
|
||||||
set(OGRE_FFMPEG_VIDEOPLAYER_SOURCE_FILES
|
set(OGRE_FFMPEG_VIDEOPLAYER_SOURCE_FILES
|
||||||
videoplayer.cpp
|
videoplayer.cpp
|
||||||
videostate.cpp
|
videostate.cpp
|
||||||
videodefs.hpp
|
videodefs.hpp
|
||||||
libavwrapper.cpp
|
libavwrapper.cpp
|
||||||
audiodecoder.cpp
|
audiodecoder.cpp
|
||||||
audiofactory.hpp
|
audiofactory.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Find FFMPEG
|
# Find FFMPEG
|
||||||
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
|
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
|
||||||
unset(FFMPEG_LIBRARIES CACHE)
|
unset(FFMPEG_LIBRARIES CACHE)
|
||||||
@ -30,10 +29,14 @@ else()
|
|||||||
message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).")
|
message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(${FFMPEG_INCLUDE_DIRS})
|
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})
|
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})
|
link_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
40
extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp
vendored
40
extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp
vendored
@ -152,8 +152,8 @@ int MovieAudioDecoder::synchronize_audio()
|
|||||||
double avg_diff = mAudioDiffAccum * (1.0 - mAudioDiffAvgCoef);
|
double avg_diff = mAudioDiffAccum * (1.0 - mAudioDiffAvgCoef);
|
||||||
if(fabs(avg_diff) >= mAudioDiffThreshold)
|
if(fabs(avg_diff) >= mAudioDiffThreshold)
|
||||||
{
|
{
|
||||||
int n = av_get_bytes_per_sample(mAVStream->codec->sample_fmt) *
|
int n = av_get_bytes_per_sample(mOutputSampleFormat) *
|
||||||
mAVStream->codec->channels;
|
av_get_channel_layout_nb_channels(mOutputChannelLayout);
|
||||||
sample_skip = ((int)(diff * mAVStream->codec->sample_rate) * n);
|
sample_skip = ((int)(diff * mAVStream->codec->sample_rate) * n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ int MovieAudioDecoder::synchronize_audio()
|
|||||||
return sample_skip;
|
return sample_skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MovieAudioDecoder::audio_decode_frame(AVFrame *frame)
|
int MovieAudioDecoder::audio_decode_frame(AVFrame *frame, int &sample_skip)
|
||||||
{
|
{
|
||||||
AVPacket *pkt = &mPacket;
|
AVPacket *pkt = &mPacket;
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ int MovieAudioDecoder::audio_decode_frame(AVFrame *frame)
|
|||||||
if(!mDataBuf || mDataBufLen < frame->nb_samples)
|
if(!mDataBuf || mDataBufLen < frame->nb_samples)
|
||||||
{
|
{
|
||||||
av_freep(&mDataBuf);
|
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)
|
frame->nb_samples, mOutputSampleFormat, 0) < 0)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
@ -212,8 +212,8 @@ int MovieAudioDecoder::audio_decode_frame(AVFrame *frame)
|
|||||||
(double)mAVStream->codec->sample_rate;
|
(double)mAVStream->codec->sample_rate;
|
||||||
|
|
||||||
/* We have data, return it and come back for more later */
|
/* We have data, return it and come back for more later */
|
||||||
return frame->nb_samples * mAVStream->codec->channels *
|
return frame->nb_samples * av_get_channel_layout_nb_channels(mOutputChannelLayout) *
|
||||||
av_get_bytes_per_sample(mAVStream->codec->sample_fmt);
|
av_get_bytes_per_sample(mOutputSampleFormat);
|
||||||
}
|
}
|
||||||
av_free_packet(pkt);
|
av_free_packet(pkt);
|
||||||
|
|
||||||
@ -221,6 +221,18 @@ int MovieAudioDecoder::audio_decode_frame(AVFrame *frame)
|
|||||||
if(mVideoState->audioq.get(pkt, mVideoState) < 0)
|
if(mVideoState->audioq.get(pkt, mVideoState) < 0)
|
||||||
return -1;
|
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 update, update the audio clock w/pts */
|
||||||
if((uint64_t)pkt->pts != AV_NOPTS_VALUE)
|
if((uint64_t)pkt->pts != AV_NOPTS_VALUE)
|
||||||
mAudioClock = av_q2d(mAVStream->time_base)*pkt->pts;
|
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)
|
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();
|
int sample_skip = synchronize_audio();
|
||||||
size_t total = 0;
|
size_t total = 0;
|
||||||
|
|
||||||
@ -237,7 +259,7 @@ size_t MovieAudioDecoder::read(char *stream, size_t len)
|
|||||||
if(mFramePos >= mFrameSize)
|
if(mFramePos >= mFrameSize)
|
||||||
{
|
{
|
||||||
/* We have already sent all our data; get more */
|
/* 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(mFrameSize < 0)
|
||||||
{
|
{
|
||||||
/* If error, we're done */
|
/* If error, we're done */
|
||||||
@ -260,8 +282,8 @@ size_t MovieAudioDecoder::read(char *stream, size_t len)
|
|||||||
{
|
{
|
||||||
len1 = std::min<size_t>(len1, -mFramePos);
|
len1 = std::min<size_t>(len1, -mFramePos);
|
||||||
|
|
||||||
int n = av_get_bytes_per_sample(mAVStream->codec->sample_fmt) *
|
int n = av_get_bytes_per_sample(mOutputSampleFormat)
|
||||||
mAVStream->codec->channels;
|
* av_get_channel_layout_nb_channels(mOutputChannelLayout);
|
||||||
|
|
||||||
/* add samples by copying the first sample*/
|
/* add samples by copying the first sample*/
|
||||||
if(n == 1)
|
if(n == 1)
|
||||||
|
@ -77,7 +77,8 @@ private:
|
|||||||
* skip (negative means to duplicate). */
|
* skip (negative means to duplicate). */
|
||||||
int synchronize_audio();
|
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:
|
public:
|
||||||
MovieAudioDecoder(VideoState *is);
|
MovieAudioDecoder(VideoState *is);
|
||||||
@ -101,6 +102,8 @@ public:
|
|||||||
virtual double getAudioClock();
|
virtual double getAudioClock();
|
||||||
|
|
||||||
/// This is the main interface to be used by the user's audio library.
|
/// 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);
|
size_t read(char *stream, size_t len);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ class MovieAudioFactory
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual boost::shared_ptr<MovieAudioDecoder> createDecoder(VideoState* videoState) = 0;
|
virtual boost::shared_ptr<MovieAudioDecoder> createDecoder(VideoState* videoState) = 0;
|
||||||
|
virtual ~MovieAudioFactory() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
66
extern/ogre-ffmpeg-videoplayer/videoplayer.cpp
vendored
66
extern/ogre-ffmpeg-videoplayer/videoplayer.cpp
vendored
@ -1,5 +1,6 @@
|
|||||||
#include "videoplayer.hpp"
|
#include "videoplayer.hpp"
|
||||||
|
|
||||||
|
#include "audiofactory.hpp"
|
||||||
#include "videostate.hpp"
|
#include "videostate.hpp"
|
||||||
|
|
||||||
namespace Video
|
namespace Video
|
||||||
@ -31,6 +32,13 @@ void VideoPlayer::playVideo(const std::string &resourceName)
|
|||||||
mState = new VideoState;
|
mState = new VideoState;
|
||||||
mState->setAudioFactory(mAudioFactory.get());
|
mState->setAudioFactory(mAudioFactory.get());
|
||||||
mState->init(resourceName);
|
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) {
|
catch(std::exception& e) {
|
||||||
std::cerr<< "Failed to play video: "<<e.what() <<std::endl;
|
std::cerr<< "Failed to play video: "<<e.what() <<std::endl;
|
||||||
@ -38,19 +46,17 @@ void VideoPlayer::playVideo(const std::string &resourceName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoPlayer::update ()
|
bool VideoPlayer::update ()
|
||||||
{
|
{
|
||||||
if(mState)
|
if(mState)
|
||||||
{
|
return mState->update();
|
||||||
if(!mState->update())
|
return false;
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string VideoPlayer::getTextureName()
|
std::string VideoPlayer::getTextureName()
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
if (mState)
|
if (mState && !mState->mTexture.isNull())
|
||||||
name = mState->mTexture->getName();
|
name = mState->mTexture->getName();
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@ -58,7 +64,7 @@ std::string VideoPlayer::getTextureName()
|
|||||||
int VideoPlayer::getVideoWidth()
|
int VideoPlayer::getVideoWidth()
|
||||||
{
|
{
|
||||||
int width=0;
|
int width=0;
|
||||||
if (mState)
|
if (mState && !mState->mTexture.isNull())
|
||||||
width = mState->mTexture->getWidth();
|
width = mState->mTexture->getWidth();
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
@ -66,7 +72,7 @@ int VideoPlayer::getVideoWidth()
|
|||||||
int VideoPlayer::getVideoHeight()
|
int VideoPlayer::getVideoHeight()
|
||||||
{
|
{
|
||||||
int height=0;
|
int height=0;
|
||||||
if (mState)
|
if (mState && !mState->mTexture.isNull())
|
||||||
height = mState->mTexture->getHeight();
|
height = mState->mTexture->getHeight();
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
@ -82,14 +88,48 @@ void VideoPlayer::close()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VideoPlayer::isPlaying ()
|
|
||||||
{
|
|
||||||
return mState != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VideoPlayer::hasAudioStream()
|
bool VideoPlayer::hasAudioStream()
|
||||||
{
|
{
|
||||||
return mState && mState->audio_st != NULL;
|
return mState && mState->audio_st != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoPlayer::play()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
19
extern/ogre-ffmpeg-videoplayer/videoplayer.hpp
vendored
19
extern/ogre-ffmpeg-videoplayer/videoplayer.hpp
vendored
@ -29,16 +29,29 @@ namespace Video
|
|||||||
bool hasAudioStream();
|
bool hasAudioStream();
|
||||||
|
|
||||||
/// Play the given video. If a video is already playing, the old video is closed first.
|
/// 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);
|
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.
|
/// 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.
|
/// Stop the currently playing video, if a video is playing.
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
bool isPlaying();
|
|
||||||
|
|
||||||
/// Return the texture name of the currently playing video, or "" if no video is playing.
|
/// Return the texture name of the currently playing video, or "" if no video is playing.
|
||||||
std::string getTextureName();
|
std::string getTextureName();
|
||||||
/// Return the width of the currently playing video, or 0 if no video is playing.
|
/// Return the width of the currently playing video, or 0 if no video is playing.
|
||||||
|
261
extern/ogre-ffmpeg-videoplayer/videostate.cpp
vendored
261
extern/ogre-ffmpeg-videoplayer/videostate.cpp
vendored
@ -25,12 +25,26 @@ extern "C"
|
|||||||
#include <libavutil/time.h>
|
#include <libavutil/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <libavutil/mathematics.h>
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
|
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
|
||||||
#define av_frame_alloc avcodec_alloc_frame
|
#define av_frame_alloc avcodec_alloc_frame
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* flushString = "FLUSH";
|
||||||
|
struct FlushPacket : AVPacket
|
||||||
|
{
|
||||||
|
FlushPacket()
|
||||||
|
: AVPacket()
|
||||||
|
{
|
||||||
|
data = ( (uint8_t*)flushString);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static FlushPacket flush_pkt;
|
||||||
|
|
||||||
#include "videoplayer.hpp"
|
#include "videoplayer.hpp"
|
||||||
#include "audiodecoder.hpp"
|
#include "audiodecoder.hpp"
|
||||||
#include "audiofactory.hpp"
|
#include "audiofactory.hpp"
|
||||||
@ -46,14 +60,18 @@ namespace Video
|
|||||||
|
|
||||||
VideoState::VideoState()
|
VideoState::VideoState()
|
||||||
: format_ctx(NULL), av_sync_type(AV_SYNC_DEFAULT)
|
: format_ctx(NULL), av_sync_type(AV_SYNC_DEFAULT)
|
||||||
, external_clock_base(0.0)
|
|
||||||
, audio_st(NULL)
|
, audio_st(NULL)
|
||||||
, video_st(NULL), frame_last_pts(0.0)
|
, video_st(NULL), frame_last_pts(0.0)
|
||||||
, video_clock(0.0), sws_context(NULL), rgbaFrame(NULL), pictq_size(0)
|
, video_clock(0.0), sws_context(NULL), rgbaFrame(NULL), pictq_size(0)
|
||||||
, pictq_rindex(0), pictq_windex(0)
|
, pictq_rindex(0), pictq_windex(0)
|
||||||
, quit(false)
|
, mQuit(false), mPaused(false)
|
||||||
, mAudioFactory(NULL)
|
, mAudioFactory(NULL)
|
||||||
|
, mSeekRequested(false)
|
||||||
|
, mSeekPos(0)
|
||||||
|
, mVideoEnded(false)
|
||||||
{
|
{
|
||||||
|
mFlushPktData = flush_pkt.data;
|
||||||
|
|
||||||
// Register all formats and codecs
|
// Register all formats and codecs
|
||||||
av_register_all();
|
av_register_all();
|
||||||
}
|
}
|
||||||
@ -77,7 +95,7 @@ void PacketQueue::put(AVPacket *pkt)
|
|||||||
pkt1->pkt = *pkt;
|
pkt1->pkt = *pkt;
|
||||||
pkt1->next = NULL;
|
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)
|
if(av_dup_packet(&pkt1->pkt) < 0)
|
||||||
{
|
{
|
||||||
@ -104,7 +122,7 @@ void PacketQueue::put(AVPacket *pkt)
|
|||||||
int PacketQueue::get(AVPacket *pkt, VideoState *is)
|
int PacketQueue::get(AVPacket *pkt, VideoState *is)
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(this->mutex);
|
boost::unique_lock<boost::mutex> lock(this->mutex);
|
||||||
while(!is->quit)
|
while(!is->mQuit)
|
||||||
{
|
{
|
||||||
AVPacketList *pkt1 = this->first_pkt;
|
AVPacketList *pkt1 = this->first_pkt;
|
||||||
if(pkt1)
|
if(pkt1)
|
||||||
@ -143,7 +161,8 @@ void PacketQueue::clear()
|
|||||||
for(pkt = this->first_pkt; pkt != NULL; pkt = pkt1)
|
for(pkt = this->first_pkt; pkt != NULL; pkt = pkt1)
|
||||||
{
|
{
|
||||||
pkt1 = pkt->next;
|
pkt1 = pkt->next;
|
||||||
av_free_packet(&pkt->pkt);
|
if (pkt->pkt.data != flush_pkt.data)
|
||||||
|
av_free_packet(&pkt->pkt);
|
||||||
av_freep(&pkt);
|
av_freep(&pkt);
|
||||||
}
|
}
|
||||||
this->last_pkt = NULL;
|
this->last_pkt = NULL;
|
||||||
@ -188,14 +207,17 @@ void VideoState::video_display(VideoPicture *vp)
|
|||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
if (mTexture.isNull())
|
||||||
if(static_cast<int>(mTexture->getWidth()) != (*this->video_st)->codec->width ||
|
|
||||||
static_cast<int>(mTexture->getHeight()) != (*this->video_st)->codec->height)
|
|
||||||
{
|
{
|
||||||
mTexture->unload();
|
static int i = 0;
|
||||||
mTexture->setWidth((*this->video_st)->codec->width);
|
mTexture = Ogre::TextureManager::getSingleton().createManual(
|
||||||
mTexture->setHeight((*this->video_st)->codec->height);
|
"ffmpeg/VideoTexture" + Ogre::StringConverter::toString(++i),
|
||||||
mTexture->createInternalResources();
|
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::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();
|
Ogre::HardwarePixelBufferSharedPtr buffer = mTexture->getBuffer();
|
||||||
@ -205,6 +227,7 @@ void VideoState::video_display(VideoPicture *vp)
|
|||||||
|
|
||||||
void VideoState::video_refresh()
|
void VideoState::video_refresh()
|
||||||
{
|
{
|
||||||
|
boost::mutex::scoped_lock lock(this->pictq_mutex);
|
||||||
if(this->pictq_size == 0)
|
if(this->pictq_size == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -212,16 +235,15 @@ void VideoState::video_refresh()
|
|||||||
{
|
{
|
||||||
VideoPicture* vp = &this->pictq[this->pictq_rindex];
|
VideoPicture* vp = &this->pictq[this->pictq_rindex];
|
||||||
this->video_display(vp);
|
this->video_display(vp);
|
||||||
|
|
||||||
this->pictq_rindex = (pictq_rindex+1) % VIDEO_PICTURE_QUEUE_SIZE;
|
this->pictq_rindex = (pictq_rindex+1) % VIDEO_PICTURE_QUEUE_SIZE;
|
||||||
this->frame_last_pts = vp->pts;
|
this->frame_last_pts = vp->pts;
|
||||||
this->pictq_mutex.lock();
|
|
||||||
this->pictq_size--;
|
this->pictq_size--;
|
||||||
this->pictq_cond.notify_one();
|
this->pictq_cond.notify_one();
|
||||||
this->pictq_mutex.unlock();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const float threshold = 0.03;
|
const float threshold = 0.03f;
|
||||||
if (this->pictq[pictq_rindex].pts > this->get_master_clock() + threshold)
|
if (this->pictq[pictq_rindex].pts > this->get_master_clock() + threshold)
|
||||||
return; // not ready yet to show this picture
|
return; // not ready yet to show this picture
|
||||||
|
|
||||||
@ -236,19 +258,18 @@ void VideoState::video_refresh()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert (this->pictq_rindex < VIDEO_PICTURE_QUEUE_SIZE);
|
||||||
VideoPicture* vp = &this->pictq[this->pictq_rindex];
|
VideoPicture* vp = &this->pictq[this->pictq_rindex];
|
||||||
|
|
||||||
this->video_display(vp);
|
this->video_display(vp);
|
||||||
|
|
||||||
this->frame_last_pts = vp->pts;
|
this->frame_last_pts = vp->pts;
|
||||||
|
|
||||||
this->pictq_mutex.lock();
|
|
||||||
this->pictq_size -= i;
|
this->pictq_size -= i;
|
||||||
// update queue for next picture
|
// update queue for next picture
|
||||||
this->pictq_size--;
|
this->pictq_size--;
|
||||||
this->pictq_rindex++;
|
this->pictq_rindex = (this->pictq_rindex+1) % VIDEO_PICTURE_QUEUE_SIZE;
|
||||||
this->pictq_cond.notify_one();
|
this->pictq_cond.notify_one();
|
||||||
this->pictq_mutex.unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,12 +281,14 @@ int VideoState::queue_picture(AVFrame *pFrame, double pts)
|
|||||||
/* wait until we have a new pic */
|
/* wait until we have a new pic */
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(this->pictq_mutex);
|
boost::unique_lock<boost::mutex> 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));
|
this->pictq_cond.timed_wait(lock, boost::posix_time::milliseconds(1));
|
||||||
}
|
}
|
||||||
if(this->quit)
|
if(this->mQuit)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
this->pictq_mutex.lock();
|
||||||
|
|
||||||
// windex is set to 0 initially
|
// windex is set to 0 initially
|
||||||
vp = &this->pictq[this->pictq_windex];
|
vp = &this->pictq[this->pictq_windex];
|
||||||
|
|
||||||
@ -292,7 +315,6 @@ int VideoState::queue_picture(AVFrame *pFrame, double pts)
|
|||||||
|
|
||||||
// now we inform our display thread that we have a pic ready
|
// 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_windex = (this->pictq_windex+1) % VIDEO_PICTURE_QUEUE_SIZE;
|
||||||
this->pictq_mutex.lock();
|
|
||||||
this->pictq_size++;
|
this->pictq_size++;
|
||||||
this->pictq_mutex.unlock();
|
this->pictq_mutex.unlock();
|
||||||
|
|
||||||
@ -353,6 +375,21 @@ void VideoState::video_thread_loop(VideoState *self)
|
|||||||
|
|
||||||
while(self->videoq.get(packet, self) >= 0)
|
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
|
// Save global pts to be stored in pFrame
|
||||||
global_video_pkt_pts = packet->pts;
|
global_video_pkt_pts = packet->pts;
|
||||||
// Decode video frame
|
// Decode video frame
|
||||||
@ -394,8 +431,67 @@ void VideoState::decode_thread_loop(VideoState *self)
|
|||||||
throw std::runtime_error("No streams to decode");
|
throw std::runtime_error("No streams to decode");
|
||||||
|
|
||||||
// main decode loop
|
// 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) ||
|
if((self->audio_st && self->audioq.size > MAX_AUDIOQ_SIZE) ||
|
||||||
(self->video_st && self->videoq.size > MAX_VIDEOQ_SIZE))
|
(self->video_st && self->videoq.size > MAX_VIDEOQ_SIZE))
|
||||||
{
|
{
|
||||||
@ -404,7 +500,13 @@ void VideoState::decode_thread_loop(VideoState *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(av_read_frame(pFormatCtx, packet) < 0)
|
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?
|
// Is this a packet from the video stream?
|
||||||
if(self->video_st && packet->stream_index == self->video_st-pFormatCtx->streams)
|
if(self->video_st && packet->stream_index == self->video_st-pFormatCtx->streams)
|
||||||
@ -414,17 +516,6 @@ void VideoState::decode_thread_loop(VideoState *self)
|
|||||||
else
|
else
|
||||||
av_free_packet(packet);
|
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) {
|
catch(std::runtime_error& e) {
|
||||||
std::cerr << "An error occured playing the video: " << e.what () << std::endl;
|
std::cerr << "An error occured playing the video: " << e.what () << std::endl;
|
||||||
@ -433,17 +524,14 @@ void VideoState::decode_thread_loop(VideoState *self)
|
|||||||
std::cerr << "An error occured playing the video: " << e.getFullDescription () << std::endl;
|
std::cerr << "An error occured playing the video: " << e.getFullDescription () << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->quit = true;
|
self->mQuit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool VideoState::update()
|
bool VideoState::update()
|
||||||
{
|
{
|
||||||
if(this->quit)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
this->video_refresh();
|
this->video_refresh();
|
||||||
return true;
|
return !this->mVideoEnded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -510,7 +598,7 @@ void VideoState::init(const std::string& resourceName)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
this->av_sync_type = AV_SYNC_DEFAULT;
|
this->av_sync_type = AV_SYNC_DEFAULT;
|
||||||
this->quit = false;
|
this->mQuit = false;
|
||||||
|
|
||||||
this->stream = Ogre::ResourceGroupManager::getSingleton().openResource(resourceName);
|
this->stream = Ogre::ResourceGroupManager::getSingleton().openResource(resourceName);
|
||||||
if(this->stream.isNull())
|
if(this->stream.isNull())
|
||||||
@ -564,7 +652,7 @@ void VideoState::init(const std::string& resourceName)
|
|||||||
audio_index = i;
|
audio_index = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->external_clock_base = av_gettime();
|
mExternalClock.set(0);
|
||||||
|
|
||||||
if(audio_index >= 0)
|
if(audio_index >= 0)
|
||||||
this->stream_open(audio_index, this->format_ctx);
|
this->stream_open(audio_index, this->format_ctx);
|
||||||
@ -572,24 +660,6 @@ void VideoState::init(const std::string& resourceName)
|
|||||||
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(
|
|
||||||
"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<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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -598,13 +668,13 @@ void VideoState::init(const std::string& resourceName)
|
|||||||
|
|
||||||
void VideoState::deinit()
|
void VideoState::deinit()
|
||||||
{
|
{
|
||||||
this->quit = true;
|
this->mQuit = true;
|
||||||
|
|
||||||
|
this->audioq.flush();
|
||||||
|
this->videoq.flush();
|
||||||
|
|
||||||
mAudioDecoder.reset();
|
mAudioDecoder.reset();
|
||||||
|
|
||||||
this->audioq.cond.notify_one();
|
|
||||||
this->videoq.cond.notify_one();
|
|
||||||
|
|
||||||
if (this->parse_thread.joinable())
|
if (this->parse_thread.joinable())
|
||||||
this->parse_thread.join();
|
this->parse_thread.join();
|
||||||
if (this->video_thread.joinable())
|
if (this->video_thread.joinable())
|
||||||
@ -639,11 +709,17 @@ void VideoState::deinit()
|
|||||||
}
|
}
|
||||||
avformat_close_input(&this->format_ctx);
|
avformat_close_input(&this->format_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mTexture.isNull())
|
||||||
|
{
|
||||||
|
Ogre::TextureManager::getSingleton().remove(mTexture->getName());
|
||||||
|
mTexture.setNull();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double VideoState::get_external_clock()
|
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()
|
double VideoState::get_master_clock()
|
||||||
@ -667,5 +743,62 @@ double VideoState::get_audio_clock()
|
|||||||
return mAudioDecoder->getAudioClock();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
extern/ogre-ffmpeg-videoplayer/videostate.hpp
vendored
33
extern/ogre-ffmpeg-videoplayer/videostate.hpp
vendored
@ -27,6 +27,21 @@ struct VideoState;
|
|||||||
class MovieAudioFactory;
|
class MovieAudioFactory;
|
||||||
class MovieAudioDecoder;
|
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 {
|
struct PacketQueue {
|
||||||
PacketQueue()
|
PacketQueue()
|
||||||
: first_pkt(NULL), last_pkt(NULL), flushing(false), nb_packets(0), size(0)
|
: 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 init(const std::string& resourceName);
|
||||||
void deinit();
|
void deinit();
|
||||||
|
|
||||||
|
void setPaused(bool isPaused);
|
||||||
|
void seekTo(double time);
|
||||||
|
|
||||||
|
double getDuration();
|
||||||
|
|
||||||
int stream_open(int stream_index, AVFormatContext *pFormatCtx);
|
int stream_open(int stream_index, AVFormatContext *pFormatCtx);
|
||||||
|
|
||||||
bool update();
|
bool update();
|
||||||
@ -93,15 +113,18 @@ struct VideoState {
|
|||||||
MovieAudioFactory* mAudioFactory;
|
MovieAudioFactory* mAudioFactory;
|
||||||
boost::shared_ptr<MovieAudioDecoder> mAudioDecoder;
|
boost::shared_ptr<MovieAudioDecoder> mAudioDecoder;
|
||||||
|
|
||||||
|
ExternalClock mExternalClock;
|
||||||
|
|
||||||
Ogre::DataStreamPtr stream;
|
Ogre::DataStreamPtr stream;
|
||||||
AVFormatContext* format_ctx;
|
AVFormatContext* format_ctx;
|
||||||
|
|
||||||
int av_sync_type;
|
int av_sync_type;
|
||||||
uint64_t external_clock_base;
|
|
||||||
|
|
||||||
AVStream** audio_st;
|
AVStream** audio_st;
|
||||||
PacketQueue audioq;
|
PacketQueue audioq;
|
||||||
|
|
||||||
|
uint8_t* mFlushPktData;
|
||||||
|
|
||||||
AVStream** video_st;
|
AVStream** video_st;
|
||||||
double frame_last_pts;
|
double frame_last_pts;
|
||||||
double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
|
double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
|
||||||
@ -113,11 +136,15 @@ struct VideoState {
|
|||||||
boost::mutex pictq_mutex;
|
boost::mutex pictq_mutex;
|
||||||
boost::condition_variable pictq_cond;
|
boost::condition_variable pictq_cond;
|
||||||
|
|
||||||
|
|
||||||
boost::thread parse_thread;
|
boost::thread parse_thread;
|
||||||
boost::thread video_thread;
|
boost::thread video_thread;
|
||||||
|
|
||||||
volatile bool quit;
|
volatile bool mSeekRequested;
|
||||||
|
uint64_t mSeekPos;
|
||||||
|
|
||||||
|
volatile bool mVideoEnded;
|
||||||
|
volatile bool mPaused;
|
||||||
|
volatile bool mQuit;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
@version 120
|
@version 120
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SH_GLSLES == 1 && SH_FRAGMENT_SHADER
|
#if SH_GLSLES == 1
|
||||||
precision mediump int;
|
precision mediump int;
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
#endif
|
#endif
|
||||||
|
@ -499,7 +499,7 @@
|
|||||||
|
|
||||||
#if SHADOWS || SHADOWS_PSSM
|
#if SHADOWS || SHADOWS_PSSM
|
||||||
float fadeRange = shadowFar_fadeStart.x - shadowFar_fadeStart.y;
|
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);
|
shadow = (depthPassthrough > shadowFar_fadeStart.x) ? 1.0 : ((depthPassthrough > shadowFar_fadeStart.y) ? 1.0-((1.0-shadow)*fade) : shadow);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -514,11 +514,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if UNDERWATER
|
#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
|
#endif
|
||||||
|
|
||||||
#if SHADOWS || SHADOWS_PSSM
|
#if SHADOWS || SHADOWS_PSSM
|
||||||
shOutputColour(0) *= (lightResult - float4(directionalResult * (1.0-shadow),0));
|
shOutputColour(0) *= (lightResult - float4(directionalResult * (1.0-shadow),0.0));
|
||||||
#else
|
#else
|
||||||
shOutputColour(0) *= lightResult;
|
shOutputColour(0) *= lightResult;
|
||||||
#endif
|
#endif
|
||||||
@ -574,7 +574,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// prevent negative colour output (for example with negative lights)
|
// 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
|
#endif
|
||||||
|
@ -6,11 +6,11 @@ float depthShadowPCF (shTexture2D shadowMap, float4 shadowMapPos, float2 offset)
|
|||||||
shadowMapPos /= shadowMapPos.w;
|
shadowMapPos /= shadowMapPos.w;
|
||||||
float3 o = float3(offset.xy, -offset.x) * 0.3;
|
float3 o = float3(offset.xy, -offset.x) * 0.3;
|
||||||
//float3 o = float3(0,0,0);
|
//float3 o = float3(0,0,0);
|
||||||
float c = (shadowMapPos.z <= FIXED_BIAS + shSample(shadowMap, shadowMapPos.xy - o.xy).r) ? 1 : 0; // top left
|
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; // bottom right
|
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; // bottom left
|
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; // top right
|
c += (shadowMapPos.z <= FIXED_BIAS + shSample(shadowMap, shadowMapPos.xy - o.zy).r) ? 1.0 : 0.0; // top right
|
||||||
return c / 4;
|
return c / 4.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,47 +2,51 @@
|
|||||||
|
|
||||||
<MyGUI type="Layout">
|
<MyGUI type="Layout">
|
||||||
|
|
||||||
<Widget type="Window" skin="" layer="Windows" align="Left|Top" position="0 0 565 390" name="_Main">
|
<Widget type="Window" skin="" layer="Windows" align="Left Top" position="0 0 584 398" name="_Main">
|
||||||
|
|
||||||
<Widget type="ImageBox" skin="ImageBox" position="-70 0 705 390" align="Top|Right" name="JImage">
|
<Widget type="ImageBox" skin="ImageBox" position="-71 0 728 398" align="Left Top" name="JImage">
|
||||||
<Property key="ImageTexture" value="textures\tx_menubook.dds"/>
|
<Property key="ImageTexture" value="textures\tx_menubook.dds"/>
|
||||||
<Widget type="Widget" position="70 0 565 390" align="Top|Right">
|
<Widget type="Widget" position="71 0 584 398" align="Left Top">
|
||||||
|
|
||||||
<Widget type="Widget" position="0 0 282 390">
|
<Widget type="Widget" position="0 0 292 398">
|
||||||
<Widget type="ImageButton" skin="ImageBox" position="205 350 48 32" name="PrevPageBTN">
|
<Widget type="ImageButton" skin="ImageBox" position="205 358 48 32" name="PrevPageBTN">
|
||||||
<Property key="ImageHighlighted" value="textures\tx_menubook_prev_over.dds"/>
|
<Property key="ImageHighlighted" value="textures\tx_menubook_prev_over.dds"/>
|
||||||
<Property key="ImageNormal" value="textures\tx_menubook_prev_idle.dds"/>
|
<Property key="ImageNormal" value="textures\tx_menubook_prev_idle.dds"/>
|
||||||
<Property key="ImagePushed" value="textures\tx_menubook_prev_pressed.dds"/>
|
<Property key="ImagePushed" value="textures\tx_menubook_prev_pressed.dds"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="Widget" position="282 0 282 390">
|
<Widget type="Widget" position="292 0 292 398">
|
||||||
<Widget type="ImageButton" skin="ImageBox" position="18 350 48 32" name="NextPageBTN">
|
<Widget type="ImageButton" skin="ImageBox" position="38 358 48 32" name="NextPageBTN">
|
||||||
<Property key="ImageHighlighted" value="textures\tx_menubook_next_over.dds"/>
|
<Property key="ImageHighlighted" value="textures\tx_menubook_next_over.dds"/>
|
||||||
<Property key="ImageNormal" value="textures\tx_menubook_next_idle.dds"/>
|
<Property key="ImageNormal" value="textures\tx_menubook_next_idle.dds"/>
|
||||||
<Property key="ImagePushed" value="textures\tx_menubook_next_pressed.dds"/>
|
<Property key="ImagePushed" value="textures\tx_menubook_next_pressed.dds"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="ImageButton" skin="ImageBox" position="40 350 64 32" name="TakeButton">
|
<Widget type="ImageButton" skin="ImageBox" position="40 358 64 32" name="TakeButton">
|
||||||
<Property key="ImageHighlighted" value="textures\tx_menubook_take_over.dds"/>
|
<Property key="ImageHighlighted" value="textures\tx_menubook_take_over.dds"/>
|
||||||
<Property key="ImageNormal" value="textures\tx_menubook_take_idle.dds"/>
|
<Property key="ImageNormal" value="textures\tx_menubook_take_idle.dds"/>
|
||||||
<Property key="ImagePushed" value="textures\tx_menubook_take_pressed.dds"/>
|
<Property key="ImagePushed" value="textures\tx_menubook_take_pressed.dds"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="ImageButton" skin="ImageBox" position="460 350 48 32" name="CloseButton">
|
<Widget type="ImageButton" skin="ImageBox" position="488 358 48 32" name="CloseButton">
|
||||||
<Property key="ImageHighlighted" value="textures\tx_menubook_close_over.dds"/>
|
<Property key="ImageHighlighted" value="textures\tx_menubook_close_over.dds"/>
|
||||||
<Property key="ImageNormal" value="textures\tx_menubook_close_idle.dds"/>
|
<Property key="ImageNormal" value="textures\tx_menubook_close_idle.dds"/>
|
||||||
<Property key="ImagePushed" value="textures\tx_menubook_close_pressed.dds"/>
|
<Property key="ImagePushed" value="textures\tx_menubook_close_pressed.dds"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="TextBox" skin="NormalText" position="150 350 32 16" name="LeftPageNumber">
|
<Widget type="TextBox" skin="NormalText" position="30 358 250 16" name="LeftPageNumber">
|
||||||
<Property key="TextColour" value="0 0 0"/>
|
<Property key="TextColour" value="0 0 0"/>
|
||||||
|
<Property key="TextAlign" value="Center"/>
|
||||||
|
<Property key="NeedMouse" value="false"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="TextBox" skin="NormalText" position="410 350 32 16" name="RightPageNumber">
|
<Widget type="TextBox" skin="NormalText" position="310 358 250 16" name="RightPageNumber">
|
||||||
<Property key="TextColour" value="0 0 0"/>
|
<Property key="TextColour" value="0 0 0"/>
|
||||||
|
<Property key="TextAlign" value="Center"/>
|
||||||
|
<Property key="NeedMouse" value="false"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="Widget" skin="" position="30 15 240 328" name="LeftPage"/>
|
<Widget type="Widget" skin="" position="30 15 250 328" name="LeftPage"/>
|
||||||
<Widget type="Widget" skin="" position="300 15 240 328" name="RightPage"/>
|
<Widget type="Widget" skin="" position="310 15 250 328" name="RightPage"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 498 198" name="_Main">
|
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 498 198" name="_Main">
|
||||||
|
|
||||||
<!-- Class name -->
|
<!-- Class name -->
|
||||||
<Widget type="TextBox" skin="NormalText" position="8 8 48 23" name="LabelT" align="Left Top">
|
<Widget type="TextBox" skin="NormalText" position="8 8 52 23" name="LabelT" align="Left Top">
|
||||||
<Property key="Caption" value="#{sName}:"/>
|
<Property key="Caption" value="#{sName}:"/>
|
||||||
<Property key="TextAlign" value="Left VCenter"/>
|
<Property key="TextAlign" value="Left VCenter"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
@ -69,33 +69,46 @@
|
|||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<!-- Player level, race and class -->
|
<!-- Player level, race and class -->
|
||||||
<Widget type="Widget" skin="MW_Box" position="8 78 212 62" align="Left Top HStretch">
|
<Widget type="Widget" skin="MW_Box" position="8 78 212 62" align="Top HStretch">
|
||||||
<Widget type="TextBox" skin="NormalText" position="4 4 100 18" name="Level_str" align="Left Top HStretch">
|
<Widget type="HBox" position="4 4 204 18" align="Top HStretch">
|
||||||
<Property key="Caption" value="#{sLevel}"/>
|
<Widget type="AutoSizedTextBox" skin="NormalText" position="0 0 200 18" name="Level_str" align="Left Top">
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
<Property key="Caption" value="#{sLevel}"/>
|
||||||
<UserString key="ToolTipLayout" value="LevelToolTip"/>
|
<UserString key="ToolTipType" value="Layout"/>
|
||||||
|
<UserString key="ToolTipLayout" value="LevelToolTip"/>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="TextBox" skin="SandTextRight" position="200 0 40 18" name="LevelText" align="Right Top">
|
||||||
|
<Property key="TextAlign" value="Right Top"/>
|
||||||
|
<UserString key="ToolTipType" value="Layout"/>
|
||||||
|
<UserString key="ToolTipLayout" value="LevelToolTip"/>
|
||||||
|
<UserString key="HStretch" value="true"/>
|
||||||
|
</Widget>
|
||||||
|
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="TextBox" skin="NormalText" position="4 22 100 18" name="Race_str" align="Left Top HStretch">
|
<Widget type="HBox" position="4 24 204 18" align="Top HStretch">
|
||||||
<Property key="Caption" value="#{sRace}"/>
|
<Widget type="AutoSizedTextBox" skin="NormalText" position="0 0 95 18" name="Race_str" align="Left Top">
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
<Property key="Caption" value="#{sRace}"/>
|
||||||
<UserString key="ToolTipLayout" value="TextWithCenteredCaptionToolTip"/>
|
<UserString key="ToolTipType" value="Layout"/>
|
||||||
|
<UserString key="ToolTipLayout" value="TextWithCenteredCaptionToolTip"/>
|
||||||
|
</Widget>
|
||||||
|
<Widget type="TextBox" skin="SandTextRight" position="104 0 200 18" name="RaceText" align="Left Top">
|
||||||
|
<Property key="TextAlign" value="Right Top"/>
|
||||||
|
<UserString key="ToolTipType" value="Layout"/>
|
||||||
|
<UserString key="ToolTipLayout" value="TextWithCenteredCaptionToolTip"/>
|
||||||
|
<UserString key="HStretch" value="true"/>
|
||||||
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
<Widget type="TextBox" skin="NormalText" position="4 40 100 18" name="Class_str" align="Left Top HStretch">
|
<Widget type="HBox" position="4 42 204 18" align="Top HStretch">
|
||||||
<Property key="Caption" value="#{sClass}"/>
|
<Widget type="AutoSizedTextBox" skin="NormalText" position="0 0 95 18" name="Class_str" align="Left Top">
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
<Property key="Caption" value="#{sClass}"/>
|
||||||
<UserString key="ToolTipLayout" value="ClassToolTip"/>
|
<UserString key="ToolTipType" value="Layout"/>
|
||||||
</Widget>
|
<UserString key="ToolTipLayout" value="ClassToolTip"/>
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="104 4 104 18" name="LevelText" align="Right Top">
|
</Widget>
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
<Widget type="TextBox" skin="SandTextRight" position="104 0 200 18" name="ClassText" align="Left Top">
|
||||||
<UserString key="ToolTipLayout" value="LevelToolTip"/>
|
<Property key="TextAlign" value="Right Top"/>
|
||||||
</Widget>
|
<UserString key="ToolTipType" value="Layout"/>
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="104 22 104 18" name="RaceText" align="Right Top">
|
<UserString key="ToolTipLayout" value="ClassToolTip"/>
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
<UserString key="HStretch" value="true"/>
|
||||||
<UserString key="ToolTipLayout" value="TextWithCenteredCaptionToolTip"/>
|
</Widget>
|
||||||
</Widget>
|
|
||||||
<Widget type="TextBox" skin="SandTextRight" position="104 40 104 18" name="ClassText" align="Right Top">
|
|
||||||
<UserString key="ToolTipType" value="Layout"/>
|
|
||||||
<UserString key="ToolTipLayout" value="ClassToolTip"/>
|
|
||||||
</Widget>
|
</Widget>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user