1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-25 15:35:23 +00:00

Merge branch 'master' of https://github.com/zinnschlag/openmw into dialogoue3

This commit is contained in:
Marek Kochanowicz 2014-03-07 17:16:38 +01:00
commit 020e3f8fc5
137 changed files with 2559 additions and 1198 deletions

View File

@ -7,7 +7,6 @@ branches:
- /openmw-.*$/
before_install:
- pwd
- git fetch --tags
- echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
- echo "yes" | sudo apt-add-repository ppa:openmw/openmw
- sudo apt-get update -qq

View File

@ -6,34 +6,63 @@ if (APPLE)
set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/${APP_BUNDLE_NAME}")
endif (APPLE)
# Macros
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
include(OpenMWMacros)
# Version
message(STATUS "Configuring OpenMW...")
include(GetGitRevisionDescription)
set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 29)
set(OPENMW_VERSION_RELEASE 0)
get_git_tag_revision(TAGHASH --tags --max-count=1 "HEAD...")
get_git_head_revision(REFSPEC COMMITHASH)
git_describe(VERSION --tags ${TAGHASH})
set(OPENMW_VERSION_COMMITHASH "")
set(OPENMW_VERSION_TAGHASH "")
string(REGEX MATCH "^openmw-[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+.*" MATCH "${VERSION}")
if (MATCH)
string(REGEX REPLACE "^openmw-([0-9]+)\\..*" "\\1" OPENMW_VERSION_MAJOR "${VERSION}")
string(REGEX REPLACE "^openmw-[0-9]+\\.([0-9]+).*" "\\1" OPENMW_VERSION_MINOR "${VERSION}")
string(REGEX REPLACE "^openmw-[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" OPENMW_VERSION_RELEASE "${VERSION}")
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
set(OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}")
set(OPENMW_VERSION_TAGHASH "${TAGHASH}")
if(EXISTS ${PROJECT_SOURCE_DIR}/.git)
if(NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/shallow)
find_package(Git)
message(STATUS "Configuring OpenMW ${OPENMW_VERSION}...")
else (MATCH)
message(FATAL_ERROR "Failed to get valid version information from Git")
endif (MATCH)
if(GIT_FOUND)
include(GetGitRevisionDescription)
get_git_tag_revision(TAGHASH --tags --max-count=1)
get_git_head_revision(REFSPEC COMMITHASH)
git_describe(VERSION --tags ${TAGHASH})
string(REGEX MATCH "^openmw-[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+.*" MATCH "${VERSION}")
if(MATCH)
string(REGEX REPLACE "^openmw-([0-9]+)\\..*" "\\1" GIT_VERSION_MAJOR "${VERSION}")
string(REGEX REPLACE "^openmw-[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_MINOR "${VERSION}")
string(REGEX REPLACE "^openmw-[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_RELEASE "${VERSION}")
set(GIT_VERSION "${GIT_VERSION_MAJOR}.${GIT_VERSION_MINOR}.${GIT_VERSION_RELEASE}")
if(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION})
message(FATAL_ERROR "Silly Zini forgot to update the version again...")
else(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION})
set(OPENMW_VERSION_MAJOR ${GIT_VERSION_MAJOR})
set(OPENMW_VERSION_MINOR ${GIT_VERSION_MINOR})
set(OPENMW_VERSION_RELEASE ${GIT_VERSION_RELEASE})
set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}")
set(OPENMW_VERSION_TAGHASH "${TAGHASH}")
endif(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION})
message(STATUS "OpenMW version ${OPENMW_VERSION}")
else(MATCH)
message(WARNING "Failed to get valid version information from Git")
endif(MATCH)
else(GIT_FOUND)
message(WARNING "Git executable not found")
endif(GIT_FOUND)
else(NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/shallow)
message(STATUS "Shallow Git clone detected, not attempting to retrieve version info")
endif(NOT EXISTS ${PROJECT_SOURCE_DIR}/.git/shallow)
endif(EXISTS ${PROJECT_SOURCE_DIR}/.git)
# Macros
include(OpenMWMacros)
# doxygen main page
@ -209,6 +238,14 @@ if (UNIX AND NOT APPLE)
find_package (Threads)
endif()
# Look for stdint.h
include(CheckIncludeFile)
check_include_file(stdint.h HAVE_STDINT_H)
if(NOT HAVE_STDINT_H)
unset(HAVE_STDINT_H CACHE)
message(FATAL_ERROR "stdint.h was not found" )
endif()
include (CheckIncludeFileCXX)
check_include_file_cxx(unordered_map HAVE_UNORDERED_MAP)
if (HAVE_UNORDERED_MAP)

View File

@ -76,17 +76,20 @@ Launcher::MainDialog::MainDialog(QWidget *parent)
QString revision(OPENMW_VERSION_COMMITHASH);
QString tag(OPENMW_VERSION_TAGHASH);
if (revision == tag) {
versionLabel->setText(tr("OpenMW %0 release").arg(OPENMW_VERSION));
} else {
versionLabel->setText(tr("OpenMW development (%0)").arg(revision.left(10)));
}
if (!revision.isEmpty() && !tag.isEmpty())
{
if (revision == tag) {
versionLabel->setText(tr("OpenMW %0 release").arg(OPENMW_VERSION));
} else {
versionLabel->setText(tr("OpenMW development (%0)").arg(revision.left(10)));
}
// Add the compile date and time
versionLabel->setToolTip(tr("Compiled on %0 %1").arg(QLocale(QLocale::C).toDate(QString(__DATE__).simplified(),
QLatin1String("MMM d yyyy")).toString(Qt::SystemLocaleLongDate),
QLocale(QLocale::C).toTime(QString(__TIME__).simplified(),
QLatin1String("hh:mm:ss")).toString(Qt::SystemLocaleShortDate)));
// Add the compile date and time
versionLabel->setToolTip(tr("Compiled on %0 %1").arg(QLocale(QLocale::C).toDate(QString(__DATE__).simplified(),
QLatin1String("MMM d yyyy")).toString(Qt::SystemLocaleLongDate),
QLocale(QLocale::C).toTime(QString(__TIME__).simplified(),
QLatin1String("hh:mm:ss")).toString(Qt::SystemLocaleShortDate)));
}
createIcons();
}

View File

@ -64,8 +64,12 @@ opencs_units (view/world
)
opencs_units (view/render
scenewidget
)
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
)
opencs_units_noqt (view/render
navigation navigation1st navigationfree navigationorbit
)
opencs_units_noqt (view/world
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate

View File

@ -9,15 +9,22 @@
#include <OgreRoot.h>
#include <OgreRenderWindow.h>
#include <components/ogreinit/ogreinit.hpp>
#include "model/doc/document.hpp"
#include "model/world/data.hpp"
CS::Editor::Editor()
: mDocumentManager (mCfgMgr), mViewManager (mDocumentManager)
CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
: mDocumentManager (mCfgMgr), mViewManager (mDocumentManager),
mIpcServerName ("org.openmw.OpenCS")
{
mIpcServerName = "org.openmw.OpenCS";
Files::PathContainer dataDirs = readConfig();
setupDataFiles();
setupDataFiles (dataDirs);
CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg");
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
mNewGame.setLocalData (mLocal);
mFileDialog.setLocalData (mLocal);
@ -42,7 +49,16 @@ CS::Editor::Editor()
this, SLOT (createNewGame (const boost::filesystem::path&)));
}
void CS::Editor::setupDataFiles()
void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs)
{
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
{
QString path = QString::fromStdString(iter->string());
mFileDialog.addFiles(path);
}
}
Files::PathContainer CS::Editor::readConfig()
{
boost::program_options::variables_map variables;
boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options");
@ -58,6 +74,8 @@ void CS::Editor::setupDataFiles()
mCfgMgr.readConfiguration(variables, desc);
mDocumentManager.setResourceDir (variables["resources"].as<std::string>());
Files::PathContainer dataDirs, dataLocal;
if (!variables["data"].empty()) {
dataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
@ -83,23 +101,11 @@ void CS::Editor::setupDataFiles()
messageBox.exec();
QApplication::exit (1);
return;
}
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
mDocumentManager.setResourceDir (variables["resources"].as<std::string>());
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
{
QString path = QString::fromStdString(iter->string());
mFileDialog.addFiles(path);
}
//load the settings into the userSettings instance.
const QString settingFileName = "opencs.cfg";
CSMSettings::UserSettings::instance().loadSettings(settingFileName);
return dataDirs;
}
void CS::Editor::createGame()
@ -210,8 +216,6 @@ int CS::Editor::run()
if (mLocal.empty())
return 1;
// temporarily disable OGRE-integration (need to fix path problem first)
#if 0
// TODO: setting
Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem"));
@ -228,7 +232,6 @@ int CS::Editor::run()
#endif
Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, &params);
hiddenWindow->setActive(false);
#endif
mStartup.show();

View File

@ -10,6 +10,8 @@
#include <components/files/configurationmanager.hpp>
#endif
#include <components/files/multidircollection.hpp>
#include "model/settings/usersettings.hpp"
#include "model/doc/documentmanager.hpp"
@ -20,6 +22,11 @@
#include "view/settings/usersettingsdialog.hpp"
namespace OgreInit
{
class OgreInit;
}
namespace CS
{
class Editor : public QObject
@ -37,7 +44,10 @@ namespace CS
boost::filesystem::path mLocal;
void setupDataFiles();
void setupDataFiles (const Files::PathContainer& dataDirs);
Files::PathContainer readConfig();
///< \return data paths
// not implemented
Editor (const Editor&);
@ -45,7 +55,7 @@ namespace CS
public:
Editor();
Editor (OgreInit::OgreInit& ogreInit);
bool makeIPCServer();
void connectToIPCServer();

View File

@ -40,15 +40,9 @@ int main(int argc, char *argv[])
{
Q_INIT_RESOURCE (resources);
// TODO: Ogre startup shouldn't be here, but it currently has to:
// SceneWidget destructor will delete the created render window, which would be called _after_ Root has shut down :(
Application mApplication (argc, argv);
// temporarily disable OGRE-integration (need to fix path problem first)
#if 0
OgreInit::OgreInit ogreInit;
ogreInit.init("./opencsOgre.log"); // TODO log path?
#endif
Application application (argc, argv);
#ifdef Q_OS_MAC
QDir dir(QCoreApplication::applicationDirPath());
@ -66,12 +60,12 @@ int main(int argc, char *argv[])
QStringList libraryPaths;
libraryPaths << pluginsPath.path() << QCoreApplication::applicationDirPath();
mApplication.setLibraryPaths(libraryPaths);
application.setLibraryPaths(libraryPaths);
#endif
mApplication.setWindowIcon (QIcon (":./opencs.png"));
application.setWindowIcon (QIcon (":./opencs.png"));
CS::Editor editor;
CS::Editor editor (ogreInit);
if(!editor.makeIPCServer())
{

View File

@ -98,7 +98,7 @@ namespace CSMWorld
UniversalId::Type type = UniversalId::Type_None);
///< \param type Will be ignored, unless the collection supports multiple record types
virtual void cloneRecord(const std::string& origin,
virtual void cloneRecord(const std::string& origin,
const std::string& destination,
const UniversalId::Type type);
@ -198,7 +198,7 @@ namespace CSMWorld
}
template<typename ESXRecordT, typename IdAccessorT>
void Collection<ESXRecordT, IdAccessorT>::cloneRecord(const std::string& origin,
void Collection<ESXRecordT, IdAccessorT>::cloneRecord(const std::string& origin,
const std::string& destination,
const UniversalId::Type type)
{

View File

@ -74,7 +74,7 @@ namespace CSMWorld
UniversalId::Type type = UniversalId::Type_None) = 0;
///< If the record type does not match, an exception is thrown.
virtual void cloneRecord(const std::string& origin,
virtual void cloneRecord(const std::string& origin,
const std::string& destination,
const UniversalId::Type type) = 0;

View File

@ -247,12 +247,12 @@ CSMWorld::Data::Data() : mRefs (mCells)
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic);
addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal);
addModel (new IdTable (&mTopicInfos), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo);
addModel (new IdTable (&mJournalInfos), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo);
addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mTopicInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo);
addModel (new IdTable (&mJournalInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo);
addModel (new IdTable (&mCells, IdTable::Reordering_None, IdTable::Viewing_Id), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs), UniversalId::Type_References, UniversalId::Type_Reference, false);
addModel (new IdTable (&mRefs, IdTable::Reordering_None, IdTable::Viewing_Cell), UniversalId::Type_References, UniversalId::Type_Reference, false);
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false);
}

View File

@ -4,8 +4,9 @@
#include "collectionbase.hpp"
#include "columnbase.hpp"
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering)
: mIdCollection (idCollection), mReordering (reordering)
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering,
Viewing viewing)
: mIdCollection (idCollection), mReordering (reordering), mViewing (viewing)
{}
CSMWorld::IdTable::~IdTable()
@ -188,4 +189,45 @@ void CSMWorld::IdTable::reorderRows (int baseIndex, const std::vector<int>& newO
CSMWorld::IdTable::Reordering CSMWorld::IdTable::getReordering() const
{
return mReordering;
}
CSMWorld::IdTable::Viewing CSMWorld::IdTable::getViewing() const
{
return mViewing;
}
std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const
{
std::string id;
std::string hint;
if (mViewing==Viewing_Cell)
{
int cellColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Cell);
int idColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
if (cellColumn!=-1 && idColumn!=-1)
{
id = mIdCollection->getData (row, cellColumn).toString().toUtf8().constData();
hint = "r:" + std::string (mIdCollection->getData (row, idColumn).toString().toUtf8().constData());
}
}
else if (mViewing==Viewing_Id)
{
int column = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
if (column!=-1)
{
id = mIdCollection->getData (row, column).toString().toUtf8().constData();
hint = "c:" + id;
}
}
if (id.empty())
return std::make_pair (UniversalId::Type_None, "");
if (id[0]=='#')
id = "sys::default";
return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint);
}

View File

@ -25,10 +25,20 @@ namespace CSMWorld
Reordering_WithinTopic
};
enum Viewing
{
Viewing_None,
Viewing_Id, // use ID column to generate view request (ID is transformed into
// worldspace and original ID is passed as hint with c: prefix)
Viewing_Cell // use cell column to generate view request (cell ID is transformed
// into worldspace and record ID is passed as hint with r: prefix)
};
private:
CollectionBase *mIdCollection;
Reordering mReordering;
Viewing mViewing;
// not implemented
IdTable (const IdTable&);
@ -36,7 +46,8 @@ namespace CSMWorld
public:
IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_WithinTopic);
IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None,
Viewing viewing = Viewing_None);
///< The ownership of \a idCollection is not transferred.
virtual ~IdTable();
@ -63,8 +74,8 @@ namespace CSMWorld
void addRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None);
///< \param type Will be ignored, unless the collection supports multiple record types
void cloneRecord(const std::string& origin,
const std::string& destination,
void cloneRecord(const std::string& origin,
const std::string& destination,
UniversalId::Type type = UniversalId::Type_None);
QModelIndex getModelIndex (const std::string& id, int column) const;
@ -86,6 +97,12 @@ namespace CSMWorld
/// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex).
Reordering getReordering() const;
Viewing getViewing() const;
std::pair<UniversalId, std::string> view (int row) const;
///< Return the UniversalId and the hint for viewing \a row. If viewing is not
/// supported by this table, return (UniversalId::Type_None, "").
};
}

View File

@ -90,14 +90,14 @@ namespace
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};
static const TypeData sIndexArg[] =
{
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};
}

View File

@ -16,4 +16,6 @@ void CSVDoc::SubView::updateEditorSetting (const QString &settingName, const QSt
{
}
void CSVDoc::SubView::setStatusBar (bool show) {}
void CSVDoc::SubView::setStatusBar (bool show) {}
void CSVDoc::SubView::useHint (const std::string& hint) {}

View File

@ -40,9 +40,12 @@ namespace CSVDoc
virtual void setStatusBar (bool show);
///< Default implementation: ignored
virtual void useHint (const std::string& hint);
///< Default implementation: ignored
signals:
void focusId (const CSMWorld::UniversalId& universalId);
void focusId (const CSMWorld::UniversalId& universalId, const std::string& hint);
};
}

View File

@ -115,10 +115,6 @@ void CSVDoc::View::setupWorldMenu()
world->addSeparator(); // items that don't represent single record lists follow here
QAction *scene = new QAction (tr ("Scene"), this);
connect (scene, SIGNAL (triggered()), this, SLOT (addSceneSubView()));
world->addAction (scene);
QAction *regionMap = new QAction (tr ("Region Map"), this);
connect (regionMap, SIGNAL (triggered()), this, SLOT (addRegionMapSubView()));
world->addAction (regionMap);
@ -310,7 +306,7 @@ void CSVDoc::View::updateProgress (int current, int max, int type, int threads)
mOperations->setProgress (current, max, type, threads);
}
void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id)
void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::string& hint)
{
/// \todo add an user setting for limiting the number of sub views per top level view. Automatically open a new top level view if this
/// number is exceeded
@ -322,12 +318,15 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id)
SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
if (!hint.empty())
view->useHint (hint);
view->setStatusBar (mShowStatusBar->isChecked());
mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view);
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this,
SLOT (addSubView (const CSMWorld::UniversalId&)));
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)), this,
SLOT (addSubView (const CSMWorld::UniversalId&, const std::string&)));
CSMSettings::UserSettings::instance().updateSettings("Display Format");
@ -429,11 +428,6 @@ void CSVDoc::View::addFiltersSubView()
addSubView (CSMWorld::UniversalId::Type_Filters);
}
void CSVDoc::View::addSceneSubView()
{
addSubView (CSMWorld::UniversalId::Type_Scene);
}
void CSVDoc::View::addTopicsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Topics);

View File

@ -120,7 +120,9 @@ namespace CSVDoc
public slots:
void addSubView (const CSMWorld::UniversalId& id);
void addSubView (const CSMWorld::UniversalId& id, const std::string& hint = "");
///< \param hint Suggested view point (e.g. coordinates in a 3D scene or a line number
/// in a script).
void abortOperation (int type);
@ -166,8 +168,6 @@ namespace CSVDoc
void addFiltersSubView();
void addSceneSubView();
void addTopicsSubView();
void addJournalsSubView();

View File

@ -0,0 +1,19 @@
#include "navigation.hpp"
float CSVRender::Navigation::getFactor (bool mouse) const
{
float factor = mFastModeFactor;
if (mouse)
factor /= 2; /// \todo make this configurable
return factor;
}
CSVRender::Navigation::~Navigation() {}
void CSVRender::Navigation::setFastModeFactor (float factor)
{
mFastModeFactor = factor;
}

View File

@ -0,0 +1,46 @@
#ifndef OPENCS_VIEW_NAVIGATION_H
#define OPENCS_VIEW_NAVIGATION_H
class QPoint;
namespace Ogre
{
class Camera;
}
namespace CSVRender
{
class Navigation
{
float mFastModeFactor;
protected:
float getFactor (bool mouse) const;
public:
virtual ~Navigation();
void setFastModeFactor (float factor);
///< Set currently applying fast mode factor.
virtual bool activate (Ogre::Camera *camera) = 0;
///< \return Update required?
virtual bool wheelMoved (int delta) = 0;
///< \return Update required?
virtual bool mouseMoved (const QPoint& delta, int mode) = 0;
///< \param mode: 0: default mouse key, 1: default mouse key and modifier key 1
/// \return Update required?
virtual bool handleMovementKeys (int vertical, int horizontal) = 0;
///< \return Update required?
virtual bool handleRollKeys (int delta) = 0;
///< \return Update required?
};
}
#endif

View File

@ -0,0 +1,85 @@
#include "navigation1st.hpp"
#include <OgreCamera.h>
#include <QPoint>
CSVRender::Navigation1st::Navigation1st() : mCamera (0) {}
bool CSVRender::Navigation1st::activate (Ogre::Camera *camera)
{
mCamera = camera;
mCamera->setFixedYawAxis (true);
Ogre::Radian pitch = mCamera->getOrientation().getPitch();
Ogre::Radian limit (Ogre::Math::PI/2-0.5);
if (pitch>limit)
mCamera->pitch (-(pitch-limit));
else if (pitch<-limit)
mCamera->pitch (pitch-limit);
return true;
}
bool CSVRender::Navigation1st::wheelMoved (int delta)
{
mCamera->move (getFactor (true) * mCamera->getDirection() * delta);
return true;
}
bool CSVRender::Navigation1st::mouseMoved (const QPoint& delta, int mode)
{
if (mode==0)
{
// turn camera
if (delta.x())
mCamera->yaw (Ogre::Degree (getFactor (true) * delta.x()));
if (delta.y())
{
Ogre::Radian oldPitch = mCamera->getOrientation().getPitch();
float deltaPitch = getFactor (true) * delta.y();
Ogre::Radian newPitch = oldPitch + Ogre::Degree (deltaPitch);
Ogre::Radian limit (Ogre::Math::PI/2-0.5);
if ((deltaPitch>0 && newPitch<limit) || (deltaPitch<0 && newPitch>-limit))
mCamera->pitch (Ogre::Degree (deltaPitch));
}
return true;
}
else if (mode==1)
{
// pan camera
if (delta.x())
mCamera->move (getFactor (true) * mCamera->getDerivedRight() * delta.x());
if (delta.y())
mCamera->move (getFactor (true) * -mCamera->getDerivedUp() * delta.y());
return true;
}
return false;
}
bool CSVRender::Navigation1st::handleMovementKeys (int vertical, int horizontal)
{
if (vertical)
mCamera->move (getFactor (false) * mCamera->getDirection() * vertical);
if (horizontal)
mCamera->move (getFactor (true) * mCamera->getDerivedRight() * horizontal);
return true;
}
bool CSVRender::Navigation1st::handleRollKeys (int delta)
{
// we don't roll this way in 1st person mode
return false;
}

View File

@ -0,0 +1,35 @@
#ifndef OPENCS_VIEW_NAVIGATION1ST_H
#define OPENCS_VIEW_NAVIGATION1ST_H
#include "navigation.hpp"
namespace CSVRender
{
/// \brief First person-like camera controls
class Navigation1st : public Navigation
{
Ogre::Camera *mCamera;
public:
Navigation1st();
virtual bool activate (Ogre::Camera *camera);
///< \return Update required?
virtual bool wheelMoved (int delta);
///< \return Update required?
virtual bool mouseMoved (const QPoint& delta, int mode);
///< \param mode: 0: default mouse key, 1: default mouse key and modifier key 1
/// \return Update required?
virtual bool handleMovementKeys (int vertical, int horizontal);
///< \return Update required?
virtual bool handleRollKeys (int delta);
///< \return Update required?
};
}
#endif

View File

@ -0,0 +1,66 @@
#include "navigationfree.hpp"
#include <OgreCamera.h>
#include <QPoint>
CSVRender::NavigationFree::NavigationFree() : mCamera (0) {}
bool CSVRender::NavigationFree::activate (Ogre::Camera *camera)
{
mCamera = camera;
mCamera->setFixedYawAxis (false);
return false;
}
bool CSVRender::NavigationFree::wheelMoved (int delta)
{
mCamera->move (getFactor (true) * mCamera->getDirection() * delta);
return true;
}
bool CSVRender::NavigationFree::mouseMoved (const QPoint& delta, int mode)
{
if (mode==0)
{
// turn camera
if (delta.x())
mCamera->yaw (Ogre::Degree (getFactor (true) * delta.x()));
if (delta.y())
mCamera->pitch (Ogre::Degree (getFactor (true) * delta.y()));
return true;
}
else if (mode==1)
{
// pan camera
if (delta.x())
mCamera->move (getFactor (true) * mCamera->getDerivedRight() * delta.x());
if (delta.y())
mCamera->move (getFactor (true) * -mCamera->getDerivedUp() * delta.y());
return true;
}
return false;
}
bool CSVRender::NavigationFree::handleMovementKeys (int vertical, int horizontal)
{
if (vertical)
mCamera->move (getFactor (false) * mCamera->getDerivedUp() * vertical);
if (horizontal)
mCamera->move (getFactor (true) * mCamera->getDerivedRight() * horizontal);
return true;
}
bool CSVRender::NavigationFree::handleRollKeys (int delta)
{
mCamera->roll (Ogre::Degree (getFactor (false) * delta));
return true;
}

View File

@ -0,0 +1,35 @@
#ifndef OPENCS_VIEW_NAVIGATIONFREE_H
#define OPENCS_VIEW_NAVIGATIONFREE_H
#include "navigation.hpp"
namespace CSVRender
{
/// \brief Free camera controls
class NavigationFree : public Navigation
{
Ogre::Camera *mCamera;
public:
NavigationFree();
virtual bool activate (Ogre::Camera *camera);
///< \return Update required?
virtual bool wheelMoved (int delta);
///< \return Update required?
virtual bool mouseMoved (const QPoint& delta, int mode);
///< \param mode: 0: default mouse key, 1: default mouse key and modifier key 1
/// \return Update required?
virtual bool handleMovementKeys (int vertical, int horizontal);
///< \return Update required?
virtual bool handleRollKeys (int delta);
///< \return Update required?
};
}
#endif

View File

@ -0,0 +1,100 @@
#include "navigationorbit.hpp"
#include <OgreCamera.h>
#include <QPoint>
void CSVRender::NavigationOrbit::rotateCamera (const Ogre::Vector3& diff)
{
Ogre::Vector3 pos = mCamera->getPosition();
float distance = (pos-mCentre).length();
Ogre::Vector3 direction = (pos+diff)-mCentre;
direction.normalise();
mCamera->setPosition (mCentre + direction*distance);
mCamera->lookAt (mCentre);
}
CSVRender::NavigationOrbit::NavigationOrbit() : mCamera (0), mCentre (0, 0, 0), mDistance (100)
{}
bool CSVRender::NavigationOrbit::activate (Ogre::Camera *camera)
{
mCamera = camera;
mCamera->setFixedYawAxis (false);
if ((mCamera->getPosition()-mCentre).length()<mDistance)
{
// move camera out of the centre area
Ogre::Vector3 direction = mCentre-mCamera->getPosition();
direction.normalise();
if (direction.length()==0)
direction = Ogre::Vector3 (1, 0, 0);
mCamera->setPosition (mCentre - direction * mDistance);
}
mCamera->lookAt (mCentre);
return true;
}
bool CSVRender::NavigationOrbit::wheelMoved (int delta)
{
Ogre::Vector3 diff = getFactor (true) * mCamera->getDirection() * delta;
Ogre::Vector3 pos = mCamera->getPosition();
if (delta>0 && diff.length()>=(pos-mCentre).length()-mDistance)
{
pos = mCentre-(mCamera->getDirection() * mDistance);
}
else
{
pos += diff;
}
mCamera->setPosition (pos);
return true;
}
bool CSVRender::NavigationOrbit::mouseMoved (const QPoint& delta, int mode)
{
Ogre::Vector3 diff =
getFactor (true) * -mCamera->getDerivedRight() * delta.x()
+ getFactor (true) * mCamera->getDerivedUp() * delta.y();
if (mode==0)
{
rotateCamera (diff);
return true;
}
else if (mode==1)
{
mCamera->move (diff);
mCentre += diff;
return true;
}
return false;
}
bool CSVRender::NavigationOrbit::handleMovementKeys (int vertical, int horizontal)
{
rotateCamera (
- getFactor (false) * -mCamera->getDerivedRight() * horizontal
+ getFactor (false) * mCamera->getDerivedUp() * vertical);
return true;
}
bool CSVRender::NavigationOrbit::handleRollKeys (int delta)
{
mCamera->roll (Ogre::Degree (getFactor (false) * delta));
return true;
}

View File

@ -0,0 +1,42 @@
#ifndef OPENCS_VIEW_NAVIGATIONORBIT_H
#define OPENCS_VIEW_NAVIGATIONORBIT_H
#include "navigation.hpp"
#include <OgreVector3.h>
namespace CSVRender
{
/// \brief Orbiting camera controls
class NavigationOrbit : public Navigation
{
Ogre::Camera *mCamera;
Ogre::Vector3 mCentre;
int mDistance;
void rotateCamera (const Ogre::Vector3& diff);
///< Rotate camera around centre.
public:
NavigationOrbit();
virtual bool activate (Ogre::Camera *camera);
///< \return Update required?
virtual bool wheelMoved (int delta);
///< \return Update required?
virtual bool mouseMoved (const QPoint& delta, int mode);
///< \param mode: 0: default mouse key, 1: default mouse key and modifier key 1
/// \return Update required?
virtual bool handleMovementKeys (int vertical, int horizontal);
///< \return Update required?
virtual bool handleRollKeys (int delta);
///< \return Update required?
};
}
#endif

View File

@ -0,0 +1,6 @@
#include "pagedworldspacewidget.hpp"
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent)
: WorldspaceWidget (parent)
{}

View File

@ -0,0 +1,18 @@
#ifndef OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
#define OPENCS_VIEW_PAGEDWORLDSPACEWIDGET_H
#include "worldspacewidget.hpp"
namespace CSVRender
{
class PagedWorldspaceWidget : public WorldspaceWidget
{
Q_OBJECT
public:
PagedWorldspaceWidget (QWidget *parent);
};
}
#endif

View File

@ -2,24 +2,34 @@
#include <QEvent>
#include <QResizeEvent>
#include <QTimer>
#include <OgreRoot.h>
#include <OgreRenderWindow.h>
#include <OgreEntity.h>
#include <OgreCamera.h>
#include <OgreSceneNode.h>
#include <OgreViewport.h>
#include "navigation.hpp"
namespace CSVRender
{
SceneWidget::SceneWidget(QWidget *parent)
: QWidget(parent)
, mWindow(NULL)
, mCamera(NULL)
, mSceneMgr(NULL)
, mSceneMgr(NULL), mNavigation (0), mUpdate (false)
, mKeyForward (false), mKeyBackward (false), mKeyLeft (false), mKeyRight (false)
, mKeyRollLeft (false), mKeyRollRight (false)
, mFast (false), mDragging (false), mMod1 (false)
, mFastFactor (4) /// \todo make this configurable
{
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground);
setFocusPolicy (Qt::StrongFocus);
mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
// Throw in a random color just to make sure multiple scenes work
@ -44,6 +54,16 @@ namespace CSVRender
mCamera->lookAt(0,0,0);
mCamera->setNearClipDistance(0.1);
mCamera->setFarClipDistance(3000);
QTimer *timer = new QTimer (this);
connect (timer, SIGNAL (timeout()), this, SLOT (update()));
timer->start (20); /// \todo make this configurable
}
void SceneWidget::setAmbient (const Ogre::ColourValue& colour)
{
mSceneMgr->setAmbientLight (colour);
}
void SceneWidget::updateOgreWindow()
@ -81,7 +101,21 @@ namespace CSVRender
SceneWidget::~SceneWidget()
{
Ogre::Root::getSingleton().destroyRenderTarget(mWindow);
if (mWindow)
Ogre::Root::getSingleton().destroyRenderTarget (mWindow);
if (mSceneMgr)
Ogre::Root::getSingleton().destroySceneManager (mSceneMgr);
}
void SceneWidget::setNavigation (Navigation *navigation)
{
if ((mNavigation = navigation))
{
mNavigation->setFastModeFactor (mFast ? mFastFactor : 1);
if (mNavigation->activate (mCamera))
mUpdate = true;
}
}
void SceneWidget::paintEvent(QPaintEvent* e)
@ -93,7 +127,6 @@ namespace CSVRender
e->accept();
}
QPaintEngine* SceneWidget::paintEngine() const
{
// We don't want another paint engine to get in the way.
@ -130,4 +163,151 @@ namespace CSVRender
return QWidget::event(e);
}
void SceneWidget::keyPressEvent (QKeyEvent *event)
{
switch (event->key())
{
case Qt::Key_W: mKeyForward = true; break;
case Qt::Key_S: mKeyBackward = true; break;
case Qt::Key_A: mKeyLeft = true; break;
case Qt::Key_D: mKeyRight = true; break;
case Qt::Key_Q: mKeyRollLeft = true; break;
case Qt::Key_E: mKeyRollRight = true; break;
case Qt::Key_Control: mMod1 = true; break;
case Qt::Key_Shift:
mFast = true;
if (mNavigation)
mNavigation->setFastModeFactor (mFastFactor);
break;
default: QWidget::keyPressEvent (event);
}
}
void SceneWidget::keyReleaseEvent (QKeyEvent *event)
{
switch (event->key())
{
case Qt::Key_W: mKeyForward = false; break;
case Qt::Key_S: mKeyBackward = false; break;
case Qt::Key_A: mKeyLeft = false; break;
case Qt::Key_D: mKeyRight = false; break;
case Qt::Key_Q: mKeyRollLeft = false; break;
case Qt::Key_E: mKeyRollRight = false; break;
case Qt::Key_Control: mMod1 = false; break;
case Qt::Key_Shift:
mFast = false;
if (mNavigation)
mNavigation->setFastModeFactor (1);
break;
default: QWidget::keyReleaseEvent (event);
}
}
void SceneWidget::wheelEvent (QWheelEvent *event)
{
if (mNavigation)
if (event->delta())
if (mNavigation->wheelMoved (event->delta()))
mUpdate = true;
}
void SceneWidget::leaveEvent (QEvent *event)
{
mDragging = false;
}
void SceneWidget::mouseMoveEvent (QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
{
if (mDragging)
{
QPoint diff = mOldPos-event->pos();
mOldPos = event->pos();
if (mNavigation)
if (mNavigation->mouseMoved (diff, mMod1 ? 1 : 0))
mUpdate = true;
}
else
{
mDragging = true;
mOldPos = event->pos();
}
}
}
void SceneWidget::mouseReleaseEvent (QMouseEvent *event)
{
if (!(event->buttons() & Qt::LeftButton))
mDragging = false;
}
void SceneWidget::focusOutEvent (QFocusEvent *event)
{
mKeyForward = false;
mKeyBackward = false;
mKeyLeft = false;
mKeyRight = false;
mFast = false;
mMod1 = false;
QWidget::focusOutEvent (event);
}
void SceneWidget::update()
{
if (mNavigation)
{
int horizontal = 0;
int vertical = 0;
if (mKeyForward && !mKeyBackward)
vertical = 1;
else if (!mKeyForward && mKeyBackward)
vertical = -1;
if (mKeyLeft && !mKeyRight)
horizontal = -1;
else if (!mKeyLeft && mKeyRight)
horizontal = 1;
if (horizontal || vertical)
if (mNavigation->handleMovementKeys (vertical, horizontal))
mUpdate = true;
int roll = 0;
if (mKeyRollLeft && !mKeyRollRight)
roll = 1;
else if (!mKeyRollLeft && mKeyRollRight)
roll = -1;
if (roll)
if (mNavigation->handleRollKeys (roll))
mUpdate = true;
}
if (mUpdate)
{
mUpdate = false;
mWindow->update();
}
}
int SceneWidget::getFastFactor() const
{
return mFast ? mFastFactor : 1;
}
}

View File

@ -8,33 +8,77 @@ namespace Ogre
class Camera;
class SceneManager;
class RenderWindow;
class ColourValue;
}
namespace CSVRender
{
class Navigation;
class SceneWidget : public QWidget
{
Q_OBJECT
public:
SceneWidget(QWidget *parent);
virtual ~SceneWidget(void);
public:
QPaintEngine* paintEngine() const;
SceneWidget(QWidget *parent);
virtual ~SceneWidget();
private:
void paintEvent(QPaintEvent* e);
void resizeEvent(QResizeEvent* e);
bool event(QEvent* e);
QPaintEngine* paintEngine() const;
void updateOgreWindow();
void setAmbient (const Ogre::ColourValue& colour);
///< \note The actual ambient colour may differ based on lighting settings.
Ogre::Camera* mCamera;
Ogre::SceneManager* mSceneMgr;
Ogre::RenderWindow* mWindow;
protected:
void setNavigation (Navigation *navigation);
///< \attention The ownership of \a navigation is not transferred to *this.
private:
void paintEvent(QPaintEvent* e);
void resizeEvent(QResizeEvent* e);
bool event(QEvent* e);
void keyPressEvent (QKeyEvent *event);
void keyReleaseEvent (QKeyEvent *event);
void focusOutEvent (QFocusEvent *event);
void wheelEvent (QWheelEvent *event);
void leaveEvent (QEvent *event);
void mouseMoveEvent (QMouseEvent *event);
void mouseReleaseEvent (QMouseEvent *event);
void updateOgreWindow();
int getFastFactor() const;
Ogre::Camera* mCamera;
Ogre::SceneManager* mSceneMgr;
Ogre::RenderWindow* mWindow;
Navigation *mNavigation;
bool mUpdate;
bool mKeyForward;
bool mKeyBackward;
bool mKeyLeft;
bool mKeyRight;
bool mKeyRollLeft;
bool mKeyRollRight;
bool mFast;
bool mDragging;
bool mMod1;
QPoint mOldPos;
int mFastFactor;
private slots:
void update();
};
}
#endif

View File

@ -0,0 +1,66 @@
#include "unpagedworldspacewidget.hpp"
#include <OgreColourValue.h>
#include "../../model/doc/document.hpp"
#include "../../model/world/data.hpp"
#include "../../model/world/idtable.hpp"
void CSVRender::UnpagedWorldspaceWidget::update()
{
const CSMWorld::Record<CSMWorld::Cell>& record =
dynamic_cast<const CSMWorld::Record<CSMWorld::Cell>&> (mCellsModel->getRecord (mCellId));
Ogre::ColourValue colour;
colour.setAsABGR (record.get().mAmbi.mAmbient);
setAmbient (colour);
/// \todo deal with mSunlight and mFog/mForDensity
}
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId,
CSMDoc::Document& document, QWidget *parent)
: WorldspaceWidget (parent), mCellId (cellId)
{
mCellsModel = &dynamic_cast<CSMWorld::IdTable&> (
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
connect (mCellsModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (cellDataChanged (const QModelIndex&, const QModelIndex&)));
connect (mCellsModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (cellRowsAboutToBeRemoved (const QModelIndex&, int, int)));
update();
}
void CSVRender::UnpagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
int index = mCellsModel->findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
QModelIndex cellIndex = mCellsModel->getModelIndex (mCellId, index);
if (cellIndex.row()>=topLeft.row() && cellIndex.row()<=bottomRight.row())
{
if (mCellsModel->data (cellIndex).toInt()==CSMWorld::RecordBase::State_Deleted)
{
emit closeRequest();
}
else
{
/// \todo possible optimisation: check columns and update only if relevant columns have
/// changed
update();
}
}
}
void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelIndex& parent,
int start, int end)
{
QModelIndex cellIndex = mCellsModel->getModelIndex (mCellId, 0);
if (cellIndex.row()>=start && cellIndex.row()<=end)
emit closeRequest();
}

View File

@ -0,0 +1,44 @@
#ifndef OPENCS_VIEW_UNPAGEDWORLDSPACEWIDGET_H
#define OPENCS_VIEW_UNPAGEDWORLDSPACEWIDGET_H
#include <string>
#include "worldspacewidget.hpp"
class QModelIndex;
namespace CSMDoc
{
class Document;
}
namespace CSMWorld
{
class IdTable;
}
namespace CSVRender
{
class UnpagedWorldspaceWidget : public WorldspaceWidget
{
Q_OBJECT
std::string mCellId;
CSMWorld::IdTable *mCellsModel;
void update();
public:
UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document,
QWidget *parent);
private slots:
void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void cellRowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
};
}
#endif

View File

@ -0,0 +1,38 @@
#include "worldspacewidget.hpp"
#include "../world/scenetoolmode.hpp"
CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent)
: SceneWidget (parent)
{}
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
{
if (mode=="1st")
setNavigation (&m1st);
else if (mode=="free")
setNavigation (&mFree);
else if (mode=="orbit")
setNavigation (&mOrbit);
}
void CSVRender::WorldspaceWidget::selectDefaultNavigationMode()
{
setNavigation (&m1st);
}
CSVWorld::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
CSVWorld::SceneToolbar *parent)
{
CSVWorld::SceneToolMode *tool = new CSVWorld::SceneToolMode (parent);
tool->addButton (":door.png", "1st"); /// \todo replace icons
tool->addButton (":GMST.png", "free");
tool->addButton (":Info.png", "orbit");
connect (tool, SIGNAL (modeChanged (const std::string&)),
this, SLOT (selectNavigationMode (const std::string&)));
return tool;
}

View File

@ -0,0 +1,46 @@
#ifndef OPENCS_VIEW_WORLDSPACEWIDGET_H
#define OPENCS_VIEW_WORLDSPACEWIDGET_H
#include "scenewidget.hpp"
#include "navigation1st.hpp"
#include "navigationfree.hpp"
#include "navigationorbit.hpp"
namespace CSVWorld
{
class SceneToolMode;
class SceneToolbar;
}
namespace CSVRender
{
class WorldspaceWidget : public SceneWidget
{
Q_OBJECT
CSVRender::Navigation1st m1st;
CSVRender::NavigationFree mFree;
CSVRender::NavigationOrbit mOrbit;
public:
WorldspaceWidget (QWidget *parent = 0);
CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent);
///< \important The created tool is not added to the toolbar (via addTool). Doing that
/// is the responsibility of the calling function.
void selectDefaultNavigationMode();
private slots:
void selectNavigationMode (const std::string& mode);
signals:
void closeRequest();
};
}
#endif

View File

@ -40,5 +40,5 @@ void CSVTools::ReportSubView::updateEditorSetting (const QString& key, const QSt
void CSVTools::ReportSubView::show (const QModelIndex& index)
{
focusId (mModel->getUniversalId (index.row()));
focusId (mModel->getUniversalId (index.row()), "");
}

View File

@ -9,7 +9,8 @@
#include "../filter/filterbox.hpp"
#include "../render/scenewidget.hpp"
#include "../render/pagedworldspacewidget.hpp"
#include "../render/unpagedworldspacewidget.hpp"
#include "tablebottombox.hpp"
#include "creator.hpp"
@ -32,37 +33,20 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
layout2->setContentsMargins (QMargins (0, 0, 0, 0));
SceneToolbar *toolbar = new SceneToolbar (48, this);
// test
SceneToolMode *tool = new SceneToolMode (toolbar);
tool->addButton (":door.png", "a");
tool->addButton (":GMST.png", "b");
tool->addButton (":Info.png", "c");
toolbar->addTool (tool);
toolbar->addTool (new SceneToolMode (toolbar));
toolbar->addTool (new SceneToolMode (toolbar));
toolbar->addTool (new SceneToolMode (toolbar));
if (id.getId()[0]=='#')
mScene = new CSVRender::PagedWorldspaceWidget (this);
else
mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this);
SceneToolMode *tool = mScene->makeNavigationSelector (toolbar);
toolbar->addTool (tool);
layout2->addWidget (toolbar, 0);
// temporarily disable OGRE-integration (need to fix path problem first)
#if 0
CSVRender::SceneWidget* sceneWidget = new CSVRender::SceneWidget(this);
layout2->addWidget (sceneWidget, 1);
layout2->addWidget (mScene, 1);
layout->insertLayout (0, layout2, 1);
#endif
/// \todo replace with rendering widget
QPalette palette2 (palette());
palette2.setColor (QPalette::Background, Qt::white);
QLabel *placeholder = new QLabel ("Here goes the 3D scene", this);
placeholder->setAutoFillBackground (true);
placeholder->setPalette (palette2);
placeholder->setAlignment (Qt::AlignHCenter);
layout2->addWidget (placeholder, 1);
layout->insertLayout (0, layout2, 1);
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
@ -73,6 +57,10 @@ toolbar->addTool (new SceneToolMode (toolbar));
widget->setLayout (layout);
setWidget (widget);
mScene->selectDefaultNavigationMode();
connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
}
void CSVWorld::SceneSubView::setEditLock (bool locked)
@ -91,3 +79,8 @@ void CSVWorld::SceneSubView::setStatusBar (bool show)
{
mBottom->setStatusBar (show);
}
void CSVWorld::SceneSubView::closeRequest()
{
deleteLater();
}

View File

@ -10,6 +10,11 @@ namespace CSMDoc
class Document;
}
namespace CSVRender
{
class WorldspaceWidget;
}
namespace CSVWorld
{
class Table;
@ -21,6 +26,7 @@ namespace CSVWorld
Q_OBJECT
TableBottomBox *mBottom;
CSVRender::WorldspaceWidget *mScene;
public:
@ -31,6 +37,10 @@ namespace CSVWorld
virtual void updateEditorSetting (const QString& key, const QString& value);
virtual void setStatusBar (bool show);
private slots:
void closeRequest();
};
}

View File

@ -2,7 +2,6 @@
#include "table.hpp"
#include <QHeaderView>
#include <QAction>
#include <QApplication>
#include <QMenu>
@ -10,6 +9,8 @@
#include <QString>
#include <QtCore/qnamespace.h>
#include "../../model/doc/document.hpp"
#include "../../model/world/data.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/idtableproxymodel.hpp"
@ -35,8 +36,21 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
if (selectedRows.size()==1)
{
menu.addAction (mEditAction);
if (mCreateAction)
menu.addAction(mCloneAction);
if (mModel->getViewing()!=CSMWorld::IdTable::Viewing_None)
{
int row = selectedRows.begin()->row();
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
CSMWorld::UniversalId id = mModel->view (row).first;
if (!mDocument.getData().getCells().getRecord (id.getId()).isDeleted())
menu.addAction (mViewAction);
}
}
if (mCreateAction)
@ -162,11 +176,12 @@ std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
return deletableIds;
}
CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack,
bool createAndDelete, bool sorting, const CSMDoc::Document& document)
: mUndoStack (undoStack), mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0), mDocument(document)
CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
bool createAndDelete, bool sorting, CSMDoc::Document& document)
: mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0),
mDocument (document)
{
mModel = &dynamic_cast<CSMWorld::IdTable&> (*data.getTableModel (id));
mModel = &dynamic_cast<CSMWorld::IdTable&> (*mDocument.getData().getTableModel (id));
mProxyModel = new CSMWorld::IdTableProxyModel (this);
mProxyModel->setSourceModel (mModel);
@ -190,7 +205,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q
mModel->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
CommandDelegate *delegate = CommandDelegateFactoryCollection::get().makeDelegate (display,
undoStack, this);
mDocument.getUndoStack(), this);
mDelegates.push_back (delegate);
setItemDelegateForColumn (i, delegate);
@ -230,6 +245,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q
connect (mMoveDownAction, SIGNAL (triggered()), this, SLOT (moveDownRecord()));
addAction (mMoveDownAction);
mViewAction = new QAction (tr ("View"), this);
connect (mViewAction, SIGNAL (triggered()), this, SLOT (viewRecord()));
addAction (mViewAction);
connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (tableSizeUpdate()));
@ -268,13 +287,13 @@ void CSVWorld::Table::revertRecord()
if (revertableIds.size()>0)
{
if (revertableIds.size()>1)
mUndoStack.beginMacro (tr ("Revert multiple records"));
mDocument.getUndoStack().beginMacro (tr ("Revert multiple records"));
for (std::vector<std::string>::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter)
mUndoStack.push (new CSMWorld::RevertCommand (*mModel, *iter));
mDocument.getUndoStack().push (new CSMWorld::RevertCommand (*mModel, *iter));
if (revertableIds.size()>1)
mUndoStack.endMacro();
mDocument.getUndoStack().endMacro();
}
}
}
@ -288,13 +307,13 @@ void CSVWorld::Table::deleteRecord()
if (deletableIds.size()>0)
{
if (deletableIds.size()>1)
mUndoStack.beginMacro (tr ("Delete multiple records"));
mDocument.getUndoStack().beginMacro (tr ("Delete multiple records"));
for (std::vector<std::string>::const_iterator iter (deletableIds.begin()); iter!=deletableIds.end(); ++iter)
mUndoStack.push (new CSMWorld::DeleteCommand (*mModel, *iter));
mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (*mModel, *iter));
if (deletableIds.size()>1)
mUndoStack.endMacro();
mDocument.getUndoStack().endMacro();
}
}
}
@ -306,7 +325,7 @@ void CSVWorld::Table::editRecord()
QModelIndexList selectedRows = selectionModel()->selectedRows();
if (selectedRows.size()==1)
emit editRequest (selectedRows.begin()->row());
emit editRequest (getUniversalId (selectedRows.begin()->row()), "");
}
}
@ -347,7 +366,7 @@ void CSVWorld::Table::moveUpRecord()
for (int i=1; i<row2-row; ++i)
newOrder[i] = i;
mUndoStack.push (new CSMWorld::ReorderRowsCommand (*mModel, row, newOrder));
mDocument.getUndoStack().push (new CSMWorld::ReorderRowsCommand (*mModel, row, newOrder));
}
}
}
@ -376,11 +395,28 @@ void CSVWorld::Table::moveDownRecord()
for (int i=1; i<row2-row; ++i)
newOrder[i] = i;
mUndoStack.push (new CSMWorld::ReorderRowsCommand (*mModel, row, newOrder));
mDocument.getUndoStack().push (new CSMWorld::ReorderRowsCommand (*mModel, row, newOrder));
}
}
}
void CSVWorld::Table::viewRecord()
{
QModelIndexList selectedRows = selectionModel()->selectedRows();
if (selectedRows.size()==1)
{
int row =selectedRows.begin()->row();
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
std::pair<CSMWorld::UniversalId, std::string> params = mModel->view (row);
if (params.first.getType()!=CSMWorld::UniversalId::Type_None)
emit editRequest (params.first, params.second);
}
}
void CSVWorld::Table::updateEditorSetting (const QString &settingName, const QString &settingValue)
{
int columns = mModel->columnCount();
@ -517,7 +553,7 @@ void CSVWorld::Table::dropEvent(QDropEvent *event)
std::auto_ptr<CSMWorld::ModifyCommand> command (new CSMWorld::ModifyCommand
(*mProxyModel, index, QVariant (QString::fromUtf8 (record.getId().c_str()))));
mUndoStack.push (command.release());
mDocument.getUndoStack().push (command.release());
}
} //TODO handle drops from different document
}

View File

@ -10,13 +10,14 @@
#include "../../model/filter/node.hpp"
#include "../../model/world/columnbase.hpp"
namespace CSMDoc {
class Document;
}
class QUndoStack;
class QAction;
namespace CSMDoc
{
class Document;
}
namespace CSMWorld
{
class Data;
@ -35,7 +36,6 @@ namespace CSVWorld
Q_OBJECT
std::vector<CommandDelegate *> mDelegates;
QUndoStack& mUndoStack;
QAction *mEditAction;
QAction *mCreateAction;
QAction *mCloneAction;
@ -43,14 +43,12 @@ namespace CSVWorld
QAction *mDeleteAction;
QAction *mMoveUpAction;
QAction *mMoveDownAction;
QAction *mViewAction;
CSMWorld::IdTableProxyModel *mProxyModel;
CSMWorld::IdTable *mModel;
bool mEditLock;
int mRecordStatusDisplay;
/// \brief This variable is used exclusivly for checking if dropEvents came from the same document. Most likely you
/// should NOT use it for anything else.
const CSMDoc::Document& mDocument;
CSMDoc::Document& mDocument;
private:
@ -70,9 +68,8 @@ namespace CSVWorld
public:
Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete,
bool sorting, const CSMDoc::Document& document);
Table (const CSMWorld::UniversalId& id, bool createAndDelete,
bool sorting, CSMDoc::Document& document);
///< \param createAndDelete Allow creation and deletion of records.
/// \param sorting Allow changing order of rows in the view via column headers.
@ -86,7 +83,7 @@ namespace CSVWorld
signals:
void editRequest (int row);
void editRequest (const CSMWorld::UniversalId& id, const std::string& hint);
void selectionSizeChanged (int size);
@ -112,6 +109,8 @@ namespace CSVWorld
void moveDownRecord();
void viewRecord();
public slots:
void tableSizeUpdate();

View File

@ -24,7 +24,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this), 0);
layout->insertWidget (0, mTable =
new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete(), sorting, document), 2);
new Table (id, mBottom->canCreateAndDelete(), sorting, document), 2);
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
@ -36,7 +36,8 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D
setWidget (widget);
connect (mTable, SIGNAL (editRequest (int)), this, SLOT (editRequest (int)));
connect (mTable, SIGNAL (editRequest (const CSMWorld::UniversalId&, const std::string&)),
this, SLOT (editRequest (const CSMWorld::UniversalId&, const std::string&)));
connect (mTable, SIGNAL (selectionSizeChanged (int)),
mBottom, SLOT (selectionSizeChanged (int)));
@ -81,9 +82,9 @@ void CSVWorld::TableSubView::setEditLock (bool locked)
mBottom->setEditLock (locked);
}
void CSVWorld::TableSubView::editRequest (int row)
void CSVWorld::TableSubView::editRequest (const CSMWorld::UniversalId& id, const std::string& hint)
{
focusId (mTable->getUniversalId (row));
focusId (id, hint);
}
void CSVWorld::TableSubView::updateEditorSetting(const QString &settingName, const QString &settingValue)

View File

@ -53,7 +53,7 @@ namespace CSVWorld
private slots:
void editRequest (int row);
void editRequest (const CSMWorld::UniversalId& id, const std::string& hint);
void cloneRequest (const CSMWorld::UniversalId& toClone);
void createFilterRequest(std::vector< CSMWorld::UniversalId >& types,
Qt::DropAction action);

View File

@ -159,3 +159,10 @@ if (BUILD_WITH_CODE_COVERAGE)
add_definitions (--coverage)
target_link_libraries(openmw gcov)
endif()
if (MSVC)
# Debug version needs increased number of sections beyond 2^16
if (CMAKE_CL_64)
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj")
endif (CMAKE_CL_64)
endif (MSVC)

View File

@ -1,6 +1,7 @@
#include "engine.hpp"
#include <stdexcept>
#include <iomanip>
#include <OgreRoot.h>
#include <OgreRenderWindow.h>
@ -456,7 +457,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
else
{
pos.pos[0] = pos.pos[1] = pos.pos[2] = 0;
pos.rot[0] = pos.rot[1] = pos.pos[2] = 0;
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
world->changeToExteriorCell (pos);
}
@ -621,4 +622,4 @@ void OMW::Engine::setActivationDistanceOverride (int distance)
void OMW::Engine::setWarningsMode (int mode)
{
mWarningsMode = mode;
}
}

View File

@ -3,7 +3,7 @@
#include <string>
#include <libs/platform/stdint.h>
#include <stdint.h>
namespace ESM
{

View File

@ -5,7 +5,7 @@
#include <deque>
#include <map>
#include <libs/platform/stdint.h>
#include <stdint.h>
#include "../mwdialogue/journalentry.hpp"
#include "../mwdialogue/topic.hpp"

View File

@ -6,7 +6,7 @@
#include "MyGUI_TextureUtility.h"
#include "MyGUI_FactoryManager.h"
#include <platform/stdint.h>
#include <stdint.h>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

View File

@ -5,7 +5,7 @@
#include "MyGUI_Widget.h"
#include <functional>
#include <platform/stdint.h>
#include <stdint.h>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>

View File

@ -1,5 +1,7 @@
#include "enchantingdialog.hpp"
#include <iomanip>
#include <boost/lexical_cast.hpp>
#include "../mwbase/environment.hpp"

View File

@ -206,9 +206,9 @@ struct JournalViewModelImpl : JournalViewModel
const MWDialogue::Quest& quest = i->second;
// Unfortunately Morrowind.esm has no quest names, since the quest book was added with tribunal.
if (quest.getName().empty())
visitor (reinterpret_cast <QuestId> (&i->second), toUtf8Span (i->first));
else
// Note that even with Tribunal, some quests still don't have quest names. I'm assuming those are not supposed
// to appear in the quest book.
if (!quest.getName().empty())
visitor (reinterpret_cast <QuestId> (&i->second), toUtf8Span (quest.getName()));
}
}

View File

@ -4,7 +4,7 @@
#include <string>
#include <memory>
#include <functional>
#include <platform/stdint.h>
#include <stdint.h>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>

View File

@ -1,6 +1,13 @@
#include "loadingscreen.hpp"
#include <OgreRenderWindow.h>
#include <OgreMaterialManager.h>
#include <OgreTechnique.h>
#include <OgreRectangle2D.h>
#include <OgreSceneNode.h>
#include <OgreTextureManager.h>
#include <OgreViewport.h>
#include <OgreHardwarePixelBuffer.h>
#include <openengine/ogre/fader.hpp>
@ -66,6 +73,10 @@ namespace MWGui
void LoadingScreen::loadingOn()
{
// Early-out if already on
if (mRectangle->getVisible())
return;
// Temporarily turn off VSync, we want to do actual loading rather than waiting for the screen to sync.
// Threaded loading would be even better, of course - especially because some drivers force VSync to on and we can't change it.
// In Ogre 1.8, the swapBuffers argument is useless and setVSyncEnabled is bugged with GLX, nothing we can do :/
@ -74,16 +85,36 @@ namespace MWGui
mWindow->setVSyncEnabled(false);
#endif
if (!mFirstLoad)
{
mBackgroundImage->setImageTexture("");
int width = mWindow->getWidth();
int height = mWindow->getHeight();
const std::string textureName = "@loading_background";
Ogre::TexturePtr texture;
texture = Ogre::TextureManager::getSingleton().getByName(textureName);
if (texture.isNull())
{
texture = Ogre::TextureManager::getSingleton().createManual(textureName,
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D,
width, height, 0, mWindow->suggestPixelFormat(), Ogre::TU_DYNAMIC_WRITE_ONLY);
}
texture->unload();
texture->setWidth(width);
texture->setHeight(height);
texture->createInternalResources();
mWindow->copyContentsToMemory(texture->getBuffer()->lock(Ogre::Image::Box(0,0,width,height), Ogre::HardwareBuffer::HBL_DISCARD));
texture->getBuffer()->unlock();
mBackgroundImage->setImageTexture(texture->getName());
}
setVisible(true);
if (mFirstLoad)
{
changeWallpaper();
}
else
{
mBackgroundImage->setImageTexture("");
}
MWBase::Environment::get().getWindowManager()->pushGuiMode(mFirstLoad ? GM_LoadingWallpaper : GM_Loading);
}
@ -197,8 +228,6 @@ namespace MWGui
MWBase::Environment::get().getInputManager()->update(0, true);
mWindow->getViewport(0)->setClearEveryFrame(false);
// First, swap buffers from last draw, then, queue an update of the
// window contents, but don't swap buffers (which would have
// caused a sync / flush and would be expensive).
@ -208,9 +237,6 @@ namespace MWGui
mWindow->update(false);
mWindow->getViewport(0)->setClearEveryFrame(true);
mRectangle->setVisible(false);
// resume 3d rendering

View File

@ -2,6 +2,7 @@
#define MWGUI_LOADINGSCREEN_H
#include <OgreSceneManager.h>
#include <OgreTimer.h>
#include "windowbase.hpp"

View File

@ -3,6 +3,7 @@
#include <boost/lexical_cast.hpp>
#include <OgreSceneNode.h>
#include <OgreVector2.h>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"

View File

@ -1,7 +1,7 @@
#ifndef MWGUI_MAPWINDOW_H
#define MWGUI_MAPWINDOW_H
#include <libs/platform/stdint.h>
#include <stdint.h>
#include "windowpinnablebase.hpp"

View File

@ -1,5 +1,7 @@
#include "repair.hpp"
#include <iomanip>
#include <boost/lexical_cast.hpp>
#include "../mwbase/world.hpp"

View File

@ -1,5 +1,7 @@
#include "tooltips.hpp"
#include <iomanip>
#include <boost/lexical_cast.hpp>
#include "../mwbase/world.hpp"

View File

@ -3,6 +3,8 @@
#include <cassert>
#include <iterator>
#include <OgreTextureManager.h>
#include "MyGUI_UString.h"
#include "MyGUI_IPointer.h"
#include "MyGUI_ResourceImageSetPointer.h"

View File

@ -455,7 +455,7 @@ namespace MWInput
mInputBinder->adjustMouseRegion(width, height);
}
bool InputManager::keyPressed( const SDL_KeyboardEvent &arg )
void InputManager::keyPressed( const SDL_KeyboardEvent &arg )
{
// Cut, copy & paste
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
@ -501,7 +501,6 @@ namespace MWInput
if (kc != OIS::KC_UNASSIGNED)
MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), 0);
return true;
}
void InputManager::textInput(const SDL_TextInputEvent &arg)
@ -512,23 +511,21 @@ namespace MWInput
MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::None, *it);
}
bool InputManager::keyReleased(const SDL_KeyboardEvent &arg )
void InputManager::keyReleased(const SDL_KeyboardEvent &arg )
{
mInputBinder->keyReleased (arg);
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc));
return true;
}
bool InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id )
void InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id )
{
mInputBinder->mousePressed (arg, id);
if (id != SDL_BUTTON_LEFT && id != SDL_BUTTON_RIGHT)
return true; // MyGUI has no use for these events
return; // MyGUI has no use for these events
MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id));
if (MyGUI::InputManager::getInstance ().getMouseFocusWidget () != 0)
@ -539,20 +536,16 @@ namespace MWInput
MWBase::Environment::get().getSoundManager ()->playSound ("Menu Click", 1.f, 1.f);
}
}
return true;
}
bool InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id )
void InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id )
{
mInputBinder->mouseReleased (arg, id);
MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id));
return true;
}
bool InputManager::mouseMoved(const SFO::MouseMotionEvent &arg )
void InputManager::mouseMoved(const SFO::MouseMotionEvent &arg )
{
mInputBinder->mouseMoved (arg);
@ -600,8 +593,6 @@ namespace MWInput
MWBase::Environment::get().getWorld()->setCameraDistance(arg.zrel, true, true);
}
}
return true;
}
void InputManager::windowFocusChange(bool have_focus)

View File

@ -86,13 +86,13 @@ namespace MWInput
virtual void resetToDefaultBindings();
public:
virtual bool keyPressed(const SDL_KeyboardEvent &arg );
virtual bool keyReleased( const SDL_KeyboardEvent &arg );
virtual void keyPressed(const SDL_KeyboardEvent &arg );
virtual void keyReleased( const SDL_KeyboardEvent &arg );
virtual void textInput (const SDL_TextInputEvent &arg);
virtual bool mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id );
virtual bool mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id );
virtual bool mouseMoved( const SFO::MouseMotionEvent &arg );
virtual void mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id );
virtual void mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id );
virtual void mouseMoved( const SFO::MouseMotionEvent &arg );
virtual void windowVisibilityChange( bool visible );
virtual void windowFocusChange( bool have_focus );

View File

@ -15,7 +15,7 @@
#include "../mwbase/dialoguemanager.hpp"
#include "npcstats.hpp"
#include "creaturestats.hpp"
#include "steering.hpp"
#include "movement.hpp"
#include "character.hpp" // fixme: for getActiveWeapon
@ -140,11 +140,12 @@ namespace MWMechanics
{
MWMechanics::DrawState_ state = actor.getClass().getCreatureStats(actor).getDrawState();
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
actor.getClass().getNpcStats(actor).setDrawState(MWMechanics::DrawState_Weapon);
actor.getClass().getCreatureStats(actor).setDrawState(MWMechanics::DrawState_Weapon);
//Get weapon speed and range
MWWorld::ContainerStoreIterator weaponSlot =
MWMechanics::getActiveWeapon(cls.getNpcStats(actor), cls.getInventoryStore(actor), &weaptype);
MWMechanics::getActiveWeapon(cls.getCreatureStats(actor), cls.getInventoryStore(actor), &weaptype);
if (weaptype == WeapType_HandToHand)
{
const MWWorld::Store<ESM::GameSetting> &gmst =
@ -242,17 +243,21 @@ namespace MWMechanics
//target is at far distance: build path to target OR follow target (if previously actor had reached it once)
mFollowTarget = false;
buildNewPath(actor);
buildNewPath(actor); //may fail to build a path, check before use
//delete visited path node
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
//try shortcut
if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))
mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees();
else
mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
mRotate = true;
//if no new path leave mTargetAngle unchanged
if(!mPathFinder.getPath().empty())
{
//try shortcut
if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))
mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees();
else
mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
mRotate = true;
}
mMovement.mPosition[1] = 1;
mReadyToAttack = false;
@ -302,9 +307,13 @@ namespace MWMechanics
dest.mZ = mTarget.getRefData().getPosition().pos[2];
Ogre::Vector3 newPathTarget = Ogre::Vector3(dest.mX, dest.mY, dest.mZ);
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back();
Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ);
float dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length());
float dist = -1; //hack to indicate first time, to construct a new path
if(!mPathFinder.getPath().empty())
{
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back();
Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ);
dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length());
}
float targetPosThreshold;
bool isOutside = actor.getCell()->getCell()->isExterior();
@ -313,7 +322,7 @@ namespace MWMechanics
else
targetPosThreshold = 100;
if(dist > targetPosThreshold)
if((dist < 0) || (dist > targetPosThreshold))
{
//construct new path only if target has moved away more than on <targetPosThreshold>
ESM::Position pos = actor.getRefData().getPosition();
@ -334,8 +343,11 @@ namespace MWMechanics
//maybe here is a mistake (?): PathFinder::getPathSize() returns number of grid points in the path,
//not the actual path length. Here we should know if the new path is actually more effective.
//if(pathFinder2.getPathSize() < mPathFinder.getPathSize())
newPathFinder.syncStart(mPathFinder.getPath());
mPathFinder = newPathFinder;
if(!mPathFinder.getPath().empty())
{
newPathFinder.syncStart(mPathFinder.getPath());
mPathFinder = newPathFinder;
}
}
}
}

View File

@ -6,6 +6,8 @@
#include <vector>
#include <algorithm>
#include <iomanip>
#include <boost/format.hpp>
#include <components/esm/loadskil.hpp>
@ -509,4 +511,4 @@ void MWMechanics::NpcStats::readState (const ESM::NpcStats& state)
mTimeToStartDrowning = state.mTimeToStartDrowning;
mLastDrowningHit = state.mLastDrowningHit;
mLevelHealthBonus = state.mLevelHealthBonus;
}
}

View File

@ -393,6 +393,8 @@ namespace MWMechanics
void PathFinder::syncStart(const std::list<ESM::Pathgrid::Point> &path)
{
if (mPath.size() < 2)
return; //nothing to pop
std::list<ESM::Pathgrid::Point>::const_iterator oldStart = path.begin();
std::list<ESM::Pathgrid::Point>::iterator iter = ++mPath.begin();

View File

@ -10,6 +10,8 @@
#include <OgreSceneManager.h>
#include <OgreControllerManager.h>
#include <OgreStaticGeometry.h>
#include <OgreSceneNode.h>
#include <OgreTechnique.h>
#include <components/esm/loadligh.hpp>
#include <components/esm/loadweap.hpp>
@ -293,6 +295,17 @@ void Animation::addAnimSource(const std::string &model)
}
}
if (grp == 0 && dstval->getNode()->getName() == "Bip01")
{
mNonAccumRoot = dstval->getNode();
mAccumRoot = mNonAccumRoot->getParent();
if(!mAccumRoot)
{
std::cerr<< "Non-Accum root for "<<mPtr.getCellRef().mRefID<<" is skeleton root??" <<std::endl;
mNonAccumRoot = NULL;
}
}
ctrls[i].setSource(mAnimationTimePtr[grp]);
grpctrls[grp].push_back(ctrls[i]);
}

View File

@ -1,10 +1,13 @@
#include "characterpreview.hpp"
#include <OgreSceneManager.h>
#include <OgreRoot.h>
#include <OgreHardwarePixelBuffer.h>
#include <OgreCamera.h>
#include <OgreSceneNode.h>
#include <OgreTextureManager.h>
#include <OgreViewport.h>
#include <OgreRenderTexture.h>
#include <libs/openengine/ogre/selectionbuffer.hpp>

View File

@ -3,6 +3,7 @@
#include <OgreRenderTarget.h>
#include <OgreMaterialManager.h>
#include <OgreVector3.h>
#include <components/esm/loadnpc.hpp>

View File

@ -7,6 +7,8 @@
#include <OgreMaterial.h>
#include <OgreMaterialManager.h>
#include <OgreManualObject.h>
#include <OgreTechnique.h>
#include <OgreSceneNode.h>
#include <openengine/bullet/physic.hpp>

View File

@ -2,6 +2,8 @@
#include <OgreSceneManager.h>
#include <OgreParticleSystem.h>
#include <OgreSceneNode.h>
#include <OgreTechnique.h>
#include "animation.hpp"
#include "renderconst.hpp"

View File

@ -75,10 +75,9 @@ namespace MWRender
if (land)
{
if (!land->isDataLoaded(ESM::Land::DATA_VHGT))
{
land->loadData(ESM::Land::DATA_VHGT);
}
int mask = ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX;
if (!land->isDataLoaded(mask))
land->loadData(mask);
}
for (int cellY=0; cellY<cellSize; ++cellY)

View File

@ -6,6 +6,8 @@
#include <OgreSceneNode.h>
#include <OgreCamera.h>
#include <OgreTextureManager.h>
#include <OgreRenderTexture.h>
#include <OgreViewport.h>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"

View File

@ -4,6 +4,11 @@
#include <OgreEntity.h>
#include <OgreParticleSystem.h>
#include <OgreSubEntity.h>
#include <OgreSkeleton.h>
#include <OgreSkeletonInstance.h>
#include <OgreSceneNode.h>
#include <OgreBone.h>
#include <OgreTechnique.h>
#include <extern/shiny/Main/Factory.hpp>

View File

@ -109,6 +109,7 @@ void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh)
{
uniqueID = uniqueID+1;
sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID));
sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition());
mStaticGeometrySmall[ptr.getCell()] = sg;
sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance"));
@ -122,6 +123,7 @@ void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh)
{
uniqueID = uniqueID+1;
sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID));
sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition());
mStaticGeometry[ptr.getCell()] = sg;
}
else

View File

@ -9,6 +9,8 @@
#include <OgreMeshManager.h>
#include <OgreMaterialManager.h>
#include <OgreCamera.h>
#include <OgreSceneNode.h>
#include <OgreMesh.h>
#include "renderconst.hpp"

View File

@ -7,6 +7,8 @@
#include <OgreRenderTarget.h>
#include <OgreViewport.h>
#include <OgreRoot.h>
#include <OgreRenderTexture.h>
#include <OgreSceneNode.h>
#include <extern/shiny/Main/Factory.hpp>

View File

@ -5,12 +5,14 @@
#include <OgreRoot.h>
#include <OgreRenderWindow.h>
#include <OgreSceneManager.h>
#include <OgreSceneNode.h>
#include <OgreViewport.h>
#include <OgreCamera.h>
#include <OgreTextureManager.h>
#include <OgreHardwarePixelBuffer.h>
#include <OgreControllerManager.h>
#include <OgreMeshManager.h>
#include <OgreRenderTexture.h>
#include <SDL_video.h>
@ -649,6 +651,18 @@ void RenderingManager::setGlare(bool glare)
mSkyManager->setGlare(glare);
}
void RenderingManager::updateTerrain()
{
if (mTerrain)
{
// Avoid updating with dims.getCenter for each cell. Player position should be good enough
mTerrain->update(mRendering.getCamera()->getRealPosition());
mTerrain->syncLoad();
// need to update again so the chunks that were just loaded can be made visible
mTerrain->update(mRendering.getCamera()->getRealPosition());
}
}
void RenderingManager::requestMap(MWWorld::CellStore* cell)
{
if (cell->getCell()->isExterior())
@ -659,9 +673,6 @@ void RenderingManager::requestMap(MWWorld::CellStore* cell)
Ogre::Vector2 center (cell->getCell()->getGridX() + 0.5, cell->getCell()->getGridY() + 0.5);
dims.merge(mTerrain->getWorldBoundingBox(center));
if (dims.isFinite())
mTerrain->update(dims.getCenter());
mLocalMap->requestMap(cell, dims.getMinimum().z, dims.getMaximum().z);
}
else
@ -981,13 +992,11 @@ void RenderingManager::screenshot(Image &image, int w, int h)
Ogre::PixelFormat pf = rt->suggestPixelFormat();
std::vector<Ogre::uchar> data;
data.resize(w * h * Ogre::PixelUtil::getNumElemBytes(pf));
Ogre::PixelBox pb(w, h, 1, pf, &data[0]);
rt->copyContentsToMemory(pb);
image.loadDynamicImage(&data[0], w, h, pf);
image.loadDynamicImage(
OGRE_ALLOC_T(Ogre::uchar, w * h * Ogre::PixelUtil::getNumElemBytes(pf), Ogre::MEMCATEGORY_GENERAL),
w, h, 1, pf, true // autoDelete=true, frees memory we allocate
);
rt->copyContentsToMemory(image.getPixelBox()); // getPixelBox returns a box sharing the same memory as the image
Ogre::TextureManager::getSingleton().remove(tempName);
mRendering.getCamera()->setAspectRatio(oldAspect);
@ -1045,20 +1054,16 @@ void RenderingManager::enableTerrain(bool enable)
{
if (!mTerrain)
{
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
Loading::ScopedLoad load(listener);
mTerrain = new Terrain::World(listener, mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
mTerrain = new Terrain::World(mRendering.getScene(), new MWRender::TerrainStorage(), RV_Terrain,
Settings::Manager::getBool("distant land", "Terrain"),
Settings::Manager::getBool("shader", "Terrain"));
Settings::Manager::getBool("shader", "Terrain"), Terrain::Align_XY, 1, 64);
mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"),
Settings::Manager::getBool("split", "Shadows"));
mTerrain->update(mRendering.getCamera()->getRealPosition());
mTerrain->setLoadingListener(NULL);
}
mTerrain->setVisible(true);
}
else
if (mTerrain)
else if (mTerrain)
mTerrain->setVisible(false);
}

View File

@ -180,6 +180,10 @@ public:
void removeWaterRippleEmitter (const MWWorld::Ptr& ptr);
void updateWaterRippleEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
void updateTerrain ();
///< update the terrain according to the player position. Usually done automatically, but should be done manually
/// before calling requestMap
void requestMap (MWWorld::CellStore* cell);
///< request the local map for a cell

View File

@ -4,6 +4,10 @@
#include <OgreStringConverter.h>
#include <OgreHardwarePixelBuffer.h>
#include <OgreRoot.h>
#include <OgreRectangle2D.h>
#include <OgreSceneNode.h>
#include <OgreRenderTexture.h>
#include <OgreViewport.h>
#include <extern/shiny/Main/Factory.hpp>

View File

@ -9,6 +9,8 @@
#include <OgreShadowCameraSetupPSSM.h>
#include <OgreHardwarePixelBuffer.h>
#include <OgreCamera.h>
#include <OgreRenderTexture.h>
#include <OgreViewport.h>
#include <extern/shiny/Main/Factory.hpp>

View File

@ -11,6 +11,7 @@
#include <OgreBillboardSet.h>
#include <OgreEntity.h>
#include <OgreSubEntity.h>
#include <OgreTechnique.h>
#include <OgreMeshManager.h>

View File

@ -5,6 +5,7 @@
#include <OgreStringConverter.h>
#include <OgreRenderSystem.h>
#include <OgreResourceGroupManager.h>
#include <OgreResourceBackgroundQueue.h>
#include <OgreRoot.h>
#include <boost/algorithm/string.hpp>
@ -13,12 +14,14 @@
#include "../mwbase/environment.hpp"
#include "../mwworld/esmstore.hpp"
#include <components/terrain/quadtreenode.hpp>
namespace MWRender
{
Ogre::AxisAlignedBox TerrainStorage::getBounds()
void TerrainStorage::getBounds(float& minX, float& maxX, float& minY, float& maxY)
{
int minX = 0, minY = 0, maxX = 0, maxY = 0;
minX = 0, minY = 0, maxX = 0, maxY = 0;
const MWWorld::ESMStore &esmStore =
MWBase::Environment::get().getWorld()->getStore();
@ -39,8 +42,6 @@ namespace MWRender
// since grid coords are at cell origin, we need to add 1 cell
maxX += 1;
maxY += 1;
return Ogre::AxisAlignedBox(minX, minY, 0, maxX, maxY, 0);
}
ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
@ -48,10 +49,6 @@ namespace MWRender
const MWWorld::ESMStore &esmStore =
MWBase::Environment::get().getWorld()->getStore();
ESM::Land* land = esmStore.get<ESM::Land>().search(cellX, cellY);
// Load the data we are definitely going to need
int mask = ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX;
if (land && !land->isDataLoaded(mask))
land->loadData(mask);
return land;
}
@ -169,10 +166,10 @@ namespace MWRender
}
void TerrainStorage::fillVertexBuffers (int lodLevel, float size, const Ogre::Vector2& center,
Ogre::HardwareVertexBufferSharedPtr vertexBuffer,
Ogre::HardwareVertexBufferSharedPtr normalBuffer,
Ogre::HardwareVertexBufferSharedPtr colourBuffer)
void TerrainStorage::fillVertexBuffers (int lodLevel, float size, const Ogre::Vector2& center, Terrain::Alignment align,
std::vector<float>& positions,
std::vector<float>& normals,
std::vector<Ogre::uint8>& colours)
{
// LOD level n means every 2^n-th vertex is kept
size_t increment = 1 << lodLevel;
@ -186,11 +183,8 @@ namespace MWRender
size_t numVerts = size*(ESM::Land::LAND_SIZE-1)/increment + 1;
std::vector<uint8_t> colors;
colors.resize(numVerts*numVerts*4);
std::vector<float> positions;
colours.resize(numVerts*numVerts*4);
positions.resize(numVerts*numVerts*3);
std::vector<float> normals;
normals.resize(numVerts*numVerts*3);
Ogre::Vector3 normal;
@ -276,7 +270,7 @@ namespace MWRender
color.a = 1;
Ogre::uint32 rsColor;
Ogre::Root::getSingleton().getRenderSystem()->convertColourValue(color, &rsColor);
memcpy(&colors[vertX*numVerts*4 + vertY*4], &rsColor, sizeof(Ogre::uint32));
memcpy(&colours[vertX*numVerts*4 + vertY*4], &rsColor, sizeof(Ogre::uint32));
++vertX;
}
@ -289,10 +283,6 @@ namespace MWRender
assert(vertX_ == numVerts); // Ensure we covered whole area
}
assert(vertY_ == numVerts); // Ensure we covered whole area
vertexBuffer->writeData(0, vertexBuffer->getSizeInBytes(), &positions[0], true);
normalBuffer->writeData(0, normalBuffer->getSizeInBytes(), &normals[0], true);
colourBuffer->writeData(0, colourBuffer->getSizeInBytes(), &colors[0], true);
}
TerrainStorage::UniqueTextureId TerrainStorage::getVtexIndexAt(int cellX, int cellY,
@ -318,9 +308,6 @@ namespace MWRender
ESM::Land* land = getLand(cellX, cellY);
if (land)
{
if (!land->isDataLoaded(ESM::Land::DATA_VTEX))
land->loadData(ESM::Land::DATA_VTEX);
int tex = land->mLandData->mTextures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
if (tex == 0)
return std::make_pair(0,0); // vtex 0 is always the base texture, regardless of plugin
@ -345,8 +332,24 @@ namespace MWRender
return texture;
}
void TerrainStorage::getBlendmaps (const std::vector<Terrain::QuadTreeNode*>& nodes, std::vector<Terrain::LayerCollection>& out, bool pack)
{
for (std::vector<Terrain::QuadTreeNode*>::const_iterator it = nodes.begin(); it != nodes.end(); ++it)
{
out.push_back(Terrain::LayerCollection());
out.back().mTarget = *it;
getBlendmapsImpl((*it)->getSize(), (*it)->getCenter(), pack, out.back().mBlendmaps, out.back().mLayers);
}
}
void TerrainStorage::getBlendmaps(float chunkSize, const Ogre::Vector2 &chunkCenter,
bool pack, std::vector<Ogre::TexturePtr> &blendmaps, std::vector<Terrain::LayerInfo> &layerList)
bool pack, std::vector<Ogre::PixelBox> &blendmaps, std::vector<Terrain::LayerInfo> &layerList)
{
getBlendmapsImpl(chunkSize, chunkCenter, pack, blendmaps, layerList);
}
void TerrainStorage::getBlendmapsImpl(float chunkSize, const Ogre::Vector2 &chunkCenter,
bool pack, std::vector<Ogre::PixelBox> &blendmaps, std::vector<Terrain::LayerInfo> &layerList)
{
// TODO - blending isn't completely right yet; the blending radius appears to be
// different at a cell transition (2 vertices, not 4), so we may need to create a larger blendmap
@ -391,16 +394,14 @@ namespace MWRender
// Second iteration - create and fill in the blend maps
const int blendmapSize = ESM::Land::LAND_TEXTURE_SIZE+1;
std::vector<Ogre::uchar> data;
data.resize(blendmapSize * blendmapSize * channels, 0);
for (int i=0; i<numBlendmaps; ++i)
{
Ogre::PixelFormat format = pack ? Ogre::PF_A8B8G8R8 : Ogre::PF_A8;
static int count=0;
Ogre::TexturePtr map = Ogre::TextureManager::getSingleton().createManual("terrain/blend/"
+ Ogre::StringConverter::toString(count++), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D, blendmapSize, blendmapSize, 0, format);
Ogre::uchar* pData =
OGRE_ALLOC_T(Ogre::uchar, blendmapSize*blendmapSize*channels, Ogre::MEMCATEGORY_GENERAL);
memset(pData, 0, blendmapSize*blendmapSize*channels);
for (int y=0; y<blendmapSize; ++y)
{
@ -412,16 +413,12 @@ namespace MWRender
int channel = pack ? std::max(0, (layerIndex-1) % 4) : 0;
if (blendIndex == i)
data[y*blendmapSize*channels + x*channels + channel] = 255;
pData[y*blendmapSize*channels + x*channels + channel] = 255;
else
data[y*blendmapSize*channels + x*channels + channel] = 0;
pData[y*blendmapSize*channels + x*channels + channel] = 0;
}
}
// All done, upload to GPU
Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size()));
map->loadRawData(stream, blendmapSize, blendmapSize, format);
blendmaps.push_back(map);
blendmaps.push_back(Ogre::PixelBox(blendmapSize, blendmapSize, 1, format, pData));
}
}
@ -543,6 +540,12 @@ namespace MWRender
info.mSpecular = true;
}
// This wasn't cached, so the textures are probably not loaded either.
// Background load them so they are hopefully already loaded once we need them!
Ogre::ResourceBackgroundQueue::getSingleton().load("Texture", info.mDiffuseMap, "General");
if (!info.mNormalMap.empty())
Ogre::ResourceBackgroundQueue::getSingleton().load("Texture", info.mNormalMap, "General");
mLayerInfoMap[texture] = info;
return info;

View File

@ -1,6 +1,9 @@
#ifndef MWRENDER_TERRAINSTORAGE_H
#define MWRENDER_TERRAINSTORAGE_H
#include <components/esm/loadland.hpp>
#include <components/esm/loadltex.hpp>
#include <components/terrain/storage.hpp>
namespace MWRender
@ -14,10 +17,10 @@ namespace MWRender
public:
/// Get bounds of the whole terrain in cell units
virtual Ogre::AxisAlignedBox getBounds();
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY);
/// Get the minimum and maximum heights of a terrain chunk.
/// @note Should only be called for chunks <= 1 cell, i.e. leafs of the quad tree.
/// Get the minimum and maximum heights of a terrain region.
/// @note Will only be called for chunks with size = minBatchSize, i.e. leafs of the quad tree.
/// Larger chunks can simply merge AABB of children.
/// @param size size of the chunk in cell units
/// @param center center of the chunk in cell units
@ -27,20 +30,23 @@ namespace MWRender
virtual bool getMinMaxHeights (float size, const Ogre::Vector2& center, float& min, float& max);
/// Fill vertex buffers for a terrain chunk.
/// @note May be called from background threads. Make sure to only call thread-safe functions from here!
/// @note returned colors need to be in render-system specific format! Use RenderSystem::convertColourValue.
/// @param lodLevel LOD level, 0 = most detailed
/// @param size size of the terrain chunk in cell units
/// @param center center of the chunk in cell units
/// @param vertexBuffer buffer to write vertices
/// @param normalBuffer buffer to write vertex normals
/// @param colourBuffer buffer to write vertex colours
virtual void fillVertexBuffers (int lodLevel, float size, const Ogre::Vector2& center,
Ogre::HardwareVertexBufferSharedPtr vertexBuffer,
Ogre::HardwareVertexBufferSharedPtr normalBuffer,
Ogre::HardwareVertexBufferSharedPtr colourBuffer);
/// @param positions buffer to write vertices
/// @param normals buffer to write vertex normals
/// @param colours buffer to write vertex colours
virtual void fillVertexBuffers (int lodLevel, float size, const Ogre::Vector2& center, Terrain::Alignment align,
std::vector<float>& positions,
std::vector<float>& normals,
std::vector<Ogre::uint8>& colours);
/// Create textures holding layer blend values for a terrain chunk.
/// @note The terrain chunk shouldn't be larger than one cell since otherwise we might
/// have to do a ridiculous amount of different layers. For larger chunks, composite maps should be used.
/// @note May be called from *one* background thread.
/// @param chunkSize size of the terrain chunk in cell units
/// @param chunkCenter center of the chunk in cell units
/// @param pack Whether to pack blend values for up to 4 layers into one texture (one in each channel) -
@ -49,9 +55,21 @@ namespace MWRender
/// @param blendmaps created blendmaps will be written here
/// @param layerList names of the layer textures used will be written here
virtual void getBlendmaps (float chunkSize, const Ogre::Vector2& chunkCenter, bool pack,
std::vector<Ogre::TexturePtr>& blendmaps,
std::vector<Ogre::PixelBox>& blendmaps,
std::vector<Terrain::LayerInfo>& layerList);
/// Retrieve pixel data for textures holding layer blend values for terrain chunks and layer texture information.
/// This variant is provided to eliminate the overhead of virtual function calls when retrieving a large number of blendmaps at once.
/// @note The terrain chunks shouldn't be larger than one cell since otherwise we might
/// have to do a ridiculous amount of different layers. For larger chunks, composite maps should be used.
/// @note May be called from *one* background thread.
/// @param nodes A collection of nodes for which to retrieve the aforementioned data
/// @param out Output vector
/// @param pack Whether to pack blend values for up to 4 layers into one texture (one in each channel) -
/// otherwise, each texture contains blend values for one layer only. Shader-based rendering
/// can utilize packing, FFP can't.
virtual void getBlendmaps (const std::vector<Terrain::QuadTreeNode*>& nodes, std::vector<Terrain::LayerCollection>& out, bool pack);
virtual float getHeightAt (const Ogre::Vector3& worldPos);
virtual Terrain::LayerInfo getDefaultLayer();
@ -81,6 +99,11 @@ namespace MWRender
std::map<std::string, Terrain::LayerInfo> mLayerInfoMap;
Terrain::LayerInfo getLayerInfo(const std::string& texture);
// Non-virtual
void getBlendmapsImpl (float chunkSize, const Ogre::Vector2& chunkCenter, bool pack,
std::vector<Ogre::PixelBox>& blendmaps,
std::vector<Terrain::LayerInfo>& layerList);
};
}

View File

@ -9,6 +9,11 @@
#include <OgreRoot.h>
#include <OgreHardwarePixelBuffer.h>
#include <OgreRenderWindow.h>
#include <OgreTextureManager.h>
#include <OgreTechnique.h>
#include <OgreRectangle2D.h>
#include <OgreMaterialManager.h>
#include <OgreSceneNode.h>
#include <boost/thread.hpp>

View File

@ -1,11 +1,16 @@
#include "water.hpp"
#include <OgreRenderTarget.h>
#include <OgreRenderTexture.h>
#include <OgreEntity.h>
#include <OgreMeshManager.h>
#include <OgreMaterialManager.h>
#include <OgreHardwarePixelBuffer.h>
#include <OgreRoot.h>
#include <OgreCamera.h>
#include <OgreTextureManager.h>
#include <OgreViewport.h>
#include <OgreSceneNode.h>
#include <OgreTechnique.h>
#include "sky.hpp"
#include "renderingmanager.hpp"

View File

@ -4,7 +4,7 @@
#include <string>
#include <map>
#include <libs/platform/stdint.h>
#include <stdint.h>
#include "locals.hpp"

View File

@ -3,6 +3,8 @@
#include <iostream>
#include <vector>
#include <stdint.h>
#include <boost/thread.hpp>
#include "openal_output.hpp"
@ -172,6 +174,7 @@ class OpenAL_SoundStream : public Sound
DecoderPtr mDecoder;
volatile bool mIsFinished;
volatile bool mIsInitialBatchEnqueued;
void updateAll(bool local);
@ -264,7 +267,7 @@ private:
OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder, float basevol, float pitch, int flags)
: Sound(Ogre::Vector3(0.0f), 1.0f, basevol, pitch, 1.0f, 1000.0f, flags)
, mOutput(output), mSource(src), mSamplesQueued(0), mDecoder(decoder), mIsFinished(true)
, mOutput(output), mSource(src), mSamplesQueued(0), mDecoder(decoder), mIsFinished(true), mIsInitialBatchEnqueued(false)
{
throwALerror();
@ -315,26 +318,8 @@ void OpenAL_SoundStream::play()
alSourcei(mSource, AL_BUFFER, 0);
throwALerror();
mSamplesQueued = 0;
std::vector<char> data(mBufferSize);
bool finished = false;
for(ALuint i = 0;i < sNumBuffers && !finished;i++)
{
size_t got = mDecoder->read(&data[0], data.size());
finished = (got < data.size());
if(got > 0)
{
ALuint bufid = mBuffers[i];
alBufferData(bufid, mFormat, &data[0], got, mSampleRate);
alSourceQueueBuffers(mSource, 1, &bufid);
throwALerror();
mSamplesQueued += getBufferSampleCount(bufid);
}
}
mIsFinished = finished;
alSourcePlay(mSource);
mIsFinished = false;
mIsInitialBatchEnqueued = false;
mOutput.mStreamThread->add(this);
}
@ -342,6 +327,7 @@ void OpenAL_SoundStream::stop()
{
mOutput.mStreamThread->remove(this);
mIsFinished = true;
mIsInitialBatchEnqueued = false;
alSourceStop(mSource);
alSourcei(mSource, AL_BUFFER, 0);
@ -454,6 +440,24 @@ bool OpenAL_SoundStream::process()
} while(processed > 0);
throwALerror();
}
else if (!mIsInitialBatchEnqueued) { // nothing enqueued yet
std::vector<char> data(mBufferSize);
for(ALuint i = 0;i < sNumBuffers && !finished;i++)
{
size_t got = mDecoder->read(&data[0], data.size());
finished = (got < data.size());
if(got > 0)
{
ALuint bufid = mBuffers[i];
alBufferData(bufid, mFormat, &data[0], got, mSampleRate);
alSourceQueueBuffers(mSource, 1, &bufid);
throwALerror();
mSamplesQueued += getBufferSampleCount(bufid);
}
}
mIsInitialBatchEnqueued = true;
}
if(state != AL_PLAYING && state != AL_PAUSED)
{
@ -471,6 +475,7 @@ bool OpenAL_SoundStream::process()
std::cout<< "Error updating stream \""<<mDecoder->getName()<<"\"" <<std::endl;
mSamplesQueued = 0;
mIsFinished = true;
mIsInitialBatchEnqueued = false;
}
return !mIsFinished;
}

View File

@ -177,7 +177,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
else
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
std::ofstream stream (slot->mPath.string().c_str());
std::ofstream stream (slot->mPath.string().c_str(), std::ios::binary);
ESM::ESMWriter writer;

View File

@ -5,7 +5,7 @@
#include <string>
#include <map>
#include <libs/platform/stdint.h>
#include <stdint.h>
#include <components/interpreter/types.hpp>
#include <components/esm/variant.hpp>

View File

@ -8,6 +8,7 @@
#include <OgreViewport.h>
#include <OgreCamera.h>
#include <OgreTextureManager.h>
#include <OgreSceneNode.h>
#include <openengine/bullet/trace.h>
#include <openengine/bullet/physic.hpp>

View File

@ -43,7 +43,7 @@ namespace
mPhysics (physics), mRendering (rendering)
{}
bool InsertFunctor::InsertFunctor::operator() (const MWWorld::Ptr& ptr)
bool InsertFunctor::operator() (const MWWorld::Ptr& ptr)
{
if (mRescale)
{
@ -79,55 +79,6 @@ namespace
return true;
}
template<typename T>
void insertCellRefList(MWRender::RenderingManager& rendering,
T& cellRefList, MWWorld::CellStore &cell, MWWorld::PhysicsSystem& physics, bool rescale, Loading::Listener* loadingListener)
{
if (!cellRefList.mList.empty())
{
const MWWorld::Class& class_ =
MWWorld::Class::get (MWWorld::Ptr (&*cellRefList.mList.begin(), &cell));
for (typename T::List::iterator it = cellRefList.mList.begin();
it != cellRefList.mList.end(); it++)
{
if (rescale)
{
if (it->mRef.mScale<0.5)
it->mRef.mScale = 0.5;
else if (it->mRef.mScale>2)
it->mRef.mScale = 2;
}
if (it->mData.getCount() && it->mData.isEnabled())
{
MWWorld::Ptr ptr (&*it, &cell);
try
{
rendering.addObject(ptr);
class_.insertObject(ptr, physics);
float ax = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees();
float ay = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees();
float az = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees();
MWBase::Environment::get().getWorld()->localRotateObject(ptr, ax, ay, az);
MWBase::Environment::get().getWorld()->scaleObject(ptr, ptr.getCellRef().mScale);
class_.adjustPosition(ptr);
}
catch (const std::exception& e)
{
std::string error ("error during rendering: ");
std::cerr << error + e.what() << std::endl;
}
}
loadingListener->increaseProgress(1);
}
}
}
}
@ -211,8 +162,6 @@ namespace MWWorld
mRendering.cellAdded (cell);
mRendering.configureAmbient(*cell);
mRendering.requestMap(cell);
mRendering.configureAmbient(*cell);
}
// register local scripts
@ -246,6 +195,11 @@ namespace MWWorld
mechMgr->updateCell(old, player);
mechMgr->watchActor(player);
mRendering.updateTerrain();
for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active)
mRendering.requestMap(*active);
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
}
@ -260,12 +214,13 @@ namespace MWWorld
void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos)
{
mRendering.enableTerrain(true);
Nif::NIFFile::CacheLock cachelock;
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
Loading::ScopedLoad load(loadingListener);
mRendering.enableTerrain(true);
std::string loadingExteriorText = "#{sLoadingMessage3}";
loadingListener->setLabel(loadingExteriorText);
@ -410,11 +365,11 @@ namespace MWWorld
Nif::NIFFile::CacheLock lock;
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0.5);
mRendering.enableTerrain(false);
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
Loading::ScopedLoad load(loadingListener);
mRendering.enableTerrain(false);
std::string loadingInteriorText = "#{sLoadingMessage2}";
loadingListener->setLabel(loadingInteriorText);

View File

@ -388,6 +388,8 @@ namespace MWWorld
typedef std::vector<ESM::LandTexture>::const_iterator iterator;
// Must be threadsafe! Called from terrain background loading threads.
// Not a big deal here, since ESM::LandTexture can never be modified or inserted/erased
const ESM::LandTexture *search(size_t index, size_t plugin) const {
assert(plugin < mStatic.size());
const LandTextureList &ltexl = mStatic[plugin];
@ -487,6 +489,8 @@ namespace MWWorld
return iterator(mStatic.end());
}
// Must be threadsafe! Called from terrain background loading threads.
// Not a big deal here, since ESM::Land can never be modified or inserted/erased
ESM::Land *search(int x, int y) const {
ESM::Land land;
land.mX = x, land.mY = y;

View File

@ -1873,6 +1873,8 @@ namespace MWWorld
bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc)
{
if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled())
return false; // cannot get LOS unless both NPC's are enabled
Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(npc.getRefData().getHandle())->getHalfExtents();
float* pos1 = npc.getRefData().getPosition().pos;
Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetNpc.getRefData().getHandle())->getHalfExtents();

View File

@ -1,177 +0,0 @@
# Locate SDL library
# This module defines
# SDL_LIBRARY, the name of the library to link against
# SDL_FOUND, if false, do not try to link to SDL
# SDL_INCLUDE_DIR, where to find SDL.h
#
# This module responds to the the flag:
# SDL_BUILDING_LIBRARY
# If this is defined, then no SDL_main will be linked in because
# only applications need main().
# Otherwise, it is assumed you are building an application and this
# module will attempt to locate and set the the proper link flags
# as part of the returned SDL_LIBRARY variable.
#
# Don't forget to include SDLmain.h and SDLmain.m your project for the
# OS X framework based version. (Other versions link to -lSDLmain which
# this module will try to find on your behalf.) Also for OS X, this
# module will automatically add the -framework Cocoa on your behalf.
#
#
# Additional Note: If you see an empty SDL_LIBRARY_TEMP in your configuration
# and no SDL_LIBRARY, it means CMake did not find your SDL library
# (SDL.dll, libsdl.so, SDL.framework, etc).
# Set SDL_LIBRARY_TEMP to point to your SDL library, and configure again.
# Similarly, if you see an empty SDLMAIN_LIBRARY, you should set this value
# as appropriate. These values are used to generate the final SDL_LIBRARY
# variable, but when these values are unset, SDL_LIBRARY does not get created.
#
#
# $SDLDIR is an environment variable that would
# correspond to the ./configure --prefix=$SDLDIR
# used in building SDL.
# l.e.galup 9-20-02
#
# Modified by Eric Wing.
# Added code to assist with automated building by using environmental variables
# and providing a more controlled/consistent search behavior.
# Added new modifications to recognize OS X frameworks and
# additional Unix paths (FreeBSD, etc).
# Also corrected the header search path to follow "proper" SDL guidelines.
# Added a search for SDLmain which is needed by some platforms.
# Added a search for threads which is needed by some platforms.
# Added needed compile switches for MinGW.
#
# On OSX, this will prefer the Framework version (if found) over others.
# People will have to manually change the cache values of
# SDL_LIBRARY to override this selection or set the CMake environment
# CMAKE_INCLUDE_PATH to modify the search paths.
#
# Note that the header path has changed from SDL/SDL.h to just SDL.h
# This needed to change because "proper" SDL convention
# is #include "SDL.h", not <SDL/SDL.h>. This is done for portability
# reasons because not all systems place things in SDL/ (see FreeBSD).
#=============================================================================
# Copyright 2003-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 distribute this file outside of CMake, substitute the full
# License text for the above reference.)
FIND_PATH(SDL_INCLUDE_DIR SDL.h
HINTS
$ENV{SDLDIR}
PATH_SUFFIXES include/SDL include
PATHS
~/Library/Frameworks
/Library/Frameworks
/usr/local/include/SDL12
/usr/local/include/SDL11 # FreeBSD ports
/usr/include/SDL12
/usr/include/SDL11
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
)
#MESSAGE("SDL_INCLUDE_DIR is ${SDL_INCLUDE_DIR}")
# SDL-1.1 is the name used by FreeBSD ports...
# don't confuse it for the version number.
FIND_LIBRARY(SDL_LIBRARY_TEMP
NAMES SDL SDL-1.1
HINTS
$ENV{SDLDIR}
PATH_SUFFIXES lib64 lib
PATHS
/sw
/opt/local
/opt/csw
/opt
)
#MESSAGE("SDL_LIBRARY_TEMP is ${SDL_LIBRARY_TEMP}")
IF(NOT SDL_BUILDING_LIBRARY)
IF(NOT ${SDL_INCLUDE_DIR} MATCHES ".framework")
# Non-OS X framework versions expect you to also dynamically link to
# SDLmain. This is mainly for Windows and OS X. Other (Unix) platforms
# seem to provide SDLmain for compatibility even though they don't
# necessarily need it.
FIND_LIBRARY(SDLMAIN_LIBRARY
NAMES SDLmain SDLmain-1.1
HINTS
$ENV{SDLDIR}
PATH_SUFFIXES lib64 lib
PATHS
/sw
/opt/local
/opt/csw
/opt
)
ENDIF(NOT ${SDL_INCLUDE_DIR} MATCHES ".framework")
ENDIF(NOT SDL_BUILDING_LIBRARY)
# SDL may require threads on your system.
# The Apple build may not need an explicit flag because one of the
# frameworks may already provide it.
# But for non-OSX systems, I will use the CMake Threads package.
IF(NOT APPLE)
FIND_PACKAGE(Threads)
ENDIF(NOT APPLE)
# MinGW needs an additional library, mwindows
# It's total link flags should look like -lmingw32 -lSDLmain -lSDL -lmwindows
# (Actually on second look, I think it only needs one of the m* libraries.)
IF(MINGW)
SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
ENDIF(MINGW)
SET(SDL_FOUND "NO")
IF(SDL_LIBRARY_TEMP)
# For SDLmain
IF(NOT SDL_BUILDING_LIBRARY)
IF(SDLMAIN_LIBRARY)
SET(SDL_LIBRARY_TEMP ${SDLMAIN_LIBRARY} ${SDL_LIBRARY_TEMP})
ENDIF(SDLMAIN_LIBRARY)
ENDIF(NOT SDL_BUILDING_LIBRARY)
# For OS X, SDL uses Cocoa as a backend so it must link to Cocoa.
# CMake doesn't display the -framework Cocoa string in the UI even
# though it actually is there if I modify a pre-used variable.
# I think it has something to do with the CACHE STRING.
# So I use a temporary variable until the end so I can set the
# "real" variable in one-shot.
IF(APPLE)
SET(SDL_LIBRARY_TEMP ${SDL_LIBRARY_TEMP} "-framework Cocoa")
ENDIF(APPLE)
# For threads, as mentioned Apple doesn't need this.
# In fact, there seems to be a problem if I used the Threads package
# and try using this line, so I'm just skipping it entirely for OS X.
IF(NOT APPLE)
SET(SDL_LIBRARY_TEMP ${SDL_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
ENDIF(NOT APPLE)
# For MinGW library
IF(MINGW)
SET(SDL_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL_LIBRARY_TEMP})
ENDIF(MINGW)
# Set the final string here so the GUI reflects the final state.
SET(SDL_LIBRARY ${SDL_LIBRARY_TEMP} CACHE STRING "Where the SDL Library can be found")
# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
SET(SDL_LIBRARY_TEMP "${SDL_LIBRARY_TEMP}" CACHE INTERNAL "")
SET(SDL_FOUND "YES")
ENDIF(SDL_LIBRARY_TEMP)
#MESSAGE("SDL_LIBRARY is ${SDL_LIBRARY}")

View File

@ -85,10 +85,6 @@ function(get_git_head_revision _refspecvar _hashvar)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
#get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
@ -133,7 +129,8 @@ endfunction()
function(get_git_tag_revision _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
return()
endif()
execute_process(COMMAND

View File

@ -73,8 +73,9 @@ add_component_dir (translation
translation
)
add_definitions(-DTERRAIN_USE_SHADER=1)
add_component_dir (terrain
quadtreenode chunk world storage material
quadtreenode chunk world storage material buffercache defs
)
add_component_dir (loadinglistener

View File

@ -29,6 +29,7 @@
#include <OgreArchive.h>
#include <OgreArchiveFactory.h>
#include <OgreArchiveManager.h>
#include <OgreResourceGroupManager.h>
#include "bsa_file.hpp"
#include "../files/constrainedfiledatastream.hpp"

View File

@ -24,7 +24,7 @@
#ifndef BSA_BSA_FILE_H
#define BSA_BSA_FILE_H
#include <libs/platform/stdint.h>
#include <stdint.h>
#include <libs/platform/strings.h>
#include <string>
#include <vector>

View File

@ -1,7 +1,7 @@
#ifndef OPENMW_ESM_DEFS_H
#define OPENMW_ESM_DEFS_H
#include <libs/platform/stdint.h>
#include <stdint.h>
namespace ESM
{

View File

@ -4,7 +4,7 @@
#include <string>
#include <cstring>
#include <libs/platform/stdint.h>
#include <stdint.h>
#include <libs/platform/string.h>
namespace ESM

View File

@ -1,7 +1,7 @@
#ifndef OPENMW_ESM_READER_H
#define OPENMW_ESM_READER_H
#include <libs/platform/stdint.h>
#include <stdint.h>
#include <libs/platform/string.h>
#include <cassert>
#include <vector>

View File

@ -80,8 +80,8 @@ namespace ESM
rec.name = name;
rec.position = mStream->tellp();
rec.size = 0;
writeT<int>(0); // Size goes here
writeT<int>(0); // Unused header?
writeT<uint32_t>(0); // Size goes here
writeT<uint32_t>(0); // Unused header?
writeT(flags);
mRecords.push_back(rec);
@ -105,7 +105,7 @@ namespace ESM
rec.name = name;
rec.position = mStream->tellp();
rec.size = 0;
writeT<int>(0); // Size goes here
writeT<uint32_t>(0); // Size goes here
mRecords.push_back(rec);
assert(mRecords.back().size == 0);
@ -120,7 +120,7 @@ namespace ESM
mStream->seekp(rec.position);
mCounting = false;
write (reinterpret_cast<const char*> (&rec.size), sizeof(int));
write (reinterpret_cast<const char*> (&rec.size), sizeof(uint32_t));
mCounting = true;
mStream->seekp(0, std::ios::end);

View File

@ -17,7 +17,7 @@ class ESMWriter
{
std::string name;
std::streampos position;
size_t size;
uint32_t size;
};
public:

View File

@ -249,7 +249,7 @@ bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref)
if (id.mPaged)
{
id.mWorldspace = "default";
id.mWorldspace = "sys::default";
id.mIndex.mX = mData.mX;
id.mIndex.mY = mData.mY;
}

Some files were not shown because too many files have changed in this diff Show More