1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-07-10 07:11:35 +00:00

Merge remote-tracking branch 'upstream/master' into wizard

This commit is contained in:
pvdk 2014-03-29 11:56:35 +01:00
commit ef38fae09d
157 changed files with 3571 additions and 1193 deletions

View file

@ -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(BOOST_STATIC "Link static build of Boost into the binaries" FALSE)
option(SDL2_STATIC "Link static build of SDL 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 # Apps and tools
option(BUILD_BSATOOL "build BSA extractor" OFF) option(BUILD_BSATOOL "build BSA extractor" OFF)
option(BUILD_ESMTOOL "build ESM inspector" ON) option(BUILD_ESMTOOL "build ESM inspector" ON)
@ -131,6 +133,7 @@ set(OENGINE_OGRE
set(OENGINE_GUI set(OENGINE_GUI
${LIBDIR}/openengine/gui/manager.cpp ${LIBDIR}/openengine/gui/manager.cpp
${LIBDIR}/openengine/gui/layout.hpp
) )
set(OENGINE_BULLET set(OENGINE_BULLET
@ -468,7 +471,6 @@ if(WIN32)
INSTALL(FILES INSTALL(FILES
"${OpenMW_SOURCE_DIR}/readme.txt" "${OpenMW_SOURCE_DIR}/readme.txt"
"${OpenMW_SOURCE_DIR}/GPL3.txt" "${OpenMW_SOURCE_DIR}/GPL3.txt"
"${OpenMW_SOURCE_DIR}/OFL.txt"
"${OpenMW_SOURCE_DIR}/DejaVu Font License.txt" "${OpenMW_SOURCE_DIR}/DejaVu Font License.txt"
"${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/settings-default.cfg"
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg" "${OpenMW_BINARY_DIR}/transparency-overrides.cfg"

93
OFL.txt
View file

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

View file

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

View file

@ -9,8 +9,13 @@
#include <OgreRoot.h> #include <OgreRoot.h>
#include <OgreRenderWindow.h> #include <OgreRenderWindow.h>
#include <extern/shiny/Main/Factory.hpp>
#include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp>
#include <components/ogreinit/ogreinit.hpp> #include <components/ogreinit/ogreinit.hpp>
#include <components/bsa/resources.hpp>
#include "model/doc/document.hpp" #include "model/doc/document.hpp"
#include "model/world/data.hpp" #include "model/world/data.hpp"
@ -18,14 +23,17 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
: mDocumentManager (mCfgMgr), mViewManager (mDocumentManager), : mDocumentManager (mCfgMgr), mViewManager (mDocumentManager),
mIpcServerName ("org.openmw.OpenCS") mIpcServerName ("org.openmw.OpenCS")
{ {
Files::PathContainer dataDirs = readConfig(); std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
setupDataFiles (dataDirs); setupDataFiles (config.first);
CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg"); CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg");
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string()); ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true,
mFsStrict);
mNewGame.setLocalData (mLocal); mNewGame.setLocalData (mLocal);
mFileDialog.setLocalData (mLocal); mFileDialog.setLocalData (mLocal);
@ -53,12 +61,12 @@ void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs)
{ {
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter) for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
{ {
QString path = QString::fromStdString(iter->string()); QString path = QString::fromUtf8 (iter->string().c_str());
mFileDialog.addFiles(path); mFileDialog.addFiles(path);
} }
} }
Files::PathContainer CS::Editor::readConfig() std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfig()
{ {
boost::program_options::variables_map variables; boost::program_options::variables_map variables;
boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options"); boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options");
@ -68,13 +76,17 @@ Files::PathContainer CS::Editor::readConfig()
("data-local", boost::program_options::value<std::string>()->default_value("")) ("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false)) ("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252")) ("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); boost::program_options::notify(variables);
mCfgMgr.readConfiguration(variables, desc); mCfgMgr.readConfiguration(variables, desc);
mDocumentManager.setResourceDir (variables["resources"].as<std::string>()); mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
mFsStrict = variables["fs-strict"].as<bool>();
Files::PathContainer dataDirs, dataLocal; Files::PathContainer dataDirs, dataLocal;
if (!variables["data"].empty()) { if (!variables["data"].empty()) {
@ -105,7 +117,7 @@ Files::PathContainer CS::Editor::readConfig()
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end()); dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
return dataDirs; return std::make_pair (dataDirs, variables["fallback-archive"].as<std::vector<std::string> >());
} }
void CS::Editor::createGame() void CS::Editor::createGame()
@ -136,7 +148,7 @@ void CS::Editor::openFiles (const boost::filesystem::path &savePath)
std::vector<boost::filesystem::path> files; std::vector<boost::filesystem::path> files;
foreach (const QString &path, mFileDialog.selectedFilePaths()) 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); CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, false);
@ -149,10 +161,10 @@ void CS::Editor::createNewFile (const boost::filesystem::path &savePath)
std::vector<boost::filesystem::path> files; std::vector<boost::filesystem::path> files;
foreach (const QString &path, mFileDialog.selectedFilePaths()) { 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); CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, true);
@ -216,6 +228,15 @@ int CS::Editor::run()
if (mLocal.empty()) if (mLocal.empty())
return 1; return 1;
mStartup.show();
QApplication::setQuitOnLastWindowClosed (true);
return QApplication::exec();
}
std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
{
// TODO: setting // TODO: setting
Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem")); Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem"));
@ -233,9 +254,36 @@ int CS::Editor::run()
Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, &params); Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, &params);
hiddenWindow->setActive(false); hiddenWindow->setActive(false);
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;
} }

View file

@ -1,11 +1,15 @@
#ifndef CS_EDITOR_H #ifndef CS_EDITOR_H
#define CS_EDITOR_H #define CS_EDITOR_H
#include <memory>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QLocalServer> #include <QLocalServer>
#include <QLocalSocket> #include <QLocalSocket>
#include <extern/shiny/Main/Factory.hpp>
#ifndef Q_MOC_RUN #ifndef Q_MOC_RUN
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#endif #endif
@ -41,12 +45,13 @@ namespace CS
CSVDoc::NewGameDialogue mNewGame; CSVDoc::NewGameDialogue mNewGame;
CSVSettings::UserSettingsDialog mSettings; CSVSettings::UserSettingsDialog mSettings;
CSVDoc::FileDialog mFileDialog; CSVDoc::FileDialog mFileDialog;
boost::filesystem::path mLocal; boost::filesystem::path mLocal;
boost::filesystem::path mResources;
bool mFsStrict;
void setupDataFiles (const Files::PathContainer& dataDirs); void setupDataFiles (const Files::PathContainer& dataDirs);
Files::PathContainer readConfig(); std::pair<Files::PathContainer, std::vector<std::string> > readConfig();
///< \return data paths ///< \return data paths
// not implemented // not implemented
@ -63,6 +68,9 @@ namespace CS
int run(); int run();
///< \return error status ///< \return error status
std::auto_ptr<sh::Factory> setupGraphics();
///< The returned factory must persist at least as long as *this.
private slots: private slots:
void createGame(); void createGame();

View file

@ -7,6 +7,8 @@
#include <QApplication> #include <QApplication>
#include <QIcon> #include <QIcon>
#include <extern/shiny/Main/Factory.hpp>
#include <components/ogreinit/ogreinit.hpp> #include <components/ogreinit/ogreinit.hpp>
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -42,6 +44,8 @@ int main(int argc, char *argv[])
OgreInit::OgreInit ogreInit; OgreInit::OgreInit ogreInit;
std::auto_ptr<sh::Factory> shinyFactory;
Application application (argc, argv); Application application (argc, argv);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -73,5 +77,7 @@ int main(int argc, char *argv[])
// return 0; // return 0;
} }
shinyFactory = editor.setupGraphics();
return editor.run(); return editor.run();
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -250,9 +250,9 @@ CSMWorld::Data::Data() : mRefs (mCells)
addModel (new IdTable (&mTopicInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo); 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 (&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 (&mCells, IdTable::Reordering_None, IdTable::Viewing_Id), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables, addModel (new IdTable (&mReferenceables, IdTable::Reordering_None, IdTable::Viewing_None, true),
UniversalId::Type_Referenceable); UniversalId::Type_Referenceables, UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Reordering_None, IdTable::Viewing_Cell), UniversalId::Type_References, UniversalId::Type_Reference, false); 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); addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false);
} }

View file

@ -5,8 +5,8 @@
#include "columnbase.hpp" #include "columnbase.hpp"
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering, CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering,
Viewing viewing) Viewing viewing, bool preview)
: mIdCollection (idCollection), mReordering (reordering), mViewing (viewing) : mIdCollection (idCollection), mReordering (reordering), mViewing (viewing), mPreview (preview)
{} {}
CSMWorld::IdTable::~IdTable() CSMWorld::IdTable::~IdTable()
@ -196,6 +196,11 @@ CSMWorld::IdTable::Viewing CSMWorld::IdTable::getViewing() const
return mViewing; return mViewing;
} }
bool CSMWorld::IdTable::hasPreview() const
{
return mPreview;
}
std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const
{ {
std::string id; std::string id;
@ -230,4 +235,9 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
id = "sys::default"; id = "sys::default";
return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint); return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint);
}
int CSMWorld::IdTable::getColumnId(int column) const
{
return mIdCollection->getColumn(column).getId();
} }

View file

@ -39,6 +39,7 @@ namespace CSMWorld
CollectionBase *mIdCollection; CollectionBase *mIdCollection;
Reordering mReordering; Reordering mReordering;
Viewing mViewing; Viewing mViewing;
bool mPreview;
// not implemented // not implemented
IdTable (const IdTable&); IdTable (const IdTable&);
@ -47,7 +48,7 @@ namespace CSMWorld
public: public:
IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None, IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None,
Viewing viewing = Viewing_None); Viewing viewing = Viewing_None, bool preview = false);
///< The ownership of \a idCollection is not transferred. ///< The ownership of \a idCollection is not transferred.
virtual ~IdTable(); virtual ~IdTable();
@ -100,9 +101,13 @@ namespace CSMWorld
Viewing getViewing() const; Viewing getViewing() const;
bool hasPreview() const;
std::pair<UniversalId, std::string> view (int row) const; std::pair<UniversalId, std::string> view (int row) const;
///< Return the UniversalId and the hint for viewing \a row. If viewing is not ///< Return the UniversalId and the hint for viewing \a row. If viewing is not
/// supported by this table, return (UniversalId::Type_None, ""). /// supported by this table, return (UniversalId::Type_None, "").
int getColumnId(int column) const;
}; };
} }

View file

@ -8,7 +8,7 @@ CSMWorld::TableMimeData::TableMimeData (UniversalId id, const CSMDoc::Document&
mDocument(document) mDocument(document)
{ {
mUniversalId.push_back (id); 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) : 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) 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; 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 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) 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 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) 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 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) 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 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) 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: default:
return CSMWorld::ColumnBase::Display_None; return CSMWorld::ColumnBase::Display_None;
} }
}
const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const
{
return &mDocument;
} }

View file

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

View file

@ -92,6 +92,8 @@ namespace
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" }, { 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_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 { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };

View file

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

View file

@ -40,7 +40,7 @@ OpenDialog::OpenDialog(QWidget * parent) : QDialog(parent)
mCfgMgr.processPaths(mDataLocal); mCfgMgr.processPaths(mDataLocal);
// Set the charset for reading the esm/esp files // 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; Files::PathContainer dataDirs;
dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end()); dataDirs.insert(dataDirs.end(), mDataDirs.begin(), mDataDirs.end());

View file

@ -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 /// \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 CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const
@ -18,4 +18,10 @@ 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::useHint (const std::string& hint) {}
void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
{
mUniversalId = id;
setWindowTitle (mUniversalId.toString().c_str());
}

View file

@ -27,6 +27,8 @@ namespace CSVDoc
// not implemented // not implemented
SubView (const SubView&); SubView (const SubView&);
SubView& operator= (SubView&); SubView& operator= (SubView&);
protected:
void setUniversalId(const CSMWorld::UniversalId& id);
public: public:

View file

@ -316,8 +316,16 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) /// \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()) if (!hint.empty())
view->useHint (hint); view->useHint (hint);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,7 +10,7 @@ CSVRender::Navigation1st::Navigation1st() : mCamera (0) {}
bool CSVRender::Navigation1st::activate (Ogre::Camera *camera) bool CSVRender::Navigation1st::activate (Ogre::Camera *camera)
{ {
mCamera = camera; mCamera = camera;
mCamera->setFixedYawAxis (true); mCamera->setFixedYawAxis (true, Ogre::Vector3::UNIT_Z);
Ogre::Radian pitch = mCamera->getOrientation().getPitch(); Ogre::Radian pitch = mCamera->getOrientation().getPitch();

View file

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

View file

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

View file

@ -11,7 +11,10 @@
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include <OgreViewport.h> #include <OgreViewport.h>
#include "../world/scenetoolmode.hpp"
#include "navigation.hpp" #include "navigation.hpp"
#include "lighting.hpp"
namespace CSVRender namespace CSVRender
{ {
@ -19,11 +22,12 @@ namespace CSVRender
: QWidget(parent) : QWidget(parent)
, mWindow(NULL) , mWindow(NULL)
, mCamera(NULL) , mCamera(NULL)
, mSceneMgr(NULL), mNavigation (0), mUpdate (false) , mSceneMgr(NULL), mNavigation (0), mLighting (0), mUpdate (false)
, mKeyForward (false), mKeyBackward (false), mKeyLeft (false), mKeyRight (false) , mKeyForward (false), mKeyBackward (false), mKeyLeft (false), mKeyRight (false)
, mKeyRollLeft (false), mKeyRollRight (false) , mKeyRollLeft (false), mKeyRollRight (false)
, mFast (false), mDragging (false), mMod1 (false) , mFast (false), mDragging (false), mMod1 (false)
, mFastFactor (4) /// \todo make this configurable , mFastFactor (4) /// \todo make this configurable
, mDefaultAmbient (0, 0, 0, 0), mHasDefaultAmbient (false)
{ {
setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground); setAttribute(Qt::WA_NoSystemBackground);
@ -32,28 +36,17 @@ namespace CSVRender
mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC); mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
// Throw in a random color just to make sure multiple scenes work mSceneMgr->setAmbientLight (Ogre::ColourValue (0,0,0,1));
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));
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));
mCamera = mSceneMgr->createCamera("foo"); mCamera = mSceneMgr->createCamera("foo");
Ogre::Entity* ent = mSceneMgr->createEntity("cube", Ogre::SceneManager::PT_CUBE); mCamera->setPosition (300, 0, 0);
ent->setMaterialName("BaseWhite"); mCamera->lookAt (0, 0, 0);
mCamera->setNearClipDistance (0.1);
mCamera->setFarClipDistance (30000);
mCamera->roll (Ogre::Degree (90));
mSceneMgr->getRootSceneNode()->attachObject(ent); setLighting (&mLightingDay);
mCamera->setPosition(300,300,300);
mCamera->lookAt(0,0,0);
mCamera->setNearClipDistance(0.1);
mCamera->setFarClipDistance(3000);
QTimer *timer = new QTimer (this); QTimer *timer = new QTimer (this);
@ -61,9 +54,27 @@ namespace CSVRender
timer->start (20); /// \todo make this configurable timer->start (20); /// \todo make this configurable
} }
void SceneWidget::setAmbient (const Ogre::ColourValue& colour) CSVWorld::SceneToolMode *SceneWidget::makeLightingSelector (CSVWorld::SceneToolbar *parent)
{ {
mSceneMgr->setAmbientLight (colour); 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");
connect (tool, SIGNAL (modeChanged (const std::string&)),
this, SLOT (selectLightingMode (const std::string&)));
return tool;
}
void SceneWidget::setDefaultAmbient (const Ogre::ColourValue& colour)
{
mDefaultAmbient = colour;
mHasDefaultAmbient = true;
if (mLighting)
mLighting->setDefaultAmbient (colour);
} }
void SceneWidget::updateOgreWindow() void SceneWidget::updateOgreWindow()
@ -118,6 +129,16 @@ namespace CSVRender
} }
} }
Ogre::SceneManager *SceneWidget::getSceneManager()
{
return mSceneMgr;
}
void SceneWidget::flagAsModified()
{
mUpdate = true;
}
void SceneWidget::paintEvent(QPaintEvent* e) void SceneWidget::paintEvent(QPaintEvent* e)
{ {
if (!mWindow) if (!mWindow)
@ -310,4 +331,23 @@ namespace CSVRender
{ {
return mFast ? mFastFactor : 1; 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);
}
} }

View file

@ -3,17 +3,29 @@
#include <QWidget> #include <QWidget>
#include <OgreColourValue.h>
#include "lightingday.hpp"
#include "lightingnight.hpp"
#include "lightingbright.hpp"
namespace Ogre namespace Ogre
{ {
class Camera; class Camera;
class SceneManager; class SceneManager;
class RenderWindow; class RenderWindow;
class ColourValue; }
namespace CSVWorld
{
class SceneToolMode;
class SceneToolbar;
} }
namespace CSVRender namespace CSVRender
{ {
class Navigation; class Navigation;
class Lighting;
class SceneWidget : public QWidget class SceneWidget : public QWidget
{ {
@ -26,14 +38,22 @@ namespace CSVRender
QPaintEngine* paintEngine() const; QPaintEngine* paintEngine() const;
void setAmbient (const Ogre::ColourValue& colour); CSVWorld::SceneToolMode *makeLightingSelector (CSVWorld::SceneToolbar *parent);
///< \note The actual ambient colour may differ based on lighting settings. ///< \attention The created tool is not added to the toolbar (via addTool). Doing that
/// is the responsibility of the calling function.
protected: protected:
void setNavigation (Navigation *navigation); void setNavigation (Navigation *navigation);
///< \attention The ownership of \a navigation is not transferred to *this. ///< \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: private:
void paintEvent(QPaintEvent* e); void paintEvent(QPaintEvent* e);
void resizeEvent(QResizeEvent* e); void resizeEvent(QResizeEvent* e);
@ -57,11 +77,15 @@ namespace CSVRender
int getFastFactor() const; int getFastFactor() const;
void setLighting (Lighting *lighting);
///< \attention The ownership of \a lighting is not transferred to *this.
Ogre::Camera* mCamera; Ogre::Camera* mCamera;
Ogre::SceneManager* mSceneMgr; Ogre::SceneManager* mSceneMgr;
Ogre::RenderWindow* mWindow; Ogre::RenderWindow* mWindow;
Navigation *mNavigation; Navigation *mNavigation;
Lighting *mLighting;
bool mUpdate; bool mUpdate;
bool mKeyForward; bool mKeyForward;
bool mKeyBackward; bool mKeyBackward;
@ -74,10 +98,17 @@ namespace CSVRender
bool mMod1; bool mMod1;
QPoint mOldPos; QPoint mOldPos;
int mFastFactor; int mFastFactor;
Ogre::ColourValue mDefaultAmbient;
bool mHasDefaultAmbient;
LightingDay mLightingDay;
LightingNight mLightingNight;
LightingBright mLightingBright;
private slots: private slots:
void update(); void update();
void selectLightingMode (const std::string& mode);
}; };
} }

View file

@ -15,7 +15,7 @@ void CSVRender::UnpagedWorldspaceWidget::update()
Ogre::ColourValue colour; Ogre::ColourValue colour;
colour.setAsABGR (record.get().mAmbi.mAmbient); colour.setAsABGR (record.get().mAmbi.mAmbient);
setAmbient (colour); setDefaultAmbient (colour);
/// \todo deal with mSunlight and mFog/mForDensity /// \todo deal with mSunlight and mFog/mForDensity
} }

View file

@ -1,11 +1,20 @@
#include "worldspacewidget.hpp" #include "worldspacewidget.hpp"
#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
#include <OgreEntity.h>
#include "../world/scenetoolmode.hpp" #include "../world/scenetoolmode.hpp"
CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent) CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent)
: SceneWidget (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) void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
{ {

View file

@ -28,7 +28,7 @@ namespace CSVRender
WorldspaceWidget (QWidget *parent = 0); WorldspaceWidget (QWidget *parent = 0);
CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent); CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent);
///< \important The created tool is not added to the toolbar (via addTool). Doing that ///< \attention The created tool is not added to the toolbar (via addTool). Doing that
/// is the responsibility of the calling function. /// is the responsibility of the calling function.
void selectDefaultNavigationMode(); void selectDefaultNavigationMode();

View file

@ -1,98 +1,689 @@
#include "dialoguesubview.hpp" #include "dialoguesubview.hpp"
#include <utility>
#include <memory>
#include <QGridLayout> #include <QGridLayout>
#include <QLabel> #include <QLabel>
#include <QSize>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QSpinBox> #include <QSpinBox>
#include <QLineEdit> #include <QLineEdit>
#include <QEvent>
#include <QDataWidgetMapper> #include <QDataWidgetMapper>
#include <QCheckBox>
#include <QLineEdit>
#include <QPlainTextEdit>
#include <QComboBox>
#include <QScrollArea>
#include <QPushButton>
#include <QToolButton>
#include "../../model/world/columnbase.hpp" #include "../../model/world/columnbase.hpp"
#include "../../model/world/idtable.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, #include "recordstatusdelegate.hpp"
bool createAndDelete) #include "util.hpp"
: SubView (id) #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
{ {
QWidget *widget = new QWidget (this); QVariant v = index.data(Qt::EditRole);
if (!v.isValid())
setWidget (widget);
QGridLayout *layout = new QGridLayout;
widget->setLayout (layout);
QAbstractItemModel *model = document.getData().getTableModel (id);
int columns = model->columnCount();
mWidgetMapper = new QDataWidgetMapper (this);
mWidgetMapper->setModel (model);
for (int i=0; i<columns; ++i)
{ {
int flags = model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); v = index.data(Qt::DisplayRole);
if (!v.isValid())
if (flags & CSMWorld::ColumnBase::Flag_Dialogue)
{ {
layout->addWidget (new QLabel (model->headerData (i, Qt::Horizontal).toString()), i, 0); return;
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
(model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
QWidget *widget = 0;
if (model->flags (model->index (0, i)) & Qt::ItemIsEditable)
{
switch (display)
{
case CSMWorld::ColumnBase::Display_String:
layout->addWidget (widget = new QLineEdit, i, 1);
break;
case CSMWorld::ColumnBase::Display_Integer:
/// \todo configure widget properly (range)
layout->addWidget (widget = new QSpinBox, i, 1);
break;
case CSMWorld::ColumnBase::Display_Float:
/// \todo configure widget properly (range, format?)
layout->addWidget (widget = new QDoubleSpinBox, i, 1);
break;
default: break; // silence warnings for other times for now
}
}
else
{
switch (display)
{
case CSMWorld::ColumnBase::Display_String:
case CSMWorld::ColumnBase::Display_Integer:
case CSMWorld::ColumnBase::Display_Float:
layout->addWidget (widget = new QLabel, i, 1);
break;
default: break; // silence warnings for other times for now
}
}
if (widget)
mWidgetMapper->addMapping (widget, i);
} }
} }
mWidgetMapper->setCurrentModelIndex ( if (QVariant::String == v.type())
dynamic_cast<CSMWorld::IdTable&> (*model).getModelIndex (id.getId(), 0)); {
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)
{
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;
}
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());
QLabel* label = qobject_cast<QLabel*>(editor);
if(label)
{
mNotEditableDelegate.setEditorData(label, index);
return;
}
std::map<int, CommandDelegate*>::const_iterator delegateIt(mDelegates.find(display));
if (delegateIt != mDelegates.end())
{
delegateIt->second->setEditorData(editor, index, true);
}
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*)));
}
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(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 = mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt();
if (flags & CSMWorld::ColumnBase::Flag_Dialogue)
{
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display>
(mTable->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt());
mDispatcher.makeDelegate(display);
QWidget *editor = mDispatcher.makeEditor(display, (mTable->index (row, i)));
if (editor)
{
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
{
unlockedLayout->addWidget (label, unlocked, 0);
unlockedLayout->addWidget (editor, unlocked, 1);
++unlocked;
}
}
}
}
mWidgetMapper->setCurrentModelIndex(mTable->index(row, 0));
this->setMinimumWidth(325); //TODO find better way to set the width or make it customizable
this->setWidget(mMainWidget);
this->setWidgetResizable(true);
}
/*
==============================DialogueSubView==========================================
*/
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory, bool sorting) :
SubView (id),
mEditWidget(0),
mMainLayout(NULL),
mUndoStack(document.getUndoStack()),
mTable(dynamic_cast<CSMWorld::IdTable*>(document.getData().getTableModel(id))),
mRow (-1),
mLocked(false),
mDocument(document)
{
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) 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;
}
if (mRow >= mTable->rowCount())
{
prevId();
} else {
dataChanged(mTable->index(mRow, 0));
}
}
}
}
void CSVWorld::DialogueSubView::deleteRecord()
{
int rows = mTable->rowCount();
//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 (!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));
}
}
}
}
void CSVWorld::DialogueSubView::requestFocus (const std::string& id)
{
mRow = mTable->getModelIndex (id, 0).row();
mEditWidget->remake(mRow);
}
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);
}
}

View file

@ -1,9 +1,25 @@
#ifndef CSV_WORLD_DIALOGUESUBVIEW_H #ifndef CSV_WORLD_DIALOGUESUBVIEW_H
#define CSV_WORLD_DIALOGUESUBVIEW_H #define CSV_WORLD_DIALOGUESUBVIEW_H
#include <map>
#include <memory>
#include <QAbstractItemDelegate>
#include <QScrollArea>
#include "../doc/subview.hpp" #include "../doc/subview.hpp"
#include "../../model/world/columnbase.hpp"
class QDataWidgetMapper; class QDataWidgetMapper;
class QSize;
class QEvent;
class QLabel;
class QVBoxLayout;
namespace CSMWorld
{
class IdTable;
}
namespace CSMDoc namespace CSMDoc
{ {
@ -12,15 +28,181 @@ namespace CSMDoc
namespace CSVWorld 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; QDataWidgetMapper *mWidgetMapper;
DialogueDelegateDispatcher mDispatcher;
QWidget* mMainWidget;
CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack;
public: public:
DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete); 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,
const CreatorFactoryBase& creatorFactory,
bool sorting = false);
virtual void setEditLock (bool locked); 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);
}; };
} }

View file

@ -41,10 +41,18 @@ CSVWorld::EnumDelegate::EnumDelegate (const std::vector<std::pair<int, QString>
} }
QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem& option, QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent,
const QModelIndex& index) const const QStyleOptionViewItem& option,
const QModelIndex& index) const
{ {
if (!index.data().isValid()) 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, CSMWorld::ColumnBase::Display display) const
{
if (!index.data(Qt::EditRole).isValid() && !index.data(Qt::DisplayRole).isValid())
return 0; return 0;
QComboBox *comboBox = new QComboBox (parent); QComboBox *comboBox = new QComboBox (parent);
@ -56,11 +64,22 @@ QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptio
return comboBox; 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)) 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(); std::size_t size = mValues.size();

View file

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

View file

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

View file

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

View file

@ -34,13 +34,16 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
SceneToolbar *toolbar = new SceneToolbar (48, this); SceneToolbar *toolbar = new SceneToolbar (48, this);
if (id.getId()[0]=='#') if (id.getId()=="sys::default")
mScene = new CSVRender::PagedWorldspaceWidget (this); mScene = new CSVRender::PagedWorldspaceWidget (this);
else else
mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this); mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this);
SceneToolMode *tool = mScene->makeNavigationSelector (toolbar); SceneToolMode *navigationTool = mScene->makeNavigationSelector (toolbar);
toolbar->addTool (tool); toolbar->addTool (navigationTool);
SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar);
toolbar->addTool (lightingTool);
layout2->addWidget (toolbar, 0); layout2->addWidget (toolbar, 0);

View file

@ -71,9 +71,9 @@ void CSVWorld::ScriptEdit::dropEvent (QDropEvent* event)
{ {
if (stringNeedsQuote(it->getId())) if (stringNeedsQuote(it->getId()))
{ {
insertPlainText(QString::fromStdString ('"' + it->getId() + '"')); insertPlainText(QString::fromUtf8 (('"' + it->getId() + '"').c_str()));
} else { } 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 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… //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)); return !(string.contains(mWhiteListQoutes));
} }

View file

@ -16,6 +16,7 @@
#include "scenesubview.hpp" #include "scenesubview.hpp"
#include "dialoguecreator.hpp" #include "dialoguecreator.hpp"
#include "infocreator.hpp" #include "infocreator.hpp"
#include "previewsubview.hpp"
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
{ {
@ -78,4 +79,62 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CreatorFactory<CSVFilter::FilterCreator> >); CreatorFactory<CSVFilter::FilterCreator> >);
manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>); 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>);
} }

View file

@ -39,18 +39,6 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
if (mCreateAction) if (mCreateAction)
menu.addAction(mCloneAction); menu.addAction(mCloneAction);
if (mModel->getViewing()!=CSMWorld::IdTable::Viewing_None)
{
int row = selectedRows.begin()->row();
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
CSMWorld::UniversalId id = mModel->view (row).first;
if (!mDocument.getData().getCells().getRecord (id.getId()).isDeleted())
menu.addAction (mViewAction);
}
} }
if (mCreateAction) if (mCreateAction)
@ -95,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()); menu.exec (event->globalPos());
} }
@ -249,6 +259,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
connect (mViewAction, SIGNAL (triggered()), this, SLOT (viewRecord())); connect (mViewAction, SIGNAL (triggered()), this, SLOT (viewRecord()));
addAction (mViewAction); 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)), connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (tableSizeUpdate())); this, SLOT (tableSizeUpdate()));
@ -275,7 +289,7 @@ CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
{ {
return CSMWorld::UniversalId ( return CSMWorld::UniversalId (
static_cast<CSMWorld::UniversalId::Type> (mProxyModel->data (mProxyModel->index (row, 2)).toInt()), 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() void CSVWorld::Table::revertRecord()
@ -406,7 +420,7 @@ void CSVWorld::Table::viewRecord()
if (selectedRows.size()==1) if (selectedRows.size()==1)
{ {
int row =selectedRows.begin()->row(); int row = selectedRows.begin()->row();
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row(); row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
@ -417,6 +431,18 @@ void CSVWorld::Table::viewRecord()
} }
} }
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) void CSVWorld::Table::updateEditorSetting (const QString &settingName, const QString &settingValue)
{ {
int columns = mModel->columnCount(); int columns = mModel->columnCount();
@ -507,28 +533,15 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event)
} }
drag->setMimeData (mime); drag->setMimeData (mime);
drag->setPixmap (QString::fromStdString (mime->getIcon())); drag->setPixmap (QString::fromUtf8 (mime->getIcon().c_str()));
drag->exec(Qt::CopyAction);
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);
} }
} }
void CSVWorld::Table::dragEnterEvent(QDragEnterEvent *event) void CSVWorld::Table::dragEnterEvent(QDragEnterEvent *event)
{ {
event->acceptProposedAction(); event->acceptProposedAction();
} }
void CSVWorld::Table::dropEvent(QDropEvent *event) void CSVWorld::Table::dropEvent(QDropEvent *event)
@ -560,7 +573,7 @@ void CSVWorld::Table::dropEvent(QDropEvent *event)
void CSVWorld::Table::dragMoveEvent(QDragMoveEvent *event) void CSVWorld::Table::dragMoveEvent(QDragMoveEvent *event)
{ {
event->accept(); event->accept();
} }
std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const
@ -575,7 +588,7 @@ std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column
if (display == columndisplay) 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; return titles;

View file

@ -44,6 +44,7 @@ namespace CSVWorld
QAction *mMoveUpAction; QAction *mMoveUpAction;
QAction *mMoveDownAction; QAction *mMoveDownAction;
QAction *mViewAction; QAction *mViewAction;
QAction *mPreviewAction;
CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTableProxyModel *mProxyModel;
CSMWorld::IdTable *mModel; CSMWorld::IdTable *mModel;
bool mEditLock; bool mEditLock;
@ -111,6 +112,8 @@ namespace CSVWorld
void viewRecord(); void viewRecord();
void previewRecord();
public slots: public slots:
void tableSizeUpdate(); void tableSizeUpdate();

View file

@ -4,8 +4,18 @@
#include <stdexcept> #include <stdexcept>
#include <QUndoStack> #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/commands.hpp"
#include "../../model/world/tablemimedata.hpp"
CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model)
: mModel (model) : mModel (model)
@ -117,10 +127,56 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode
} }
QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, 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()) QVariant variant = index.data();
return 0; 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); return QStyledItemDelegate::createEditor (parent, option, index);
} }
@ -140,4 +196,67 @@ bool CSVWorld::CommandDelegate::updateEditorSetting (const QString &settingName,
const QString &settingValue) const QString &settingValue)
{ {
return false; 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
} }

View file

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

View file

@ -33,7 +33,7 @@ add_openmw_dir (mwgui
merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks
keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog
recharge recharge mode videowidget
) )
add_openmw_dir (mwdialogue add_openmw_dir (mwdialogue
@ -44,7 +44,7 @@ add_openmw_dir (mwscript
locals scriptmanagerimp compilercontext interpretercontext cellextensions miscextensions locals scriptmanagerimp compilercontext interpretercontext cellextensions miscextensions
guiextensions soundextensions skyextensions statsextensions containerextensions guiextensions soundextensions skyextensions statsextensions containerextensions
aiextensions controlextensions extensions globalscripts ref dialogueextensions aiextensions controlextensions extensions globalscripts ref dialogueextensions
animationextensions transformationextensions consoleextensions userextensions locals animationextensions transformationextensions consoleextensions userextensions
) )
add_openmw_dir (mwsound add_openmw_dir (mwsound

View file

@ -12,7 +12,7 @@
#include <components/compiler/extensions0.hpp> #include <components/compiler/extensions0.hpp>
#include <components/bsa/bsa_archive.hpp> #include <components/bsa/resources.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/translation/translation.hpp> #include <components/translation/translation.hpp>
#include <components/nif/niffile.hpp> #include <components/nif/niffile.hpp>
@ -192,50 +192,6 @@ OMW::Engine::~Engine()
SDL_Quit(); 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 // add resources directory
// \note This function works recursively. // \note This function works recursively.
@ -383,10 +339,12 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
std::string aa = settings.getString("antialiasing", "Video"); std::string aa = settings.getString("antialiasing", "Video");
windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0"; windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0";
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS,
settings.getBool("minimize on focus loss", "Video") ? "1" : "0");
mOgre->createWindow("OpenMW", windowSettings); mOgre->createWindow("OpenMW", windowSettings);
loadBSA(); Bsa::registerResources (mFileCollections, mArchives, true, mFSStrict);
// Create input and UI first to set up a bootstrapping environment for // Create input and UI first to set up a bootstrapping environment for
// showing a loading screen and keeping the window responsive while doing so // showing a loading screen and keeping the window responsive while doing so
@ -401,6 +359,16 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding); mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding);
mEnvironment.setWindowManager (window); 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 // Create the world
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles, mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles,
mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap, mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap,
@ -418,9 +386,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
Compiler::registerExtensions (mExtensions); Compiler::registerExtensions (mExtensions);
// Create sound system
mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound));
// Create script system // Create script system
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full); mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full);
mScriptContext->setExtensions (&mExtensions); mScriptContext->setExtensions (&mExtensions);
@ -479,7 +444,19 @@ void OMW::Engine::go()
// start in main menu // start in main menu
if (!mSkipMenu) if (!mSkipMenu)
{
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); 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 else
MWBase::Environment::get().getStateManager()->newGame (true); MWBase::Environment::get().getStateManager()->newGame (true);

View file

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

View file

@ -25,7 +25,7 @@ namespace MWBase
virtual ~InputManager() {} 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; virtual void changeInputMode(bool guiMode) = 0;

View file

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

View file

@ -96,6 +96,10 @@ namespace MWBase
*/ */
virtual void update() = 0; 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 setNewGame(bool newgame) = 0;
virtual void pushGuiMode (MWGui::GuiMode mode) = 0; virtual void pushGuiMode (MWGui::GuiMode mode) = 0;

View file

@ -420,8 +420,6 @@ namespace MWBase
virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) = 0; virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) = 0;
/// \todo this does not belong here /// \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 frameStarted (float dt, bool paused) = 0;
virtual void screenshot (Ogre::Image& image, int w, int h) = 0; virtual void screenshot (Ogre::Image& image, int w, int h) = 0;

View file

@ -28,16 +28,16 @@
namespace namespace
{ {
struct CustomData : public MWWorld::CustomData struct ContainerCustomData : public MWWorld::CustomData
{ {
MWWorld::ContainerStore mContainerStore; MWWorld::ContainerStore mContainerStore;
virtual MWWorld::CustomData *clone() const; 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()) if (!ptr.getRefData().getCustomData())
{ {
std::auto_ptr<CustomData> data (new CustomData); std::auto_ptr<ContainerCustomData> data (new ContainerCustomData);
MWWorld::LiveCellRef<ESM::Container> *ref = MWWorld::LiveCellRef<ESM::Container> *ref =
ptr.get<ESM::Container>(); ptr.get<ESM::Container>();
@ -174,7 +174,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); 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 std::string Container::getScript (const MWWorld::Ptr& ptr) const
@ -267,7 +267,7 @@ namespace MWClass
ensureCustomData (ptr); ensureCustomData (ptr);
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore. dynamic_cast<ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
readState (state2.mInventory); readState (state2.mInventory);
} }
@ -278,7 +278,7 @@ namespace MWClass
ensureCustomData (ptr); ensureCustomData (ptr);
dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mContainerStore. dynamic_cast<ContainerCustomData&> (*ptr.getRefData().getCustomData()).mContainerStore.
writeState (state2.mInventory); writeState (state2.mInventory);
} }
} }

View file

@ -37,7 +37,7 @@
namespace namespace
{ {
struct CustomData : public MWWorld::CustomData struct CreatureCustomData : public MWWorld::CustomData
{ {
MWMechanics::CreatureStats mCreatureStats; MWMechanics::CreatureStats mCreatureStats;
MWWorld::ContainerStore* mContainerStore; // may be InventoryStore for some creatures MWWorld::ContainerStore* mContainerStore; // may be InventoryStore for some creatures
@ -45,13 +45,13 @@ namespace
virtual MWWorld::CustomData *clone() const; virtual MWWorld::CustomData *clone() const;
CustomData() : mContainerStore(0) {} CreatureCustomData() : mContainerStore(0) {}
virtual ~CustomData() { delete mContainerStore; } 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(); cloned->mContainerStore = mContainerStore->clone();
return cloned; return cloned;
} }
@ -63,7 +63,7 @@ namespace MWClass
{ {
if (!ptr.getRefData().getCustomData()) if (!ptr.getRefData().getCustomData())
{ {
std::auto_ptr<CustomData> data (new CustomData); std::auto_ptr<CreatureCustomData> data (new CreatureCustomData);
static bool inited = false; static bool inited = false;
if(!inited) if(!inited)
@ -123,8 +123,13 @@ namespace MWClass
else else
data->mContainerStore = new MWWorld::ContainerStore(); 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 // store
ptr.getRefData().setCustomData (data.release()); ptr.getRefData().setCustomData(data.release());
getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr), "", getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr), "",
MWBase::Environment::get().getWorld()->getStore()); MWBase::Environment::get().getWorld()->getStore());
@ -134,7 +139,7 @@ namespace MWClass
getContainerStore(ptr).add(MWWorld::ContainerStore::sGoldId, ref->mBase->mData.mGold, ptr); getContainerStore(ptr).add(MWWorld::ContainerStore::sGoldId, ref->mBase->mData.mGold, ptr);
if (ref->mBase->mFlags & ESM::Creature::Weapon) if (ref->mBase->mFlags & ESM::Creature::Weapon)
getInventoryStore(ptr).autoEquip(ptr); getInventoryStore(ptr).autoEquip(ptr);
} }
} }
@ -192,7 +197,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mCreatureStats; return dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData()).mCreatureStats;
} }
@ -456,7 +461,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); 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 MWWorld::InventoryStore& Creature::getInventoryStore(const MWWorld::Ptr &ptr) const
@ -559,7 +564,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); 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 Ogre::Vector3 Creature::getMovementVector (const MWWorld::Ptr& ptr) const
@ -786,7 +791,7 @@ namespace MWClass
ensureCustomData (ptr); ensureCustomData (ptr);
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()); CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData());
customData.mContainerStore->readState (state2.mInventory); customData.mContainerStore->readState (state2.mInventory);
customData.mCreatureStats.readState (state2.mCreatureStats); customData.mCreatureStats.readState (state2.mCreatureStats);
@ -800,7 +805,7 @@ namespace MWClass
ensureCustomData (ptr); ensureCustomData (ptr);
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()); CreatureCustomData& customData = dynamic_cast<CreatureCustomData&> (*ptr.getRefData().getCustomData());
customData.mContainerStore->writeState (state2.mInventory); customData.mContainerStore->writeState (state2.mInventory);
customData.mCreatureStats.writeState (state2.mCreatureStats); customData.mCreatureStats.writeState (state2.mCreatureStats);

View file

@ -9,15 +9,15 @@
namespace namespace
{ {
struct CustomData : public MWWorld::CustomData struct CreatureLevListCustomData : public MWWorld::CustomData
{ {
// TODO: save the creature we spawned here // TODO: save the creature we spawned here
virtual MWWorld::CustomData *clone() const; 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()) if (!ptr.getRefData().getCustomData())
{ {
std::auto_ptr<CustomData> data (new CustomData); std::auto_ptr<CreatureLevListCustomData> data (new CreatureLevListCustomData);
MWWorld::LiveCellRef<ESM::CreatureLevList> *ref = MWWorld::LiveCellRef<ESM::CreatureLevList> *ref =
ptr.get<ESM::CreatureLevList>(); ptr.get<ESM::CreatureLevList>();

View file

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

View file

@ -39,7 +39,7 @@
namespace namespace
{ {
struct CustomData : public MWWorld::CustomData struct NpcCustomData : public MWWorld::CustomData
{ {
MWMechanics::NpcStats mNpcStats; MWMechanics::NpcStats mNpcStats;
MWMechanics::Movement mMovement; MWMechanics::Movement mMovement;
@ -48,9 +48,9 @@ namespace
virtual MWWorld::CustomData *clone() const; 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) void autoCalculateAttributes (const ESM::NPC* npc, MWMechanics::CreatureStats& creatureStats)
@ -262,7 +262,7 @@ namespace MWClass
} }
if (!ptr.getRefData().getCustomData()) 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>(); MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
@ -357,6 +357,11 @@ namespace MWClass
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "", data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "",
MWBase::Environment::get().getWorld()->getStore()); MWBase::Environment::get().getWorld()->getStore());
// Relates to NPC gold reset delay
data->mNpcStats.setTradeTime(MWWorld::TimeStamp(0.0, 0));
data->mNpcStats.setGoldPool(gold);
// store // store
ptr.getRefData().setCustomData (data.release()); ptr.getRefData().setCustomData (data.release());
@ -365,6 +370,8 @@ namespace MWClass
getContainerStore(ptr).add(MWWorld::ContainerStore::sGoldId, gold, ptr); getContainerStore(ptr).add(MWWorld::ContainerStore::sGoldId, gold, ptr);
getInventoryStore(ptr).autoEquip(ptr); getInventoryStore(ptr).autoEquip(ptr);
} }
} }
@ -436,14 +443,14 @@ namespace MWClass
{ {
ensureCustomData (ptr); 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 MWMechanics::NpcStats& Npc::getNpcStats (const MWWorld::Ptr& ptr) const
{ {
ensureCustomData (ptr); ensureCustomData (ptr);
return dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()).mNpcStats; return dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData()).mNpcStats;
} }
@ -819,7 +826,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); 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) MWWorld::InventoryStore& Npc::getInventoryStore (const MWWorld::Ptr& ptr)
@ -827,7 +834,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); 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 std::string Npc::getScript (const MWWorld::Ptr& ptr) const
@ -841,7 +848,7 @@ namespace MWClass
float Npc::getSpeed(const MWWorld::Ptr& ptr) const float Npc::getSpeed(const MWWorld::Ptr& ptr) const
{ {
const MWBase::World *world = MWBase::Environment::get().getWorld(); 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 MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects();
const float normalizedEncumbrance = Npc::getEncumbrance(ptr) / Npc::getCapacity(ptr); const float normalizedEncumbrance = Npc::getEncumbrance(ptr) / Npc::getCapacity(ptr);
@ -896,7 +903,7 @@ namespace MWClass
float Npc::getJump(const MWWorld::Ptr &ptr) const 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 MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects();
const float encumbranceTerm = fJumpEncumbranceBase->getFloat() + const float encumbranceTerm = fJumpEncumbranceBase->getFloat() +
fJumpEncumbranceMultiplier->getFloat() * fJumpEncumbranceMultiplier->getFloat() *
@ -935,7 +942,7 @@ namespace MWClass
if (fallHeight >= fallDistanceMin) if (fallHeight >= fallDistanceMin)
{ {
const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified(); 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 jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude;
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat(); const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat(); const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
@ -960,7 +967,7 @@ namespace MWClass
{ {
ensureCustomData (ptr); 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 Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const
@ -1266,7 +1273,7 @@ namespace MWClass
ensureCustomData (ptr); ensureCustomData (ptr);
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()); NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData());
customData.mInventoryStore.readState (state2.mInventory); customData.mInventoryStore.readState (state2.mInventory);
customData.mNpcStats.readState (state2.mNpcStats); customData.mNpcStats.readState (state2.mNpcStats);
@ -1280,7 +1287,7 @@ namespace MWClass
ensureCustomData (ptr); ensureCustomData (ptr);
CustomData& customData = dynamic_cast<CustomData&> (*ptr.getRefData().getCustomData()); NpcCustomData& customData = dynamic_cast<NpcCustomData&> (*ptr.getRefData().getCustomData());
customData.mInventoryStore.writeState (state2.mInventory); customData.mInventoryStore.writeState (state2.mInventory);
customData.mNpcStats.writeState (state2.mNpcStats); customData.mNpcStats.writeState (state2.mNpcStats);

View file

@ -26,16 +26,6 @@ namespace
return path; return path;
} }
std::string getCountString(const int count)
{
if (count == 1)
return "";
if (count > 9999)
return boost::lexical_cast<std::string>(int(count/1000.f)) + "k";
else
return boost::lexical_cast<std::string>(count);
}
} }
namespace MWGui namespace MWGui
@ -226,7 +216,7 @@ namespace MWGui
text->setNeedMouseFocus(false); text->setNeedMouseFocus(false);
text->setTextShadow(true); text->setTextShadow(true);
text->setTextShadowColour(MyGUI::Colour(0,0,0)); text->setTextShadowColour(MyGUI::Colour(0,0,0));
text->setCaption(getCountString(ingredient->getUserData<MWWorld::Ptr>()->getRefData().getCount())); text->setCaption(ItemView::getCountString(ingredient->getUserData<MWWorld::Ptr>()->getRefData().getCount()));
} }
mItemView->update(); mItemView->update();

View file

@ -23,19 +23,6 @@
#include "sortfilteritemmodel.hpp" #include "sortfilteritemmodel.hpp"
#include "pickpocketitemmodel.hpp" #include "pickpocketitemmodel.hpp"
namespace
{
std::string getCountString(const int count)
{
if (count == 1)
return "";
if (count > 9999)
return boost::lexical_cast<std::string>(int(count/1000.f)) + "k";
else
return boost::lexical_cast<std::string>(count);
}
}
namespace MWGui namespace MWGui
{ {
@ -79,7 +66,7 @@ namespace MWGui
text->setNeedMouseFocus(false); text->setNeedMouseFocus(false);
text->setTextShadow(true); text->setTextShadow(true);
text->setTextShadowColour(MyGUI::Colour(0,0,0)); text->setTextShadowColour(MyGUI::Colour(0,0,0));
text->setCaption(getCountString(count)); text->setCaption(ItemView::getCountString(count));
sourceView->update(); sourceView->update();

View file

@ -23,18 +23,7 @@
#include "travelwindow.hpp" #include "travelwindow.hpp"
#include "bookpage.hpp" #include "bookpage.hpp"
#include "journalbooks.hpp" // to_utf8_span
namespace
{
MWGui::BookTypesetter::Utf8Span to_utf8_span (char const * text)
{
typedef MWGui::BookTypesetter::Utf8Point point;
point begin = reinterpret_cast <point> (text);
return MWGui::BookTypesetter::Utf8Span (begin, begin + strlen (text));
}
}
namespace MWGui namespace MWGui
{ {

View file

@ -1,3 +1,6 @@
#ifndef OPENMW_GAME_MWGUI_HUD_H
#define OPENMW_GAME_MWGUI_HUD_H
#include "mapwindow.hpp" #include "mapwindow.hpp"
#include "../mwmechanics/stat.hpp" #include "../mwmechanics/stat.hpp"
@ -117,3 +120,5 @@ namespace MWGui
void updatePositions(); void updatePositions();
}; };
} }
#endif

View file

@ -162,6 +162,7 @@ namespace MWGui
} }
const ItemStack& item = mTradeModel->getItem(index); const ItemStack& item = mTradeModel->getItem(index);
std::string sound = MWWorld::Class::get(item.mBase).getDownSoundId(item.mBase);
MWWorld::Ptr object = item.mBase; MWWorld::Ptr object = item.mBase;
int count = item.mCount; int count = item.mCount;
@ -170,6 +171,7 @@ namespace MWGui
if (item.mBase.getCellRef().mRefID.size() > 6 if (item.mBase.getCellRef().mRefID.size() > 6
&& item.mBase.getCellRef().mRefID.substr(0,6) == "bound_") && item.mBase.getCellRef().mRefID.substr(0,6) == "bound_")
{ {
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
MWBase::Environment::get().getWindowManager()->messageBox("#{sBarterDialog12}"); MWBase::Environment::get().getWindowManager()->messageBox("#{sBarterDialog12}");
return; return;
} }
@ -213,6 +215,7 @@ namespace MWGui
int services = MWBase::Environment::get().getWindowManager()->getTradeWindow()->getMerchantServices(); int services = MWBase::Environment::get().getWindowManager()->getTradeWindow()->getMerchantServices();
if (!MWWorld::Class::get(object).canSell(object, services)) if (!MWWorld::Class::get(object).canSell(object, services))
{ {
MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);
MWBase::Environment::get().getWindowManager()-> MWBase::Environment::get().getWindowManager()->
messageBox("#{sBarterDialog4}"); messageBox("#{sBarterDialog4}");
return; return;

View file

@ -1,3 +1,6 @@
#ifndef OPENMW_GAME_MWGUI_ITEMSELECTION_H
#define OPENMW_GAME_MWGUI_ITEMSELECTION_H
#include "container.hpp" #include "container.hpp"
namespace MWGui namespace MWGui
@ -32,3 +35,5 @@ namespace MWGui
}; };
} }
#endif

View file

@ -13,23 +13,19 @@
#include "itemmodel.hpp" #include "itemmodel.hpp"
namespace
{
std::string getCountString(const int count)
{
if (count == 1)
return "";
if (count > 9999)
return boost::lexical_cast<std::string>(int(count/1000.f)) + "k";
else
return boost::lexical_cast<std::string>(count);
}
}
namespace MWGui namespace MWGui
{ {
std::string ItemView::getCountString(int count)
{
if (count == 1)
return "";
if (count > 9999)
return boost::lexical_cast<std::string>(int(count/1000.f)) + "k";
else
return boost::lexical_cast<std::string>(count);
}
ItemView::ItemView() ItemView::ItemView()
: mModel(NULL) : mModel(NULL)
, mScrollView(NULL) , mScrollView(NULL)

View file

@ -30,6 +30,8 @@ namespace MWGui
void update(); void update();
static std::string getCountString(int count);
private: private:
virtual void initialiseOverride(); virtual void initialiseOverride();

View file

@ -2,15 +2,6 @@
namespace namespace
{ {
MWGui::BookTypesetter::Utf8Span to_utf8_span (char const * text)
{
typedef MWGui::BookTypesetter::Utf8Point point;
point begin = reinterpret_cast <point> (text);
return MWGui::BookTypesetter::Utf8Span (begin, begin + strlen (text));
}
const MyGUI::Colour linkHot (0.40f, 0.40f, 0.80f); const MyGUI::Colour linkHot (0.40f, 0.40f, 0.80f);
const MyGUI::Colour linkNormal (0.20f, 0.20f, 0.60f); const MyGUI::Colour linkNormal (0.20f, 0.20f, 0.60f);
const MyGUI::Colour linkActive (0.50f, 0.50f, 1.00f); const MyGUI::Colour linkActive (0.50f, 0.50f, 1.00f);
@ -178,6 +169,15 @@ namespace
namespace MWGui namespace MWGui
{ {
MWGui::BookTypesetter::Utf8Span to_utf8_span (char const * text)
{
typedef MWGui::BookTypesetter::Utf8Point point;
point begin = reinterpret_cast <point> (text);
return MWGui::BookTypesetter::Utf8Span (begin, begin + strlen (text));
}
typedef TypesetBook::Ptr book; typedef TypesetBook::Ptr book;
JournalBooks::JournalBooks (JournalViewModel::Ptr model) : JournalBooks::JournalBooks (JournalViewModel::Ptr model) :

View file

@ -6,6 +6,8 @@
namespace MWGui namespace MWGui
{ {
MWGui::BookTypesetter::Utf8Span to_utf8_span (char const * text);
struct JournalBooks struct JournalBooks
{ {
typedef TypesetBook::Ptr Book; typedef TypesetBook::Ptr Book;

View file

@ -226,7 +226,7 @@ namespace MWGui
} }
mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
MWBase::Environment::get().getInputManager()->update(0, true); MWBase::Environment::get().getInputManager()->update(0, true, true);
// First, swap buffers from last draw, then, queue an update of the // First, swap buffers from last draw, then, queue an update of the
// window contents, but don't swap buffers (which would have // window contents, but don't swap buffers (which would have

View file

@ -13,6 +13,7 @@
#include "../mwstate/character.hpp" #include "../mwstate/character.hpp"
#include "savegamedialog.hpp" #include "savegamedialog.hpp"
#include "confirmationdialog.hpp"
namespace MWGui namespace MWGui
{ {
@ -21,12 +22,13 @@ namespace MWGui
: OEngine::GUI::Layout("openmw_mainmenu.layout") : OEngine::GUI::Layout("openmw_mainmenu.layout")
, mButtonBox(0), mWidth (w), mHeight (h) , mButtonBox(0), mWidth (w), mHeight (h)
, mSaveGameDialog(NULL) , mSaveGameDialog(NULL)
, mBackground(NULL)
{ {
getWidget(mVersionText, "VersionText"); getWidget(mVersionText, "VersionText");
std::stringstream sstream; std::stringstream sstream;
sstream << "OpenMW version: " << OPENMW_VERSION; sstream << "OpenMW version: " << OPENMW_VERSION;
// adding info about git hash if availible // adding info about git hash if available
std::string rev = OPENMW_VERSION_COMMITHASH; std::string rev = OPENMW_VERSION_COMMITHASH;
std::string tag = OPENMW_VERSION_TAGHASH; std::string tag = OPENMW_VERSION_TAGHASH;
if (!rev.empty() && !tag.empty()) if (!rev.empty() && !tag.empty())
@ -58,10 +60,24 @@ namespace MWGui
{ {
if (visible) if (visible)
updateMenu(); updateMenu();
else
showBackground(
MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) &&
MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame);
OEngine::GUI::Layout::setVisible (visible); OEngine::GUI::Layout::setVisible (visible);
} }
void MainMenu::onNewGameConfirmed()
{
MWBase::Environment::get().getStateManager()->newGame();
}
void MainMenu::onExitConfirmed()
{
MWBase::Environment::get().getStateManager()->requestQuit();
}
void MainMenu::onButtonClicked(MyGUI::Widget *sender) void MainMenu::onButtonClicked(MyGUI::Widget *sender)
{ {
std::string name = *sender->getUserData<std::string>(); std::string name = *sender->getUserData<std::string>();
@ -73,11 +89,33 @@ namespace MWGui
} }
else if (name == "options") else if (name == "options")
MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings); MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings);
else if (name == "credits")
MWBase::Environment::get().getWindowManager()->playVideo("mw_credits.bik", true);
else if (name == "exitgame") else if (name == "exitgame")
MWBase::Environment::get().getStateManager()->requestQuit(); {
if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame)
onExitConfirmed();
else
{
ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
dialog->open("#{sMessage2}");
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &MainMenu::onExitConfirmed);
dialog->eventCancelClicked.clear();
}
}
else if (name == "newgame") else if (name == "newgame")
{ {
MWBase::Environment::get().getStateManager()->newGame(); if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame)
onNewGameConfirmed();
else
{
ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
dialog->open("#{sNotifyMessage54}");
dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &MainMenu::onNewGameConfirmed);
dialog->eventCancelClicked.clear();
}
} }
else else
@ -92,11 +130,42 @@ namespace MWGui
} }
} }
void MainMenu::showBackground(bool show)
{
if (mBackground)
{
MyGUI::Gui::getInstance().destroyWidget(mBackground);
mBackground = NULL;
}
if (show)
{
if (!mBackground)
{
mBackground = MyGUI::Gui::getInstance().createWidgetReal<MyGUI::ImageBox>("ImageBox", 0,0,1,1,
MyGUI::Align::Stretch, "Menu");
mBackground->setImageTexture("black.png");
// Use black bars to correct aspect ratio. The video player also does it, so we need to do it
// for mw_logo.bik to align correctly with menu_morrowind.dds.
MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize();
// No way to un-hardcode this right now, menu_morrowind.dds is 1024x512 but was designed for 4:3
double imageaspect = 4.0/3.0;
int leftPadding = std::max(0.0, (screenSize.width - screenSize.height * imageaspect) / 2);
int topPadding = std::max(0.0, (screenSize.height - screenSize.width / imageaspect) / 2);
MyGUI::ImageBox* image = mBackground->createWidget<MyGUI::ImageBox>("ImageBox",
leftPadding, topPadding, screenSize.width - leftPadding*2, screenSize.height - topPadding*2, MyGUI::Align::Default);
image->setImageTexture("textures\\menu_morrowind.dds");
}
}
}
void MainMenu::updateMenu() void MainMenu::updateMenu()
{ {
setCoord(0,0, mWidth, mHeight); setCoord(0,0, mWidth, mHeight);
if (!mButtonBox) if (!mButtonBox)
mButtonBox = mMainWidget->createWidget<MyGUI::Widget>("", MyGUI::IntCoord(0, 0, 0, 0), MyGUI::Align::Default); mButtonBox = mMainWidget->createWidget<MyGUI::Widget>("", MyGUI::IntCoord(0, 0, 0, 0), MyGUI::Align::Default);
@ -104,6 +173,8 @@ namespace MWGui
MWBase::StateManager::State state = MWBase::Environment::get().getStateManager()->getState(); MWBase::StateManager::State state = MWBase::Environment::get().getStateManager()->getState();
showBackground(state == MWBase::StateManager::State_NoGame);
std::vector<std::string> buttons; std::vector<std::string> buttons;
if (state==MWBase::StateManager::State_Running) if (state==MWBase::StateManager::State_Running)
@ -120,7 +191,10 @@ namespace MWGui
buttons.push_back("savegame"); buttons.push_back("savegame");
buttons.push_back("options"); buttons.push_back("options");
//buttons.push_back("credits");
if (state==MWBase::StateManager::State_NoGame)
buttons.push_back("credits");
buttons.push_back("exitgame"); buttons.push_back("exitgame");
// Create new buttons if needed // Create new buttons if needed
@ -155,12 +229,27 @@ namespace MWGui
assert(mButtons.find(*it) != mButtons.end()); assert(mButtons.find(*it) != mButtons.end());
MWGui::ImageButton* button = mButtons[*it]; MWGui::ImageButton* button = mButtons[*it];
button->setVisible(true); button->setVisible(true);
MyGUI::IntSize requested = button->getRequestedSize(); MyGUI::IntSize requested = button->getRequestedSize();
button->setCoord((maxwidth-requested.width) / 2, curH, requested.width, requested.height);
curH += requested.height; // Trim off some of the excessive padding
// TODO: perhaps do this within ImageButton?
int trim = 8;
button->setImageCoord(MyGUI::IntCoord(0, trim, requested.width, requested.height-trim));
int height = requested.height-trim*2;
button->setImageTile(MyGUI::IntSize(requested.width, height));
button->setCoord((maxwidth-requested.width) / 2, curH, requested.width, height);
curH += height;
} }
mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight/2 - curH/2, maxwidth, curH); if (state == MWBase::StateManager::State_NoGame)
{
// Align with the background image
int bottomPadding=48;
mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight - curH - bottomPadding, maxwidth, curH);
}
else
mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight/2 - curH/2, maxwidth, curH);
} }
} }

View file

@ -1,3 +1,6 @@
#ifndef OPENMW_GAME_MWGUI_MAINMENU_H
#define OPENMW_GAME_MWGUI_MAINMENU_H
#include <openengine/gui/layout.hpp> #include <openengine/gui/layout.hpp>
#include "imagebutton.hpp" #include "imagebutton.hpp"
@ -26,9 +29,15 @@ namespace MWGui
MyGUI::Widget* mButtonBox; MyGUI::Widget* mButtonBox;
MyGUI::TextBox* mVersionText; MyGUI::TextBox* mVersionText;
MyGUI::ImageBox* mBackground;
std::map<std::string, MWGui::ImageButton*> mButtons; std::map<std::string, MWGui::ImageButton*> mButtons;
void onButtonClicked (MyGUI::Widget* sender); void onButtonClicked (MyGUI::Widget* sender);
void onNewGameConfirmed();
void onExitConfirmed();
void showBackground(bool show);
void updateMenu(); void updateMenu();
@ -36,3 +45,5 @@ namespace MWGui
}; };
} }
#endif

View file

@ -47,9 +47,7 @@ namespace MWGui
GM_Loading, GM_Loading,
GM_LoadingWallpaper, GM_LoadingWallpaper,
GM_QuickKeysMenu, GM_QuickKeysMenu
GM_Video
}; };
// Windows shown in inventory mode // Windows shown in inventory mode

View file

@ -19,28 +19,8 @@
#include "windowmanagerimp.hpp" #include "windowmanagerimp.hpp"
#include "itemselection.hpp" #include "itemselection.hpp"
#include "spellwindow.hpp"
namespace
{
bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right)
{
int cmp = left.getClass().getName(left).compare(
right.getClass().getName(right));
return cmp < 0;
}
bool sortSpells(const std::string& left, const std::string& right)
{
const MWWorld::Store<ESM::Spell> &spells =
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>();
const ESM::Spell* a = spells.find(left);
const ESM::Spell* b = spells.find(right);
int cmp = a->mName.compare(b->mName);
return cmp < 0;
}
}
namespace MWGui namespace MWGui
{ {

View file

@ -86,7 +86,21 @@ namespace MWGui
{ {
std::stringstream title; std::stringstream title;
title << it->getSignature().mPlayerName; title << it->getSignature().mPlayerName;
title << " (Level " << it->getSignature().mPlayerLevel << " " << it->getSignature().mPlayerClass << ")";
// For a custom class, we will not find it in the store (unless we loaded the savegame first).
// Fall back to name stored in savegame header in that case.
std::string className;
if (it->getSignature().mPlayerClassId.empty())
className = it->getSignature().mPlayerClassName;
else
{
// Find the localised name for this class from the store
const ESM::Class* class_ = MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find(
it->getSignature().mPlayerClassId);
className = class_->mName;
}
title << " (Level " << it->getSignature().mPlayerLevel << " " << className << ")";
mCharacterSelection->addItem (title.str()); mCharacterSelection->addItem (title.str());
@ -169,7 +183,10 @@ namespace MWGui
else else
{ {
if (mCurrentCharacter && slot) if (mCurrentCharacter && slot)
{
MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot);
MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu);
}
} }
setVisible(false); setVisible(false);
@ -241,7 +258,13 @@ namespace MWGui
struct tm* timeinfo; struct tm* timeinfo;
timeinfo = localtime(&time); timeinfo = localtime(&time);
text << asctime(timeinfo) << "\n"; // Use system/environment locale settings for datetime formatting
std::setlocale(LC_TIME, "");
const int size=1024;
char buffer[size];
if (std::strftime(buffer, size, "%x %X", timeinfo) > 0)
text << buffer << "\n";
text << "Level " << slot->mProfile.mPlayerLevel << "\n"; text << "Level " << slot->mProfile.mPlayerLevel << "\n";
text << slot->mProfile.mPlayerCell << "\n"; text << slot->mProfile.mPlayerCell << "\n";
// text << "Time played: " << slot->mProfile.mTimePlayed << "\n"; // text << "Time played: " << slot->mProfile.mTimePlayed << "\n";

View file

@ -83,91 +83,116 @@ namespace
} }
return false; return false;
} }
const char* checkButtonType = "CheckButton";
const char* sliderType = "Slider";
std::string getSettingType(MyGUI::Widget* widget)
{
return widget->getUserString("SettingType");
}
std::string getSettingName(MyGUI::Widget* widget)
{
return widget->getUserString("SettingName");
}
std::string getSettingCategory(MyGUI::Widget* widget)
{
return widget->getUserString("SettingCategory");
}
std::string getSettingValueType(MyGUI::Widget* widget)
{
return widget->getUserString("SettingValueType");
}
void getSettingMinMax(MyGUI::Widget* widget, float& min, float& max)
{
const char* settingMin = "SettingMin";
const char* settingMax = "SettingMax";
min = 0.f;
max = 1.f;
if (!widget->getUserString(settingMin).empty())
min = boost::lexical_cast<float>(widget->getUserString(settingMin));
if (!widget->getUserString(settingMax).empty())
max = boost::lexical_cast<float>(widget->getUserString(settingMax));
}
} }
namespace MWGui namespace MWGui
{ {
void SettingsWindow::configureWidgets(MyGUI::Widget* widget)
{
MyGUI::EnumeratorWidgetPtr widgets = widget->getEnumerator();
while (widgets.next())
{
MyGUI::Widget* current = widgets.current();
std::string type = getSettingType(current);
if (type == checkButtonType)
{
std::string initialValue = Settings::Manager::getBool(getSettingName(current),
getSettingCategory(current))
? "#{sOn}" : "#{sOff}";
current->castType<MyGUI::Button>()->setCaptionWithReplacing(initialValue);
current->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
}
if (type == sliderType)
{
MyGUI::ScrollBar* scroll = current->castType<MyGUI::ScrollBar>();
if (getSettingValueType(current) == "Float")
{
// TODO: ScrollBar isn't meant for this. should probably use a dedicated FloatSlider widget
float min,max;
getSettingMinMax(scroll, min, max);
float value = Settings::Manager::getFloat(getSettingName(current), getSettingCategory(current));
value = (value-min)/(max-min);
scroll->setScrollPosition( value * (scroll->getScrollRange()-1));
}
else
{
int value = Settings::Manager::getFloat(getSettingName(current), getSettingCategory(current));
scroll->setScrollPosition(value);
}
scroll->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
}
configureWidgets(current);
}
}
SettingsWindow::SettingsWindow() : SettingsWindow::SettingsWindow() :
WindowBase("openmw_settings_window.layout") WindowBase("openmw_settings_window.layout")
{ {
configureWidgets(mMainWidget);
getWidget(mOkButton, "OkButton"); getWidget(mOkButton, "OkButton");
getWidget(mBestAttackButton, "BestAttackButton");
getWidget(mGrabCursorButton, "GrabCursorButton");
getWidget(mSubtitlesButton, "SubtitlesButton");
getWidget(mCrosshairButton, "CrosshairButton");
getWidget(mResolutionList, "ResolutionList"); getWidget(mResolutionList, "ResolutionList");
getWidget(mMenuTransparencySlider, "MenuTransparencySlider");
getWidget(mToolTipDelaySlider, "ToolTipDelaySlider");
getWidget(mViewDistanceSlider, "ViewDistanceSlider");
getWidget(mFullscreenButton, "FullscreenButton"); getWidget(mFullscreenButton, "FullscreenButton");
getWidget(mVSyncButton, "VSyncButton"); getWidget(mVSyncButton, "VSyncButton");
getWidget(mFPSButton, "FPSButton"); getWidget(mFPSButton, "FPSButton");
getWidget(mFOVSlider, "FOVSlider"); getWidget(mFOVSlider, "FOVSlider");
getWidget(mMasterVolumeSlider, "MasterVolume");
getWidget(mVoiceVolumeSlider, "VoiceVolume");
getWidget(mEffectsVolumeSlider, "EffectsVolume");
getWidget(mFootstepsVolumeSlider, "FootstepsVolume");
getWidget(mMusicVolumeSlider, "MusicVolume");
getWidget(mAnisotropySlider, "AnisotropySlider"); getWidget(mAnisotropySlider, "AnisotropySlider");
getWidget(mTextureFilteringButton, "TextureFilteringButton"); getWidget(mTextureFilteringButton, "TextureFilteringButton");
getWidget(mAnisotropyLabel, "AnisotropyLabel"); getWidget(mAnisotropyLabel, "AnisotropyLabel");
getWidget(mAnisotropyBox, "AnisotropyBox"); getWidget(mAnisotropyBox, "AnisotropyBox");
getWidget(mWaterShaderButton, "WaterShaderButton");
getWidget(mReflectObjectsButton, "ReflectObjectsButton");
getWidget(mReflectActorsButton, "ReflectActorsButton");
getWidget(mReflectTerrainButton, "ReflectTerrainButton");
getWidget(mShadersButton, "ShadersButton"); getWidget(mShadersButton, "ShadersButton");
getWidget(mShaderModeButton, "ShaderModeButton"); getWidget(mShaderModeButton, "ShaderModeButton");
getWidget(mShadowsEnabledButton, "ShadowsEnabledButton"); getWidget(mShadowsEnabledButton, "ShadowsEnabledButton");
getWidget(mShadowsLargeDistance, "ShadowsLargeDistance");
getWidget(mShadowsTextureSize, "ShadowsTextureSize"); getWidget(mShadowsTextureSize, "ShadowsTextureSize");
getWidget(mActorShadows, "ActorShadows");
getWidget(mStaticsShadows, "StaticsShadows");
getWidget(mMiscShadows, "MiscShadows");
getWidget(mTerrainShadows, "TerrainShadows");
getWidget(mControlsBox, "ControlsBox"); getWidget(mControlsBox, "ControlsBox");
getWidget(mResetControlsButton, "ResetControlsButton"); getWidget(mResetControlsButton, "ResetControlsButton");
getWidget(mInvertYButton, "InvertYButton");
getWidget(mCameraSensitivitySlider, "CameraSensitivitySlider");
getWidget(mRefractionButton, "RefractionButton"); getWidget(mRefractionButton, "RefractionButton");
mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mBestAttackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mGrabCursorButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mInvertYButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked);
mShadersButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadersToggled);
mShaderModeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShaderModeToggled); mShaderModeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShaderModeToggled);
mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mRefractionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mReflectObjectsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mReflectTerrainButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mReflectActorsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mTextureFilteringButton->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringChanged); mTextureFilteringButton->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringChanged);
mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled);
mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mFOVSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mToolTipDelaySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected);
mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mShadowsEnabledButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mShadowsLargeDistance->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mShadowsTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onShadowTextureSizeChanged); mShadowsTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onShadowTextureSizeChanged);
mActorShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mStaticsShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mMiscShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mTerrainShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled);
mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mEffectsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mFootstepsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mMusicVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
center(); center();
@ -194,73 +219,25 @@ namespace MWGui
mResolutionList->addItem(str); mResolutionList->addItem(str);
} }
// read settings
int menu_transparency = (mMenuTransparencySlider->getScrollRange()-1) * Settings::Manager::getFloat("menu transparency", "GUI");
mMenuTransparencySlider->setScrollPosition(menu_transparency);
int tooltip_delay = (mToolTipDelaySlider->getScrollRange()-1) * Settings::Manager::getFloat("tooltip delay", "GUI");
mToolTipDelaySlider->setScrollPosition(tooltip_delay);
mSubtitlesButton->setCaptionWithReplacing(Settings::Manager::getBool("subtitles", "GUI") ? "#{sOn}" : "#{sOff}");
mCrosshairButton->setCaptionWithReplacing(Settings::Manager::getBool("crosshair", "HUD") ? "#{sOn}" : "#{sOff}");
mBestAttackButton->setCaptionWithReplacing(Settings::Manager::getBool("best attack", "Game") ? "#{sOn}" : "#{sOff}");
mGrabCursorButton->setCaptionWithReplacing(Settings::Manager::getBool("grab cursor", "Input") ? "#{sOn}" : "#{sOff}");
float fovVal = (Settings::Manager::getFloat("field of view", "General")-sFovMin)/(sFovMax-sFovMin);
mFOVSlider->setScrollPosition(fovVal * (mFOVSlider->getScrollRange()-1));
MyGUI::TextBox* fovText;
getWidget(fovText, "FovText");
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int(Settings::Manager::getFloat("field of view", "General"))) + ")");
float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0;
mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1));
std::string tf = Settings::Manager::getString("texture filtering", "General"); std::string tf = Settings::Manager::getString("texture filtering", "General");
mTextureFilteringButton->setCaption(textureFilteringToStr(tf)); mTextureFilteringButton->setCaption(textureFilteringToStr(tf));
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(Settings::Manager::getInt("anisotropy", "General")) + ")"); mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(Settings::Manager::getInt("anisotropy", "General")) + ")");
float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-sViewDistMin)/(sViewDistMax-sViewDistMin);
int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val;
mViewDistanceSlider->setScrollPosition(viewdist);
mMasterVolumeSlider->setScrollPosition(Settings::Manager::getFloat("master volume", "Sound") * (mMasterVolumeSlider->getScrollRange()-1));
mMusicVolumeSlider->setScrollPosition(Settings::Manager::getFloat("music volume", "Sound") * (mMusicVolumeSlider->getScrollRange()-1));
mEffectsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("sfx volume", "Sound") * (mEffectsVolumeSlider->getScrollRange()-1));
mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1));
mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1));
mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}");
mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect statics", "Water") ? "#{sOn}" : "#{sOff}");
mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}");
mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}");
mShadowsTextureSize->setCaption (Settings::Manager::getString ("texture size", "Shadows")); mShadowsTextureSize->setCaption (Settings::Manager::getString ("texture size", "Shadows"));
mShadowsLargeDistance->setCaptionWithReplacing(Settings::Manager::getBool("split", "Shadows") ? "#{sOn}" : "#{sOff}");
mShadowsEnabledButton->setCaptionWithReplacing(Settings::Manager::getBool("enabled", "Shadows") ? "#{sOn}" : "#{sOff}");
mActorShadows->setCaptionWithReplacing(Settings::Manager::getBool("actor shadows", "Shadows") ? "#{sOn}" : "#{sOff}");
mStaticsShadows->setCaptionWithReplacing(Settings::Manager::getBool("statics shadows", "Shadows") ? "#{sOn}" : "#{sOff}");
mMiscShadows->setCaptionWithReplacing(Settings::Manager::getBool("misc shadows", "Shadows") ? "#{sOn}" : "#{sOff}");
mTerrainShadows->setCaptionWithReplacing(Settings::Manager::getBool("terrain shadows", "Shadows") ? "#{sOn}" : "#{sOff}");
float cameraSens = (Settings::Manager::getFloat("camera sensitivity", "Input")-0.2)/(5.0-0.2);
mCameraSensitivitySlider->setScrollPosition (cameraSens * (mCameraSensitivitySlider->getScrollRange()-1));
mCameraSensitivitySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
mInvertYButton->setCaptionWithReplacing(Settings::Manager::getBool("invert y axis", "Input") ? "#{sOn}" : "#{sOff}");
mShadersButton->setCaptionWithReplacing (Settings::Manager::getBool("shaders", "Objects") ? "#{sOn}" : "#{sOff}");
mShaderModeButton->setCaption (Settings::Manager::getString("shader mode", "General")); mShaderModeButton->setCaption (Settings::Manager::getString("shader mode", "General"));
mRefractionButton->setCaptionWithReplacing (Settings::Manager::getBool("refraction", "Water") ? "#{sOn}" : "#{sOff}");
if (!Settings::Manager::getBool("shaders", "Objects")) if (!Settings::Manager::getBool("shaders", "Objects"))
{ {
mRefractionButton->setEnabled(false); mRefractionButton->setEnabled(false);
mShadowsEnabledButton->setEnabled(false); mShadowsEnabledButton->setEnabled(false);
} }
mFullscreenButton->setCaptionWithReplacing(Settings::Manager::getBool("fullscreen", "Video") ? "#{sOn}" : "#{sOff}");
mVSyncButton->setCaptionWithReplacing(Settings::Manager::getBool("vsync", "Video") ? "#{sOn}": "#{sOff}");
mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD"))); mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD")));
MyGUI::TextBox* fovText;
getWidget(fovText, "FovText");
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int(Settings::Manager::getInt("field of view", "General"))) + ")");
} }
void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender)
@ -320,6 +297,39 @@ namespace MWGui
newState = true; newState = true;
} }
if (_sender == mVSyncButton)
{
// Ogre::Window::setVSyncEnabled is bugged in 1.8
#if OGRE_VERSION < (1 << 16 | 9 << 8 | 0)
MWBase::Environment::get().getWindowManager()->
messageBox("VSync will be applied after a restart", std::vector<std::string>());
#endif
}
if (_sender == mShadersButton)
{
if (newState == false)
{
// refraction needs shaders to display underwater fog
mRefractionButton->setCaptionWithReplacing("#{sOff}");
mRefractionButton->setEnabled(false);
Settings::Manager::setBool("refraction", "Water", false);
// shadows not supported
mShadowsEnabledButton->setEnabled(false);
mShadowsEnabledButton->setCaptionWithReplacing("#{sOff}");
Settings::Manager::setBool("enabled", "Shadows", false);
}
else
{
// re-enable
mRefractionButton->setEnabled(true);
mShadowsEnabledButton->setEnabled(true);
}
}
if (_sender == mFullscreenButton) if (_sender == mFullscreenButton)
{ {
// check if this resolution is supported in fullscreen // check if this resolution is supported in fullscreen
@ -341,64 +351,15 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()-> MWBase::Environment::get().getWindowManager()->
messageBox(msg); messageBox(msg);
_sender->castType<MyGUI::Button>()->setCaption(off); _sender->castType<MyGUI::Button>()->setCaption(off);
} return;
else
{
Settings::Manager::setBool("fullscreen", "Video", newState);
apply();
} }
} }
else if (_sender == mVSyncButton)
if (getSettingType(_sender) == checkButtonType)
{ {
Settings::Manager::setBool("vsync", "Video", newState); Settings::Manager::setBool(getSettingName(_sender), getSettingCategory(_sender), newState);
// Ogre::Window::setVSyncEnabled is bugged in 1.8
#if OGRE_VERSION < (1 << 16 | 9 << 8 | 0)
MWBase::Environment::get().getWindowManager()->
messageBox("VSync will be applied after a restart", std::vector<std::string>());
#endif
apply();
}
else
{
if (_sender == mVSyncButton)
Settings::Manager::setBool("vsync", "Video", newState);
if (_sender == mWaterShaderButton)
Settings::Manager::setBool("shader", "Water", newState);
else if (_sender == mRefractionButton)
Settings::Manager::setBool("refraction", "Water", newState);
else if (_sender == mReflectObjectsButton)
{
Settings::Manager::setBool("reflect misc", "Water", newState);
Settings::Manager::setBool("reflect statics", "Water", newState);
Settings::Manager::setBool("reflect statics small", "Water", newState);
}
else if (_sender == mReflectActorsButton)
Settings::Manager::setBool("reflect actors", "Water", newState);
else if (_sender == mReflectTerrainButton)
Settings::Manager::setBool("reflect terrain", "Water", newState);
else if (_sender == mShadowsEnabledButton)
Settings::Manager::setBool("enabled", "Shadows", newState);
else if (_sender == mShadowsLargeDistance)
Settings::Manager::setBool("split", "Shadows", newState);
else if (_sender == mActorShadows)
Settings::Manager::setBool("actor shadows", "Shadows", newState);
else if (_sender == mStaticsShadows)
Settings::Manager::setBool("statics shadows", "Shadows", newState);
else if (_sender == mMiscShadows)
Settings::Manager::setBool("misc shadows", "Shadows", newState);
else if (_sender == mTerrainShadows)
Settings::Manager::setBool("terrain shadows", "Shadows", newState);
else if (_sender == mInvertYButton)
Settings::Manager::setBool("invert y axis", "Input", newState);
else if (_sender == mCrosshairButton)
Settings::Manager::setBool("crosshair", "HUD", newState);
else if (_sender == mSubtitlesButton)
Settings::Manager::setBool("subtitles", "GUI", newState);
else if (_sender == mBestAttackButton)
Settings::Manager::setBool("best attack", "Game", newState);
else if (_sender == mGrabCursorButton)
Settings::Manager::setBool("grab cursor", "Input", newState);
apply(); apply();
return;
} }
} }
@ -419,50 +380,6 @@ namespace MWGui
apply(); apply();
} }
void SettingsWindow::onShadersToggled(MyGUI::Widget* _sender)
{
std::string on = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOn", "On");
std::string off = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOff", "On");
std::string val = static_cast<MyGUI::Button*>(_sender)->getCaption();
if (val == off)
val = on;
else
val = off;
static_cast<MyGUI::Button*>(_sender)->setCaptionWithReplacing (val);
if (val == off)
{
Settings::Manager::setBool("shaders", "Objects", false);
// refraction needs shaders to display underwater fog
mRefractionButton->setCaptionWithReplacing("#{sOff}");
mRefractionButton->setEnabled(false);
Settings::Manager::setBool("refraction", "Water", false);
Settings::Manager::setBool("underwater effect", "Water", false);
// shadows not supported
mShadowsEnabledButton->setEnabled(false);
mShadowsEnabledButton->setCaptionWithReplacing("#{sOff}");
Settings::Manager::setBool("enabled", "Shadows", false);
}
else
{
Settings::Manager::setBool("shaders", "Objects", true);
// re-enable
mReflectObjectsButton->setEnabled(true);
mReflectActorsButton->setEnabled(true);
mReflectTerrainButton->setEnabled(true);
mRefractionButton->setEnabled(true);
mShadowsEnabledButton->setEnabled(true);
}
apply();
}
void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender) void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender)
{ {
int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3; int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3;
@ -479,39 +396,34 @@ namespace MWGui
void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos) void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos)
{ {
float val = pos / float(scroller->getScrollRange()-1); if (getSettingType(scroller) == "Slider")
if (scroller == mMenuTransparencySlider)
Settings::Manager::setFloat("menu transparency", "GUI", val);
else if (scroller == mToolTipDelaySlider)
Settings::Manager::setFloat("tooltip delay", "GUI", val);
else if (scroller == mViewDistanceSlider)
Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * sViewDistMin + val * sViewDistMax);
else if (scroller == mFOVSlider)
{ {
MyGUI::TextBox* fovText; if (getSettingValueType(scroller) == "Float")
getWidget(fovText, "FovText"); {
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int((1-val) * sFovMin + val * sFovMax)) + ")"); float value = pos / float(scroller->getScrollRange()-1);
Settings::Manager::setFloat("field of view", "General", (1-val) * sFovMin + val * sFovMax);
}
else if (scroller == mAnisotropySlider)
{
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(int(val*16)) + ")");
Settings::Manager::setInt("anisotropy", "General", val * 16);
}
else if (scroller == mMasterVolumeSlider)
Settings::Manager::setFloat("master volume", "Sound", val);
else if (scroller == mVoiceVolumeSlider)
Settings::Manager::setFloat("voice volume", "Sound", val);
else if (scroller == mEffectsVolumeSlider)
Settings::Manager::setFloat("sfx volume", "Sound", val);
else if (scroller == mFootstepsVolumeSlider)
Settings::Manager::setFloat("footsteps volume", "Sound", val);
else if (scroller == mMusicVolumeSlider)
Settings::Manager::setFloat("music volume", "Sound", val);
else if (scroller == mCameraSensitivitySlider)
Settings::Manager::setFloat("camera sensitivity", "Input", (1-val) * 0.2 + val * 5.f);
apply(); float min,max;
getSettingMinMax(scroller, min, max);
value = min + (max-min) * value;
Settings::Manager::setFloat(getSettingName(scroller), getSettingCategory(scroller), value);
if (scroller == mFOVSlider)
{
MyGUI::TextBox* fovText;
getWidget(fovText, "FovText");
fovText->setCaption("Field of View (" + boost::lexical_cast<std::string>(int(value)) + ")");
}
}
else
{
Settings::Manager::setInt(getSettingName(scroller), getSettingCategory(scroller), pos);
if (scroller == mAnisotropySlider)
{
mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast<std::string>(pos) + ")");
}
}
apply();
}
} }
void SettingsWindow::apply() void SettingsWindow::apply()

View file

@ -19,61 +19,29 @@ namespace MWGui
void updateControlsBox(); void updateControlsBox();
private: protected:
static int const sFovMin = 30;
static int const sFovMax = 140;
static int const sViewDistMin = 2000;
static int const sViewDistMax = 5600;
protected:
MyGUI::Button* mOkButton; MyGUI::Button* mOkButton;
MyGUI::ScrollBar* mMenuTransparencySlider;
MyGUI::ScrollBar* mToolTipDelaySlider;
MyGUI::Button* mSubtitlesButton;
MyGUI::Button* mCrosshairButton;
MyGUI::Button* mBestAttackButton;
MyGUI::Button* mGrabCursorButton;
// graphics // graphics
MyGUI::ListBox* mResolutionList; MyGUI::ListBox* mResolutionList;
MyGUI::Button* mFullscreenButton; MyGUI::Button* mFullscreenButton;
MyGUI::Button* mVSyncButton; MyGUI::Button* mVSyncButton;
MyGUI::Button* mFPSButton; MyGUI::Button* mFPSButton;
MyGUI::ScrollBar* mViewDistanceSlider;
MyGUI::ScrollBar* mFOVSlider; MyGUI::ScrollBar* mFOVSlider;
MyGUI::ScrollBar* mAnisotropySlider; MyGUI::ScrollBar* mAnisotropySlider;
MyGUI::ComboBox* mTextureFilteringButton; MyGUI::ComboBox* mTextureFilteringButton;
MyGUI::TextBox* mAnisotropyLabel; MyGUI::TextBox* mAnisotropyLabel;
MyGUI::Widget* mAnisotropyBox; MyGUI::Widget* mAnisotropyBox;
MyGUI::Button* mWaterShaderButton;
MyGUI::Button* mReflectObjectsButton;
MyGUI::Button* mReflectActorsButton;
MyGUI::Button* mReflectTerrainButton;
MyGUI::Button* mShadersButton; MyGUI::Button* mShadersButton;
MyGUI::Button* mShaderModeButton; MyGUI::Button* mShaderModeButton;
MyGUI::Button* mRefractionButton; MyGUI::Button* mRefractionButton;
MyGUI::Button* mShadowsEnabledButton; MyGUI::Button* mShadowsEnabledButton;
MyGUI::Button* mShadowsLargeDistance;
MyGUI::ComboBox* mShadowsTextureSize; MyGUI::ComboBox* mShadowsTextureSize;
MyGUI::Button* mActorShadows;
MyGUI::Button* mStaticsShadows;
MyGUI::Button* mMiscShadows;
MyGUI::Button* mTerrainShadows;
// audio
MyGUI::ScrollBar* mMasterVolumeSlider;
MyGUI::ScrollBar* mVoiceVolumeSlider;
MyGUI::ScrollBar* mEffectsVolumeSlider;
MyGUI::ScrollBar* mFootstepsVolumeSlider;
MyGUI::ScrollBar* mMusicVolumeSlider;
// controls // controls
MyGUI::ScrollView* mControlsBox; MyGUI::ScrollView* mControlsBox;
MyGUI::Button* mResetControlsButton; MyGUI::Button* mResetControlsButton;
MyGUI::Button* mInvertYButton;
MyGUI::ScrollBar* mCameraSensitivitySlider;
void onOkButtonClicked(MyGUI::Widget* _sender); void onOkButtonClicked(MyGUI::Widget* _sender);
void onFpsToggled(MyGUI::Widget* _sender); void onFpsToggled(MyGUI::Widget* _sender);
@ -84,7 +52,6 @@ namespace MWGui
void onResolutionAccept(); void onResolutionAccept();
void onResolutionCancel(); void onResolutionCancel();
void onShadersToggled(MyGUI::Widget* _sender);
void onShaderModeToggled(MyGUI::Widget* _sender); void onShaderModeToggled(MyGUI::Widget* _sender);
void onShadowTextureSizeChanged(MyGUI::ComboBox* _sender, size_t pos); void onShadowTextureSizeChanged(MyGUI::ComboBox* _sender, size_t pos);
@ -94,6 +61,8 @@ namespace MWGui
void onResetDefaultBindingsAccept (); void onResetDefaultBindingsAccept ();
void apply(); void apply();
void configureWidgets(MyGUI::Widget* widget);
}; };
} }

View file

@ -18,8 +18,16 @@
#include "inventorywindow.hpp" #include "inventorywindow.hpp"
#include "confirmationdialog.hpp" #include "confirmationdialog.hpp"
namespace namespace MWGui
{ {
bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right)
{
int cmp = left.getClass().getName(left).compare(
right.getClass().getName(right));
return cmp < 0;
}
bool sortSpells(const std::string& left, const std::string& right) bool sortSpells(const std::string& left, const std::string& right)
{ {
const MWWorld::Store<ESM::Spell> &spells = const MWWorld::Store<ESM::Spell> &spells =
@ -32,16 +40,6 @@ namespace
return cmp < 0; return cmp < 0;
} }
bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right)
{
int cmp = MWWorld::Class::get(left).getName(left).compare(
MWWorld::Class::get(right).getName(right));
return cmp < 0;
}
}
namespace MWGui
{
SpellWindow::SpellWindow(DragAndDrop* drag) SpellWindow::SpellWindow(DragAndDrop* drag)
: WindowPinnableBase("openmw_spell_window.layout") : WindowPinnableBase("openmw_spell_window.layout")
, NoDrop(drag, mMainWidget) , NoDrop(drag, mMainWidget)

View file

@ -2,11 +2,16 @@
#define MWGUI_SPELLWINDOW_H #define MWGUI_SPELLWINDOW_H
#include "windowpinnablebase.hpp" #include "windowpinnablebase.hpp"
#include "../mwworld/ptr.hpp"
namespace MWGui namespace MWGui
{ {
class SpellIcons; class SpellIcons;
bool sortItems(const MWWorld::Ptr& left, const MWWorld::Ptr& right);
bool sortSpells(const std::string& left, const std::string& right);
class SpellWindow : public WindowPinnableBase, public NoDrop class SpellWindow : public WindowPinnableBase, public NoDrop
{ {
public: public:

View file

@ -84,8 +84,11 @@ namespace MWGui
mCurrentBalance = 0; mCurrentBalance = 0;
mCurrentMerchantOffer = 0; mCurrentMerchantOffer = 0;
checkTradeTime();
std::vector<MWWorld::Ptr> itemSources; std::vector<MWWorld::Ptr> itemSources;
MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources); MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources);
// Important: actor goes last, so that items purchased by the merchant go into his inventory // Important: actor goes last, so that items purchased by the merchant go into his inventory
itemSources.push_back(actor); itemSources.push_back(actor);
std::vector<MWWorld::Ptr> worldItems; std::vector<MWWorld::Ptr> worldItems;
@ -360,6 +363,8 @@ namespace MWGui
addOrRemoveGold(-mCurrentBalance, mPtr); addOrRemoveGold(-mCurrentBalance, mPtr);
} }
updateTradeTime();
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse( MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse(
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sBarterDialog5")->getString()); MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sBarterDialog5")->getString());
@ -474,4 +479,33 @@ namespace MWGui
} }
return merchantGold; return merchantGold;
} }
// Relates to NPC gold reset delay
void TradeWindow::checkTradeTime()
{
MWWorld::ContainerStore store = mPtr.getClass().getContainerStore(mPtr);
const MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
double delay = boost::lexical_cast<double>(MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->getInt());
// if time stamp longer than gold reset delay, reset gold.
if (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getTradeTime() + delay)
{
addOrRemoveGold(-store.count(MWWorld::ContainerStore::sGoldId), mPtr);
addOrRemoveGold(+sellerStats.getGoldPool(), mPtr);
}
}
void TradeWindow::updateTradeTime()
{
MWWorld::ContainerStore store = mPtr.getClass().getContainerStore(mPtr);
MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
double delay = boost::lexical_cast<double>(MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->getInt());
// If trade timestamp is within reset delay don't set
if ( ! (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getTradeTime() &&
MWBase::Environment::get().getWorld()->getTimeStamp() < sellerStats.getTradeTime() + delay) )
{
sellerStats.setTradeTime(MWBase::Environment::get().getWorld()->getTimeStamp());
}
}
} }

View file

@ -100,6 +100,10 @@ namespace MWGui
virtual void onReferenceUnavailable(); virtual void onReferenceUnavailable();
int getMerchantGold(); int getMerchantGold();
// Relates to NPC gold reset delay
void checkTradeTime();
void updateTradeTime();
}; };
} }

View file

@ -0,0 +1,45 @@
#include "videowidget.hpp"
namespace MWGui
{
VideoWidget::VideoWidget()
: mAllowSkipping(true)
{
eventKeyButtonPressed += MyGUI::newDelegate(this, &VideoWidget::onKeyPressed);
setNeedKeyFocus(true);
}
void VideoWidget::playVideo(const std::string &video, bool allowSkipping)
{
mAllowSkipping = allowSkipping;
mPlayer.playVideo(video);
setImageTexture(mPlayer.getTextureName());
}
int VideoWidget::getVideoWidth()
{
return mPlayer.getVideoWidth();
}
int VideoWidget::getVideoHeight()
{
return mPlayer.getVideoHeight();
}
void VideoWidget::onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char)
{
if (_key == MyGUI::KeyCode::Escape && mAllowSkipping)
mPlayer.stopVideo();
}
bool VideoWidget::update()
{
mPlayer.update();
return mPlayer.isPlaying();
}
}

View file

@ -0,0 +1,39 @@
#ifndef OPENMW_MWGUI_VIDEOWIDGET_H
#define OPENMW_MWGUI_VIDEOWIDGET_H
#include <MyGUI_ImageBox.h>
#include "../mwrender/videoplayer.hpp"
namespace MWGui
{
/**
* Widget that plays a video. Can be skipped by pressing Esc.
*/
class VideoWidget : public MyGUI::ImageBox
{
public:
MYGUI_RTTI_DERIVED(VideoWidget)
VideoWidget();
void playVideo (const std::string& video, bool allowSkipping);
int getVideoWidth();
int getVideoHeight();
/// @return Is the video still playing?
bool update();
private:
bool mAllowSkipping;
MWRender::VideoPlayer mPlayer;
void onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char);
};
}
#endif

View file

@ -4,6 +4,7 @@
#include <iterator> #include <iterator>
#include <OgreTextureManager.h> #include <OgreTextureManager.h>
#include <OgreRenderWindow.h>
#include "MyGUI_UString.h" #include "MyGUI_UString.h"
#include "MyGUI_IPointer.h" #include "MyGUI_IPointer.h"
@ -59,6 +60,7 @@
#include "bookpage.hpp" #include "bookpage.hpp"
#include "itemview.hpp" #include "itemview.hpp"
#include "fontloader.hpp" #include "fontloader.hpp"
#include "videowidget.hpp"
namespace MWGui namespace MWGui
{ {
@ -104,6 +106,8 @@ namespace MWGui
, mRecharge(NULL) , mRecharge(NULL)
, mRepair(NULL) , mRepair(NULL)
, mCompanionWindow(NULL) , mCompanionWindow(NULL)
, mVideoBackground(NULL)
, mVideoWidget(NULL)
, mTranslationDataStorage (translationDataStorage) , mTranslationDataStorage (translationDataStorage)
, mCharGen(NULL) , mCharGen(NULL)
, mInputBlocker(NULL) , mInputBlocker(NULL)
@ -155,6 +159,7 @@ namespace MWGui
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ExposedWindow>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ExposedWindow>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollView>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollView>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollBar>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollBar>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<VideoWidget>("Widget");
BookPage::registerMyGUIComponents (); BookPage::registerMyGUIComponents ();
ItemView::registerComponents(); ItemView::registerComponents();
@ -186,6 +191,13 @@ namespace MWGui
// hide mygui's pointer // hide mygui's pointer
MyGUI::PointerManager::getInstance().setVisible(false); MyGUI::PointerManager::getInstance().setVisible(false);
mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal<MyGUI::ImageBox>("ImageBox", 0,0,1,1,
MyGUI::Align::Default, "Overlay");
mVideoBackground->setImageTexture("black.png");
mVideoBackground->setVisible(false);
mVideoWidget = mVideoBackground->createWidgetReal<VideoWidget>("ImageBox", 0,0,1,1, MyGUI::Align::Default);
} }
void WindowManager::initUI() void WindowManager::initUI()
@ -391,6 +403,7 @@ namespace MWGui
mCompanionWindow->setVisible(false); mCompanionWindow->setVisible(false);
mInventoryWindow->setTrading(false); mInventoryWindow->setTrading(false);
mRecharge->setVisible(false); mRecharge->setVisible(false);
mVideoBackground->setVisible(false);
mHud->setVisible(mHudEnabled); mHud->setVisible(mHudEnabled);
@ -539,10 +552,6 @@ namespace MWGui
setCursorVisible(false); setCursorVisible(false);
break; break;
case GM_Video:
setCursorVisible(false);
mHud->setVisible(false);
break;
default: default:
// Unsupported mode, switch back to game // Unsupported mode, switch back to game
break; break;
@ -894,6 +903,7 @@ namespace MWGui
void WindowManager::windowResized(int x, int y) void WindowManager::windowResized(int x, int y)
{ {
sizeVideo(x, y);
mGuiManager->windowResized(); mGuiManager->windowResized();
mLoadingScreen->onResChange (x,y); mLoadingScreen->onResChange (x,y);
if (!mHud) if (!mHud)
@ -1401,4 +1411,57 @@ namespace MWGui
mMap->readRecord(reader, type); mMap->readRecord(reader, type);
} }
void WindowManager::playVideo(const std::string &name, bool allowSkipping)
{
mVideoWidget->playVideo("video\\" + name, allowSkipping);
// Turn off all rendering except for the GUI
mRendering->getScene()->clearSpecialCaseRenderQueues();
// SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work?
for(int i = 0;i < Ogre::RENDER_QUEUE_MAX;++i)
{
if(i > 0 && i < 96)
mRendering->getScene()->addSpecialCaseRenderQueue(i);
}
mRendering->getScene()->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize();
sizeVideo(screenSize.width, screenSize.height);
setKeyFocusWidget(mVideoWidget);
mVideoBackground->setVisible(true);
bool cursorWasVisible = mCursorVisible;
setCursorVisible(false);
while (mVideoWidget->update())
{
MWBase::Environment::get().getInputManager()->update(0, true, false);
mRendering->getWindow()->update();
}
setCursorVisible(cursorWasVisible);
// Restore normal rendering
mRendering->getScene()->clearSpecialCaseRenderQueues();
mRendering->getScene()->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE);
mVideoBackground->setVisible(false);
}
void WindowManager::sizeVideo(int screenWidth, int screenHeight)
{
// Use black bars to correct aspect ratio
mVideoBackground->setSize(screenWidth, screenHeight);
double imageaspect = static_cast<double>(mVideoWidget->getVideoWidth())/mVideoWidget->getVideoHeight();
int leftPadding = std::max(0.0, (screenWidth - screenHeight * imageaspect) / 2);
int topPadding = std::max(0.0, (screenHeight - screenWidth / imageaspect) / 2);
mVideoWidget->setCoord(leftPadding, topPadding,
screenWidth - leftPadding*2, screenHeight - topPadding*2);
}
} }

View file

@ -18,6 +18,7 @@ namespace MyGUI
class Widget; class Widget;
class Window; class Window;
class UString; class UString;
class ImageBox;
} }
namespace Compiler namespace Compiler
@ -80,6 +81,7 @@ namespace MWGui
class SoulgemDialog; class SoulgemDialog;
class Recharge; class Recharge;
class CompanionWindow; class CompanionWindow;
class VideoWidget;
class WindowManager : public MWBase::WindowManager class WindowManager : public MWBase::WindowManager
{ {
@ -98,6 +100,10 @@ namespace MWGui
virtual Loading::Listener* getLoadingScreen(); virtual Loading::Listener* getLoadingScreen();
/// @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);
/** /**
* Should be called each frame to update windows/gui elements. * Should be called each frame to update windows/gui elements.
* This could mean updating sizes of gui elements or opening * This could mean updating sizes of gui elements or opening
@ -332,6 +338,8 @@ namespace MWGui
Repair* mRepair; Repair* mRepair;
Recharge* mRecharge; Recharge* mRecharge;
CompanionWindow* mCompanionWindow; CompanionWindow* mCompanionWindow;
MyGUI::ImageBox* mVideoBackground;
VideoWidget* mVideoWidget;
Translation::Storage& mTranslationDataStorage; Translation::Storage& mTranslationDataStorage;
Cursor* mSoftwareCursor; Cursor* mSoftwareCursor;
@ -390,6 +398,8 @@ namespace MWGui
void onCursorChange(const std::string& name); void onCursorChange(const std::string& name);
void onKeyFocusChanged(MyGUI::Widget* widget); void onKeyFocusChanged(MyGUI::Widget* widget);
void sizeVideo(int screenWidth, int screenHeight);
}; };
} }

View file

@ -96,12 +96,12 @@ namespace MWInput
: mOgre(ogre) : mOgre(ogre)
, mPlayer(NULL) , mPlayer(NULL)
, mEngine(engine) , mEngine(engine)
, mMouseLookEnabled(true) , mMouseLookEnabled(false)
, mMouseX(ogre.getWindow()->getWidth ()/2.f) , mMouseX(ogre.getWindow()->getWidth ()/2.f)
, mMouseY(ogre.getWindow()->getHeight ()/2.f) , mMouseY(ogre.getWindow()->getHeight ()/2.f)
, mMouseWheel(0) , mMouseWheel(0)
, mDragDrop(false) , mDragDrop(false)
, mGuiCursorEnabled(false) , mGuiCursorEnabled(true)
, mUserFile(userFile) , mUserFile(userFile)
, mUserFileExists(userFileExists) , mUserFileExists(userFileExists)
, mInvertY (Settings::Manager::getBool("invert y axis", "Input")) , mInvertY (Settings::Manager::getBool("invert y axis", "Input"))
@ -256,18 +256,21 @@ namespace MWInput
} }
} }
void InputManager::update(float dt, bool loading) void InputManager::update(float dt, bool disableControls, bool disableEvents)
{ {
mInputManager->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible()); mInputManager->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible());
mInputManager->capture(loading); mInputManager->capture(disableEvents);
// inject some fake mouse movement to force updating MyGUI's widget states // inject some fake mouse movement to force updating MyGUI's widget states
MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel); MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel);
// update values of channels (as a result of pressed keys) // update values of channels (as a result of pressed keys)
if (!loading) if (!disableControls)
mInputBinder->update(dt); mInputBinder->update(dt);
if (disableControls)
return;
bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)
&& MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console; && MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console;
@ -288,9 +291,6 @@ namespace MWInput
mInputManager->warpMouse(mMouseX, mMouseY); mInputManager->warpMouse(mMouseX, mMouseY);
} }
if (loading)
return;
// Disable movement in Gui mode // Disable movement in Gui mode
if (MWBase::Environment::get().getWindowManager()->isGuiMode() if (MWBase::Environment::get().getWindowManager()->isGuiMode()
|| MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running) || MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running)
@ -626,9 +626,7 @@ namespace MWInput
if (MyGUI::InputManager::getInstance ().isModalAny()) if (MyGUI::InputManager::getInstance ().isModalAny())
return; return;
if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video) if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
MWBase::Environment::get().getWorld ()->stopVideo ();
else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
{ {
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx); MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx);

View file

@ -68,7 +68,7 @@ namespace MWInput
/// Clear all savegame-specific data /// Clear all savegame-specific data
virtual void clear(); virtual void clear();
virtual void update(float dt, bool loading); virtual void update(float dt, bool disableControls, bool disableEvents=false);
void setPlayer (MWWorld::Player* player) { mPlayer = player; } void setPlayer (MWWorld::Player* player) { mPlayer = player; }

View file

@ -10,16 +10,6 @@
#include "steering.hpp" #include "steering.hpp"
#include "movement.hpp" #include "movement.hpp"
namespace
{
float sgn(float a)
{
if(a > 0)
return 1.0;
return -1.0;
}
}
MWMechanics::AiActivate::AiActivate(const std::string &objectId) MWMechanics::AiActivate::AiActivate(const std::string &objectId)
: mObjectId(objectId) : mObjectId(objectId)
{ {
@ -38,7 +28,7 @@ bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration)
MWWorld::Ptr player = world->getPlayerPtr(); MWWorld::Ptr player = world->getPlayerPtr();
if(cell->mData.mX != player.getCell()->getCell()->mData.mX) if(cell->mData.mX != player.getCell()->getCell()->mData.mX)
{ {
int sideX = sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX);
//check if actor is near the border of an inactive cell. If so, stop walking. //check if actor is near the border of an inactive cell. If so, stop walking.
if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) >
sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
@ -49,7 +39,7 @@ bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor,float duration)
} }
if(cell->mData.mY != player.getCell()->getCell()->mData.mY) if(cell->mData.mY != player.getCell()->getCell()->mData.mY)
{ {
int sideY = sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY);
//check if actor is near the border of an inactive cell. If so, stop walking. //check if actor is near the border of an inactive cell. If so, stop walking.
if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) >
sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f))

View file

@ -11,16 +11,6 @@
#include "steering.hpp" #include "steering.hpp"
#include "movement.hpp" #include "movement.hpp"
namespace
{
float sgn(float a)
{
if(a > 0)
return 1.0;
return -1.0;
}
}
/* /*
TODO: Test vanilla behavior on passing x0, y0, and z0 with duration of anything including 0. TODO: Test vanilla behavior on passing x0, y0, and z0 with duration of anything including 0.
TODO: Different behavior for AIEscort a d x y z and AIEscortCell a c d x y z. TODO: Different behavior for AIEscort a d x y z and AIEscortCell a c d x y z.
@ -91,7 +81,7 @@ namespace MWMechanics
if(actor.getCell()->getCell()->mData.mX != player.getCell()->getCell()->mData.mX) if(actor.getCell()->getCell()->mData.mX != player.getCell()->getCell()->mData.mX)
{ {
int sideX = sgn(actor.getCell()->getCell()->mData.mX - player.getCell()->getCell()->mData.mX); int sideX = PathFinder::sgn(actor.getCell()->getCell()->mData.mX - player.getCell()->getCell()->mData.mX);
// Check if actor is near the border of an inactive cell. If so, pause walking. // Check if actor is near the border of an inactive cell. If so, pause walking.
if(sideX * (pos.pos[0] - actor.getCell()->getCell()->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE / if(sideX * (pos.pos[0] - actor.getCell()->getCell()->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE /
2.0 - 200)) 2.0 - 200))
@ -102,7 +92,7 @@ namespace MWMechanics
} }
if(actor.getCell()->getCell()->mData.mY != player.getCell()->getCell()->mData.mY) if(actor.getCell()->getCell()->mData.mY != player.getCell()->getCell()->mData.mY)
{ {
int sideY = sgn(actor.getCell()->getCell()->mData.mY - player.getCell()->getCell()->mData.mY); int sideY = PathFinder::sgn(actor.getCell()->getCell()->mData.mY - player.getCell()->getCell()->mData.mY);
// Check if actor is near the border of an inactive cell. If so, pause walking. // Check if actor is near the border of an inactive cell. If so, pause walking.
if(sideY*(pos.pos[1] - actor.getCell()->getCell()->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE / if(sideY*(pos.pos[1] - actor.getCell()->getCell()->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE /
2.0 - 200)) 2.0 - 200))

View file

@ -9,16 +9,6 @@
#include "steering.hpp" #include "steering.hpp"
#include "movement.hpp" #include "movement.hpp"
namespace
{
float sgn(float a)
{
if(a > 0)
return 1.0;
return -1.0;
}
}
namespace MWMechanics namespace MWMechanics
{ {
AiTravel::AiTravel(float x, float y, float z) AiTravel::AiTravel(float x, float y, float z)
@ -43,7 +33,7 @@ namespace MWMechanics
MWWorld::Ptr player = world->getPlayerPtr(); MWWorld::Ptr player = world->getPlayerPtr();
if(cell->mData.mX != player.getCell()->getCell()->mData.mX) if(cell->mData.mX != player.getCell()->getCell()->mData.mX)
{ {
int sideX = sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX);
//check if actor is near the border of an inactive cell. If so, stop walking. //check if actor is near the border of an inactive cell. If so, stop walking.
if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) >
sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
@ -54,7 +44,7 @@ namespace MWMechanics
} }
if(cell->mData.mY != player.getCell()->getCell()->mData.mY) if(cell->mData.mY != player.getCell()->getCell()->mData.mY)
{ {
int sideY = sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY);
//check if actor is near the border of an inactive cell. If so, stop walking. //check if actor is near the border of an inactive cell. If so, stop walking.
if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) >
sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f))

View file

@ -15,16 +15,6 @@
#include "steering.hpp" #include "steering.hpp"
#include "movement.hpp" #include "movement.hpp"
namespace
{
float sgn(float a)
{
if(a > 0)
return 1.0;
return -1.0;
}
}
namespace MWMechanics namespace MWMechanics
{ {
// NOTE: determined empirically but probably need further tweaking // NOTE: determined empirically but probably need further tweaking

View file

@ -414,6 +414,16 @@ void CharacterController::playRandomDeath(float startpoint)
mDeathState = CharState_SwimDeath; mDeathState = CharState_SwimDeath;
mCurrentDeath = "swimdeath"; mCurrentDeath = "swimdeath";
} }
else if (mHitState == CharState_KnockDown)
{
mDeathState = CharState_DeathKnockDown;
mCurrentDeath = "deathknockdown";
}
else if (mHitState == CharState_KnockOut)
{
mDeathState = CharState_DeathKnockOut;
mCurrentDeath = "deathknockout";
}
else else
{ {
int selected=0; int selected=0;
@ -1245,12 +1255,8 @@ void CharacterController::update(float duration)
else //avoid z-rotating for knockdown else //avoid z-rotating for knockdown
world->rotateObject(mPtr, rot.x, rot.y, 0.0f, true); world->rotateObject(mPtr, rot.x, rot.y, 0.0f, true);
// always control actual movement by animation unless this: if (mMovementAnimVelocity == 0)
// FIXME: actor falling/landing should be controlled by physics engine
if(mMovementAnimVelocity == 0.0f && (vec.length() > 0.0f || mJumpState != JumpState_None))
{
world->queueMovement(mPtr, vec); world->queueMovement(mPtr, vec);
}
} }
movement = vec; movement = vec;
@ -1290,7 +1296,7 @@ void CharacterController::update(float duration)
} }
// Update movement // Update movement
if(moved.squaredLength() > 1.0f) if(mMovementAnimVelocity > 0)
world->queueMovement(mPtr, moved); world->queueMovement(mPtr, moved);
} }
mSkipAnim = false; mSkipAnim = false;

View file

@ -90,6 +90,8 @@ enum CharacterState {
CharState_Death4, CharState_Death4,
CharState_Death5, CharState_Death5,
CharState_SwimDeath, CharState_SwimDeath,
CharState_DeathKnockDown,
CharState_DeathKnockOut,
CharState_Hit, CharState_Hit,
CharState_KnockDown, CharState_KnockDown,

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