Merge branch 'master' of https://github.com/OpenMW/openmw.git into AIFix2

Conflicts:
	apps/openmw/mwmechanics/aifollow.cpp
actorid
gus 11 years ago
commit bee057346b

@ -12,7 +12,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 28)
set(OPENMW_VERSION_MINOR 29)
set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_VERSION_COMMITHASH "")
@ -73,6 +73,8 @@ option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binarie
option(BOOST_STATIC "Link static build of Boost into the binaries" FALSE)
option(SDL2_STATIC "Link static build of SDL into the binaries" FALSE)
option(OPENMW_UNITY_BUILD "Use fewer compilation units to speed up compile time" FALSE)
# Apps and tools
option(BUILD_BSATOOL "build BSA extractor" OFF)
option(BUILD_ESMTOOL "build ESM inspector" ON)
@ -130,6 +132,7 @@ set(OENGINE_OGRE
set(OENGINE_GUI
${LIBDIR}/openengine/gui/manager.cpp
${LIBDIR}/openengine/gui/layout.hpp
)
set(OENGINE_BULLET
@ -238,6 +241,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)
@ -455,7 +466,6 @@ if(WIN32)
INSTALL(FILES
"${OpenMW_SOURCE_DIR}/readme.txt"
"${OpenMW_SOURCE_DIR}/GPL3.txt"
"${OpenMW_SOURCE_DIR}/OFL.txt"
"${OpenMW_SOURCE_DIR}/DejaVu Font License.txt"
"${OpenMW_BINARY_DIR}/settings-default.cfg"
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg"

@ -1,93 +0,0 @@
Copyright (c) 2010, 2011 Georg Duffner (http://www.georgduffner.at)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

@ -60,16 +60,21 @@ opencs_hdrs_noqt (view/doc
opencs_units (view/world
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
scenetoolmode infocreator scriptedit
scenetoolmode infocreator scriptedit dialoguesubview previewsubview
)
opencs_units (view/render
scenewidget
)
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
previewwidget
)
opencs_units_noqt (view/render
navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight
lightingbright
)
opencs_units_noqt (view/world
dialoguesubview subviews
enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
scripthighlighter idvalidator dialoguecreator
)
@ -143,6 +148,9 @@ if(WIN32)
set(QT_USE_QTMAIN TRUE)
endif(WIN32)
set(BOOST_COMPONENTS system filesystem program_options thread wave)
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
include(${QT_USE_FILE})
@ -183,6 +191,8 @@ if(APPLE)
endif(APPLE)
target_link_libraries(opencs
${OGRE_LIBRARIES}
${SHINY_LIBRARIES}
${Boost_LIBRARIES}
${QT_LIBRARIES}
components

@ -9,15 +9,30 @@
#include <OgreRoot.h>
#include <OgreRenderWindow.h>
#include <extern/shiny/Main/Factory.hpp>
#include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp>
#include <components/ogreinit/ogreinit.hpp>
#include <components/bsa/resources.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";
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
setupDataFiles (config.first);
CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg");
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
setupDataFiles();
Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true,
mFsStrict);
mNewGame.setLocalData (mLocal);
mFileDialog.setLocalData (mLocal);
@ -42,7 +57,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::fromUtf8 (iter->string().c_str());
mFileDialog.addFiles(path);
}
}
std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfig()
{
boost::program_options::variables_map variables;
boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options");
@ -52,12 +76,18 @@ void CS::Editor::setupDataFiles()
("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252"))
("resources", boost::program_options::value<std::string>()->default_value("resources"));
("resources", boost::program_options::value<std::string>()->default_value("resources"))
("fallback-archive", boost::program_options::value<std::vector<std::string> >()->
default_value(std::vector<std::string>(), "fallback-archive")->multitoken());
boost::program_options::notify(variables);
mCfgMgr.readConfiguration(variables, desc);
mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
mFsStrict = variables["fs-strict"].as<bool>();
Files::PathContainer dataDirs, dataLocal;
if (!variables["data"].empty()) {
dataDirs = Files::PathContainer(variables["data"].as<Files::PathContainer>());
@ -83,23 +113,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 std::make_pair (dataDirs, variables["fallback-archive"].as<std::vector<std::string> >());
}
void CS::Editor::createGame()
@ -130,7 +148,7 @@ void CS::Editor::openFiles (const boost::filesystem::path &savePath)
std::vector<boost::filesystem::path> files;
foreach (const QString &path, mFileDialog.selectedFilePaths())
files.push_back(path.toStdString());
files.push_back(path.toUtf8().constData());
CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, false);
@ -143,10 +161,10 @@ void CS::Editor::createNewFile (const boost::filesystem::path &savePath)
std::vector<boost::filesystem::path> files;
foreach (const QString &path, mFileDialog.selectedFilePaths()) {
files.push_back(path.toStdString());
files.push_back(path.toUtf8().constData());
}
files.push_back(mFileDialog.filename().toStdString());
files.push_back(mFileDialog.filename().toUtf8().constData());
CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, true);
@ -210,8 +228,15 @@ int CS::Editor::run()
if (mLocal.empty())
return 1;
// temporarily disable OGRE-integration (need to fix path problem first)
#if 0
mStartup.show();
QApplication::setQuitOnLastWindowClosed (true);
return QApplication::exec();
}
std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
{
// TODO: setting
Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem"));
@ -228,11 +253,37 @@ int CS::Editor::run()
#endif
Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, &params);
hiddenWindow->setActive(false);
#endif
mStartup.show();
sh::OgrePlatform* platform =
new sh::OgrePlatform ("General", (mResources / "materials").string());
QApplication::setQuitOnLastWindowClosed (true);
if (!boost::filesystem::exists (mCfgMgr.getCachePath()))
boost::filesystem::create_directories (mCfgMgr.getCachePath());
return QApplication::exec();
platform->setCacheFolder (mCfgMgr.getCachePath().string());
std::auto_ptr<sh::Factory> factory (new sh::Factory (platform));
factory->setCurrentLanguage (sh::Language_GLSL); /// \todo make this configurable
factory->setWriteSourceCache (true);
factory->setReadSourceCache (true);
factory->setReadMicrocodeCache (true);
factory->setWriteMicrocodeCache (true);
factory->loadAllFiles();
sh::Factory::getInstance().setGlobalSetting ("fog", "true");
sh::Factory::getInstance().setGlobalSetting ("shadows", "false");
sh::Factory::getInstance().setGlobalSetting ("shadows_pssm", "false");
sh::Factory::getInstance ().setGlobalSetting ("render_refraction", "false");
sh::Factory::getInstance ().setGlobalSetting ("viewproj_fix", "false");
sh::Factory::getInstance ().setGlobalSetting ("num_lights", "8");
/// \todo add more configurable shiny settings
return factory;
}

@ -1,15 +1,21 @@
#ifndef CS_EDITOR_H
#define CS_EDITOR_H
#include <memory>
#include <QObject>
#include <QString>
#include <QLocalServer>
#include <QLocalSocket>
#include <extern/shiny/Main/Factory.hpp>
#ifndef Q_MOC_RUN
#include <components/files/configurationmanager.hpp>
#endif
#include <components/files/multidircollection.hpp>
#include "model/settings/usersettings.hpp"
#include "model/doc/documentmanager.hpp"
@ -20,6 +26,11 @@
#include "view/settings/usersettingsdialog.hpp"
namespace OgreInit
{
class OgreInit;
}
namespace CS
{
class Editor : public QObject
@ -34,10 +45,14 @@ namespace CS
CSVDoc::NewGameDialogue mNewGame;
CSVSettings::UserSettingsDialog mSettings;
CSVDoc::FileDialog mFileDialog;
boost::filesystem::path mLocal;
boost::filesystem::path mResources;
bool mFsStrict;
void setupDataFiles();
void setupDataFiles (const Files::PathContainer& dataDirs);
std::pair<Files::PathContainer, std::vector<std::string> > readConfig();
///< \return data paths
// not implemented
Editor (const Editor&);
@ -45,7 +60,7 @@ namespace CS
public:
Editor();
Editor (OgreInit::OgreInit& ogreInit);
bool makeIPCServer();
void connectToIPCServer();
@ -53,6 +68,9 @@ namespace CS
int run();
///< \return error status
std::auto_ptr<sh::Factory> setupGraphics();
///< The returned factory must persist at least as long as *this.
private slots:
void createGame();

@ -7,6 +7,8 @@
#include <QApplication>
#include <QIcon>
#include <extern/shiny/Main/Factory.hpp>
#include <components/ogreinit/ogreinit.hpp>
#ifdef Q_OS_MAC
@ -40,15 +42,11 @@ 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
std::auto_ptr<sh::Factory> shinyFactory;
Application application (argc, argv);
#ifdef Q_OS_MAC
QDir dir(QCoreApplication::applicationDirPath());
@ -66,12 +64,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())
{
@ -79,5 +77,7 @@ int main(int argc, char *argv[])
// return 0;
}
shinyFactory = editor.setupGraphics();
return editor.run();
}

@ -143,6 +143,6 @@ void CSMTools::Tools::verifierMessage (const QString& message, int type)
std::map<int, int>::iterator iter = mActiveReports.find (type);
if (iter!=mActiveReports.end())
mReports[iter->second]->add (message.toStdString());
mReports[iter->second]->add (message.toUtf8().constData());
}

@ -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)
{
@ -448,7 +448,8 @@ namespace CSMWorld
template<typename ESXRecordT, typename IdAccessorT>
void Collection<ESXRecordT, IdAccessorT>::setRecord (int index, const Record<ESXRecordT>& record)
{
if (IdAccessorT().getId (mRecords.at (index).get())!=IdAccessorT().getId (record.get()))
if (Misc::StringUtils::lowerCase (IdAccessorT().getId (mRecords.at (index).get()))!=
Misc::StringUtils::lowerCase (IdAccessorT().getId (record.get())))
throw std::runtime_error ("attempt to change the ID of a record");
mRecords.at (index) = record;

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

@ -17,4 +17,9 @@ bool CSMWorld::ColumnBase::isUserEditable() const
std::string CSMWorld::ColumnBase::getTitle() const
{
return Columns::getName (static_cast<Columns::ColumnId> (mColumnId));
}
int CSMWorld::ColumnBase::getId() const
{
return mColumnId;
}

@ -28,6 +28,7 @@ namespace CSMWorld
{
Display_None, //Do not use
Display_String,
Display_LongString,
//CONCRETE TYPES STARTS HERE
Display_Skill,
@ -105,6 +106,8 @@ namespace CSMWorld
///< Can this column be edited directly by the user?
virtual std::string getTitle() const;
virtual int getId() const;
};
template<typename ESXRecordT>

@ -37,7 +37,6 @@ namespace CSMWorld
}
};
/// \note Shares ID with IdColumn. A table can not have both.
template<typename ESXRecordT>
struct StringIdColumn : public Column<ESXRecordT>
{
@ -202,7 +201,7 @@ namespace CSMWorld
struct DescriptionColumn : public Column<ESXRecordT>
{
DescriptionColumn()
: Column<ESXRecordT> (Columns::ColumnId_Description, ColumnBase::Display_String)
: Column<ESXRecordT> (Columns::ColumnId_Description, ColumnBase::Display_LongString)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
@ -834,15 +833,15 @@ namespace CSMWorld
virtual bool isUserEditable() const
{
return false;
return true;
}
};
/// \note Shares ID with StringIdColumn. A table can not have both.
template<typename ESXRecordT>
struct IdColumn : public Column<ESXRecordT>
{
IdColumn() : Column<ESXRecordT> (Columns::ColumnId_Id, ColumnBase::Display_String) {}
IdColumn() : Column<ESXRecordT> (Columns::ColumnId_ReferenceableId,
ColumnBase::Display_Referenceable) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
@ -1114,7 +1113,7 @@ namespace CSMWorld
virtual bool isUserEditable() const
{
return false;
return true;
}
};
@ -1380,7 +1379,7 @@ namespace CSMWorld
template<typename ESXRecordT>
struct QuestDescriptionColumn : public Column<ESXRecordT>
{
QuestDescriptionColumn() : Column<ESXRecordT> (Columns::ColumnId_QuestDescription, ColumnBase::Display_String) {}
QuestDescriptionColumn() : Column<ESXRecordT> (Columns::ColumnId_QuestDescription, ColumnBase::Display_LongString) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
@ -1560,7 +1559,7 @@ namespace CSMWorld
template<typename ESXRecordT>
struct ResponseColumn : public Column<ESXRecordT>
{
ResponseColumn() : Column<ESXRecordT> (Columns::ColumnId_Response, ColumnBase::Display_String) {}
ResponseColumn() : Column<ESXRecordT> (Columns::ColumnId_Response, ColumnBase::Display_LongString) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{

@ -172,7 +172,8 @@ namespace CSMWorld
{ ColumnId_Rank, "Rank" },
{ ColumnId_Gender, "Gender" },
{ ColumnId_PcRank, "PC Rank" },
{ ColumnId_Scope, "Scope", },
{ ColumnId_Scope, "Scope" },
{ ColumnId_ReferenceableId, "Referenceable ID" },
{ ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" },

@ -166,6 +166,7 @@ namespace CSMWorld
ColumnId_Gender = 153,
ColumnId_PcRank = 154,
ColumnId_Scope = 155,
ColumnId_ReferenceableId = 156,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.

@ -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 (&mReferenceables), UniversalId::Type_Referenceables,
UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs), UniversalId::Type_References, UniversalId::Type_Reference, false);
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, IdTable::Reordering_None, IdTable::Viewing_None, true),
UniversalId::Type_Referenceables, UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Reordering_None, IdTable::Viewing_Cell, true), UniversalId::Type_References, UniversalId::Type_Reference, false);
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false);
}

@ -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, bool preview)
: mIdCollection (idCollection), mReordering (reordering), mViewing (viewing), mPreview (preview)
{}
CSMWorld::IdTable::~IdTable()
@ -188,4 +189,55 @@ 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;
}
bool CSMWorld::IdTable::hasPreview() const
{
return mPreview;
}
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);
}
int CSMWorld::IdTable::getColumnId(int column) const
{
return mIdCollection->getColumn(column).getId();
}

@ -25,10 +25,21 @@ 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;
bool mPreview;
// not implemented
IdTable (const IdTable&);
@ -36,7 +47,8 @@ namespace CSMWorld
public:
IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_WithinTopic);
IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None,
Viewing viewing = Viewing_None, bool preview = false);
///< The ownership of \a idCollection is not transferred.
virtual ~IdTable();
@ -63,8 +75,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 +98,16 @@ namespace CSMWorld
/// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex).
Reordering getReordering() const;
Viewing getViewing() const;
bool hasPreview() 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, "").
int getColumnId(int column) const;
};
}

@ -8,7 +8,7 @@ CSMWorld::TableMimeData::TableMimeData (UniversalId id, const CSMDoc::Document&
mDocument(document)
{
mUniversalId.push_back (id);
mObjectsFormats << QString::fromStdString ("tabledata/" + id.getTypeName());
mObjectsFormats << QString::fromUtf8 (("tabledata/" + id.getTypeName()).c_str());
}
CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) :
@ -16,7 +16,7 @@ CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id
{
for (std::vector<UniversalId>::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it)
{
mObjectsFormats << QString::fromStdString ("tabledata/" + it->getTypeName());
mObjectsFormats << QString::fromUtf8 (("tabledata/" + it->getTypeName()).c_str());
}
}
@ -64,14 +64,69 @@ std::vector< CSMWorld::UniversalId > CSMWorld::TableMimeData::getData() const
return mUniversalId;
}
bool CSMWorld::TableMimeData::isReferencable(CSMWorld::ColumnBase::Display type) const
{
return ( type == CSMWorld::ColumnBase::Display_Activator
|| type == CSMWorld::ColumnBase::Display_Potion
|| type == CSMWorld::ColumnBase::Display_Apparatus
|| type == CSMWorld::ColumnBase::Display_Armor
|| type == CSMWorld::ColumnBase::Display_Book
|| type == CSMWorld::ColumnBase::Display_Clothing
|| type == CSMWorld::ColumnBase::Display_Container
|| type == CSMWorld::ColumnBase::Display_Creature
|| type == CSMWorld::ColumnBase::Display_Door
|| type == CSMWorld::ColumnBase::Display_Ingredient
|| type == CSMWorld::ColumnBase::Display_CreatureLevelledList
|| type == CSMWorld::ColumnBase::Display_ItemLevelledList
|| type == CSMWorld::ColumnBase::Display_Light
|| type == CSMWorld::ColumnBase::Display_Lockpick
|| type == CSMWorld::ColumnBase::Display_Miscellaneous
|| type == CSMWorld::ColumnBase::Display_Npc
|| type == CSMWorld::ColumnBase::Display_Probe
|| type == CSMWorld::ColumnBase::Display_Repair
|| type == CSMWorld::ColumnBase::Display_Static
|| type == CSMWorld::ColumnBase::Display_Weapon);
}
bool CSMWorld::TableMimeData::isReferencable(CSMWorld::UniversalId::Type type) const
{
return ( type == CSMWorld::UniversalId::Type_Activator
|| type == CSMWorld::UniversalId::Type_Potion
|| type == CSMWorld::UniversalId::Type_Apparatus
|| type == CSMWorld::UniversalId::Type_Armor
|| type == CSMWorld::UniversalId::Type_Book
|| type == CSMWorld::UniversalId::Type_Clothing
|| type == CSMWorld::UniversalId::Type_Container
|| type == CSMWorld::UniversalId::Type_Creature
|| type == CSMWorld::UniversalId::Type_Door
|| type == CSMWorld::UniversalId::Type_Ingredient
|| type == CSMWorld::UniversalId::Type_CreatureLevelledList
|| type == CSMWorld::UniversalId::Type_ItemLevelledList
|| type == CSMWorld::UniversalId::Type_Light
|| type == CSMWorld::UniversalId::Type_Lockpick
|| type == CSMWorld::UniversalId::Type_Miscellaneous
|| type == CSMWorld::UniversalId::Type_Npc
|| type == CSMWorld::UniversalId::Type_Probe
|| type == CSMWorld::UniversalId::Type_Repair
|| type == CSMWorld::UniversalId::Type_Static
|| type == CSMWorld::UniversalId::Type_Weapon);
}
bool CSMWorld::TableMimeData::holdsType (CSMWorld::UniversalId::Type type) const
{
bool referencable = (type == CSMWorld::UniversalId::Type_Referenceable);
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == type)
if (referencable)
{
return true;
if (isReferencable(it->getType()))
{
return true;
}
} else {
if (it->getType() == type)
{
return true;
}
}
}
@ -80,11 +135,20 @@ bool CSMWorld::TableMimeData::holdsType (CSMWorld::UniversalId::Type type) const
bool CSMWorld::TableMimeData::holdsType (CSMWorld::ColumnBase::Display type) const
{
bool referencable = (type == CSMWorld::ColumnBase::Display_Referenceable);
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == convertEnums (type))
if (referencable)
{
return true;
if (isReferencable(it->getType()))
{
return true;
}
} else {
if (it->getType() == convertEnums (type))
{
return true;
}
}
}
@ -93,11 +157,21 @@ bool CSMWorld::TableMimeData::holdsType (CSMWorld::ColumnBase::Display type) con
CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::UniversalId::Type type) const
{
bool referencable = (type == CSMWorld::UniversalId::Type_Referenceable);
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == type)
if (referencable)
{
return *it;
if (isReferencable(it->getType()))
{
return *it;
}
} else
{
if (it->getType() == type)
{
return *it;
}
}
}
@ -106,11 +180,20 @@ CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::Univers
CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::ColumnBase::Display type) const
{
bool referencable = (type == CSMWorld::ColumnBase::Display_Referenceable);
for (std::vector<UniversalId>::const_iterator it = mUniversalId.begin(); it != mUniversalId.end(); ++it)
{
if (it->getType() == convertEnums (type))
if (referencable)
{
return *it;
if (isReferencable(it->getType()))
{
return *it;
}
} else {
if (it->getType() == convertEnums (type))
{
return *it;
}
}
}
@ -443,4 +526,9 @@ CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::U
default:
return CSMWorld::ColumnBase::Display_None;
}
}
const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const
{
return &mDocument;
}

@ -27,6 +27,9 @@ namespace CSMWorld
class TableMimeData : public QMimeData
{
std::vector<UniversalId> mUniversalId;
QStringList mObjectsFormats;
const CSMDoc::Document& mDocument;
public:
TableMimeData(UniversalId id, const CSMDoc::Document& document);
@ -48,15 +51,16 @@ namespace CSMWorld
UniversalId returnMatching(UniversalId::Type type) const;
const CSMDoc::Document* getDocumentPtr() const;
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
private:
std::vector<UniversalId> mUniversalId;
QStringList mObjectsFormats;
const CSMDoc::Document& mDocument;
bool isReferencable(CSMWorld::UniversalId::Type type) const;
bool isReferencable(CSMWorld::ColumnBase::Display type) const;
};
}

@ -90,14 +90,16 @@ 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_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 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
};
}

@ -95,7 +95,8 @@ namespace CSMWorld
Type_TopicInfo,
Type_JournalInfos,
Type_JournalInfo,
Type_Scene
Type_Scene,
Type_Preview
};
enum { NumberOfTypes = Type_Scene+1 };

@ -40,7 +40,7 @@ OpenDialog::OpenDialog(QWidget * parent) : QDialog(parent)
mCfgMgr.processPaths(mDataLocal);
// Set the charset for reading the esm/esp files
QString encoding = QString::fromStdString(variables["encoding"].as<std::string>());
QString encoding = QString::fromUtf8 (variables["encoding"].as<std::string>().c_str());
Files::PathContainer dataDirs;
dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end());

@ -4,7 +4,7 @@ CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id)
{
/// \todo add a button to the title bar that clones this sub view
setWindowTitle (mUniversalId.toString().c_str());
setWindowTitle (QString::fromUtf8 (mUniversalId.toString().c_str()));
}
CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const
@ -16,4 +16,12 @@ 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) {}
void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
{
mUniversalId = id;
setWindowTitle (mUniversalId.toString().c_str());
}

@ -27,6 +27,8 @@ namespace CSVDoc
// not implemented
SubView (const SubView&);
SubView& operator= (SubView&);
protected:
void setUniversalId(const CSMWorld::UniversalId& id);
public:
@ -40,9 +42,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);
};
}

@ -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
@ -320,14 +316,25 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id)
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
const std::vector<CSMWorld::UniversalId::Type> referenceables(CSMWorld::UniversalId::listReferenceableTypes());
SubView *view = NULL;
if(std::find(referenceables.begin(), referenceables.end(), id.getType()) != referenceables.end())
{
view = mSubViewFactory.makeSubView (CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Referenceable, id.getId()), *mDocument);
} else
{
view = mSubViewFactory.makeSubView (id, *mDocument);
}
assert(view);
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 +436,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);

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

@ -120,7 +120,7 @@ void CSVFilter::EditWidget::createFilterRequest (std::vector< std::pair< std::st
{
ss<<"!or(";
} else {
ss << orAnd << oldContent.toStdString() << ',';
ss << orAnd << oldContent.toUtf8().constData() << ',';
}
for (unsigned i = 0; i < count; ++i)
@ -137,7 +137,7 @@ void CSVFilter::EditWidget::createFilterRequest (std::vector< std::pair< std::st
} else {
if (!replaceMode)
{
ss << orAnd << oldContent.toStdString() <<',';
ss << orAnd << oldContent.toUtf8().constData() <<',';
} else {
ss<<'!';
}

@ -5,7 +5,7 @@
#include <QLineEdit>
#include <QPalette>
#include <qt4/QtCore/qnamespace.h>
#include <QtCore/qnamespace.h>
#include "../../model/filter/parser.hpp"
#include "../../model/filter/node.hpp"

@ -4,7 +4,7 @@
#include <vector>
#include <QWidget>
#include <qt4/QtCore/qnamespace.h>
#include <QtCore/qnamespace.h>
#include "../../model/filter/node.hpp"
#include "../../model/world/universalid.hpp"

@ -4,7 +4,7 @@
#include <boost/shared_ptr.hpp>
#include <QWidget>
#include <qt4/QtCore/qnamespace.h>
#include <QtCore/qnamespace.h>
#include <QHBoxLayout>

@ -0,0 +1,4 @@
#include "lighting.hpp"
CSVRender::Lighting::~Lighting() {}

@ -0,0 +1,27 @@
#ifndef OPENCS_VIEW_LIGHTING_H
#define OPENCS_VIEW_LIGHTING_H
namespace Ogre
{
class SceneManager;
class ColourValue;
}
namespace CSVRender
{
class Lighting
{
public:
virtual ~Lighting();
virtual void activate (Ogre::SceneManager *sceneManager,
const Ogre::ColourValue *defaultAmbient = 0) = 0;
virtual void deactivate() = 0;
virtual void setDefaultAmbient (const Ogre::ColourValue& colour) = 0;
};
}
#endif

@ -0,0 +1,30 @@
#include "lightingbright.hpp"
#include <OgreSceneManager.h>
CSVRender::LightingBright::LightingBright() : mSceneManager (0), mLight (0) {}
void CSVRender::LightingBright::activate (Ogre::SceneManager *sceneManager,
const Ogre::ColourValue *defaultAmbient)
{
mSceneManager = sceneManager;
mSceneManager->setAmbientLight (Ogre::ColourValue (1.0, 1.0, 1.0, 1));
mLight = mSceneManager->createLight();
mLight->setType (Ogre::Light::LT_DIRECTIONAL);
mLight->setDirection (Ogre::Vector3 (0, 0, -1));
mLight->setDiffuseColour (Ogre::ColourValue (1.0, 1.0, 1.0));
}
void CSVRender::LightingBright::deactivate()
{
if (mLight)
{
mSceneManager->destroyLight (mLight);
mLight = 0;
}
}
void CSVRender::LightingBright::setDefaultAmbient (const Ogre::ColourValue& colour) {}

@ -0,0 +1,31 @@
#ifndef OPENCS_VIEW_LIGHTING_BRIGHT_H
#define OPENCS_VIEW_LIGHTING_BRIGHT_H
#include "lighting.hpp"
namespace Ogre
{
class Light;
}
namespace CSVRender
{
class LightingBright : public Lighting
{
Ogre::SceneManager *mSceneManager;
Ogre::Light *mLight;
public:
LightingBright();
virtual void activate (Ogre::SceneManager *sceneManager,
const Ogre::ColourValue *defaultAmbient = 0);
virtual void deactivate();
virtual void setDefaultAmbient (const Ogre::ColourValue& colour);
};
}
#endif

@ -0,0 +1,36 @@
#include "lightingday.hpp"
#include <OgreSceneManager.h>
CSVRender::LightingDay::LightingDay() : mSceneManager (0), mLight (0) {}
void CSVRender::LightingDay::activate (Ogre::SceneManager *sceneManager,
const Ogre::ColourValue *defaultAmbient)
{
mSceneManager = sceneManager;
if (defaultAmbient)
mSceneManager->setAmbientLight (*defaultAmbient);
else
mSceneManager->setAmbientLight (Ogre::ColourValue (0.7, 0.7, 0.7, 1));
mLight = mSceneManager->createLight();
mLight->setType (Ogre::Light::LT_DIRECTIONAL);
mLight->setDirection (Ogre::Vector3 (0, 0, -1));
mLight->setDiffuseColour (Ogre::ColourValue (1, 1, 1));
}
void CSVRender::LightingDay::deactivate()
{
if (mLight)
{
mSceneManager->destroyLight (mLight);
mLight = 0;
}
}
void CSVRender::LightingDay::setDefaultAmbient (const Ogre::ColourValue& colour)
{
mSceneManager->setAmbientLight (colour);
}

@ -0,0 +1,31 @@
#ifndef OPENCS_VIEW_LIGHTING_DAY_H
#define OPENCS_VIEW_LIGHTING_DAY_H
#include "lighting.hpp"
namespace Ogre
{
class Light;
}
namespace CSVRender
{
class LightingDay : public Lighting
{
Ogre::SceneManager *mSceneManager;
Ogre::Light *mLight;
public:
LightingDay();
virtual void activate (Ogre::SceneManager *sceneManager,
const Ogre::ColourValue *defaultAmbient = 0);
virtual void deactivate();
virtual void setDefaultAmbient (const Ogre::ColourValue& colour);
};
}
#endif

@ -0,0 +1,36 @@
#include "lightingnight.hpp"
#include <OgreSceneManager.h>
CSVRender::LightingNight::LightingNight() : mSceneManager (0), mLight (0) {}
void CSVRender::LightingNight::activate (Ogre::SceneManager *sceneManager,
const Ogre::ColourValue *defaultAmbient)
{
mSceneManager = sceneManager;
if (defaultAmbient)
mSceneManager->setAmbientLight (*defaultAmbient);
else
mSceneManager->setAmbientLight (Ogre::ColourValue (0.2, 0.2, 0.2, 1));
mLight = mSceneManager->createLight();
mLight->setType (Ogre::Light::LT_DIRECTIONAL);
mLight->setDirection (Ogre::Vector3 (0, 0, -1));
mLight->setDiffuseColour (Ogre::ColourValue (0.2, 0.2, 0.2));
}
void CSVRender::LightingNight::deactivate()
{
if (mLight)
{
mSceneManager->destroyLight (mLight);
mLight = 0;
}
}
void CSVRender::LightingNight::setDefaultAmbient (const Ogre::ColourValue& colour)
{
mSceneManager->setAmbientLight (colour);
}

@ -0,0 +1,31 @@
#ifndef OPENCS_VIEW_LIGHTING_NIGHT_H
#define OPENCS_VIEW_LIGHTING_NIGHT_H
#include "lighting.hpp"
namespace Ogre
{
class Light;
}
namespace CSVRender
{
class LightingNight : public Lighting
{
Ogre::SceneManager *mSceneManager;
Ogre::Light *mLight;
public:
LightingNight();
virtual void activate (Ogre::SceneManager *sceneManager,
const Ogre::ColourValue *defaultAmbient = 0);
virtual void deactivate();
virtual void setDefaultAmbient (const Ogre::ColourValue& colour);
};
}
#endif

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

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

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

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

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

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

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

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

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

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

@ -0,0 +1,201 @@
#include "previewwidget.hpp"
#include <OgreSceneManager.h>
#include <OgreSceneNode.h>
#include "../../model/world/data.hpp"
#include "../../model/world/idtable.hpp"
void CSVRender::PreviewWidget::setup()
{
setNavigation (&mOrbit);
mNode = getSceneManager()->getRootSceneNode()->createChildSceneNode();
mNode->setPosition (Ogre::Vector3 (0, 0, 0));
setModel();
QAbstractItemModel *referenceables =
mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables);
connect (referenceables, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (ReferenceableDataChanged (const QModelIndex&, const QModelIndex&)));
connect (referenceables, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (ReferenceableAboutToBeRemoved (const QModelIndex&, int, int)));
}
void CSVRender::PreviewWidget::setModel()
{
if (mNode)
{
mObject.setNull();
if (mReferenceableId.empty())
return;
int column =
mData.getReferenceables().findColumnIndex (CSMWorld::Columns::ColumnId_Model);
int row = mData.getReferenceables().searchId (mReferenceableId);
if (row==-1)
return;
QVariant value = mData.getReferenceables().getData (row, column);
if (!value.isValid())
return;
std::string model = value.toString().toUtf8().constData();
if (model.empty())
return;
mObject = NifOgre::Loader::createObjects (mNode, "Meshes\\" + model);
}
}
void CSVRender::PreviewWidget::adjust()
{
if (mNode)
{
int row = mData.getReferences().getIndex (mReferenceId);
float scale = mData.getReferences().getData (row, mData.getReferences().
findColumnIndex (CSMWorld::Columns::ColumnId_Scale)).toFloat();
float rotX = mData.getReferences().getData (row, mData.getReferences().
findColumnIndex (CSMWorld::Columns::ColumnId_PositionXRot)).toFloat();
float rotY = mData.getReferences().getData (row, mData.getReferences().
findColumnIndex (CSMWorld::Columns::ColumnId_PositionYRot)).toFloat();
float rotZ = mData.getReferences().getData (row, mData.getReferences().
findColumnIndex (CSMWorld::Columns::ColumnId_PositionZRot)).toFloat();
mNode->setScale (scale, scale, scale);
Ogre::Quaternion xr (Ogre::Radian(-rotX), Ogre::Vector3::UNIT_X);
Ogre::Quaternion yr (Ogre::Radian(-rotY), Ogre::Vector3::UNIT_Y);
Ogre::Quaternion zr (Ogre::Radian(-rotZ), Ogre::Vector3::UNIT_Z);
mNode->setOrientation (xr*yr*zr);
}
}
CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data,
const std::string& referenceableId, QWidget *parent)
: SceneWidget (parent), mData (data), mNode (0), mReferenceableId (referenceableId)
{
setup();
}
CSVRender::PreviewWidget::PreviewWidget (CSMWorld::Data& data,
const std::string& referenceableId, const std::string& referenceId, QWidget *parent)
: SceneWidget (parent), mData (data), mReferenceableId (referenceableId),
mReferenceId (referenceId)
{
setup();
adjust();
QAbstractItemModel *references =
mData.getTableModel (CSMWorld::UniversalId::Type_References);
connect (references, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (ReferenceDataChanged (const QModelIndex&, const QModelIndex&)));
connect (references, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (ReferenceAboutToBeRemoved (const QModelIndex&, int, int)));
}
void CSVRender::PreviewWidget::ReferenceableDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
if (mReferenceableId.empty())
return;
CSMWorld::IdTable& referenceables = dynamic_cast<CSMWorld::IdTable&> (
*mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables));
QModelIndex index = referenceables.getModelIndex (mReferenceableId, 0);
if (index.row()>=topLeft.row() && index.row()<=bottomRight.row())
{
/// \todo possible optimisation; check columns and only update if relevant columns have
/// changed
setModel();
flagAsModified();
}
}
void CSVRender::PreviewWidget::ReferenceableAboutToBeRemoved (const QModelIndex& parent, int start,
int end)
{
if (mReferenceableId.empty())
return;
CSMWorld::IdTable& referenceables = dynamic_cast<CSMWorld::IdTable&> (
*mData.getTableModel (CSMWorld::UniversalId::Type_Referenceables));
QModelIndex index = referenceables.getModelIndex (mReferenceableId, 0);
if (index.row()>=start && index.row()<=end)
{
if (mReferenceId.empty())
{
// this is a preview for a referenceble
emit closeRequest();
}
else
{
// this is a preview for a reference
mObject.setNull();
flagAsModified();
}
}
}
void CSVRender::PreviewWidget::ReferenceDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
if (mReferenceId.empty())
return;
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
int columnIndex = references.findColumnIndex (CSMWorld::Columns::ColumnId_ReferenceableId);
QModelIndex index = references.getModelIndex (mReferenceId, columnIndex);
if (index.row()>=topLeft.row() && index.row()<=bottomRight.row())
{
/// \todo possible optimisation; check columns and only update if relevant columns have
/// changed
adjust();
if (index.column()>=topLeft.column() && index.column()<=bottomRight.row())
{
mReferenceableId = references.data (index).toString().toUtf8().constData();
emit referenceableIdChanged (mReferenceableId);
setModel();
}
flagAsModified();
}
}
void CSVRender::PreviewWidget::ReferenceAboutToBeRemoved (const QModelIndex& parent, int start,
int end)
{
if (mReferenceId.empty())
return;
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
QModelIndex index = references.getModelIndex (mReferenceId, 0);
if (index.row()>=start && index.row()<=end)
emit closeRequest();
}

@ -0,0 +1,64 @@
#ifndef OPENCS_VIEW_PREVIEWWIDGET_H
#define OPENCS_VIEW_PREVIEWWIDGET_H
#include <components/nifogre/ogrenifloader.hpp>
#include "scenewidget.hpp"
#include "navigationorbit.hpp"
class QModelIndex;
namespace CSMWorld
{
class Data;
}
namespace CSVRender
{
class PreviewWidget : public SceneWidget
{
Q_OBJECT
CSMWorld::Data& mData;
CSVRender::NavigationOrbit mOrbit;
NifOgre::ObjectScenePtr mObject;
Ogre::SceneNode *mNode;
std::string mReferenceId;
std::string mReferenceableId;
void setup();
void setModel();
void adjust();
///< Adjust referenceable preview according to the reference
public:
PreviewWidget (CSMWorld::Data& data, const std::string& referenceableId,
QWidget *parent = 0);
PreviewWidget (CSMWorld::Data& data, const std::string& referenceableId,
const std::string& referenceId, QWidget *parent = 0);
signals:
void closeRequest();
void referenceableIdChanged (const std::string& id);
private slots:
void ReferenceableDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight);
void ReferenceableAboutToBeRemoved (const QModelIndex& parent, int start, int end);
void ReferenceDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void ReferenceAboutToBeRemoved (const QModelIndex& parent, int start, int end);
};
}
#endif

@ -2,48 +2,79 @@
#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 "../world/scenetoolmode.hpp"
#include "navigation.hpp"
#include "lighting.hpp"
namespace CSVRender
{
SceneWidget::SceneWidget(QWidget *parent)
: QWidget(parent)
, mWindow(NULL)
, mCamera(NULL)
, mSceneMgr(NULL)
, mSceneMgr(NULL), mNavigation (0), mLighting (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
, mDefaultAmbient (0, 0, 0, 0), mHasDefaultAmbient (false)
{
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground);
mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
setFocusPolicy (Qt::StrongFocus);
// Throw in a random color just to make sure multiple scenes work
Ogre::Real r = Ogre::Math::RangeRandom(0, 1);
Ogre::Real g = Ogre::Math::RangeRandom(0, 1);
Ogre::Real b = Ogre::Math::RangeRandom(0, 1);
mSceneMgr->setAmbientLight(Ogre::ColourValue(r,g,b,1));
mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
Ogre::Light* l = mSceneMgr->createLight();
l->setType (Ogre::Light::LT_DIRECTIONAL);
l->setDirection (Ogre::Vector3(-0.4, -0.7, 0.3));
l->setDiffuseColour (Ogre::ColourValue(0.7,0.7,0.7));
mSceneMgr->setAmbientLight (Ogre::ColourValue (0,0,0,1));
mCamera = mSceneMgr->createCamera("foo");
Ogre::Entity* ent = mSceneMgr->createEntity("cube", Ogre::SceneManager::PT_CUBE);
ent->setMaterialName("BaseWhite");
mCamera->setPosition (300, 0, 0);
mCamera->lookAt (0, 0, 0);
mCamera->setNearClipDistance (0.1);
mCamera->setFarClipDistance (30000);
mCamera->roll (Ogre::Degree (90));
setLighting (&mLightingDay);
QTimer *timer = new QTimer (this);
connect (timer, SIGNAL (timeout()), this, SLOT (update()));
timer->start (20); /// \todo make this configurable
}
CSVWorld::SceneToolMode *SceneWidget::makeLightingSelector (CSVWorld::SceneToolbar *parent)
{
CSVWorld::SceneToolMode *tool = new CSVWorld::SceneToolMode (parent);
tool->addButton (":door.png", "day"); /// \todo replace icons
tool->addButton (":GMST.png", "night");
tool->addButton (":Info.png", "bright");
mSceneMgr->getRootSceneNode()->attachObject(ent);
connect (tool, SIGNAL (modeChanged (const std::string&)),
this, SLOT (selectLightingMode (const std::string&)));
mCamera->setPosition(300,300,300);
mCamera->lookAt(0,0,0);
mCamera->setNearClipDistance(0.1);
mCamera->setFarClipDistance(3000);
return tool;
}
void SceneWidget::setDefaultAmbient (const Ogre::ColourValue& colour)
{
mDefaultAmbient = colour;
mHasDefaultAmbient = true;
if (mLighting)
mLighting->setDefaultAmbient (colour);
}
void SceneWidget::updateOgreWindow()
@ -81,7 +112,31 @@ 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;
}
}
Ogre::SceneManager *SceneWidget::getSceneManager()
{
return mSceneMgr;
}
void SceneWidget::flagAsModified()
{
mUpdate = true;
}
void SceneWidget::paintEvent(QPaintEvent* e)
@ -93,7 +148,6 @@ namespace CSVRender
e->accept();
}
QPaintEngine* SceneWidget::paintEngine() const
{
// We don't want another paint engine to get in the way.
@ -130,4 +184,170 @@ 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;
}
void SceneWidget::setLighting (Lighting *lighting)
{
if (mLighting)
mLighting->deactivate();
mLighting = lighting;
mLighting->activate (mSceneMgr, mHasDefaultAmbient ? &mDefaultAmbient : 0);
}
void SceneWidget::selectLightingMode (const std::string& mode)
{
if (mode=="day")
setLighting (&mLightingDay);
else if (mode=="night")
setLighting (&mLightingNight);
else if (mode=="bright")
setLighting (&mLightingBright);
}
}

@ -3,6 +3,12 @@
#include <QWidget>
#include <OgreColourValue.h>
#include "lightingday.hpp"
#include "lightingnight.hpp"
#include "lightingbright.hpp"
namespace Ogre
{
class Camera;
@ -10,31 +16,100 @@ namespace Ogre
class RenderWindow;
}
namespace CSVWorld
{
class SceneToolMode;
class SceneToolbar;
}
namespace CSVRender
{
class Navigation;
class Lighting;
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();
CSVWorld::SceneToolMode *makeLightingSelector (CSVWorld::SceneToolbar *parent);
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
/// is the responsibility of the calling function.
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.
Ogre::SceneManager *getSceneManager();
void flagAsModified();
void setDefaultAmbient (const Ogre::ColourValue& colour);
///< \note The actual ambient colour may differ based on lighting settings.
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;
void setLighting (Lighting *lighting);
///< \attention The ownership of \a lighting is not transferred to *this.
Ogre::Camera* mCamera;
Ogre::SceneManager* mSceneMgr;
Ogre::RenderWindow* mWindow;
Navigation *mNavigation;
Lighting *mLighting;
bool mUpdate;
bool mKeyForward;
bool mKeyBackward;
bool mKeyLeft;
bool mKeyRight;
bool mKeyRollLeft;
bool mKeyRollRight;
bool mFast;
bool mDragging;
bool mMod1;
QPoint mOldPos;
int mFastFactor;
Ogre::ColourValue mDefaultAmbient;
bool mHasDefaultAmbient;
LightingDay mLightingDay;
LightingNight mLightingNight;
LightingBright mLightingBright;
private slots:
void update();
void selectLightingMode (const std::string& mode);
};
}
#endif

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

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

@ -0,0 +1,47 @@
#include "worldspacewidget.hpp"
#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
#include "../world/scenetoolmode.hpp"
CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent)
: SceneWidget (parent)
{
Ogre::Entity* ent = getSceneManager()->createEntity("cube", Ogre::SceneManager::PT_CUBE);
ent->setMaterialName("BaseWhite");
getSceneManager()->getRootSceneNode()->attachObject(ent);
}
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;
}

@ -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);
///< \attention 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

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

@ -1,98 +1,689 @@
#include "dialoguesubview.hpp"
#include <utility>
#include <memory>
#include <QGridLayout>
#include <QLabel>
#include <QSize>
#include <QAbstractItemModel>
#include <QDoubleSpinBox>
#include <QSpinBox>
#include <QLineEdit>
#include <QEvent>
#include <QDataWidgetMapper>
#include <QCheckBox>
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QComboBox>
#include <QScrollArea>
#include <QPushButton>
#include <QToolButton>
#include "../../model/world/columnbase.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/columns.hpp"
#include "../../model/world/record.hpp"
#include "../../model/world/tablemimedata.hpp"
#include "../../model/doc/document.hpp"
#include "../../model/world/commands.hpp"
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
bool createAndDelete)
: SubView (id)
#include "recordstatusdelegate.hpp"
#include "util.hpp"
#include "tablebottombox.hpp"
/*
==============================NotEditableSubDelegate==========================================
*/
CSVWorld::NotEditableSubDelegate::NotEditableSubDelegate(const CSMWorld::IdTable* table, QObject * parent) :
QAbstractItemDelegate(parent),
mTable(table)
{}
void CSVWorld::NotEditableSubDelegate::setEditorData (QLabel* editor, const QModelIndex& index) const
{
QVariant v = index.data(Qt::EditRole);
if (!v.isValid())
{
v = index.data(Qt::DisplayRole);
if (!v.isValid())
{
return;
}
}
if (QVariant::String == v.type())
{
editor->setText(v.toString());
} else //else we are facing enums
{
int data = v.toInt();
std::vector<std::string> enumNames (CSMWorld::Columns::getEnums (static_cast<CSMWorld::Columns::ColumnId> (mTable->getColumnId (index.column()))));
editor->setText(QString::fromUtf8(enumNames.at(data).c_str()));
}
}
void CSVWorld::NotEditableSubDelegate::setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
{
//not editable widgets will not save model data
}
void CSVWorld::NotEditableSubDelegate::paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
//does nothing
}
QSize CSVWorld::NotEditableSubDelegate::sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const
{
return QSize();
}
QWidget* CSVWorld::NotEditableSubDelegate::createEditor (QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index,
CSMWorld::ColumnBase::Display display) const
{
return new QLabel(parent);
}
/*
==============================DialogueDelegateDispatcherProxy==========================================
*/
CSVWorld::DialogueDelegateDispatcherProxy::refWrapper::refWrapper(const QModelIndex& index) :
mIndex(index)
{}
CSVWorld::DialogueDelegateDispatcherProxy::DialogueDelegateDispatcherProxy(QWidget* editor, CSMWorld::ColumnBase::Display display) :
mEditor(editor),
mDisplay(display),
mIndexWrapper(NULL)
{
}
void CSVWorld::DialogueDelegateDispatcherProxy::editorDataCommited()
{
if (mIndexWrapper.get())
{
emit editorDataCommited(mEditor, mIndexWrapper->mIndex, mDisplay);
}
}
void CSVWorld::DialogueDelegateDispatcherProxy::setIndex(const QModelIndex& index)
{
mIndexWrapper.reset(new refWrapper(index));
}
QWidget* CSVWorld::DialogueDelegateDispatcherProxy::getEditor() const
{
return mEditor;
}
void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>& data, const CSMDoc::Document* document)
{
QLineEdit* lineEdit = qobject_cast<QLineEdit*>(mEditor);
{
if (!lineEdit || !mIndexWrapper.get())
{
return;
}
}
for (unsigned i = 0; i < data.size(); ++i)
{
CSMWorld::UniversalId::Type type = data[i].getType();
if (mDisplay == CSMWorld::ColumnBase::Display_Referenceable)
{
if ( type == CSMWorld::UniversalId::Type_Activator
|| type == CSMWorld::UniversalId::Type_Potion
|| type == CSMWorld::UniversalId::Type_Apparatus
|| type == CSMWorld::UniversalId::Type_Armor
|| type == CSMWorld::UniversalId::Type_Book
|| type == CSMWorld::UniversalId::Type_Clothing
|| type == CSMWorld::UniversalId::Type_Container
|| type == CSMWorld::UniversalId::Type_Creature
|| type == CSMWorld::UniversalId::Type_Door
|| type == CSMWorld::UniversalId::Type_Ingredient
|| type == CSMWorld::UniversalId::Type_CreatureLevelledList
|| type == CSMWorld::UniversalId::Type_ItemLevelledList
|| type == CSMWorld::UniversalId::Type_Light
|| type == CSMWorld::UniversalId::Type_Lockpick
|| type == CSMWorld::UniversalId::Type_Miscellaneous
|| type == CSMWorld::UniversalId::Type_Npc
|| type == CSMWorld::UniversalId::Type_Probe
|| type == CSMWorld::UniversalId::Type_Repair
|| type == CSMWorld::UniversalId::Type_Static
|| type == CSMWorld::UniversalId::Type_Weapon)
{
type = CSMWorld::UniversalId::Type_Referenceable;
}
}
if (mDisplay == CSMWorld::TableMimeData::convertEnums(type))
{
emit tableMimeDataDropped(mEditor, mIndexWrapper->mIndex, data[i], document);
emit editorDataCommited(mEditor, mIndexWrapper->mIndex, mDisplay);
break;
}
}
}
/*
==============================DialogueDelegateDispatcher==========================================
*/
CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, QUndoStack& undoStack) :
mParent(parent),
mTable(table),
mUndoStack(undoStack),
mNotEditableDelegate(table, parent)
{
}
CSVWorld::CommandDelegate* CSVWorld::DialogueDelegateDispatcher::makeDelegate(CSMWorld::ColumnBase::Display display)
{
QWidget *widget = new QWidget (this);
CommandDelegate *delegate = NULL;
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
if (delegateIt == mDelegates.end())
{
delegate = CommandDelegateFactoryCollection::get().makeDelegate (
display, mUndoStack, mParent);
mDelegates.insert(std::make_pair<int, CommandDelegate*>(display, delegate));
} else
{
delegate = delegateIt->second;
}
return delegate;
}
setWidget (widget);
void CSVWorld::DialogueDelegateDispatcher::editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display)
{
setModelData(editor, mTable, index, display);
}
void CSVWorld::DialogueDelegateDispatcher::setEditorData (QWidget* editor, const QModelIndex& index) const
{
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
(mTable->headerData (index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
QGridLayout *layout = new QGridLayout;
QLabel* label = qobject_cast<QLabel*>(editor);
if(label)
{
mNotEditableDelegate.setEditorData(label, index);
return;
}
widget->setLayout (layout);
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
if (delegateIt != mDelegates.end())
{
delegateIt->second->setEditorData(editor, index, true);
}
QAbstractItemModel *model = document.getData().getTableModel (id);
for (unsigned i = 0; i < mProxys.size(); ++i)
{
if (mProxys[i]->getEditor() == editor)
{
mProxys[i]->setIndex(index);
}
}
}
void CSVWorld::DialogueDelegateDispatcher::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
{
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
if (delegateIt != mDelegates.end())
{
delegateIt->second->setModelData(editor, model, index);
}
}
void CSVWorld::DialogueDelegateDispatcher::paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
//Does nothing
}
QSize CSVWorld::DialogueDelegateDispatcher::sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const
{
return QSize(); //silencing warning, otherwise does nothing
}
QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::Display display, const QModelIndex& index)
{
QVariant variant = index.data();
if (!variant.isValid())
{
variant = index.data(Qt::DisplayRole);
if (!variant.isValid())
{
return NULL;
}
}
QWidget* editor = NULL;
if (! (mTable->flags (index) & Qt::ItemIsEditable))
{
return mNotEditableDelegate.createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display);
}
std::map<int, CommandDelegate*>::iterator delegateIt(mDelegates.find(display));
if (delegateIt != mDelegates.end())
{
editor = delegateIt->second->createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display);
DialogueDelegateDispatcherProxy* proxy = new DialogueDelegateDispatcherProxy(editor, display);
bool skip = false;
if (qobject_cast<DropLineEdit*>(editor))
{
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
connect(editor, SIGNAL(tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>&, const CSMDoc::Document*)),
proxy, SLOT(tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>&, const CSMDoc::Document*)));
connect(proxy, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
skip = true;
}
if(!skip && qobject_cast<QCheckBox*>(editor))
{
connect(editor, SIGNAL(stateChanged(int)), proxy, SLOT(editorDataCommited()));
skip = true;
}
if(!skip && qobject_cast<QPlainTextEdit*>(editor))
{
connect(editor, SIGNAL(textChanged()), proxy, SLOT(editorDataCommited()));
skip = true;
}
if(!skip && qobject_cast<QComboBox*>(editor))
{
connect(editor, SIGNAL(currentIndexChanged (int)), proxy, SLOT(editorDataCommited()));
skip = true;
}
if(!skip && qobject_cast<QAbstractSpinBox*>(editor))
{
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
skip = true;
}
connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)));
mProxys.push_back(proxy); //deleted in the destructor
}
return editor;
}
CSVWorld::DialogueDelegateDispatcher::~DialogueDelegateDispatcher()
{
for (unsigned i = 0; i < mProxys.size(); ++i)
{
delete mProxys[i]; //unique_ptr could be handy
}
}
/*
=============================================================EditWidget=====================================================
*/
CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, QUndoStack& undoStack, bool createAndDelete) :
mDispatcher(this, table, undoStack),
QScrollArea(parent),
mWidgetMapper(NULL),
mMainWidget(NULL),
mUndoStack(undoStack),
mTable(table)
{
remake (row);
connect(&mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
}
int columns = model->columnCount();
void CSVWorld::EditWidget::remake(int row)
{
if (mMainWidget)
{
delete mMainWidget;
}
mMainWidget = new QWidget (this);
//not sure if widget mapper can handle deleting the widgets that were mapped
if (mWidgetMapper)
{
delete mWidgetMapper;
}
mWidgetMapper = new QDataWidgetMapper (this);
mWidgetMapper->setModel (model);
mWidgetMapper->setModel(mTable);
mWidgetMapper->setItemDelegate(&mDispatcher);
QFrame* line = new QFrame(mMainWidget);
line->setObjectName(QString::fromUtf8("line"));
line->setGeometry(QRect(320, 150, 118, 3));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
QVBoxLayout *mainLayout = new QVBoxLayout(mMainWidget);
QGridLayout *unlockedLayout = new QGridLayout();
QGridLayout *lockedLayout = new QGridLayout();
mainLayout->addLayout(lockedLayout, 0);
mainLayout->addWidget(line, 1);
mainLayout->addLayout(unlockedLayout, 2);
mainLayout->addStretch(1);
int unlocked = 0;
int locked = 0;
const int columns = mTable->columnCount();
for (int i=0; i<columns; ++i)
{
int flags = model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt();
int flags = mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt();
if (flags & CSMWorld::ColumnBase::Flag_Dialogue)
{
layout->addWidget (new QLabel (model->headerData (i, Qt::Horizontal).toString()), i, 0);
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
(model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
(mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
QWidget *widget = 0;
mDispatcher.makeDelegate(display);
QWidget *editor = mDispatcher.makeEditor(display, (mTable->index (row, i)));
if (model->flags (model->index (0, i)) & Qt::ItemIsEditable)
if (editor)
{
switch (display)
mWidgetMapper->addMapping (editor, i);
QLabel* label = new QLabel(mTable->headerData (i, Qt::Horizontal).toString(), mMainWidget);
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
editor->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
if (! (mTable->flags (mTable->index (row, i)) & Qt::ItemIsEditable))
{
lockedLayout->addWidget (label, locked, 0);
lockedLayout->addWidget (editor, locked, 1);
++locked;
} else
{
case CSMWorld::ColumnBase::Display_String:
unlockedLayout->addWidget (label, unlocked, 0);
unlockedLayout->addWidget (editor, unlocked, 1);
++unlocked;
}
}
}
}
layout->addWidget (widget = new QLineEdit, i, 1);
break;
mWidgetMapper->setCurrentModelIndex(mTable->index(row, 0));
case CSMWorld::ColumnBase::Display_Integer:
this->setMinimumWidth(325); //TODO find better way to set the width or make it customizable
this->setWidget(mMainWidget);
this->setWidgetResizable(true);
}
/// \todo configure widget properly (range)
layout->addWidget (widget = new QSpinBox, i, 1);
break;
/*
==============================DialogueSubView==========================================
*/
case CSMWorld::ColumnBase::Display_Float:
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory, bool sorting) :
/// \todo configure widget properly (range, format?)
layout->addWidget (widget = new QDoubleSpinBox, i, 1);
break;
SubView (id),
mEditWidget(0),
mMainLayout(NULL),
mUndoStack(document.getUndoStack()),
mTable(dynamic_cast<CSMWorld::IdTable*>(document.getData().getTableModel(id))),
mRow (-1),
mLocked(false),
mDocument(document)
default: break; // silence warnings for other times for now
}
{
connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&)));
mRow = mTable->getModelIndex (id.getId(), 0).row();
QWidget *mainWidget = new QWidget(this);
QHBoxLayout *buttonsLayout = new QHBoxLayout;
QToolButton* prevButton = new QToolButton(mainWidget);
prevButton->setIcon(QIcon(":/go-previous.png"));
QToolButton* nextButton = new QToolButton(mainWidget);
nextButton->setIcon(QIcon(":/go-next.png"));
buttonsLayout->addWidget(prevButton, 0);
buttonsLayout->addWidget(nextButton, 1);
buttonsLayout->addStretch(2);
QToolButton* cloneButton = new QToolButton(mainWidget);
cloneButton->setIcon(QIcon(":/edit-clone.png"));
QToolButton* addButton = new QToolButton(mainWidget);
addButton->setIcon(QIcon(":/add.png"));
QToolButton* deleteButton = new QToolButton(mainWidget);
deleteButton->setIcon(QIcon(":/edit-delete.png"));
QToolButton* revertButton = new QToolButton(mainWidget);
revertButton->setIcon(QIcon(":/edit-undo.png"));
if (mTable->hasPreview())
{
QToolButton* previewButton = new QToolButton(mainWidget);
previewButton->setIcon(QIcon(":/edit-preview.png"));
buttonsLayout->addWidget(previewButton);
connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview()));
}
if (mTable->getViewing()!=CSMWorld::IdTable::Viewing_None)
{
QToolButton* viewButton = new QToolButton(mainWidget);
viewButton->setIcon(QIcon(":/cell.png"));
buttonsLayout->addWidget(viewButton);
connect(viewButton, SIGNAL(clicked()), this, SLOT(viewRecord()));
}
buttonsLayout->addWidget(cloneButton);
buttonsLayout->addWidget(addButton);
buttonsLayout->addWidget(deleteButton);
buttonsLayout->addWidget(revertButton);
connect(nextButton, SIGNAL(clicked()), this, SLOT(nextId()));
connect(prevButton, SIGNAL(clicked()), this, SLOT(prevId()));
connect(cloneButton, SIGNAL(clicked()), this, SLOT(cloneRequest()));
connect(revertButton, SIGNAL(clicked()), this, SLOT(revertRecord()));
connect(deleteButton, SIGNAL(clicked()), this, SLOT(deleteRecord()));
mMainLayout = new QVBoxLayout(mainWidget);
mEditWidget = new EditWidget(mainWidget, mRow, mTable, mUndoStack, false);
connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
mMainLayout->addWidget(mEditWidget);
mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
mMainLayout->addWidget (mBottom =
new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this));
mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&)));
connect(addButton, SIGNAL(clicked()), mBottom, SLOT(createRequest()));
if(!mBottom->canCreateAndDelete())
{
cloneButton->setDisabled(true);
addButton->setDisabled(true);
deleteButton->setDisabled(true);
}
dataChanged(mTable->index(mRow, 0));
mMainLayout->addLayout(buttonsLayout);
setWidget(mainWidget);
}
void CSVWorld::DialogueSubView::prevId()
{
int newRow = mRow - 1;
if (newRow < 0)
{
return;
}
while (newRow >= 0)
{
QModelIndex newIndex(mTable->index(newRow, 0));
if (!newIndex.isValid())
{
return;
}
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (newRow, 1)).toInt());
if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased))
{
mEditWidget->remake(newRow);
setUniversalId(CSMWorld::UniversalId (static_cast<CSMWorld::UniversalId::Type> (mTable->data (mTable->index (newRow, 2)).toInt()),
mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()));
mRow = newRow;
mEditWidget->setDisabled(mLocked);
return;
}
--newRow;
}
}
void CSVWorld::DialogueSubView::nextId()
{
int newRow = mRow + 1;
if (newRow >= mTable->rowCount())
{
return;
}
while (newRow < mTable->rowCount())
{
QModelIndex newIndex(mTable->index(newRow, 0));
if (!newIndex.isValid())
{
return;
}
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (newRow, 1)).toInt());
if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased))
{
mEditWidget->remake(newRow);
setUniversalId(CSMWorld::UniversalId (static_cast<CSMWorld::UniversalId::Type> (mTable->data (mTable->index (newRow, 2)).toInt()),
mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData()));
mRow = newRow;
mEditWidget->setDisabled(mLocked);
return;
}
++newRow;
}
}
void CSVWorld::DialogueSubView::setEditLock (bool locked)
{
mLocked = locked;
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)
{
mEditWidget->setDisabled(true);
} else
{
mEditWidget->setDisabled(mLocked);
}
}
void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index)
{
if (index.row() == mRow)
{
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)
{
mEditWidget->setDisabled(true);
} else
{
mEditWidget->setDisabled(mLocked);
}
}
}
void CSVWorld::DialogueSubView::tableMimeDataDropped(QWidget* editor,
const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document)
{
if (document == &mDocument)
{
qobject_cast<DropLineEdit*>(editor)->setText(id.getId().c_str());
}
}
void CSVWorld::DialogueSubView::revertRecord()
{
int rows = mTable->rowCount();
if (!mLocked && mTable->columnCount() > 0 && mRow < mTable->rowCount() )
{
CSMWorld::RecordBase::State state =
static_cast<CSMWorld::RecordBase::State> (mTable->data (mTable->index (mRow, 1)).toInt());
if (state!=CSMWorld::RecordBase::State_BaseOnly)
{
mUndoStack.push(new CSMWorld::RevertCommand(*mTable, mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData()));
}
if (rows != mTable->rowCount())
{
if (mTable->rowCount() == 0)
{
mEditWidget->setDisabled(true); //closing the editor is other option
return;
}
else
if (mRow >= mTable->rowCount())
{
switch (display)
{
case CSMWorld::ColumnBase::Display_String:
case CSMWorld::ColumnBase::Display_Integer:
case CSMWorld::ColumnBase::Display_Float:
prevId();
} else {
dataChanged(mTable->index(mRow, 0));
}
}
}
}
layout->addWidget (widget = new QLabel, i, 1);
break;
void CSVWorld::DialogueSubView::deleteRecord()
{
int rows = mTable->rowCount();
default: break; // silence warnings for other times for now
}
}
//easier than disabling the button
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
bool deledetedOrErased = (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased);
if (widget)
mWidgetMapper->addMapping (widget, i);
if (!mLocked &&
mTable->columnCount() > 0 &&
!deledetedOrErased &&
mRow < rows &&
mBottom->canCreateAndDelete())
{
mUndoStack.push(new CSMWorld::DeleteCommand(*mTable, mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData()));
if (rows != mTable->rowCount())
{
if (mTable->rowCount() == 0)
{
mEditWidget->setDisabled(true); //closing the editor is other option
return;
}
if (mRow >= mTable->rowCount())
{
prevId();
} else {
dataChanged(mTable->index(mRow, 0));
}
}
}
}
mWidgetMapper->setCurrentModelIndex (
dynamic_cast<CSMWorld::IdTable&> (*model).getModelIndex (id.getId(), 0));
void CSVWorld::DialogueSubView::requestFocus (const std::string& id)
{
mRow = mTable->getModelIndex (id, 0).row();
mEditWidget->remake(mRow);
}
void CSVWorld::DialogueSubView::setEditLock (bool locked)
void CSVWorld::DialogueSubView::cloneRequest ()
{
mBottom->cloneRequest(mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData(),
static_cast<CSMWorld::UniversalId::Type>(mTable->data(mTable->index(mRow, 2)).toInt()));
}
}
void CSVWorld::DialogueSubView::showPreview ()
{
if (mTable->hasPreview() && mRow < mTable->rowCount())
{
emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData()), "");
}
}
void CSVWorld::DialogueSubView::viewRecord()
{
if (mRow < mTable->rowCount())
{
std::pair<CSMWorld::UniversalId, std::string> params = mTable->view (mRow);
if (params.first.getType()!=CSMWorld::UniversalId::Type_None)
emit focusId (params.first, params.second);
}
}

@ -1,9 +1,25 @@
#ifndef CSV_WORLD_DIALOGUESUBVIEW_H
#define CSV_WORLD_DIALOGUESUBVIEW_H
#include <map>
#include <memory>
#include <QAbstractItemDelegate>
#include <QScrollArea>
#include "../doc/subview.hpp"
#include "../../model/world/columnbase.hpp"
class QDataWidgetMapper;
class QSize;
class QEvent;
class QLabel;
class QVBoxLayout;
namespace CSMWorld
{
class IdTable;
}
namespace CSMDoc
{
@ -12,15 +28,181 @@ namespace CSMDoc
namespace CSVWorld
{
class DialogueSubView : public CSVDoc::SubView
class CommandDelegate;
class CreatorFactoryBase;
class TableBottomBox;
class NotEditableSubDelegate : public QAbstractItemDelegate
{
const CSMWorld::IdTable* mTable;
public:
NotEditableSubDelegate(const CSMWorld::IdTable* table, QObject * parent = 0);
virtual void setEditorData (QLabel* editor, const QModelIndex& index) const;
virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const;
virtual void paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
///< does nothing
virtual QSize sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const;
///< does nothing
virtual QWidget *createEditor (QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index,
CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const;
};
//this can't be nested into the DialogueDelegateDispatcher, because it needs to emit signals
class DialogueDelegateDispatcherProxy : public QObject
{
Q_OBJECT
class refWrapper
{
public:
refWrapper(const QModelIndex& index);
const QModelIndex& mIndex;
};
QWidget* mEditor;
CSMWorld::ColumnBase::Display mDisplay;
std::auto_ptr<refWrapper> mIndexWrapper;
public:
DialogueDelegateDispatcherProxy(QWidget* editor, CSMWorld::ColumnBase::Display display);
QWidget* getEditor() const;
public slots:
void editorDataCommited();
void setIndex(const QModelIndex& index);
void tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>& data, const CSMDoc::Document* document);
signals:
void editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display);
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
};
class DialogueDelegateDispatcher : public QAbstractItemDelegate
{
Q_OBJECT
std::map<int, CommandDelegate*> mDelegates;
QObject* mParent;
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
NotEditableSubDelegate mNotEditableDelegate;
std::vector<DialogueDelegateDispatcherProxy*> mProxys; //once we move to the C++11 we should use unique_ptr
public:
DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, QUndoStack& undoStack);
~DialogueDelegateDispatcher();
CSVWorld::CommandDelegate* makeDelegate(CSMWorld::ColumnBase::Display display);
QWidget* makeEditor(CSMWorld::ColumnBase::Display display, const QModelIndex& index);
///< will return null if delegate is not present, parent of the widget is same as for dispatcher itself
virtual void setEditorData (QWidget* editor, const QModelIndex& index) const;
virtual void setModelData (QWidget* editor, QAbstractItemModel* model, const QModelIndex& index, CSMWorld::ColumnBase::Display display) const;
virtual void paint (QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
///< does nothing
virtual QSize sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const;
///< does nothing
private slots:
void editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display);
signals:
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
};
class EditWidget : public QScrollArea
{
Q_OBJECT
QDataWidgetMapper *mWidgetMapper;
DialogueDelegateDispatcher mDispatcher;
QWidget* mMainWidget;
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
public:
EditWidget (QWidget *parent, int row, CSMWorld::IdTable* table, QUndoStack& undoStack, bool createAndDelete = false);
void remake(int row);
signals:
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
};
class DialogueSubView : public CSVDoc::SubView
{
Q_OBJECT
EditWidget* mEditWidget;
QVBoxLayout* mMainLayout;
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
int mRow;
bool mLocked;
const CSMDoc::Document& mDocument;
TableBottomBox* mBottom;
public:
DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete);
DialogueSubView (const CSMWorld::UniversalId& id,
CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory,
bool sorting = false);
virtual void setEditLock (bool locked);
private slots:
void nextId();
void prevId();
void showPreview();
void viewRecord();
void revertRecord();
void deleteRecord();
void cloneRequest();
void dataChanged(const QModelIndex & index);
///\brief we need to care for deleting currently edited record
void tableMimeDataDropped(QWidget* editor, const QModelIndex& index,
const CSMWorld::UniversalId& id,
const CSMDoc::Document* document);
void requestFocus (const std::string& id);
};
}

@ -41,10 +41,18 @@ CSVWorld::EnumDelegate::EnumDelegate (const std::vector<std::pair<int, QString>
}
QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
return createEditor(parent, option, index, CSMWorld::ColumnBase::Display_None);
//overloading virtual functions is HARD
}
QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const
const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
{
if (!index.data().isValid())
if (!index.data(Qt::EditRole).isValid() && !index.data(Qt::DisplayRole).isValid())
return 0;
QComboBox *comboBox = new QComboBox (parent);
@ -56,11 +64,22 @@ QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptio
return comboBox;
}
void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index) const
void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const
{
if (QComboBox *comboBox = dynamic_cast<QComboBox *> (editor))
{
int value = index.data (Qt::EditRole).toInt();
QVariant data = index.data (Qt::EditRole);
if (tryDisplay && !data.isValid())
{
data = index.data (Qt::DisplayRole);
if (!data.isValid())
{
return;
}
}
int value = data.toInt();
std::size_t size = mValues.size();

@ -4,6 +4,7 @@
#include <vector>
#include <QString>
#include <QStyledItemDelegate>
#include <components/esm/defs.hpp>
@ -31,10 +32,16 @@ namespace CSVWorld
EnumDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent);
virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const;
virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index) const;
virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index,
CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const;
virtual void setEditorData (QWidget *editor, const QModelIndex& index) const;
virtual void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay = false) const;
virtual void paint (QPainter *painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const;

@ -0,0 +1,64 @@
#include "previewsubview.hpp"
#include <QHBoxLayout>
#include "../render/previewwidget.hpp"
#include "scenetoolbar.hpp"
#include "scenetoolmode.hpp"
CSVWorld::PreviewSubView::PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: SubView (id)
{
QHBoxLayout *layout = new QHBoxLayout;
layout->setContentsMargins (QMargins (0, 0, 0, 0));
if (document.getData().getReferenceables().searchId (id.getId())==-1)
{
std::string referenceableId =
document.getData().getReferences().getRecord (id.getId()).get().mRefID;
referenceableIdChanged (referenceableId);
mScene =
new CSVRender::PreviewWidget (document.getData(), referenceableId, id.getId(), this);
}
else
mScene = new CSVRender::PreviewWidget (document.getData(), id.getId(), this);
SceneToolbar *toolbar = new SceneToolbar (48, this);
SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar);
toolbar->addTool (lightingTool);
layout->addWidget (toolbar, 0);
layout->addWidget (mScene, 1);
QWidget *widget = new QWidget;
widget->setLayout (layout);
setWidget (widget);
connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
connect (mScene, SIGNAL (referenceableIdChanged (const std::string&)),
this, SLOT (referenceableIdChanged (const std::string&)));
}
void CSVWorld::PreviewSubView::setEditLock (bool locked) {}
void CSVWorld::PreviewSubView::closeRequest()
{
deleteLater();
}
void CSVWorld::PreviewSubView::referenceableIdChanged (const std::string& id)
{
if (id.empty())
setWindowTitle ("Preview: Reference to <nothing>");
else
setWindowTitle (("Preview: Reference to " + id).c_str());
}

@ -0,0 +1,38 @@
#ifndef CSV_WORLD_PREVIEWSUBVIEW_H
#define CSV_WORLD_PREVIEWSUBVIEW_H
#include "../doc/subview.hpp"
namespace CSMDoc
{
class Document;
}
namespace CSVRender
{
class PreviewWidget;
}
namespace CSVWorld
{
class PreviewSubView : public CSVDoc::SubView
{
Q_OBJECT
CSVRender::PreviewWidget *mScene;
public:
PreviewSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
virtual void setEditLock (bool locked);
private slots:
void closeRequest();
void referenceableIdChanged (const std::string& id);
};
}
#endif

@ -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,23 @@ 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));
layout2->addWidget (toolbar, 0);
// temporarily disable OGRE-integration (need to fix path problem first)
#if 0
CSVRender::SceneWidget* sceneWidget = new CSVRender::SceneWidget(this);
if (id.getId()=="sys::default")
mScene = new CSVRender::PagedWorldspaceWidget (this);
else
mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this);
layout2->addWidget (sceneWidget, 1);
SceneToolMode *navigationTool = mScene->makeNavigationSelector (toolbar);
toolbar->addTool (navigationTool);
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);
SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar);
toolbar->addTool (lightingTool);
layout2->addWidget (placeholder, 1);
layout2->addWidget (toolbar, 0);
layout->insertLayout (0, layout2, 1);
layout2->addWidget (mScene, 1);
layout->insertLayout (0, layout2, 1);
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
@ -73,6 +60,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 +82,8 @@ void CSVWorld::SceneSubView::setStatusBar (bool show)
{
mBottom->setStatusBar (show);
}
void CSVWorld::SceneSubView::closeRequest()
{
deleteLater();
}

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

@ -71,9 +71,9 @@ void CSVWorld::ScriptEdit::dropEvent (QDropEvent* event)
{
if (stringNeedsQuote(it->getId()))
{
insertPlainText(QString::fromStdString ('"' + it->getId() + '"'));
insertPlainText(QString::fromUtf8 (('"' + it->getId() + '"').c_str()));
} else {
insertPlainText(QString::fromStdString (it->getId()));
insertPlainText(QString::fromUtf8 (it->getId().c_str()));
}
}
}
@ -82,7 +82,7 @@ void CSVWorld::ScriptEdit::dropEvent (QDropEvent* event)
bool CSVWorld::ScriptEdit::stringNeedsQuote (const std::string& id) const
{
const QString string(QString::fromStdString(id)); //<regex> is only for c++11, so let's use qregexp for now.
const QString string(QString::fromUtf8(id.c_str())); //<regex> is only for c++11, so let's use qregexp for now.
//I'm not quite sure when do we need to put quotes. To be safe we will use quotes for anything other than…
return !(string.contains(mWhiteListQoutes));
}

@ -16,6 +16,7 @@
#include "scenesubview.hpp"
#include "dialoguecreator.hpp"
#include "infocreator.hpp"
#include "previewsubview.hpp"
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
{
@ -78,4 +79,62 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CreatorFactory<CSVFilter::FilterCreator> >);
manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>);
//edit subviews
manager.add (CSMWorld::UniversalId::Type_Region,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Spell,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Referenceable,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceableCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Birthsign,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Global,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Gmst,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Race,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Class,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Reference,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Cell,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<CellCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Filter,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Sound,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Faction,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Skill,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_JournalInfo,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<InfoCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_TopicInfo,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<InfoCreator> >(false));
manager.add (CSMWorld::UniversalId::Type_Topic,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, TopicCreatorFactory> (false));
manager.add (CSMWorld::UniversalId::Type_Journal,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, JournalCreatorFactory> (false));
//preview
manager.add (CSMWorld::UniversalId::Type_Preview, new CSVDoc::SubViewFactory<PreviewSubView>);
}

@ -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,6 +36,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
if (selectedRows.size()==1)
{
menu.addAction (mEditAction);
if (mCreateAction)
menu.addAction(mCloneAction);
}
@ -81,6 +83,28 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
}
}
if (selectedRows.size()==1)
{
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;
int index = mDocument.getData().getCells().searchId (id.getId());
// index==-1: the ID references a worldspace instead of a cell (ignore for now and go
// ahead)
if (index==-1 || !mDocument.getData().getCells().getRecord (index).isDeleted())
menu.addAction (mViewAction);
}
if (mModel->hasPreview())
menu.addAction (mPreviewAction);
}
menu.exec (event->globalPos());
}
@ -162,11 +186,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 +215,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 +255,14 @@ 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);
mPreviewAction = new QAction (tr ("Preview"), this);
connect (mPreviewAction, SIGNAL (triggered()), this, SLOT (previewRecord()));
addAction (mPreviewAction);
connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (tableSizeUpdate()));
@ -256,7 +289,7 @@ CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
{
return CSMWorld::UniversalId (
static_cast<CSMWorld::UniversalId::Type> (mProxyModel->data (mProxyModel->index (row, 2)).toInt()),
mProxyModel->data (mProxyModel->index (row, 0)).toString().toStdString());
mProxyModel->data (mProxyModel->index (row, 0)).toString().toUtf8().constData());
}
void CSVWorld::Table::revertRecord()
@ -268,13 +301,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 +321,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 +339,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 +380,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 +409,40 @@ 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::previewRecord()
{
QModelIndexList selectedRows = selectionModel()->selectedRows();
if (selectedRows.size()==1)
{
std::string id = getUniversalId (selectedRows.begin()->row()).getId();
emit editRequest (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Preview, id) , "");
}
}
void CSVWorld::Table::updateEditorSetting (const QString &settingName, const QString &settingValue)
{
int columns = mModel->columnCount();
@ -471,28 +533,15 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event)
}
drag->setMimeData (mime);
drag->setPixmap (QString::fromStdString (mime->getIcon()));
Qt::DropActions action = Qt::IgnoreAction;
switch (QApplication::keyboardModifiers())
{
case Qt::ControlModifier:
action = Qt::CopyAction;
break;
case Qt::ShiftModifier:
action = Qt::MoveAction;
break;
}
drag->exec(action);
drag->setPixmap (QString::fromUtf8 (mime->getIcon().c_str()));
drag->exec(Qt::CopyAction);
}
}
void CSVWorld::Table::dragEnterEvent(QDragEnterEvent *event)
{
event->acceptProposedAction();
event->acceptProposedAction();
}
void CSVWorld::Table::dropEvent(QDropEvent *event)
@ -517,14 +566,14 @@ 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
}
void CSVWorld::Table::dragMoveEvent(QDragMoveEvent *event)
{
event->accept();
event->accept();
}
std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const
@ -539,7 +588,7 @@ std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column
if (display == columndisplay)
{
titles.push_back(mModel->headerData (i, Qt::Horizontal).toString().toStdString());
titles.push_back(mModel->headerData (i, Qt::Horizontal).toString().toUtf8().constData());
}
}
return titles;

@ -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,13 @@ namespace CSVWorld
QAction *mDeleteAction;
QAction *mMoveUpAction;
QAction *mMoveDownAction;
QAction *mViewAction;
QAction *mPreviewAction;
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 +69,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 +84,7 @@ namespace CSVWorld
signals:
void editRequest (int row);
void editRequest (const CSMWorld::UniversalId& id, const std::string& hint);
void selectionSizeChanged (int size);
@ -112,6 +110,10 @@ namespace CSVWorld
void moveDownRecord();
void viewRecord();
void previewRecord();
public slots:
void tableSizeUpdate();

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

@ -3,7 +3,7 @@
#include "../doc/subview.hpp"
#include <qt4/QtCore/qnamespace.h>
#include <QtCore/qnamespace.h>
class QModelIndex;
@ -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);

@ -4,8 +4,18 @@
#include <stdexcept>
#include <QUndoStack>
#include <QMetaProperty>
#include <QStyledItemDelegate>
#include <QLineEdit>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QComboBox>
#include <QCheckBox>
#include <QPlainTextEdit>
#include <QEvent>
#include "../../model/world/commands.hpp"
#include "../../model/world/tablemimedata.hpp"
CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model)
: mModel (model)
@ -117,10 +127,56 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode
}
QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const
const QModelIndex& index, CSMWorld::ColumnBase::Display display) const
{
if (!index.data().isValid())
return 0;
QVariant variant = index.data();
if (!variant.isValid())
{
variant = index.data(Qt::DisplayRole);
if (!variant.isValid())
{
return 0;
}
}
if (display != CSMWorld::ColumnBase::Display_None)
{
if (variant.type() == QVariant::Color)
{
return new QLineEdit(parent);
}
if (display == CSMWorld::ColumnBase::Display_Integer)
{
return new QSpinBox(parent);
}
if (display == CSMWorld::ColumnBase::Display_Var)
{
return new QLineEdit(parent);
}
if (display == CSMWorld::ColumnBase::Display_Float)
{
return new QDoubleSpinBox(parent);
}
if (display == CSMWorld::ColumnBase::Display_LongString)
{
return new QTextEdit(parent);
}
if (display == CSMWorld::ColumnBase::Display_String ||
display == CSMWorld::ColumnBase::Display_Skill ||
display == CSMWorld::ColumnBase::Display_Script ||
display == CSMWorld::ColumnBase::Display_Race ||
display == CSMWorld::ColumnBase::Display_Class ||
display == CSMWorld::ColumnBase::Display_Faction ||
display == CSMWorld::ColumnBase::Display_Miscellaneous ||
display == CSMWorld::ColumnBase::Display_Sound)
{
return new DropLineEdit(parent);
}
if (display == CSMWorld::ColumnBase::Display_Boolean)
{
return new QCheckBox(parent);
}
}
return QStyledItemDelegate::createEditor (parent, option, index);
}
@ -140,4 +196,67 @@ bool CSVWorld::CommandDelegate::updateEditorSetting (const QString &settingName,
const QString &settingValue)
{
return false;
}
void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const
{
QVariant v = index.data(Qt::EditRole);
if (tryDisplay)
{
if (!v.isValid())
{
v = index.data(Qt::DisplayRole);
if (!v.isValid())
{
return;
}
}
QPlainTextEdit* plainTextEdit = qobject_cast<QPlainTextEdit*>(editor);
if(plainTextEdit) //for some reason it is easier to brake the loop here
{
if(plainTextEdit->toPlainText() == v.toString())
{
return;
}
}
}
QByteArray n = editor->metaObject()->userProperty().name();
if (n == "dateTime") {
if (editor->inherits("QTimeEdit"))
n = "time";
else if (editor->inherits("QDateEdit"))
n = "date";
}
if (!n.isEmpty()) {
if (!v.isValid())
v = QVariant(editor->property(n).userType(), (const void *)0);
editor->setProperty(n, v);
}
}
CSVWorld::DropLineEdit::DropLineEdit(QWidget* parent) :
QLineEdit(parent)
{
setAcceptDrops(true);
}
void CSVWorld::DropLineEdit::dragEnterEvent(QDragEnterEvent *event)
{
event->acceptProposedAction();
}
void CSVWorld::DropLineEdit::dragMoveEvent(QDragMoveEvent *event)
{
event->accept();
}
void CSVWorld::DropLineEdit::dropEvent(QDropEvent *event)
{
const CSMWorld::TableMimeData* data(dynamic_cast<const CSMWorld::TableMimeData*>(event->mimeData()));
emit tableMimeDataDropped(data->getData(), data->getDocumentPtr());
//WIP
}

@ -5,11 +5,19 @@
#include <QAbstractTableModel>
#include <QStyledItemDelegate>
#include <QLineEdit>
#include "../../model/world/columnbase.hpp"
#include "../../model/doc/document.hpp"
class QUndoStack;
namespace CSMWorld
{
class TableMimeData;
class UniversalId;
}
namespace CSVWorld
{
///< \brief Getting the data out of an editor widget
@ -79,6 +87,24 @@ namespace CSVWorld
};
class DropLineEdit : public QLineEdit
{
Q_OBJECT
public:
DropLineEdit(QWidget *parent);
private:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
signals:
void tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>& data, const CSMDoc::Document* document);
};
///< \brief Use commands instead of manipulating the model directly
class CommandDelegate : public QStyledItemDelegate
{
@ -101,8 +127,10 @@ namespace CSVWorld
virtual void setModelData (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const;
virtual QWidget *createEditor (QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const;
virtual QWidget *createEditor (QWidget *parent,
const QStyleOptionViewItem& option,
const QModelIndex& index,
CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None) const;
void setEditLock (bool locked);
@ -111,6 +139,9 @@ namespace CSVWorld
virtual bool updateEditorSetting (const QString &settingName, const QString &settingValue);
///< \return Does column require update?
virtual void setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay = false) const;
private slots:
virtual void slotUpdateEditorSetting (const QString &settingName, const QString &settingValue) {}

@ -15,7 +15,7 @@ add_openmw_dir (mwrender
renderingmanager debugging sky camera animation npcanimation creatureanimation activatoranimation
actors objects renderinginterface localmap occlusionquery water shadows
characterpreview globalmap videoplayer ripplesimulation refraction
terrainstorage renderconst effectmanager
terrainstorage renderconst effectmanager weaponanimation
)
add_openmw_dir (mwinput
@ -33,7 +33,7 @@ add_openmw_dir (mwgui
merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks
keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog
recharge
recharge mode videowidget
)
add_openmw_dir (mwdialogue
@ -44,7 +44,7 @@ add_openmw_dir (mwscript
locals scriptmanagerimp compilercontext interpretercontext cellextensions miscextensions
guiextensions soundextensions skyextensions statsextensions containerextensions
aiextensions controlextensions extensions globalscripts ref dialogueextensions
animationextensions transformationextensions consoleextensions userextensions locals
animationextensions transformationextensions consoleextensions userextensions
)
add_openmw_dir (mwsound
@ -57,7 +57,7 @@ add_openmw_dir (mwworld
cells localscripts customdata weather inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
contentloader esmloader omwloader actiontrap
contentloader esmloader omwloader actiontrap cellreflist
)
add_openmw_dir (mwclass
@ -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)

@ -1,6 +1,7 @@
#include "engine.hpp"
#include <stdexcept>
#include <iomanip>
#include <OgreRoot.h>
#include <OgreRenderWindow.h>
@ -11,7 +12,7 @@
#include <components/compiler/extensions0.hpp>
#include <components/bsa/bsa_archive.hpp>
#include <components/bsa/resources.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/translation/translation.hpp>
#include <components/nif/niffile.hpp>
@ -191,50 +192,6 @@ OMW::Engine::~Engine()
SDL_Quit();
}
// Load BSA files
void OMW::Engine::loadBSA()
{
// We use separate resource groups to handle location priority.
const Files::PathContainer& dataDirs = mFileCollections.getPaths();
int i=0;
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
{
// Last data dir has the highest priority
std::string groupName = "Data" + Ogre::StringConverter::toString(dataDirs.size()-i, 8, '0');
Ogre::ResourceGroupManager::getSingleton ().createResourceGroup (groupName);
std::string dataDirectory = iter->string();
std::cout << "Data dir " << dataDirectory << std::endl;
Bsa::addDir(dataDirectory, mFSStrict, groupName);
++i;
}
i=0;
for (std::vector<std::string>::const_iterator archive = mArchives.begin(); archive != mArchives.end(); ++archive)
{
if (mFileCollections.doesExist(*archive))
{
// Last BSA has the highest priority
std::string groupName = "DataBSA" + Ogre::StringConverter::toString(mArchives.size()-i, 8, '0');
Ogre::ResourceGroupManager::getSingleton ().createResourceGroup (groupName);
const std::string archivePath = mFileCollections.getPath(*archive).string();
std::cout << "Adding BSA archive " << archivePath << std::endl;
Bsa::addBSA(archivePath, groupName);
++i;
}
else
{
std::stringstream message;
message << "Archive '" << *archive << "' not found";
throw std::runtime_error(message.str());
}
}
}
// add resources directory
// \note This function works recursively.
@ -382,10 +339,12 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
std::string aa = settings.getString("antialiasing", "Video");
windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
mOgre->createWindow("OpenMW", windowSettings);
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS,
settings.getBool("minimize on focus loss", "Video") ? "1" : "0");
loadBSA();
mOgre->createWindow("OpenMW", windowSettings);
Bsa::registerResources (mFileCollections, mArchives, true, mFSStrict);
// Create input and UI first to set up a bootstrapping environment for
// showing a loading screen and keeping the window responsive while doing so
@ -400,10 +359,20 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding);
mEnvironment.setWindowManager (window);
// Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound));
if (!mSkipMenu)
{
std::string logo = mFallbackMap["Movies_Company_Logo"];
if (!logo.empty())
window->playVideo(logo, 1);
}
// Create the world
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles,
mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap,
mActivationDistanceOverride));
mActivationDistanceOverride, mCellName));
MWBase::Environment::get().getWorld()->setupPlayer();
input->setPlayer(&mEnvironment.getWorld()->getPlayer());
@ -417,9 +386,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
Compiler::registerExtensions (mExtensions);
// Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound));
// Create script system
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full);
mScriptContext->setExtensions (&mExtensions);
@ -439,31 +405,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mechanics->buildPlayer();
window->updatePlayer();
// load cell
ESM::Position pos;
MWBase::World *world = MWBase::Environment::get().getWorld();
if (!mCellName.empty())
{
if (world->findExteriorPosition(mCellName, pos)) {
world->changeToExteriorCell (pos);
}
else {
world->findInteriorPosition(mCellName, pos);
world->changeToInteriorCell (mCellName, pos);
}
}
else
{
pos.pos[0] = pos.pos[1] = pos.pos[2] = 0;
pos.rot[0] = pos.rot[1] = pos.pos[2] = 0;
world->changeToExteriorCell (pos);
}
Ogre::FrameEvent event;
event.timeSinceLastEvent = 0;
event.timeSinceLastFrame = 0;
frameRenderingQueued(event);
mOgre->getRoot()->addFrameListener (this);
// scripts
@ -501,15 +442,27 @@ void OMW::Engine::go()
// Play some good 'ol tunes
MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore"));
if (!mStartupScript.empty())
MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript);
// start in main menu
if (!mSkipMenu)
{
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
try
{
// Is there an ini setting for this filename or something?
MWBase::Environment::get().getSoundManager()->streamMusic("Special/morrowind title.mp3");
std::string logo = mFallbackMap["Movies_Morrowind_Logo"];
if (!logo.empty())
MWBase::Environment::get().getWindowManager()->playVideo(logo, true);
}
catch (...) {}
}
else
MWBase::Environment::get().getStateManager()->newGame (true);
if (!mStartupScript.empty())
MWBase::Environment::get().getWindowManager()->executeInConsole (mStartupScript);
// Start the main rendering loop
while (!mEnvironment.get().getStateManager()->hasQuitRequest())
Ogre::Root::getSingleton().renderOneFrame();
@ -621,4 +574,4 @@ void OMW::Engine::setActivationDistanceOverride (int distance)
void OMW::Engine::setWarningsMode (int mode)
{
mWarningsMode = mode;
}
}

@ -101,9 +101,6 @@ namespace OMW
/// add a .zip resource
void addZipResource (const boost::filesystem::path& path);
/// Load BSA files
void loadBSA();
void executeLocalScripts();
virtual bool frameRenderingQueued (const Ogre::FrameEvent& evt);

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

@ -20,9 +20,12 @@ namespace MWBase
InputManager() {}
/// Clear all savegame-specific data
virtual void clear() = 0;
virtual ~InputManager() {}
virtual void update(float dt, bool loading) = 0;
virtual void update(float dt, bool disableControls, bool disableEvents=false) = 0;
virtual void changeInputMode(bool guiMode) = 0;

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

@ -156,7 +156,7 @@ namespace MWBase
/// paused we may want to do it manually (after equipping permanent enchantment)
virtual void updateMagicEffects (const MWWorld::Ptr& ptr) = 0;
virtual void toggleAI() = 0;
virtual bool toggleAI() = 0;
virtual bool isAIActive() = 0;
virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector<MWWorld::Ptr>& objects) = 0;

@ -96,6 +96,10 @@ namespace MWBase
*/
virtual void update() = 0;
/// @note This method will block until the video finishes playing
/// (and will continually update the window while doing so)
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
virtual void setNewGame(bool newgame) = 0;
virtual void pushGuiMode (MWGui::GuiMode mode) = 0;

@ -39,6 +39,12 @@ namespace ESM
struct Spell;
struct NPC;
struct CellId;
struct Armor;
struct Weapon;
struct Clothing;
struct Enchantment;
struct Book;
struct EffectList;
}
namespace MWRender
@ -95,7 +101,8 @@ namespace MWBase
virtual ~World() {}
virtual void startNewGame() = 0;
virtual void startNewGame (bool bypass) = 0;
///< \param bypass Bypass regular game start.
virtual void clear() = 0;
@ -268,7 +275,7 @@ namespace MWBase
virtual void moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;
virtual void
moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore &newCell, float x, float y, float z) = 0;
moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore* newCell, float x, float y, float z) = 0;
virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0;
@ -276,7 +283,7 @@ namespace MWBase
virtual void localRotateObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0;
virtual MWWorld::Ptr safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos) = 0;
virtual MWWorld::Ptr safePlaceObject(const MWWorld::Ptr& ptr, MWWorld::CellStore* cell, ESM::Position pos) = 0;
///< place an object in a "safe" location (ie not in the void, etc).
virtual void indexToPosition (int cellX, int cellY, float &x, float &y, bool centre = false)
@ -413,8 +420,6 @@ namespace MWBase
virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) = 0;
/// \todo this does not belong here
virtual void playVideo(const std::string& name, bool allowSkipping) = 0;
virtual void stopVideo() = 0;
virtual void frameStarted (float dt, bool paused) = 0;
virtual void screenshot (Ogre::Image& image, int w, int h) = 0;
@ -458,8 +463,10 @@ namespace MWBase
virtual void castSpell (const MWWorld::Ptr& actor) = 0;
virtual void launchProjectile (const std::string& id, bool stack, const ESM::EffectList& effects,
virtual void launchMagicBolt (const std::string& id, bool stack, const ESM::EffectList& effects,
const MWWorld::Ptr& actor, const std::string& sourceName) = 0;
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::Ptr projectile,
const Ogre::Vector3& worldPos, const Ogre::Quaternion& orient, MWWorld::Ptr bow, float speed) = 0;
virtual const std::vector<std::string>& getContentFiles() const = 0;

@ -128,6 +128,6 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Activator> *ref =
ptr.get<ESM::Activator>();
return MWWorld::Ptr(&cell.mActivators.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Activator>().insert(*ref), &cell);
}
}

@ -148,7 +148,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Apparatus> *ref =
ptr.get<ESM::Apparatus>();
return MWWorld::Ptr(&cell.mAppas.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Apparatus>().insert(*ref), &cell);
}
bool Apparatus::canSell (const MWWorld::Ptr& item, int npcServices) const

@ -333,11 +333,11 @@ namespace MWClass
if(weapon->getTypeName() == typeid(ESM::Weapon).name() &&
(weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::SpearTwoWide ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::AxeTwoHand ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::AxeTwoHand ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow ||
weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow))
{
return std::make_pair(3,"");
@ -363,7 +363,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Armor> *ref =
ptr.get<ESM::Armor>();
return MWWorld::Ptr(&cell.mArmors.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Armor>().insert(*ref), &cell);
}
int Armor::getEnchantmentPoints (const MWWorld::Ptr& ptr) const

@ -186,7 +186,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Book> *ref =
ptr.get<ESM::Book>();
return MWWorld::Ptr(&cell.mBooks.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Book>().insert(*ref), &cell);
}
int Book::getEnchantmentPoints (const MWWorld::Ptr& ptr) const

@ -276,7 +276,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Clothing> *ref =
ptr.get<ESM::Clothing>();
return MWWorld::Ptr(&cell.mClothes.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Clothing>().insert(*ref), &cell);
}
int Clothing::getEnchantmentPoints (const MWWorld::Ptr& ptr) const

@ -28,16 +28,16 @@
namespace
{
struct CustomData : public MWWorld::CustomData
struct ContainerCustomData : public MWWorld::CustomData
{
MWWorld::ContainerStore mContainerStore;
virtual MWWorld::CustomData *clone() const;
};
MWWorld::CustomData *CustomData::clone() const
MWWorld::CustomData *ContainerCustomData::clone() const
{
return new CustomData (*this);
return new ContainerCustomData (*this);
}
}
@ -47,7 +47,7 @@ namespace MWClass
{
if (!ptr.getRefData().getCustomData())
{
std::auto_ptr<CustomData> data (new CustomData);
std::auto_ptr<ContainerCustomData> data (new ContainerCustomData);
MWWorld::LiveCellRef<ESM::Container> *ref =
ptr.get<ESM::Container>();
@ -174,7 +174,7 @@ namespace MWClass
{
ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
return dynamic_cast<ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
}
std::string Container::getScript (const MWWorld::Ptr& ptr) const
@ -257,7 +257,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Container> *ref =
ptr.get<ESM::Container>();
return MWWorld::Ptr(&cell.mContainers.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Container>().insert(*ref), &cell);
}
void Container::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
@ -267,7 +267,7 @@ namespace MWClass
ensureCustomData (ptr);
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
dynamic_cast<ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
readState (state2.mInventory);
}
@ -278,7 +278,7 @@ namespace MWClass
ensureCustomData (ptr);
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
dynamic_cast<ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
writeState (state2.mInventory);
}
}

@ -7,6 +7,7 @@
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/magiceffects.hpp"
#include "../mwmechanics/movement.hpp"
#include "../mwmechanics/disease.hpp"
#include "../mwmechanics/spellcasting.hpp"
#include "../mwbase/environment.hpp"
@ -22,6 +23,7 @@
#include "../mwworld/customdata.hpp"
#include "../mwworld/containerstore.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwrender/renderinginterface.hpp"
#include "../mwrender/actors.hpp"
@ -35,7 +37,7 @@
namespace
{
struct CustomData : public MWWorld::CustomData
struct CreatureCustomData : public MWWorld::CustomData
{
MWMechanics::CreatureStats mCreatureStats;
MWWorld::ContainerStore* mContainerStore; // may be InventoryStore for some creatures
@ -43,13 +45,13 @@ namespace
virtual MWWorld::CustomData *clone() const;
CustomData() : mContainerStore(0) {}
virtual ~CustomData() { delete mContainerStore; }
CreatureCustomData() : mContainerStore(0) {}
virtual ~CreatureCustomData() { delete mContainerStore; }
};
MWWorld::CustomData *CustomData::clone() const
MWWorld::CustomData *CreatureCustomData::clone() const
{
CustomData* cloned = new CustomData (*this);
CreatureCustomData* cloned = new CreatureCustomData (*this);
cloned->mContainerStore = mContainerStore->clone();
return cloned;
}
@ -61,7 +63,7 @@ namespace MWClass
{
if (!ptr.getRefData().getCustomData())
{
std::auto_ptr<CustomData> data (new CustomData);
std::auto_ptr<CreatureCustomData> data (new CreatureCustomData);
static bool inited = false;
if(!inited)
@ -121,18 +123,19 @@ namespace MWClass
else
data->mContainerStore = new MWWorld::ContainerStore();
// Relates to NPC gold reset delay
data->mCreatureStats.setTradeTime(MWWorld::TimeStamp(0.0, 0));
data->mCreatureStats.setGoldPool(ref->mBase->mData.mGold);
// store
ptr.getRefData().setCustomData (data.release());
ptr.getRefData().setCustomData(data.release());
getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr), "",
MWBase::Environment::get().getWorld()->getStore());
// TODO: this is not quite correct, in vanilla the merchant's gold pool is not available in his inventory.
// (except for gold you gave him)
getContainerStore(ptr).add(MWWorld::ContainerStore::sGoldId, ref->mBase->mData.mGold, ptr);
if (ref->mBase->mFlags & ESM::Creature::Weapon)
getInventoryStore(ptr).autoEquip(ptr);
getInventoryStore(ptr).autoEquip(ptr);
}
}
@ -190,7 +193,7 @@ namespace MWClass
{
ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mCreatureStats;
return dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mCreatureStats;
}
@ -242,15 +245,7 @@ namespace MWClass
Ogre::Vector3 hitPosition = result.second;
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
float hitchance = ref->mBase->mData.mCombat +
(stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
(stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
hitchance *= stats.getFatigueTerm();
hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).mMagnitude -
mageffects.get(ESM::MagicEffect::Blind).mMagnitude;
hitchance -= otherstats.getEvasion();
float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat);
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
{
@ -333,6 +328,8 @@ namespace MWClass
if (damage > 0)
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
MWMechanics::diseaseContact(victim, ptr);
victim.getClass().onHit(victim, damage, true, weapon, ptr, true);
}
@ -460,7 +457,7 @@ namespace MWClass
{
ensureCustomData (ptr);
return *dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
return *dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore;
}
MWWorld::InventoryStore& Creature::getInventoryStore(const MWWorld::Ptr &ptr) const
@ -529,7 +526,7 @@ namespace MWClass
float moveSpeed;
if(normalizedEncumbrance >= 1.0f)
moveSpeed = 0.0f;
else if(isFlying(ptr) || (mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 &&
else if(canFly(ptr) || (mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 &&
world->isLevitationEnabled()))
{
float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() +
@ -563,7 +560,7 @@ namespace MWClass
{
ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mMovement;
return dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mMovement;
}
Ogre::Vector3 Creature::getMovementVector (const MWWorld::Ptr& ptr) const
@ -679,10 +676,18 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Creature> *ref =
ptr.get<ESM::Creature>();
return MWWorld::Ptr(&cell.mCreatures.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Creature>().insert(*ref), &cell);
}
bool Creature::isFlying(const MWWorld::Ptr &ptr) const
bool Creature::isBipedal(const MWWorld::Ptr &ptr) const
{
MWWorld::LiveCellRef<ESM::Creature> *ref =
ptr.get<ESM::Creature>();
return ref->mBase->mFlags & ESM::Creature::Bipedal;
}
bool Creature::canFly(const MWWorld::Ptr &ptr) const
{
MWWorld::LiveCellRef<ESM::Creature> *ref =
ptr.get<ESM::Creature>();
@ -690,6 +695,22 @@ namespace MWClass
return ref->mBase->mFlags & ESM::Creature::Flies;
}
bool Creature::canSwim(const MWWorld::Ptr &ptr) const
{
MWWorld::LiveCellRef<ESM::Creature> *ref =
ptr.get<ESM::Creature>();
return ref->mBase->mFlags & ESM::Creature::Swims;
}
bool Creature::canWalk(const MWWorld::Ptr &ptr) const
{
MWWorld::LiveCellRef<ESM::Creature> *ref =
ptr.get<ESM::Creature>();
return ref->mBase->mFlags & ESM::Creature::Walks;
}
int Creature::getSndGenTypeFromName(const MWWorld::Ptr &ptr, const std::string &name)
{
if(name == "left")
@ -766,7 +787,7 @@ namespace MWClass
ensureCustomData (ptr);
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData());
CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData());
customData.mContainerStore->readState (state2.mInventory);
customData.mCreatureStats.readState (state2.mCreatureStats);
@ -780,12 +801,17 @@ namespace MWClass
ensureCustomData (ptr);
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData());
CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData());
customData.mContainerStore->writeState (state2.mInventory);
customData.mCreatureStats.writeState (state2.mCreatureStats);
}
int Creature::getBaseGold(const MWWorld::Ptr& ptr) const
{
return ptr.get<ESM::Creature>()->mBase->mData.mGold;
}
const ESM::GameSetting* Creature::fMinWalkSpeedCreature;
const ESM::GameSetting* Creature::fMaxWalkSpeedCreature;
const ESM::GameSetting *Creature::fEncumberedMoveEffect;

@ -3,6 +3,11 @@
#include "../mwworld/class.hpp"
namespace ESM
{
struct GameSetting;
}
namespace MWClass
{
class Creature : public MWWorld::Class
@ -119,7 +124,10 @@ namespace MWClass
return true;
}
virtual bool isFlying (const MWWorld::Ptr &ptr) const;
virtual bool isBipedal (const MWWorld::Ptr &ptr) const;
virtual bool canFly (const MWWorld::Ptr &ptr) const;
virtual bool canSwim (const MWWorld::Ptr &ptr) const;
virtual bool canWalk (const MWWorld::Ptr &ptr) const;
virtual int getSkill(const MWWorld::Ptr &ptr, int skill) const;
@ -133,6 +141,8 @@ namespace MWClass
virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
const;
///< Write additional state from \a ptr into \a state.
virtual int getBaseGold(const MWWorld::Ptr& ptr) const;
};
}

@ -9,15 +9,15 @@
namespace
{
struct CustomData : public MWWorld::CustomData
struct CreatureLevListCustomData : public MWWorld::CustomData
{
// TODO: save the creature we spawned here
virtual MWWorld::CustomData *clone() const;
};
MWWorld::CustomData *CustomData::clone() const
MWWorld::CustomData *CreatureLevListCustomData::clone() const
{
return new CustomData (*this);
return new CreatureLevListCustomData (*this);
}
}
@ -44,7 +44,7 @@ namespace MWClass
{
if (!ptr.getRefData().getCustomData())
{
std::auto_ptr<CustomData> data (new CustomData);
std::auto_ptr<CreatureLevListCustomData> data (new CreatureLevListCustomData);
MWWorld::LiveCellRef<ESM::CreatureLevList> *ref =
ptr.get<ESM::CreatureLevList>();
@ -57,7 +57,7 @@ namespace MWClass
MWWorld::ManualRef ref(store, id);
ref.getPtr().getCellRef().mPos = ptr.getCellRef().mPos;
// TODO: hold on to this for respawn purposes later
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), *ptr.getCell() , ptr.getCellRef().mPos);
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), ptr.getCell() , ptr.getCellRef().mPos);
}
ptr.getRefData().setCustomData(data.release());

@ -258,6 +258,6 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Door> *ref =
ptr.get<ESM::Door>();
return MWWorld::Ptr(&cell.mDoors.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Door>().insert(*ref), &cell);
}
}

@ -1,6 +1,8 @@
#ifndef GAME_MWCLASS_DOOR_H
#define GAME_MWCLASS_DOOR_H
#include <components/esm/loaddoor.hpp>
#include "../mwworld/class.hpp"
namespace MWClass

@ -30,7 +30,7 @@ namespace MWClass
return ref->mBase->mId;
}
void Ingredient::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{
const std::string model = getModel(ptr);
@ -89,16 +89,16 @@ namespace MWClass
return ref->mBase->mData.mValue;
}
boost::shared_ptr<MWWorld::Action> Ingredient::use (const MWWorld::Ptr& ptr) const
{
boost::shared_ptr<MWWorld::Action> action (new MWWorld::ActionEat (ptr));
action->setSound ("Swallow");
return action;
return action;
}
void Ingredient::registerSelf()
{
boost::shared_ptr<Class> instance (new Ingredient);
@ -189,7 +189,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Ingredient> *ref =
ptr.get<ESM::Ingredient>();
return MWWorld::Ptr(&cell.mIngreds.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Ingredient>().insert(*ref), &cell);
}
bool Ingredient::canSell (const MWWorld::Ptr& item, int npcServices) const

@ -26,12 +26,12 @@
namespace
{
struct CustomData : public MWWorld::CustomData
struct LightCustomData : public MWWorld::CustomData
{
float mTime;
///< Time remaining
CustomData(MWWorld::Ptr ptr)
LightCustomData(MWWorld::Ptr ptr)
{
MWWorld::LiveCellRef<ESM::Light> *ref = ptr.get<ESM::Light>();
mTime = ref->mBase->mData.mTime;
@ -40,7 +40,7 @@ namespace
virtual MWWorld::CustomData *clone() const
{
return new CustomData (*this);
return new LightCustomData (*this);
}
};
}
@ -210,7 +210,7 @@ namespace MWClass
{
ensureCustomData(ptr);
float &timeRemaining = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mTime;
float &timeRemaining = dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime;
timeRemaining = duration;
}
@ -218,7 +218,7 @@ namespace MWClass
{
ensureCustomData(ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mTime;
return dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime;
}
MWWorld::Ptr
@ -227,13 +227,13 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Light> *ref =
ptr.get<ESM::Light>();
return MWWorld::Ptr(&cell.mLights.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Light>().insert(*ref), &cell);
}
void Light::ensureCustomData (const MWWorld::Ptr& ptr) const
{
if (!ptr.getRefData().getCustomData())
ptr.getRefData().setCustomData(new CustomData(ptr));
ptr.getRefData().setCustomData(new LightCustomData(ptr));
}
bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const
@ -278,7 +278,7 @@ namespace MWClass
ensureCustomData (ptr);
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mTime = state2.mTime;
dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime = state2.mTime;
}
void Light::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
@ -288,6 +288,6 @@ namespace MWClass
ensureCustomData (ptr);
state2.mTime = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mTime;
state2.mTime = dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime;
}
}

@ -169,7 +169,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Lockpick> *ref =
ptr.get<ESM::Lockpick>();
return MWWorld::Ptr(&cell.mLockpicks.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Lockpick>().insert(*ref), &cell);
}
bool Lockpick::canSell (const MWWorld::Ptr& item, int npcServices) const

@ -218,13 +218,13 @@ namespace MWClass
MWWorld::ManualRef newRef(store, base);
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
newRef.getPtr().get<ESM::Miscellaneous>();
newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell);
newPtr = MWWorld::Ptr(&cell.get<ESM::Miscellaneous>().insert(*ref), &cell);
newPtr.getCellRef().mGoldValue = goldAmount;
newPtr.getRefData().setCount(1);
} else {
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
ptr.get<ESM::Miscellaneous>();
newPtr = MWWorld::Ptr(&cell.mMiscItems.insert(*ref), &cell);
newPtr = MWWorld::Ptr(&cell.get<ESM::Miscellaneous>().insert(*ref), &cell);
}
return newPtr;
}

@ -30,6 +30,7 @@
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/customdata.hpp"
#include "../mwworld/physicssystem.hpp"
#include "../mwworld/cellstore.hpp"
#include "../mwrender/actors.hpp"
#include "../mwrender/renderinginterface.hpp"
@ -38,7 +39,7 @@
namespace
{
struct CustomData : public MWWorld::CustomData
struct NpcCustomData : public MWWorld::CustomData
{
MWMechanics::NpcStats mNpcStats;
MWMechanics::Movement mMovement;
@ -47,9 +48,9 @@ namespace
virtual MWWorld::CustomData *clone() const;
};
MWWorld::CustomData *CustomData::clone() const
MWWorld::CustomData *NpcCustomData::clone() const
{
return new CustomData (*this);
return new NpcCustomData (*this);
}
void autoCalculateAttributes (const ESM::NPC* npc, MWMechanics::CreatureStats& creatureStats)
@ -261,7 +262,7 @@ namespace MWClass
}
if (!ptr.getRefData().getCustomData())
{
std::auto_ptr<CustomData> data(new CustomData);
std::auto_ptr<NpcCustomData> data(new NpcCustomData);
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
@ -356,14 +357,15 @@ namespace MWClass
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "",
MWBase::Environment::get().getWorld()->getStore());
// Relates to NPC gold reset delay
data->mNpcStats.setTradeTime(MWWorld::TimeStamp(0.0, 0));
data->mNpcStats.setGoldPool(gold);
// store
ptr.getRefData().setCustomData (data.release());
// TODO: this is not quite correct, in vanilla the merchant's gold pool is not available in his inventory.
// (except for gold you gave him)
getContainerStore(ptr).add(MWWorld::ContainerStore::sGoldId, gold, ptr);
getInventoryStore(ptr).autoEquip(ptr);
getInventoryStore(ptr).autoEquip(ptr);
}
}
@ -435,14 +437,14 @@ namespace MWClass
{
ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mNpcStats;
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mNpcStats;
}
MWMechanics::NpcStats& Npc::getNpcStats (const MWWorld::Ptr& ptr) const
{
ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mNpcStats;
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mNpcStats;
}
@ -497,15 +499,7 @@ namespace MWClass
if(!weapon.isEmpty())
weapskill = get(weapon).getEquipmentSkill(weapon);
MWMechanics::NpcStats &stats = getNpcStats(ptr);
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
float hitchance = stats.getSkill(weapskill).getModified() +
(stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
(stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
hitchance *= stats.getFatigueTerm();
hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).mMagnitude -
mageffects.get(ESM::MagicEffect::Blind).mMagnitude;
hitchance -= otherstats.getEvasion();
float hitchance = MWMechanics::getHitChance(ptr, victim, ptr.getClass().getSkill(ptr, weapskill));
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
{
@ -515,6 +509,7 @@ namespace MWClass
bool healthdmg;
float damage = 0.0f;
MWMechanics::NpcStats &stats = getNpcStats(ptr);
if(!weapon.isEmpty())
{
const bool weaphashealth = get(weapon).hasItemHealth(weapon);
@ -614,6 +609,8 @@ namespace MWClass
if (healthdmg && damage > 0)
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
MWMechanics::diseaseContact(victim, ptr);
othercls.onHit(victim, damage, healthdmg, weapon, ptr, true);
}
@ -647,9 +644,6 @@ namespace MWClass
ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1);
}
if (!attacker.isEmpty())
MWMechanics::diseaseContact(ptr, attacker);
if (damage > 0.0f && !object.isEmpty())
MWMechanics::resistNormalWeapon(ptr, attacker, object, damage);
@ -680,12 +674,7 @@ namespace MWClass
else
getCreatureStats(ptr).setHitRecovery(true); // Is this supposed to always occur?
if(object.isEmpty())
{
if(ishealth)
damage /= std::min(1.0f + getArmorRating(ptr)/std::max(1.0f, damage), 4.0f);
}
else if(ishealth)
if(ishealth)
{
// Hit percentages:
// cuirass = 30%
@ -831,7 +820,7 @@ namespace MWClass
{
ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore;
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore;
}
MWWorld::InventoryStore& Npc::getInventoryStore (const MWWorld::Ptr& ptr)
@ -839,7 +828,7 @@ namespace MWClass
{
ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore;
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mInventoryStore;
}
std::string Npc::getScript (const MWWorld::Ptr& ptr) const
@ -853,7 +842,7 @@ namespace MWClass
float Npc::getSpeed(const MWWorld::Ptr& ptr) const
{
const MWBase::World *world = MWBase::Environment::get().getWorld();
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
const MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects();
const float normalizedEncumbrance = Npc::getEncumbrance(ptr) / Npc::getCapacity(ptr);
@ -908,7 +897,7 @@ namespace MWClass
float Npc::getJump(const MWWorld::Ptr &ptr) const
{
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
const MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects();
const float encumbranceTerm = fJumpEncumbranceBase->getFloat() +
fJumpEncumbranceMultiplier->getFloat() *
@ -947,7 +936,7 @@ namespace MWClass
if (fallHeight >= fallDistanceMin)
{
const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude;
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
@ -972,7 +961,7 @@ namespace MWClass
{
ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mMovement;
return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mMovement;
}
Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const
@ -1252,7 +1241,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::NPC> *ref =
ptr.get<ESM::NPC>();
return MWWorld::Ptr(&cell.mNpcs.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::NPC>().insert(*ref), &cell);
}
int Npc::getSkill(const MWWorld::Ptr& ptr, int skill) const
@ -1278,7 +1267,7 @@ namespace MWClass
ensureCustomData (ptr);
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData());
NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData());
customData.mInventoryStore.readState (state2.mInventory);
customData.mNpcStats.readState (state2.mNpcStats);
@ -1292,13 +1281,22 @@ namespace MWClass
ensureCustomData (ptr);
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData());
NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData());
customData.mInventoryStore.writeState (state2.mInventory);
customData.mNpcStats.writeState (state2.mNpcStats);
static_cast<const MWMechanics::CreatureStats&> (customData.mNpcStats).writeState (state2.mCreatureStats);
}
int Npc::getBaseGold(const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
return ref->mBase->mNpdt52.mGold;
else
return ref->mBase->mNpdt12.mGold;
}
const ESM::GameSetting *Npc::fMinWalkSpeed;
const ESM::GameSetting *Npc::fMaxWalkSpeed;
const ESM::GameSetting *Npc::fEncumberedMoveEffect;

@ -166,6 +166,8 @@ namespace MWClass
virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
const;
///< Write additional state from \a ptr into \a state.
virtual int getBaseGold(const MWWorld::Ptr& ptr) const;
};
}

@ -185,7 +185,7 @@ namespace MWClass
MWWorld::LiveCellRef<ESM::Potion> *ref =
ptr.get<ESM::Potion>();
return MWWorld::Ptr(&cell.mPotions.insert(*ref), &cell);
return MWWorld::Ptr(&cell.get<ESM::Potion>().insert(*ref), &cell);
}
bool Potion::canSell (const MWWorld::Ptr& item, int npcServices) const

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

Loading…
Cancel
Save