upstream merge
openmw-30
graffy76 11 years ago
commit 0e7d40de6a

@ -86,8 +86,6 @@ option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock fram
# Sound source selection # Sound source selection
option(USE_FFMPEG "use ffmpeg for sound" ON) option(USE_FFMPEG "use ffmpeg for sound" ON)
option(USE_AUDIERE "use audiere for sound" ON)
option(USE_MPG123 "use mpg123 + libsndfile for sound" ON)
# OS X deployment # OS X deployment
option(OPENMW_OSX_DEPLOYMENT OFF) option(OPENMW_OSX_DEPLOYMENT OFF)
@ -171,27 +169,6 @@ if (USE_FFMPEG)
endif (FFMPEG_FOUND) endif (FFMPEG_FOUND)
endif (USE_FFMPEG) endif (USE_FFMPEG)
if (USE_AUDIERE AND NOT GOT_SOUND_INPUT)
find_package(Audiere)
if (AUDIERE_FOUND)
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${AUDIERE_INCLUDE_DIR})
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${AUDIERE_LIBRARY})
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_AUDIERE)
set(GOT_SOUND_INPUT 1)
endif (AUDIERE_FOUND)
endif (USE_AUDIERE AND NOT GOT_SOUND_INPUT)
if (USE_MPG123 AND NOT GOT_SOUND_INPUT)
find_package(MPG123 REQUIRED)
find_package(SNDFILE REQUIRED)
if (MPG123_FOUND AND SNDFILE_FOUND)
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${MPG123_LIBRARY} ${SNDFILE_LIBRARY})
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_MPG123)
set(GOT_SOUND_INPUT 1)
endif (MPG123_FOUND AND SNDFILE_FOUND)
endif (USE_MPG123 AND NOT GOT_SOUND_INPUT)
if (NOT GOT_SOUND_INPUT) if (NOT GOT_SOUND_INPUT)
message(WARNING "--------------------") message(WARNING "--------------------")
message(WARNING "Failed to find any sound input packages") message(WARNING "Failed to find any sound input packages")

@ -60,7 +60,7 @@ opencs_hdrs_noqt (view/doc
opencs_units (view/world opencs_units (view/world
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable
) )
opencs_units (view/render opencs_units (view/render

@ -453,7 +453,7 @@ CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters()
return mFilters; return mFilters;
} }
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
{ {
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType()); std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());

@ -1,6 +1,9 @@
#include "tablemimedata.hpp" #include "tablemimedata.hpp"
#include <string> #include <string>
#include <QDebug>
#include "universalid.hpp" #include "universalid.hpp"
#include "columnbase.hpp" #include "columnbase.hpp"
@ -11,7 +14,7 @@ mDocument(document)
mObjectsFormats << QString::fromUtf8 (("tabledata/" + id.getTypeName()).c_str()); mObjectsFormats << QString::fromUtf8 (("tabledata/" + id.getTypeName()).c_str());
} }
CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) : CSMWorld::TableMimeData::TableMimeData (const std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) :
mUniversalId (id), mDocument(document) mUniversalId (id), mDocument(document)
{ {
for (std::vector<UniversalId>::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it) for (std::vector<UniversalId>::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it)
@ -33,7 +36,8 @@ std::string CSMWorld::TableMimeData::getIcon() const
{ {
if (mUniversalId.empty()) if (mUniversalId.empty())
{ {
throw ("TableMimeData holds no UniversalId"); qDebug()<<"TableMimeData object does not hold any records!"; //because throwing in the event loop tends to be problematic
throw("TableMimeData object does not hold any records!");
} }
std::string tmpIcon; std::string tmpIcon;
@ -50,7 +54,7 @@ std::string CSMWorld::TableMimeData::getIcon() const
if (tmpIcon != mUniversalId[i].getIcon()) if (tmpIcon != mUniversalId[i].getIcon())
{ {
return ":/multitype.png"; //icon stolen from gnome return ":/multitype.png"; //icon stolen from gnome TODO: get new icon
} }
tmpIcon = mUniversalId[i].getIcon(); tmpIcon = mUniversalId[i].getIcon();
@ -531,4 +535,4 @@ CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::U
const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const
{ {
return &mDocument; return &mDocument;
} }

@ -33,7 +33,7 @@ namespace CSMWorld
public: public:
TableMimeData(UniversalId id, const CSMDoc::Document& document); TableMimeData(UniversalId id, const CSMDoc::Document& document);
TableMimeData(std::vector<UniversalId>& id, const CSMDoc::Document& document); TableMimeData(const std::vector<UniversalId>& id, const CSMDoc::Document& document);
~TableMimeData(); ~TableMimeData();
@ -56,6 +56,7 @@ namespace CSMWorld
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const; UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type); static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type); static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
private: private:

@ -64,6 +64,7 @@ namespace
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },

@ -60,6 +60,7 @@ namespace CSMWorld
Type_Spell, Type_Spell,
Type_Cells, Type_Cells,
Type_Cell, Type_Cell,
Type_Cell_Missing, //For cells that does not exist yet.
Type_Referenceables, Type_Referenceables,
Type_Referenceable, Type_Referenceable,
Type_Activator, Type_Activator,

@ -3,8 +3,12 @@
#include <sstream> #include <sstream>
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent) #include <QtGui/qevent.h>
: WorldspaceWidget (parent)
#include <apps/opencs/model/world/tablemimedata.hpp>
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document)
: WorldspaceWidget (document, parent)
{} {}
void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint) void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)
@ -44,4 +48,45 @@ void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSel
{ {
mSelection = selection; mSelection = selection;
emit cellSelectionChanged (mSelection); emit cellSelectionChanged (mSelection);
}
std::pair< int, int > CSVRender::PagedWorldspaceWidget::getCoordinatesFromId (const std::string& record) const
{
std::istringstream stream (record.c_str());
char ignore;
int x, y;
stream >> ignore >> x >> y;
return std::make_pair(x, y);
}
void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
{
bool selectionChanged = false;
for (unsigned i = 0; i < data.size(); ++i)
{
std::pair<int, int> coordinates(getCoordinatesFromId(data[i].getId()));
if (mSelection.add(CSMWorld::CellCoordinates(coordinates.first, coordinates.second)))
{
selectionChanged = true;
}
}
if (selectionChanged)
{
emit cellSelectionChanged(mSelection);
}
}
CSVRender::WorldspaceWidget::dropRequirments CSVRender::PagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const
{
switch (type)
{
case cellsExterior:
return canHandle;
case cellsInterior:
return needUnpaged;
default:
return ignored;
}
} }

@ -13,17 +13,25 @@ namespace CSVRender
CSMWorld::CellSelection mSelection; CSMWorld::CellSelection mSelection;
private:
std::pair<int, int> getCoordinatesFromId(const std::string& record) const;
public: public:
PagedWorldspaceWidget (QWidget *parent); PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document);
///< \note Sets the cell area selection to an invalid value to indicate that currently ///< \note Sets the cell area selection to an invalid value to indicate that currently
/// no cells are displayed. The cells to be displayed will be specified later through /// no cells are displayed. The cells to be displayed will be specified later through
/// hint system. /// hint system.
virtual void useViewHint (const std::string& hint); void useViewHint (const std::string& hint);
void setCellSelection (const CSMWorld::CellSelection& selection); void setCellSelection (const CSMWorld::CellSelection& selection);
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
virtual dropRequirments getDropRequirements(dropType type) const;
signals: signals:
void cellSelectionChanged (const CSMWorld::CellSelection& selection); void cellSelectionChanged (const CSMWorld::CellSelection& selection);

@ -320,7 +320,7 @@ namespace CSVRender
} }
if (mUpdate) if (mUpdate && mWindow)
{ {
mUpdate = false; mUpdate = false;
mWindow->update(); mWindow->update();

@ -36,7 +36,7 @@ namespace CSVRender
SceneWidget(QWidget *parent); SceneWidget(QWidget *parent);
virtual ~SceneWidget(); virtual ~SceneWidget();
QPaintEngine* paintEngine() const; QPaintEngine* paintEngine() const;
CSVWorld::SceneToolMode *makeLightingSelector (CSVWorld::SceneToolbar *parent); CSVWorld::SceneToolMode *makeLightingSelector (CSVWorld::SceneToolbar *parent);
///< \attention The created tool is not added to the toolbar (via addTool). Doing that ///< \attention The created tool is not added to the toolbar (via addTool). Doing that

@ -3,10 +3,13 @@
#include <OgreColourValue.h> #include <OgreColourValue.h>
#include <QtGui/qevent.h>
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
#include "../../model/world/data.hpp" #include "../../model/world/data.hpp"
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
#include "../../model/world/tablemimedata.hpp"
void CSVRender::UnpagedWorldspaceWidget::update() void CSVRender::UnpagedWorldspaceWidget::update()
{ {
@ -20,9 +23,8 @@ void CSVRender::UnpagedWorldspaceWidget::update()
/// \todo deal with mSunlight and mFog/mForDensity /// \todo deal with mSunlight and mFog/mForDensity
} }
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent)
CSMDoc::Document& document, QWidget *parent) : WorldspaceWidget (document, parent), mCellId (cellId)
: WorldspaceWidget (parent), mCellId (cellId)
{ {
mCellsModel = &dynamic_cast<CSMWorld::IdTable&> ( mCellsModel = &dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells)); *document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
@ -63,4 +65,26 @@ void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelI
if (cellIndex.row()>=start && cellIndex.row()<=end) if (cellIndex.row()>=start && cellIndex.row()<=end)
emit closeRequest(); emit closeRequest();
} }
void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
{
mCellId = data.begin()->getId();
update();
emit cellChanged(*data.begin());
}
CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const
{
switch(type)
{
case cellsInterior:
return canHandle;
case cellsExterior:
return needPaged;
default:
return ignored;
}
}

@ -31,13 +31,21 @@ namespace CSVRender
public: public:
UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document,
QWidget *parent); QWidget *parent);
virtual dropRequirments getDropRequirements(dropType type) const;
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
private slots: private slots:
void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void cellRowsAboutToBeRemoved (const QModelIndex& parent, int start, int end); void cellRowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
signals:
void cellChanged(const CSMWorld::UniversalId& id);
}; };
} }

@ -5,15 +5,20 @@
#include <OgreSceneManager.h> #include <OgreSceneManager.h>
#include <OgreEntity.h> #include <OgreEntity.h>
#include <QtGui/qevent.h>
#include "../world/scenetoolmode.hpp" #include "../world/scenetoolmode.hpp"
#include <apps/opencs/model/world/universalid.hpp>
CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent) CSVRender::WorldspaceWidget::WorldspaceWidget (const CSMDoc::Document& document, QWidget* parent)
: SceneWidget (parent) : SceneWidget (parent), mDocument(document)
{ {
Ogre::Entity* ent = getSceneManager()->createEntity("cube", Ogre::SceneManager::PT_CUBE); Ogre::Entity* ent = getSceneManager()->createEntity("cube", Ogre::SceneManager::PT_CUBE);
ent->setMaterialName("BaseWhite"); ent->setMaterialName("BaseWhite");
getSceneManager()->getRootSceneNode()->attachObject(ent); getSceneManager()->getRootSceneNode()->attachObject(ent);
setAcceptDrops(true);
} }
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode) void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
@ -46,4 +51,78 @@ CSVWorld::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
this, SLOT (selectNavigationMode (const std::string&))); this, SLOT (selectNavigationMode (const std::string&)));
return tool; return tool;
}
CSVRender::WorldspaceWidget::dropType CSVRender::WorldspaceWidget::getDropType (
const std::vector< CSMWorld::UniversalId >& data)
{
dropType output = notCells;
bool firstIteration = true;
for (unsigned i = 0; i < data.size(); ++i)
{
if (data[i].getType() == CSMWorld::UniversalId::Type_Cell ||
data[i].getType() == CSMWorld::UniversalId::Type_Cell_Missing)
{
if (*(data[i].getId().begin()) == '#') //exterior
{
if (firstIteration)
{
output = cellsExterior;
firstIteration = false;
continue;
}
if (output == cellsInterior)
{
output = cellsMixed;
break;
} else {
output = cellsInterior;
}
} else //interior
{
if (firstIteration)
{
output = cellsInterior;
firstIteration = false;
continue;
}
if (output == cellsExterior)
{
output = cellsMixed;
break;
} else {
output = cellsInterior;
}
}
} else {
output = notCells;
break;
}
}
return output;
}
void CSVRender::WorldspaceWidget::dragEnterEvent (QDragEnterEvent* event)
{
event->accept();
}
void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event)
{
event->accept();
}
void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event)
{
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
if (mime->fromDocument (mDocument))
{
emit dataDropped(mime->getData());
} //not handling drops from different documents at the moment
} }

@ -6,7 +6,13 @@
#include "navigation1st.hpp" #include "navigation1st.hpp"
#include "navigationfree.hpp" #include "navigationfree.hpp"
#include "navigationorbit.hpp" #include "navigationorbit.hpp"
#include <apps/opencs/model/doc/document.hpp>
#include <apps/opencs/model/world/tablemimedata.hpp>
namespace CSMWorld
{
class UniversalId;
}
namespace CSVWorld namespace CSVWorld
{ {
class SceneToolMode; class SceneToolMode;
@ -25,7 +31,23 @@ namespace CSVRender
public: public:
WorldspaceWidget (QWidget *parent = 0); enum dropType
{
cellsMixed,
cellsInterior,
cellsExterior,
notCells
};
enum dropRequirments
{
canHandle,
needPaged,
needUnpaged,
ignored //either mixed cells, or not cells
};
WorldspaceWidget (const CSMDoc::Document& document, QWidget *parent = 0);
CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent); CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent);
///< \attention The created tool is not added to the toolbar (via addTool). Doing that ///< \attention The created tool is not added to the toolbar (via addTool). Doing that
@ -33,9 +55,26 @@ namespace CSVRender
void selectDefaultNavigationMode(); void selectDefaultNavigationMode();
static dropType getDropType(const std::vector<CSMWorld::UniversalId>& data);
virtual dropRequirments getDropRequirements(dropType type) const = 0;
virtual void useViewHint (const std::string& hint); virtual void useViewHint (const std::string& hint);
///< Default-implementation: ignored. ///< Default-implementation: ignored.
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data) = 0;
protected:
const CSMDoc::Document& mDocument; //for checking if drop comes from same document
private:
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent* event);
void dragMoveEvent(QDragMoveEvent *event);
private slots: private slots:
void selectNavigationMode (const std::string& mode); void selectNavigationMode (const std::string& mode);
@ -43,6 +82,7 @@ namespace CSVRender
signals: signals:
void closeRequest(); void closeRequest();
void dataDropped(const std::vector<CSMWorld::UniversalId>& data);
}; };
} }

@ -0,0 +1,38 @@
#include <QDrag>
#include "../../model/world/tablemimedata.hpp"
#include "dragrecordtable.hpp"
void CSVWorld::DragRecordTable::startDrag (const CSVWorld::DragRecordTable& table)
{
CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDraggedRecords(), mDocument);
if (mime)
{
QDrag* drag = new QDrag (this);
drag->setMimeData (mime);
drag->setPixmap (QString::fromUtf8 (mime->getIcon().c_str()));
drag->exec (Qt::CopyAction);
}
}
CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document, QWidget* parent) :
mDocument(document),
QTableView(parent),
mEditLock(false)
{}
void CSVWorld::DragRecordTable::setEditLock (bool locked)
{
mEditLock = locked;
}
void CSVWorld::DragRecordTable::dragEnterEvent(QDragEnterEvent *event)
{
event->acceptProposedAction();
}
void CSVWorld::DragRecordTable::dragMoveEvent(QDragMoveEvent *event)
{
event->accept();
}

@ -0,0 +1,45 @@
#ifndef CSV_WORLD_DRAGRECORDTABLE_H
#define CSV_WORLD_DRAGRECORDTABLE_H
#include <QTableView>
#include <QtGui/qevent.h>
class QWidget;
class QAction;
namespace CSMDoc
{
class Document;
}
namespace CSMWorld
{
class UniversalId;
}
namespace CSVWorld
{
class DragRecordTable : public QTableView
{
protected:
CSMDoc::Document& mDocument;
bool mEditLock;
public:
DragRecordTable(CSMDoc::Document& document, QWidget* parent = NULL);
virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const = 0;
void setEditLock(bool locked);
protected:
void startDrag(const DragRecordTable& table);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
};
}
#endif

@ -17,6 +17,7 @@
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
#include "../../model/world/commands.hpp" #include "../../model/world/commands.hpp"
#include "../../model/world/columns.hpp" #include "../../model/world/columns.hpp"
#include "../../model/world/tablemimedata.hpp"
void CSVWorld::RegionMap::contextMenuEvent (QContextMenuEvent *event) void CSVWorld::RegionMap::contextMenuEvent (QContextMenuEvent *event)
{ {
@ -180,7 +181,7 @@ void CSVWorld::RegionMap::setRegion (const std::string& regionId)
CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId, CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId,
CSMDoc::Document& document, QWidget *parent) CSMDoc::Document& document, QWidget *parent)
: QTableView (parent), mEditLock (false), mDocument (document) : DragRecordTable(document, parent)
{ {
verticalHeader()->hide(); verticalHeader()->hide();
horizontalHeader()->hide(); horizontalHeader()->hide();
@ -223,11 +224,8 @@ CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId,
mViewInTableAction = new QAction (tr ("View Cells in Table"), this); mViewInTableAction = new QAction (tr ("View Cells in Table"), this);
connect (mViewInTableAction, SIGNAL (triggered()), this, SLOT (viewInTable())); connect (mViewInTableAction, SIGNAL (triggered()), this, SLOT (viewInTable()));
addAction (mViewInTableAction); addAction (mViewInTableAction);
}
void CSVWorld::RegionMap::setEditLock (bool locked) setAcceptDrops(true);
{
mEditLock = locked;
} }
void CSVWorld::RegionMap::selectAll() void CSVWorld::RegionMap::selectAll()
@ -343,4 +341,65 @@ void CSVWorld::RegionMap::viewInTable()
hint << ")"; hint << ")";
emit editRequest (CSMWorld::UniversalId::Type_Cells, hint.str()); emit editRequest (CSMWorld::UniversalId::Type_Cells, hint.str());
}
void CSVWorld::RegionMap::mouseMoveEvent (QMouseEvent* event)
{
startDrag(*this);
}
std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDraggedRecords() const
{
QModelIndexList selected(getSelectedCells(true, false));
std::vector<CSMWorld::UniversalId> ids;
foreach (QModelIndex it, selected)
{
ids.push_back(
CSMWorld::UniversalId(
CSMWorld::UniversalId::Type_Cell,
model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData()));
}
selected = getSelectedCells(false, true);
foreach (QModelIndex it, selected)
{
ids.push_back(
CSMWorld::UniversalId(
CSMWorld::UniversalId::Type_Cell_Missing,
model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData()));
}
return ids;
}
void CSVWorld::RegionMap::dropEvent (QDropEvent* event)
{
QModelIndex index = indexAt (event->pos());
bool exists = QTableView::model()->data(index, Qt::BackgroundRole)!=QBrush (Qt::DiagCrossPattern);
if (!index.isValid() || !exists)
{
return;
}
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
if (mime->fromDocument(mDocument) && mime->holdsType(CSMWorld::UniversalId::Type_Region))
{
CSMWorld::UniversalId record (mime->returnMatching (CSMWorld::UniversalId::Type_Region));
QAbstractItemModel *regionModel = model();
CSMWorld::IdTable *cellsModel = &dynamic_cast<CSMWorld::IdTable&> (*
mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
std::string cellId(regionModel->data (index, CSMWorld::RegionMap::Role_CellId).
toString().toUtf8().constData());
QModelIndex index2(cellsModel->getModelIndex (cellId,
cellsModel->findColumnIndex (CSMWorld::Columns::ColumnId_Region)));
mDocument.getUndoStack().push(new CSMWorld::ModifyCommand
(*cellsModel, index2, QString::fromUtf8(record.getId().c_str())));
mRegionId = record.getId();
}
} }

@ -1,8 +1,14 @@
#ifndef CSV_WORLD_REGIONMAP_H #ifndef CSV_WORLD_REGIONMAP_H
#define CSV_WORLD_REGIONMAP_H #define CSV_WORLD_REGIONMAP_H
#include <cstddef>
#include <vector>
#include <QObject>
#include <QTableView> #include <QTableView>
#include "./dragrecordtable.hpp"
class QAction; class QAction;
namespace CSMDoc namespace CSMDoc
@ -17,7 +23,7 @@ namespace CSMWorld
namespace CSVWorld namespace CSVWorld
{ {
class RegionMap : public QTableView class RegionMap : public DragRecordTable
{ {
Q_OBJECT Q_OBJECT
@ -29,8 +35,6 @@ namespace CSVWorld
QAction *mUnsetRegionAction; QAction *mUnsetRegionAction;
QAction *mViewAction; QAction *mViewAction;
QAction *mViewInTableAction; QAction *mViewInTableAction;
bool mEditLock;
CSMDoc::Document& mDocument;
std::string mRegionId; std::string mRegionId;
private: private:
@ -50,12 +54,16 @@ namespace CSVWorld
void setRegion (const std::string& regionId); void setRegion (const std::string& regionId);
///< Set region Id of selected cells. ///< Set region Id of selected cells.
void mouseMoveEvent(QMouseEvent *event);
void dropEvent(QDropEvent* event);
public: public:
RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document, RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document,
QWidget *parent = 0); QWidget *parent = 0);
void setEditLock (bool locked); virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const;
signals: signals:

@ -6,6 +6,7 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <cassert>
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
@ -18,11 +19,10 @@
#include "tablebottombox.hpp" #include "tablebottombox.hpp"
#include "creator.hpp" #include "creator.hpp"
#include "scenetoolbar.hpp"
#include "scenetoolmode.hpp" #include "scenetoolmode.hpp"
CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: SubView (id) : SubView (id), mLayout(new QHBoxLayout), mDocument(document), mScene(NULL), mToolbar(NULL)
{ {
QVBoxLayout *layout = new QVBoxLayout; QVBoxLayout *layout = new QVBoxLayout;
@ -32,33 +32,35 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id, new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id,
this), 0); this), 0);
QHBoxLayout *layout2 = new QHBoxLayout; mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
layout2->setContentsMargins (QMargins (0, 0, 0, 0)); CSVRender::WorldspaceWidget* wordspaceWidget = NULL;
widgetType whatWidget;
SceneToolbar *toolbar = new SceneToolbar (48+6, this);
if (id.getId()=="sys::default") if (id.getId()=="sys::default")
{ {
CSVRender::PagedWorldspaceWidget *widget = new CSVRender::PagedWorldspaceWidget (this); whatWidget = widget_Paged;
mScene = widget;
connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)), CSVRender::PagedWorldspaceWidget *newWidget = new CSVRender::PagedWorldspaceWidget (this, document);
this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&)));
wordspaceWidget = newWidget;
makeConnections(newWidget);
} }
else else
mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); {
whatWidget = widget_Unpaged;
SceneToolMode *navigationTool = mScene->makeNavigationSelector (toolbar); CSVRender::UnpagedWorldspaceWidget *newWidget = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this);
toolbar->addTool (navigationTool);
SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar); wordspaceWidget = newWidget;
toolbar->addTool (lightingTool);
layout2->addWidget (toolbar, 0); makeConnections(newWidget);
}
layout2->addWidget (mScene, 1); replaceToolbarAndWorldspace(wordspaceWidget, makeToolbar(wordspaceWidget, whatWidget));
layout->insertLayout (0, layout2, 1); layout->insertLayout (0, mLayout, 1);
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this); CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
@ -69,10 +71,53 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
widget->setLayout (layout); widget->setLayout (layout);
setWidget (widget); setWidget (widget);
}
mScene->selectDefaultNavigationMode(); void CSVWorld::SceneSubView::makeConnections (CSVRender::UnpagedWorldspaceWidget* widget)
{
connect (widget, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
connect(widget, SIGNAL(dataDropped(const std::vector<CSMWorld::UniversalId>&)),
this, SLOT(handleDrop(const std::vector<CSMWorld::UniversalId>&)));
connect(widget, SIGNAL(cellChanged(const CSMWorld::UniversalId&)),
this, SLOT(cellSelectionChanged(const CSMWorld::UniversalId&)));
}
void CSVWorld::SceneSubView::makeConnections (CSVRender::PagedWorldspaceWidget* widget)
{
connect (widget, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
connect(widget, SIGNAL(dataDropped(const std::vector<CSMWorld::UniversalId>&)),
this, SLOT(handleDrop(const std::vector<CSMWorld::UniversalId>&)));
connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)),
this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&)));
}
CSVWorld::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::WorldspaceWidget* widget, widgetType type)
{
CSVWorld::SceneToolbar* toolbar = new SceneToolbar (48+6, this);
SceneToolMode *navigationTool = widget->makeNavigationSelector (toolbar);
toolbar->addTool (navigationTool);
SceneToolMode *lightingTool = widget->makeLightingSelector (toolbar);
toolbar->addTool (lightingTool);
/* Add buttons specific to the type. For now no need for it.
*
switch (type)
{
case widget_Paged:
break;
case widget_Unpaged:
break;
connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest())); }
*/
return toolbar;
} }
void CSVWorld::SceneSubView::setEditLock (bool locked) void CSVWorld::SceneSubView::setEditLock (bool locked)
@ -102,8 +147,19 @@ void CSVWorld::SceneSubView::closeRequest()
deleteLater(); deleteLater();
} }
void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::UniversalId& id)
{
setUniversalId(id);
std::ostringstream stream;
stream << "Scene: " << getUniversalId().getId();
setWindowTitle (QString::fromUtf8 (stream.str().c_str()));
}
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"));
int size = selection.getSize(); int size = selection.getSize();
std::ostringstream stream; std::ostringstream stream;
@ -126,4 +182,62 @@ void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection
} }
setWindowTitle (QString::fromUtf8 (stream.str().c_str())); setWindowTitle (QString::fromUtf8 (stream.str().c_str()));
}
void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
{
CSVRender::PagedWorldspaceWidget* pagedNewWidget = NULL;
CSVRender::UnpagedWorldspaceWidget* unPagedNewWidget = NULL;
SceneToolbar* toolbar = NULL;
switch (mScene->getDropRequirements(CSVRender::WorldspaceWidget::getDropType(data)))
{
case CSVRender::WorldspaceWidget::canHandle:
mScene->handleDrop(data);
break;
case CSVRender::WorldspaceWidget::needPaged:
pagedNewWidget = new CSVRender::PagedWorldspaceWidget(this, mDocument);
toolbar = makeToolbar(pagedNewWidget, widget_Paged);
makeConnections(pagedNewWidget);
replaceToolbarAndWorldspace(pagedNewWidget, toolbar);
mScene->handleDrop(data);
break;
case CSVRender::WorldspaceWidget::needUnpaged:
unPagedNewWidget = new CSVRender::UnpagedWorldspaceWidget(data.begin()->getId(), mDocument, this);
toolbar = makeToolbar(unPagedNewWidget, widget_Unpaged);
makeConnections(unPagedNewWidget);
replaceToolbarAndWorldspace(unPagedNewWidget, toolbar);
cellSelectionChanged(*(data.begin()));
break;
case CSVRender::WorldspaceWidget::ignored:
return;
}
}
void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceWidget* widget, CSVWorld::SceneToolbar* toolbar)
{
assert(mLayout);
if (mScene)
{
mLayout->removeWidget(mScene);
mScene->deleteLater();
}
if (mToolbar)
{
mLayout->removeWidget(mToolbar);
mToolbar->deleteLater();
}
mScene = widget;
mToolbar = toolbar;
mLayout->addWidget (mToolbar, 0);
mLayout->addWidget (mScene, 1);
mScene->selectDefaultNavigationMode();
} }

@ -1,7 +1,10 @@
#ifndef CSV_WORLD_SCENESUBVIEW_H #ifndef CSV_WORLD_SCENESUBVIEW_H
#define CSV_WORLD_SCENESUBVIEW_H #define CSV_WORLD_SCENESUBVIEW_H
#include <QHBoxLayout>
#include "../doc/subview.hpp" #include "../doc/subview.hpp"
#include "scenetoolbar.hpp"
class QModelIndex; class QModelIndex;
@ -18,6 +21,8 @@ namespace CSMDoc
namespace CSVRender namespace CSVRender
{ {
class WorldspaceWidget; class WorldspaceWidget;
class PagedWorldspaceWidget;
class UnpagedWorldspaceWidget;
} }
namespace CSVWorld namespace CSVWorld
@ -32,6 +37,9 @@ namespace CSVWorld
TableBottomBox *mBottom; TableBottomBox *mBottom;
CSVRender::WorldspaceWidget *mScene; CSVRender::WorldspaceWidget *mScene;
QHBoxLayout* mLayout;
CSMDoc::Document& mDocument;
SceneToolbar* mToolbar;
public: public:
@ -45,11 +53,30 @@ namespace CSVWorld
virtual void useHint (const std::string& hint); virtual void useHint (const std::string& hint);
private:
void makeConnections(CSVRender::PagedWorldspaceWidget* widget);
void makeConnections(CSVRender::UnpagedWorldspaceWidget* widget);
void replaceToolbarAndWorldspace(CSVRender::WorldspaceWidget* widget, SceneToolbar* toolbar);
enum widgetType
{
widget_Paged,
widget_Unpaged
};
SceneToolbar* makeToolbar(CSVRender::WorldspaceWidget* widget, widgetType type);
private slots: private slots:
void closeRequest(); void closeRequest();
void cellSelectionChanged (const CSMWorld::CellSelection& selection); void cellSelectionChanged (const CSMWorld::CellSelection& selection);
void cellSelectionChanged (const CSMWorld::UniversalId& id);
void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
}; };
} }

@ -188,8 +188,8 @@ std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
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), mEditLock (false), mRecordStatusDisplay (0), : mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0),
mDocument (document) DragRecordTable(document)
{ {
mModel = &dynamic_cast<CSMWorld::IdTable&> (*mDocument.getData().getTableModel (id)); mModel = &dynamic_cast<CSMWorld::IdTable&> (*mDocument.getData().getTableModel (id));
@ -282,7 +282,7 @@ void CSVWorld::Table::setEditLock (bool locked)
for (std::vector<CommandDelegate *>::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter) for (std::vector<CommandDelegate *>::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter)
(*iter)->setEditLock (locked); (*iter)->setEditLock (locked);
mEditLock = locked; DragRecordTable::setEditLock(locked);
} }
CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
@ -518,42 +518,8 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event)
{ {
if (event->buttons() & Qt::LeftButton) if (event->buttons() & Qt::LeftButton)
{ {
QModelIndexList selectedRows = selectionModel()->selectedRows(); startDrag(*this);
if (selectedRows.size() == 0)
{
return;
}
QDrag* drag = new QDrag (this);
CSMWorld::TableMimeData* mime = NULL;
if (selectedRows.size() == 1)
{
mime = new CSMWorld::TableMimeData (getUniversalId (selectedRows.begin()->row()), mDocument);
}
else
{
std::vector<CSMWorld::UniversalId> idToDrag;
foreach (QModelIndex it, selectedRows) //I had a dream. Dream where you could use C++11 in OpenMW.
{
idToDrag.push_back (getUniversalId (it.row()));
}
mime = new CSMWorld::TableMimeData (idToDrag, mDocument);
}
drag->setMimeData (mime);
drag->setPixmap (QString::fromUtf8 (mime->getIcon().c_str()));
drag->exec(Qt::CopyAction);
} }
}
void CSVWorld::Table::dragEnterEvent(QDragEnterEvent *event)
{
event->acceptProposedAction();
} }
void CSVWorld::Table::dropEvent(QDropEvent *event) void CSVWorld::Table::dropEvent(QDropEvent *event)
@ -583,11 +549,6 @@ void CSVWorld::Table::dropEvent(QDropEvent *event)
} //TODO handle drops from different document } //TODO handle drops from different document
} }
void CSVWorld::Table::dragMoveEvent(QDragMoveEvent *event)
{
event->accept();
}
std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const
{ {
const int count = mModel->columnCount(); const int count = mModel->columnCount();
@ -605,3 +566,18 @@ std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column
} }
return titles; return titles;
} }
std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const
{
QModelIndexList selectedRows = selectionModel()->selectedRows();
std::vector<CSMWorld::UniversalId> idToDrag;
foreach (QModelIndex it, selectedRows) //I had a dream. Dream where you could use C++11 in OpenMW.
{
idToDrag.push_back (getUniversalId (it.row()));
}
return idToDrag;
}

@ -4,11 +4,11 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <QTableView>
#include <QtGui/qevent.h> #include <QtGui/qevent.h>
#include "../../model/filter/node.hpp" #include "../../model/filter/node.hpp"
#include "../../model/world/columnbase.hpp" #include "../../model/world/columnbase.hpp"
#include "dragrecordtable.hpp"
class QUndoStack; class QUndoStack;
class QAction; class QAction;
@ -31,7 +31,7 @@ namespace CSVWorld
class CommandDelegate; class CommandDelegate;
///< Table widget ///< Table widget
class Table : public QTableView class Table : public DragRecordTable
{ {
Q_OBJECT Q_OBJECT
@ -47,9 +47,7 @@ namespace CSVWorld
QAction *mPreviewAction; QAction *mPreviewAction;
CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTableProxyModel *mProxyModel;
CSMWorld::IdTable *mModel; CSMWorld::IdTable *mModel;
bool mEditLock;
int mRecordStatusDisplay; int mRecordStatusDisplay;
CSMDoc::Document& mDocument;
private: private:
@ -61,10 +59,6 @@ namespace CSVWorld
void mouseMoveEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event); void dropEvent(QDropEvent *event);
public: public:
@ -74,12 +68,14 @@ namespace CSVWorld
///< \param createAndDelete Allow creation and deletion of records. ///< \param createAndDelete Allow creation and deletion of records.
/// \param sorting Allow changing order of rows in the view via column headers. /// \param sorting Allow changing order of rows in the view via column headers.
void setEditLock (bool locked); virtual void setEditLock (bool locked);
CSMWorld::UniversalId getUniversalId (int row) const; CSMWorld::UniversalId getUniversalId (int row) const;
std::vector<std::string> getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const; std::vector<std::string> getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const;
virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const;
signals: signals:
void editRequest (const CSMWorld::UniversalId& id, const std::string& hint); void editRequest (const CSMWorld::UniversalId& id, const std::string& hint);
@ -92,6 +88,7 @@ namespace CSVWorld
/// \param modified Number of added and modified records /// \param modified Number of added and modified records
void createRequest(); void createRequest();
void cloneRequest(const CSMWorld::UniversalId&); void cloneRequest(const CSMWorld::UniversalId&);
private slots: private slots:

@ -48,7 +48,7 @@ add_openmw_dir (mwscript
) )
add_openmw_dir (mwsound add_openmw_dir (mwsound
soundmanagerimp openal_output audiere_decoder mpgsnd_decoder ffmpeg_decoder soundmanagerimp openal_output ffmpeg_decoder sound
) )
add_openmw_dir (mwworld add_openmw_dir (mwworld

@ -96,6 +96,9 @@ namespace MWBase
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check! /// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0; virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer) = 0;
/// Makes \a ptr fight \a target. Also shouts a combat taunt.
virtual void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) = 0;
enum OffenseType enum OffenseType
{ {
OT_Theft, // Taking items owned by an NPC or a faction you are not a member of OT_Theft, // Taking items owned by an NPC or a faction you are not a member of

@ -337,6 +337,12 @@ namespace MWClass
{ {
// NOTE: 'object' and/or 'attacker' may be empty. // NOTE: 'object' and/or 'attacker' may be empty.
getCreatureStats(ptr).setAttacked(true);
// Self defense
if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() < 80)
MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, attacker);
if(!successful) if(!successful)
{ {
// TODO: Handle HitAttemptOnMe script function // TODO: Handle HitAttemptOnMe script function

@ -621,7 +621,7 @@ namespace MWClass
// NOTE: 'object' and/or 'attacker' may be empty. // NOTE: 'object' and/or 'attacker' may be empty.
// Attacking peaceful NPCs is a crime // Attacking peaceful NPCs is a crime
if (!attacker.isEmpty() && ptr.getClass().isNpc() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30) if (!attacker.isEmpty() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30)
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault); MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
getCreatureStats(ptr).setAttacked(true); getCreatureStats(ptr).setAttacked(true);

@ -1447,7 +1447,7 @@ namespace MWGui
{ {
return !MyGUI::InputManager::getInstance().isModalAny() return !MyGUI::InputManager::getInstance().isModalAny()
// TODO: remove this, once we have properly serialized the state of open windows // TODO: remove this, once we have properly serialized the state of open windows
&& (!isGuiMode() || (mGuiModes.size() == 1 && getMode() == GM_MainMenu)); && (!isGuiMode() || (mGuiModes.size() == 1 && (getMode() == GM_MainMenu || getMode() == GM_Rest || getMode() == GM_RestBed)));
} }
void WindowManager::playVideo(const std::string &name, bool allowSkipping) void WindowManager::playVideo(const std::string &name, bool allowSkipping)

@ -206,8 +206,7 @@ namespace MWMechanics
if (LOS) if (LOS)
{ {
creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr()), ptr); MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player);
creatureStats.setHostile(true);
} }
} }
} }
@ -762,16 +761,11 @@ namespace MWMechanics
if (ptr.getClass().isClass(ptr, "Guard")) if (ptr.getClass().isClass(ptr, "Guard"))
creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr); creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
else else
creatureStats.getAiSequence().stack(AiCombat(player), ptr); {
creatureStats.setHostile(true); MWBase::Environment::get().getMechanicsManager()->startCombat(ptr, player);
}
} }
} }
// if I didn't report a crime was I attacked?
else if (creatureStats.getAttacked() && !creatureStats.isHostile())
{
creatureStats.getAiSequence().stack(AiCombat(player), ptr);
creatureStats.setHostile(true);
}
} }
} }
@ -850,12 +844,12 @@ namespace MWMechanics
} }
// AI and magic effects update // AI and magic effects update
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
{ {
if (!iter->first.getClass().getCreatureStats(iter->first).isDead()) if (!iter->first.getClass().getCreatureStats(iter->first).isDead())
{ {
updateActor(iter->first, duration); updateActor(iter->first, duration);
if(iter->first.getTypeName() == typeid(ESM::NPC).name()) if (iter->first.getTypeName() == typeid(ESM::NPC).name())
updateNpc(iter->first, duration, paused); updateNpc(iter->first, duration, paused);
} }
} }
@ -865,11 +859,11 @@ namespace MWMechanics
// Reaching the text keys may trigger Hit / Spellcast (and as such, particles), // Reaching the text keys may trigger Hit / Spellcast (and as such, particles),
// so updating VFX immediately after that would just remove the particle effects instantly. // so updating VFX immediately after that would just remove the particle effects instantly.
// There needs to be a magic effect update in between. // There needs to be a magic effect update in between.
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
iter->second->updateContinuousVfx(); iter->second->updateContinuousVfx();
// Animation/movement update // Animation/movement update
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
{ {
if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get( if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get(
ESM::MagicEffect::Paralyze).mMagnitude > 0) ESM::MagicEffect::Paralyze).mMagnitude > 0)
@ -878,7 +872,7 @@ namespace MWMechanics
} }
// Kill dead actors, update some variables // Kill dead actors, update some variables
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) for (PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++)
{ {
const MWWorld::Class &cls = MWWorld::Class::get(iter->first); const MWWorld::Class &cls = MWWorld::Class::get(iter->first);
CreatureStats &stats = cls.getCreatureStats(iter->first); CreatureStats &stats = cls.getCreatureStats(iter->first);
@ -886,7 +880,7 @@ namespace MWMechanics
//KnockedOutOneFrameLogic //KnockedOutOneFrameLogic
//Used for "OnKnockedOut" command //Used for "OnKnockedOut" command
//Put here to ensure that it's run for PRECISELY one frame. //Put here to ensure that it's run for PRECISELY one frame.
if(stats.getKnockedDown() && !stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Start it for one frame if nessesary if (stats.getKnockedDown() && !stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Start it for one frame if nessesary
stats.setKnockedDownOneFrame(true); stats.setKnockedDownOneFrame(true);
} }
else if (stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Turn off KnockedOutOneframe else if (stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Turn off KnockedOutOneframe
@ -904,7 +898,7 @@ namespace MWMechanics
} }
// If it's the player and God Mode is turned on, keep it alive // If it's the player and God Mode is turned on, keep it alive
if(iter->first.getRefData().getHandle()=="player" && if (iter->first.getRefData().getHandle()=="player" &&
MWBase::Environment::get().getWorld()->getGodModeState()) MWBase::Environment::get().getWorld()->getGodModeState())
{ {
MWMechanics::DynamicStat<float> stat (stats.getHealth()); MWMechanics::DynamicStat<float> stat (stats.getHealth());
@ -920,7 +914,7 @@ namespace MWMechanics
// Make sure spell effects with CasterLinked flag are removed // Make sure spell effects with CasterLinked flag are removed
// TODO: would be nice not to do this all the time... // TODO: would be nice not to do this all the time...
for(PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2) for (PtrControllerMap::iterator iter2(mActors.begin());iter2 != mActors.end();++iter2)
{ {
MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells(); MWMechanics::ActiveSpells& spells = iter2->first.getClass().getCreatureStats(iter2->first).getActiveSpells();
spells.purge(iter->first.getRefData().getHandle()); spells.purge(iter->first.getRefData().getHandle());
@ -945,10 +939,40 @@ namespace MWMechanics
stats.setMagicEffects(MWMechanics::MagicEffects()); stats.setMagicEffects(MWMechanics::MagicEffects());
calculateCreatureStatModifiers(iter->first, 0); calculateCreatureStatModifiers(iter->first, 0);
if(cls.isEssential(iter->first)) if (cls.isEssential(iter->first))
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}"); MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
} }
} }
// if player is in sneak state see if anyone detects him
const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
if (player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak))
{
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
const int radius = esmStore.get<ESM::GameSetting>().find("fSneakUseDist")->getInt();
bool detected = false;
for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
if (iter->first == player) // not the player
continue;
// is the player in range and can they be detected
if ( (Ogre::Vector3(iter->first.getRefData().getPosition().pos).squaredDistance(Ogre::Vector3(player.getRefData().getPosition().pos)) <= radius*radius)
&& MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, iter->first)
&& MWBase::Environment::get().getWorld()->getLOS(player, iter->first))
{
detected = true;
MWBase::Environment::get().getWindowManager()->setSneakVisibility(false);
break;
}
}
if (!detected)
MWBase::Environment::get().getWindowManager()->setSneakVisibility(true);
}
else
MWBase::Environment::get().getWindowManager()->setSneakVisibility(false);
} }
} }
void Actors::restoreDynamicStats(bool sleep) void Actors::restoreDynamicStats(bool sleep)
@ -1051,6 +1075,8 @@ namespace MWMechanics
if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat) if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat)
{ {
MWMechanics::AiCombat* package = static_cast<MWMechanics::AiCombat*>(stats.getAiSequence().getActivePackage()); MWMechanics::AiCombat* package = static_cast<MWMechanics::AiCombat*>(stats.getAiSequence().getActivePackage());
// TODO: This is wrong! It's comparing Ref IDs with Ogre handles. The only case where this (coincidentally) works is the player.
// possibly applies to other code using getTargetId.
if(package->getTargetId() == actor.getCellRef().mRefID) if(package->getTargetId() == actor.getCellRef().mRefID)
list.push_front(*iter); list.push_front(*iter);
} }

@ -64,6 +64,7 @@ namespace MWMechanics
void stack (const AiPackage& package, const MWWorld::Ptr& actor); void stack (const AiPackage& package, const MWWorld::Ptr& actor);
///< Add \a package to the front of the sequence (suspends current package) ///< Add \a package to the front of the sequence (suspends current package)
/// @param actor The actor that owns this AiSequence
void queue (const AiPackage& package); void queue (const AiPackage& package);
///< Add \a package to the end of the sequence (executed after all other packages have been ///< Add \a package to the end of the sequence (executed after all other packages have been

@ -13,6 +13,8 @@
#include "../mwworld/class.hpp" #include "../mwworld/class.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
#include "../mwmechanics/aicombat.hpp"
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include "spellcasting.hpp" #include "spellcasting.hpp"
@ -852,39 +854,51 @@ namespace MWMechanics
// Innocent until proven guilty // Innocent until proven guilty
bool reported = false; bool reported = false;
// Find all the NPCs within the alarm radius // Find all the actors within the alarm radius
std::vector<MWWorld::Ptr> neighbors; std::vector<MWWorld::Ptr> neighbors;
mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos), mActors.getObjectsInRange(Ogre::Vector3(ptr.getRefData().getPosition().pos),
esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getInt(), neighbors); esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getInt(), neighbors);
// Find an actor who witnessed the crime int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId();
// Find actors who witnessed the crime
for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it) for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
{ {
if ( *it == ptr if (*it == ptr) continue; // not the player
|| !it->getClass().isNpc()) continue; // not the player and is an NPC
// Was the crime seen? // Was the crime seen?
if ( ( MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) ) || if (MWBase::Environment::get().getWorld()->getLOS(ptr, *it) && awarenessCheck(ptr, *it) )
type == OT_Assault )
{ {
// TODO: Add more messages
if (type == OT_Theft)
MWBase::Environment::get().getDialogueManager()->say(*it, "thief");
if (*it == victim)
{
// Self-defense
// The victim is aware of the criminal/assailant. If being assaulted, fight back now
// (regardless of whether the assault is reported or not)
// This applies to both NPCs and creatures
// ... except if this is a guard: then the player is given a chance to pay a fine / go to jail instead
if (type == OT_Assault && !ptr.getClass().isClass(ptr, "guard"))
MWBase::Environment::get().getMechanicsManager()->startCombat(victim, ptr);
}
// Crime reporting only applies to NPCs
if (!it->getClass().isNpc())
continue;
// Will the witness report the crime? // Will the witness report the crime?
if (it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm) if (it->getClass().getCreatureStats(*it).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm)
{ {
reported = true; reported = true;
int id = MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId();
// Tell everyone, including yourself // Tell everyone, including yourself
for (std::vector<MWWorld::Ptr>::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1) for (std::vector<MWWorld::Ptr>::iterator it1 = neighbors.begin(); it1 != neighbors.end(); ++it1)
{ {
if ( *it == ptr if ( *it1 == ptr
|| !it->getClass().isNpc()) continue; // not the player and is an NPC || !it1->getClass().isNpc()) continue; // not the player and is an NPC
// TODO: Add more messages
if (type == OT_Theft)
MWBase::Environment::get().getDialogueManager()->say(*it1, "thief");
else if (type == OT_Assault)
MWBase::Environment::get().getDialogueManager()->say(*it1, "attack");
// Will other witnesses paticipate in crime // Will other witnesses paticipate in crime
if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm if ( it1->getClass().getCreatureStats(*it1).getAiSetting(CreatureStats::AI_Alarm).getBase() >= alarm
@ -896,7 +910,6 @@ namespace MWMechanics
// Mark as Alarmed for dialogue // Mark as Alarmed for dialogue
it1->getClass().getCreatureStats(*it1).setAlarmed(true); it1->getClass().getCreatureStats(*it1).setAlarmed(true);
} }
break; // Someone saw the crime and everyone has been told
} }
} }
} }
@ -1007,6 +1020,14 @@ namespace MWMechanics
return (roll >= target); return (roll >= target);
} }
void MechanicsManager::startCombat(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target)
{
MWBase::Environment::get().getDialogueManager()->say(ptr, "attack");
ptr.getClass().getCreatureStats(ptr).getAiSequence().stack(MWMechanics::AiCombat(target), ptr);
if (target == MWBase::Environment::get().getWorld()->getPlayerPtr())
ptr.getClass().getCreatureStats(ptr).setHostile(true);
}
void MechanicsManager::getObjectsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects) void MechanicsManager::getObjectsInRange(const Ogre::Vector3 &position, float radius, std::vector<MWWorld::Ptr> &objects)
{ {
mActors.getObjectsInRange(position, radius, objects); mActors.getObjectsInRange(position, radius, objects);

@ -105,6 +105,9 @@ namespace MWMechanics
/// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check! /// Check if \a observer is potentially aware of \a ptr. Does not do a line of sight check!
virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer); virtual bool awarenessCheck (const MWWorld::Ptr& ptr, const MWWorld::Ptr& observer);
/// Makes \a ptr fight \a target. Also shouts a combat taunt.
virtual void startCombat (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target);
/** /**
* @brief Commit a crime. If any actors witness the crime and report it, * @brief Commit a crime. If any actors witness the crime and report it,
* reportCrime will be called automatically. * reportCrime will be called automatically.

@ -16,7 +16,6 @@
#include "../mwmechanics/aifollow.hpp" #include "../mwmechanics/aifollow.hpp"
#include "../mwmechanics/aitravel.hpp" #include "../mwmechanics/aitravel.hpp"
#include "../mwmechanics/aiwander.hpp" #include "../mwmechanics/aiwander.hpp"
#include "../mwmechanics/aicombat.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -435,12 +434,8 @@ namespace MWScript
std::string targetID = runtime.getStringLiteral (runtime[0].mInteger); std::string targetID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop(); runtime.pop();
MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor); MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr(targetID, true);
MWBase::Environment::get().getMechanicsManager()->startCombat(actor, target);
creatureStats.setHostile(true);
creatureStats.getAiSequence().stack(
MWMechanics::AiCombat(MWBase::Environment::get().getWorld()->getPtr(targetID, true) ), actor);
} }
}; };

@ -1,137 +0,0 @@
#ifdef OPENMW_USE_AUDIERE
#include <stdexcept>
#include <iostream>
#include "audiere_decoder.hpp"
static void fail(const std::string &msg)
{ throw std::runtime_error("Audiere exception: "+msg); }
namespace MWSound
{
class OgreFile : public audiere::File
{
Ogre::DataStreamPtr mStream;
ADR_METHOD(int) read(void* buffer, int size)
{
return mStream->read(buffer, size);
}
ADR_METHOD(bool) seek(int position, SeekMode mode)
{
if(mode == CURRENT)
mStream->seek(mStream->tell()+position);
else if(mode == BEGIN)
mStream->seek(position);
else if(mode == END)
mStream->seek(mStream->size()+position);
else
return false;
return true;
}
ADR_METHOD(int) tell()
{
return mStream->tell();
}
size_t refs;
ADR_METHOD(void) ref() { ++refs; }
ADR_METHOD(void) unref()
{
if(--refs == 0)
delete this;
}
public:
OgreFile(const Ogre::DataStreamPtr &stream)
: mStream(stream), refs(1)
{ }
virtual ~OgreFile() { }
Ogre::String getName()
{ return mStream->getName(); }
};
void Audiere_Decoder::open(const std::string &fname)
{
close();
mSoundFile = audiere::FilePtr(new OgreFile(mResourceMgr.openResource(fname)));
mSoundSource = audiere::OpenSampleSource(mSoundFile);
mSoundFileName = fname;
int channels, srate;
audiere::SampleFormat format;
mSoundSource->getFormat(channels, srate, format);
if(format == audiere::SF_S16)
mSampleType = SampleType_Int16;
else if(format == audiere::SF_U8)
mSampleType = SampleType_UInt8;
else
fail("Unsupported sample type");
if(channels == 1)
mChannelConfig = ChannelConfig_Mono;
else if(channels == 2)
mChannelConfig = ChannelConfig_Stereo;
else
fail("Unsupported channel count");
mSampleRate = srate;
}
void Audiere_Decoder::close()
{
mSoundFile = NULL;
mSoundSource = NULL;
}
std::string Audiere_Decoder::getName()
{
return mSoundFileName;
}
void Audiere_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
{
*samplerate = mSampleRate;
*chans = mChannelConfig;
*type = mSampleType;
}
size_t Audiere_Decoder::read(char *buffer, size_t bytes)
{
int size = bytesToFrames(bytes, mChannelConfig, mSampleType);
size = mSoundSource->read(size, buffer);
return framesToBytes(size, mChannelConfig, mSampleType);
}
void Audiere_Decoder::rewind()
{
mSoundSource->reset();
}
size_t Audiere_Decoder::getSampleOffset()
{
return 0;
}
Audiere_Decoder::Audiere_Decoder()
{
}
Audiere_Decoder::~Audiere_Decoder()
{
close();
}
}
#endif

@ -1,46 +0,0 @@
#ifndef GAME_SOUND_AUDIERE_DECODER_H
#define GAME_SOUND_AUDIERE_DECODER_H
#include <OgreDataStream.h>
#include "audiere.h"
#include "sound_decoder.hpp"
namespace MWSound
{
class Audiere_Decoder : public Sound_Decoder
{
std::string mSoundFileName;
audiere::FilePtr mSoundFile;
audiere::SampleSourcePtr mSoundSource;
int mSampleRate;
SampleType mSampleType;
ChannelConfig mChannelConfig;
virtual void open(const std::string &fname);
virtual void close();
virtual std::string getName();
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
virtual size_t read(char *buffer, size_t bytes);
virtual void rewind();
virtual size_t getSampleOffset();
Audiere_Decoder& operator=(const Audiere_Decoder &rhs);
Audiere_Decoder(const Audiere_Decoder &rhs);
Audiere_Decoder();
public:
virtual ~Audiere_Decoder();
friend class SoundManager;
};
#ifndef DEFAULT_DECODER
#define DEFAULT_DECODER (::MWSound::Audiere_Decoder)
#endif
};
#endif

@ -1,247 +0,0 @@
#ifdef OPENMW_USE_MPG123
#include <stdexcept>
#include <iostream>
#include "mpgsnd_decoder.hpp"
static void fail(const std::string &msg)
{ throw std::runtime_error("MpgSnd exception: "+msg); }
namespace MWSound
{
//
// libSndFile io callbacks
//
sf_count_t MpgSnd_Decoder::ogresf_get_filelen(void *user_data)
{
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
return stream->size();
}
sf_count_t MpgSnd_Decoder::ogresf_seek(sf_count_t offset, int whence, void *user_data)
{
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
if(whence == SEEK_CUR)
stream->seek(stream->tell()+offset);
else if(whence == SEEK_SET)
stream->seek(offset);
else if(whence == SEEK_END)
stream->seek(stream->size()+offset);
else
return -1;
return stream->tell();
}
sf_count_t MpgSnd_Decoder::ogresf_read(void *ptr, sf_count_t count, void *user_data)
{
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
return stream->read(ptr, count);
}
sf_count_t MpgSnd_Decoder::ogresf_write(const void*, sf_count_t, void*)
{ return -1; }
sf_count_t MpgSnd_Decoder::ogresf_tell(void *user_data)
{
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
return stream->tell();
}
//
// libmpg13 io callbacks
//
ssize_t MpgSnd_Decoder::ogrempg_read(void *user_data, void *ptr, size_t count)
{
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
return stream->read(ptr, count);
}
off_t MpgSnd_Decoder::ogrempg_lseek(void *user_data, off_t offset, int whence)
{
Ogre::DataStreamPtr stream = static_cast<MpgSnd_Decoder*>(user_data)->mDataStream;
if(whence == SEEK_CUR)
stream->seek(stream->tell()+offset);
else if(whence == SEEK_SET)
stream->seek(offset);
else if(whence == SEEK_END)
stream->seek(stream->size()+offset);
else
return -1;
return stream->tell();
}
void MpgSnd_Decoder::open(const std::string &fname)
{
close();
mDataStream = mResourceMgr.openResource(fname);
SF_VIRTUAL_IO streamIO = {
ogresf_get_filelen, ogresf_seek,
ogresf_read, ogresf_write, ogresf_tell
};
mSndFile = sf_open_virtual(&streamIO, SFM_READ, &mSndInfo, this);
if(mSndFile)
{
if(mSndInfo.channels == 1)
mChanConfig = ChannelConfig_Mono;
else if(mSndInfo.channels == 2)
mChanConfig = ChannelConfig_Stereo;
else
{
sf_close(mSndFile);
mSndFile = NULL;
fail("Unsupported channel count in "+fname);
}
mSampleRate = mSndInfo.samplerate;
return;
}
mDataStream->seek(0);
mMpgFile = mpg123_new(NULL, NULL);
if(mMpgFile && mpg123_replace_reader_handle(mMpgFile, ogrempg_read, ogrempg_lseek, NULL) == MPG123_OK &&
mpg123_open_handle(mMpgFile, this) == MPG123_OK)
{
try
{
int encoding, channels;
long rate;
if(mpg123_getformat(mMpgFile, &rate, &channels, &encoding) != MPG123_OK)
fail("Failed to get audio format");
if(encoding != MPG123_ENC_SIGNED_16)
fail("Unsupported encoding in "+fname);
if(channels != 1 && channels != 2)
fail("Unsupported channel count in "+fname);
mChanConfig = ((channels==2)?ChannelConfig_Stereo:ChannelConfig_Mono);
mSampleRate = rate;
return;
}
catch(std::exception &e)
{
mpg123_close(mMpgFile);
mpg123_delete(mMpgFile);
mMpgFile = NULL;
throw;
}
mpg123_close(mMpgFile);
}
if(mMpgFile)
mpg123_delete(mMpgFile);
mMpgFile = NULL;
fail("Unsupported file type: "+fname);
}
void MpgSnd_Decoder::close()
{
if(mSndFile)
sf_close(mSndFile);
mSndFile = NULL;
if(mMpgFile)
{
mpg123_close(mMpgFile);
mpg123_delete(mMpgFile);
mMpgFile = NULL;
}
mDataStream.setNull();
}
std::string MpgSnd_Decoder::getName()
{
return mDataStream->getName();
}
void MpgSnd_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *type)
{
if(!mSndFile && !mMpgFile)
fail("No open file");
*samplerate = mSampleRate;
*chans = mChanConfig;
*type = SampleType_Int16;
}
size_t MpgSnd_Decoder::read(char *buffer, size_t bytes)
{
size_t got = 0;
if(mSndFile)
{
got = sf_read_short(mSndFile, (short*)buffer, bytes/2)*2;
}
else if(mMpgFile)
{
int err;
err = mpg123_read(mMpgFile, (unsigned char*)buffer, bytes, &got);
if(err != MPG123_OK && err != MPG123_DONE)
fail("Failed to read from file");
}
return got;
}
void MpgSnd_Decoder::readAll(std::vector<char> &output)
{
if(mSndFile && mSndInfo.frames > 0)
{
size_t pos = output.size();
output.resize(pos + mSndInfo.frames*mSndInfo.channels*2);
sf_readf_short(mSndFile, (short*)(&output[0]+pos), mSndInfo.frames);
return;
}
// Fallback in case we don't know the total already
Sound_Decoder::readAll(output);
}
void MpgSnd_Decoder::rewind()
{
if(!mSndFile && !mMpgFile)
fail("No open file");
if(mSndFile)
{
if(sf_seek(mSndFile, 0, SEEK_SET) == -1)
fail("seek failed");
}
else if(mMpgFile)
{
if(mpg123_seek(mMpgFile, 0, SEEK_SET) < 0)
fail("seek failed");
}
}
size_t MpgSnd_Decoder::getSampleOffset()
{
return 0;
}
MpgSnd_Decoder::MpgSnd_Decoder()
: mSndInfo()
, mSndFile(NULL)
, mMpgFile(NULL)
, mDataStream()
, mChanConfig(ChannelConfig_Stereo)
, mSampleRate(0)
{
static bool initdone = false;
if(!initdone)
mpg123_init();
initdone = true;
}
MpgSnd_Decoder::~MpgSnd_Decoder()
{
close();
}
}
#endif

@ -1,59 +0,0 @@
#ifndef GAME_SOUND_MPGSND_DECODER_H
#define GAME_SOUND_MPGSND_DECODER_H
#include <string>
#include <OgreDataStream.h>
#include "mpg123.h"
#include "sndfile.h"
#include "sound_decoder.hpp"
namespace MWSound
{
class MpgSnd_Decoder : public Sound_Decoder
{
SF_INFO mSndInfo;
SNDFILE *mSndFile;
mpg123_handle *mMpgFile;
Ogre::DataStreamPtr mDataStream;
static sf_count_t ogresf_get_filelen(void *user_data);
static sf_count_t ogresf_seek(sf_count_t offset, int whence, void *user_data);
static sf_count_t ogresf_read(void *ptr, sf_count_t count, void *user_data);
static sf_count_t ogresf_write(const void*, sf_count_t, void*);
static sf_count_t ogresf_tell(void *user_data);
static ssize_t ogrempg_read(void*, void*, size_t);
static off_t ogrempg_lseek(void*, off_t, int);
ChannelConfig mChanConfig;
int mSampleRate;
virtual void open(const std::string &fname);
virtual void close();
virtual std::string getName();
virtual void getInfo(int *samplerate, ChannelConfig *chans, SampleType *type);
virtual size_t read(char *buffer, size_t bytes);
virtual void readAll(std::vector<char> &output);
virtual void rewind();
virtual size_t getSampleOffset();
MpgSnd_Decoder& operator=(const MpgSnd_Decoder &rhs);
MpgSnd_Decoder(const MpgSnd_Decoder &rhs);
MpgSnd_Decoder();
public:
virtual ~MpgSnd_Decoder();
friend class SoundManager;
};
#ifndef DEFAULT_DECODER
#define DEFAULT_DECODER (::MWSound::MpgSnd_Decoder)
#endif
}
#endif

@ -17,8 +17,8 @@
#include "openal_output.hpp" #include "openal_output.hpp"
#define SOUND_OUT "OpenAL" #define SOUND_OUT "OpenAL"
/* Set up the sound manager to use FFMPEG, MPG123+libsndfile, or Audiere for /* Set up the sound manager to use FFMPEG for input.
* input. The OPENMW_USE_x macros are set in CMakeLists.txt. * The OPENMW_USE_x macros are set in CMakeLists.txt.
*/ */
#ifdef OPENMW_USE_FFMPEG #ifdef OPENMW_USE_FFMPEG
#include "ffmpeg_decoder.hpp" #include "ffmpeg_decoder.hpp"
@ -27,20 +27,6 @@
#endif #endif
#endif #endif
#ifdef OPENMW_USE_AUDIERE
#include "audiere_decoder.hpp"
#ifndef SOUND_IN
#define SOUND_IN "Audiere"
#endif
#endif
#ifdef OPENMW_USE_MPG123
#include "mpgsnd_decoder.hpp"
#ifndef SOUND_IN
#define SOUND_IN "mpg123,sndfile"
#endif
#endif
namespace MWSound namespace MWSound
{ {

@ -100,7 +100,6 @@ namespace MWWorld
void Player::setLeftRight (int value) void Player::setLeftRight (int value)
{ {
MWWorld::Ptr ptr = getPlayer(); MWWorld::Ptr ptr = getPlayer();
MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[0] = value; MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[0] = value;
} }
@ -119,7 +118,6 @@ namespace MWWorld
void Player::setUpDown(int value) void Player::setUpDown(int value)
{ {
MWWorld::Ptr ptr = getPlayer(); MWWorld::Ptr ptr = getPlayer();
MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[2] = value; MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[2] = value;
} }
@ -132,28 +130,7 @@ namespace MWWorld
void Player::setSneak(bool sneak) void Player::setSneak(bool sneak)
{ {
MWWorld::Ptr ptr = getPlayer(); MWWorld::Ptr ptr = getPlayer();
ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak); ptr.getClass().getCreatureStats(ptr).setMovementFlag(MWMechanics::CreatureStats::Flag_Sneak, sneak);
if (sneak == true)
{
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
// Find all the actors who might be able to see the player
std::vector<MWWorld::Ptr> neighbors;
MWBase::Environment::get().getMechanicsManager()->getActorsInRange( Ogre::Vector3(ptr.getRefData().getPosition().pos),
esmStore.get<ESM::GameSetting>().find("fSneakUseDist")->getInt(), neighbors);
for (std::vector<MWWorld::Ptr>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
{
if ( MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, *it) )
{
MWBase::Environment::get().getWindowManager()->setSneakVisibility(false);
break;
}
}
if (neighbors.empty())
MWBase::Environment::get().getWindowManager()->setSneakVisibility(true);
}
} }
void Player::yaw(float yaw) void Player::yaw(float yaw)

@ -1,60 +0,0 @@
# Locate Audiere
# This module defines
# AUDIERE_LIBRARY
# AUDIERE_FOUND, if false, do not try to link to Audiere
# AUDIERE_INCLUDE_DIR, where to find the headers
#
# Created by Nicolay Korslund for OpenMW (http://openmw.com)
#
# More or less a direct ripoff of FindOpenAL.cmake by Eric Wing.
#=============================================================================
# Copyright 2005-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distributed this file outside of CMake, substitute the full
# License text for the above reference.)
FIND_PATH(AUDIERE_INCLUDE_DIR audiere.h
HINTS
PATH_SUFFIXES include
PATHS
$ENV{AUDIERE_DIR}
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
)
FIND_LIBRARY(AUDIERE_LIBRARY
NAMES audiere
HINTS
PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64
PATHS
$ENV{AUDIERE_DIR}
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw
/opt/local
/opt/csw
/opt
)
SET(AUDIERE_FOUND "NO")
IF(AUDIERE_LIBRARY AND AUDIERE_INCLUDE_DIR)
SET(AUDIERE_FOUND "YES")
ENDIF(AUDIERE_LIBRARY AND AUDIERE_INCLUDE_DIR)

@ -1,47 +0,0 @@
# Locate MPG123
# This module defines
# MPG123_LIBRARY
# MPG123_FOUND, if false, do not try to link to Mpg123
# MPG123_INCLUDE_DIR, where to find the headers
#
# Created by Nicolay Korslund for OpenMW (http://openmw.com)
#
# Ripped off from other sources. In fact, this file is so generic (I
# just did a search and replace on another file) that I wonder why the
# CMake guys haven't wrapped this entire thing in a single
# function. Do we really need to repeat this stuff for every single
# library when they all work the same? </today's rant>
FIND_PATH(MPG123_INCLUDE_DIR mpg123.h
HINTS
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
)
FIND_LIBRARY(MPG123_LIBRARY
NAMES mpg123
HINTS
PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw
/opt/local
/opt/csw
/opt
)
SET(MPG123_FOUND "NO")
IF(MPG123_LIBRARY AND MPG123_INCLUDE_DIR)
SET(MPG123_FOUND "YES")
ENDIF(MPG123_LIBRARY AND MPG123_INCLUDE_DIR)

@ -1,41 +0,0 @@
# Locate SNDFILE
# This module defines
# SNDFILE_LIBRARY
# SNDFILE_FOUND, if false, do not try to link to Sndfile
# SNDFILE_INCLUDE_DIR, where to find the headers
#
# Created by Nicolay Korslund for OpenMW (http://openmw.com)
FIND_PATH(SNDFILE_INCLUDE_DIR sndfile.h
HINTS
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
)
FIND_LIBRARY(SNDFILE_LIBRARY
NAMES sndfile
HINTS
PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw
/opt/local
/opt/csw
/opt
)
SET(SNDFILE_FOUND "NO")
IF(SNDFILE_LIBRARY AND SNDFILE_INCLUDE_DIR)
SET(SNDFILE_FOUND "YES")
ENDIF(SNDFILE_LIBRARY AND SNDFILE_INCLUDE_DIR)
Loading…
Cancel
Save