forked from teamnwah/openmw-tes3coop
Merged files
This commit is contained in:
commit
a65e8393bb
202 changed files with 2956 additions and 1738 deletions
|
@ -86,8 +86,6 @@ option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock fram
|
||||||
|
|
||||||
# Sound source selection
|
# Sound source selection
|
||||||
option(USE_FFMPEG "use ffmpeg for sound" ON)
|
option(USE_FFMPEG "use ffmpeg for sound" ON)
|
||||||
option(USE_AUDIERE "use audiere for sound" ON)
|
|
||||||
option(USE_MPG123 "use mpg123 + libsndfile for sound" ON)
|
|
||||||
|
|
||||||
# OS X deployment
|
# OS X deployment
|
||||||
option(OPENMW_OSX_DEPLOYMENT OFF)
|
option(OPENMW_OSX_DEPLOYMENT OFF)
|
||||||
|
@ -171,27 +169,6 @@ if (USE_FFMPEG)
|
||||||
endif (FFMPEG_FOUND)
|
endif (FFMPEG_FOUND)
|
||||||
endif (USE_FFMPEG)
|
endif (USE_FFMPEG)
|
||||||
|
|
||||||
if (USE_AUDIERE AND NOT GOT_SOUND_INPUT)
|
|
||||||
find_package(Audiere)
|
|
||||||
if (AUDIERE_FOUND)
|
|
||||||
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${AUDIERE_INCLUDE_DIR})
|
|
||||||
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${AUDIERE_LIBRARY})
|
|
||||||
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_AUDIERE)
|
|
||||||
set(GOT_SOUND_INPUT 1)
|
|
||||||
endif (AUDIERE_FOUND)
|
|
||||||
endif (USE_AUDIERE AND NOT GOT_SOUND_INPUT)
|
|
||||||
|
|
||||||
if (USE_MPG123 AND NOT GOT_SOUND_INPUT)
|
|
||||||
find_package(MPG123 REQUIRED)
|
|
||||||
find_package(SNDFILE REQUIRED)
|
|
||||||
if (MPG123_FOUND AND SNDFILE_FOUND)
|
|
||||||
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
|
|
||||||
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${MPG123_LIBRARY} ${SNDFILE_LIBRARY})
|
|
||||||
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_MPG123)
|
|
||||||
set(GOT_SOUND_INPUT 1)
|
|
||||||
endif (MPG123_FOUND AND SNDFILE_FOUND)
|
|
||||||
endif (USE_MPG123 AND NOT GOT_SOUND_INPUT)
|
|
||||||
|
|
||||||
if (NOT GOT_SOUND_INPUT)
|
if (NOT GOT_SOUND_INPUT)
|
||||||
message(WARNING "--------------------")
|
message(WARNING "--------------------")
|
||||||
message(WARNING "Failed to find any sound input packages")
|
message(WARNING "Failed to find any sound input packages")
|
||||||
|
@ -434,7 +411,6 @@ IF(NOT WIN32 AND NOT APPLE)
|
||||||
|
|
||||||
# Install licenses
|
# Install licenses
|
||||||
INSTALL(FILES "DejaVu Font License.txt" DESTINATION "${LICDIR}" )
|
INSTALL(FILES "DejaVu Font License.txt" DESTINATION "${LICDIR}" )
|
||||||
INSTALL(FILES "OFL.txt" DESTINATION "${LICDIR}" )
|
|
||||||
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
|
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
|
||||||
ENDIF (DPKG_PROGRAM)
|
ENDIF (DPKG_PROGRAM)
|
||||||
|
|
||||||
|
|
|
@ -333,7 +333,7 @@ int load(Arguments& info)
|
||||||
|
|
||||||
// Is the user interested in this record type?
|
// Is the user interested in this record type?
|
||||||
bool interested = true;
|
bool interested = true;
|
||||||
if (info.types.size() > 0)
|
if (!info.types.empty())
|
||||||
{
|
{
|
||||||
std::vector<std::string>::iterator match;
|
std::vector<std::string>::iterator match;
|
||||||
match = std::find(info.types.begin(), info.types.end(),
|
match = std::find(info.types.begin(), info.types.end(),
|
||||||
|
|
|
@ -124,7 +124,7 @@ void printEffectList(ESM::EffectList effects)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
std::vector<ESM::ENAMstruct>::iterator eit;
|
std::vector<ESM::ENAMstruct>::iterator eit;
|
||||||
for (eit = effects.mList.begin(); eit != effects.mList.end(); eit++)
|
for (eit = effects.mList.begin(); eit != effects.mList.end(); ++eit)
|
||||||
{
|
{
|
||||||
std::cout << " Effect[" << i << "]: " << magicEffectLabel(eit->mEffectID)
|
std::cout << " Effect[" << i << "]: " << magicEffectLabel(eit->mEffectID)
|
||||||
<< " (" << eit->mEffectID << ")" << std::endl;
|
<< " (" << eit->mEffectID << ")" << std::endl;
|
||||||
|
|
|
@ -214,13 +214,13 @@ QStringList Launcher::GraphicsPage::getAvailableOptions(const QString &key, Ogre
|
||||||
uint row = 0;
|
uint row = 0;
|
||||||
Ogre::ConfigOptionMap options = renderer->getConfigOptions();
|
Ogre::ConfigOptionMap options = renderer->getConfigOptions();
|
||||||
|
|
||||||
for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); i++, row++)
|
for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); ++i, ++row)
|
||||||
{
|
{
|
||||||
Ogre::StringVector::iterator opt_it;
|
Ogre::StringVector::iterator opt_it;
|
||||||
uint idx = 0;
|
uint idx = 0;
|
||||||
|
|
||||||
for (opt_it = i->second.possibleValues.begin();
|
for (opt_it = i->second.possibleValues.begin();
|
||||||
opt_it != i->second.possibleValues.end(); opt_it++, idx++)
|
opt_it != i->second.possibleValues.end(); ++opt_it, ++idx)
|
||||||
{
|
{
|
||||||
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) {
|
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) {
|
||||||
result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified();
|
result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified();
|
||||||
|
|
|
@ -60,7 +60,7 @@ opencs_hdrs_noqt (view/doc
|
||||||
opencs_units (view/world
|
opencs_units (view/world
|
||||||
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
||||||
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
|
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
|
||||||
scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap
|
scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units (view/render
|
opencs_units (view/render
|
||||||
|
@ -95,7 +95,9 @@ opencs_units (view/settings
|
||||||
booleanview
|
booleanview
|
||||||
textview
|
textview
|
||||||
listview
|
listview
|
||||||
|
rangeview
|
||||||
resizeablestackedwidget
|
resizeablestackedwidget
|
||||||
|
spinbox
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (view/settings
|
opencs_units_noqt (view/settings
|
||||||
|
|
|
@ -121,7 +121,7 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
||||||
//iterate the data directories and add them to the file dialog for loading
|
//iterate the data directories and add them to the file dialog for loading
|
||||||
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);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,29 +1,22 @@
|
||||||
#include "setting.hpp"
|
#include "setting.hpp"
|
||||||
#include "support.hpp"
|
#include "support.hpp"
|
||||||
|
|
||||||
CSMSettings::Setting::Setting()
|
|
||||||
{
|
|
||||||
buildDefaultSetting();
|
|
||||||
}
|
|
||||||
|
|
||||||
CSMSettings::Setting::Setting(SettingType typ, const QString &settingName,
|
CSMSettings::Setting::Setting(SettingType typ, const QString &settingName,
|
||||||
const QString &pageName, const QStringList &values)
|
const QString &pageName)
|
||||||
: mIsEditorSetting (false)
|
: mIsEditorSetting (false)
|
||||||
{
|
{
|
||||||
buildDefaultSetting();
|
buildDefaultSetting();
|
||||||
|
|
||||||
int vType = static_cast <int> (typ);
|
int settingType = static_cast <int> (typ);
|
||||||
|
|
||||||
if ((vType % 2) == 0)
|
//even-numbered setting types are multi-valued
|
||||||
setProperty (Property_IsMultiValue,
|
if ((settingType % 2) == 0)
|
||||||
QVariant(true).toString());
|
setProperty (Property_IsMultiValue, QVariant(true).toString());
|
||||||
else
|
|
||||||
vType--;
|
|
||||||
|
|
||||||
setProperty (Property_ViewType, QVariant (vType / 2).toString());
|
//view type is related to setting type by an order of magnitude
|
||||||
|
setProperty (Property_SettingType, QVariant (settingType).toString());
|
||||||
setProperty (Property_Page, pageName);
|
setProperty (Property_Page, pageName);
|
||||||
setProperty (Property_Name, settingName);
|
setProperty (Property_Name, settingName);
|
||||||
setProperty (Property_DeclaredValues, values);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMSettings::Setting::buildDefaultSetting()
|
void CSMSettings::Setting::buildDefaultSetting()
|
||||||
|
@ -74,6 +67,11 @@ int CSMSettings::Setting::columnSpan() const
|
||||||
return property (Property_ColumnSpan).at(0).toInt();
|
return property (Property_ColumnSpan).at(0).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setDeclaredValues (QStringList list)
|
||||||
|
{
|
||||||
|
setProperty (Property_DeclaredValues, list);
|
||||||
|
}
|
||||||
|
|
||||||
QStringList CSMSettings::Setting::declaredValues() const
|
QStringList CSMSettings::Setting::declaredValues() const
|
||||||
{
|
{
|
||||||
return property (Property_DeclaredValues);
|
return property (Property_DeclaredValues);
|
||||||
|
@ -97,6 +95,16 @@ QStringList CSMSettings::Setting::property (SettingProperty prop) const
|
||||||
return mProperties.at(prop);
|
return mProperties.at(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setDefaultValue (int value)
|
||||||
|
{
|
||||||
|
setDefaultValues (QStringList() << QVariant (value).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setDefaultValue (double value)
|
||||||
|
{
|
||||||
|
setDefaultValues (QStringList() << QVariant (value).toString());
|
||||||
|
}
|
||||||
|
|
||||||
void CSMSettings::Setting::setDefaultValue (const QString &value)
|
void CSMSettings::Setting::setDefaultValue (const QString &value)
|
||||||
{
|
{
|
||||||
setDefaultValues (QStringList() << value);
|
setDefaultValues (QStringList() << value);
|
||||||
|
@ -166,6 +174,16 @@ bool CSMSettings::Setting::serializable() const
|
||||||
return (property (Property_Serializable).at(0) == "true");
|
return (property (Property_Serializable).at(0) == "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setSpecialValueText(const QString &text)
|
||||||
|
{
|
||||||
|
setProperty (Property_SpecialValueText, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::specialValueText() const
|
||||||
|
{
|
||||||
|
return property (Property_SpecialValueText).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
void CSMSettings::Setting::setName (const QString &value)
|
void CSMSettings::Setting::setName (const QString &value)
|
||||||
{
|
{
|
||||||
setProperty (Property_Name, value);
|
setProperty (Property_Name, value);
|
||||||
|
@ -186,6 +204,16 @@ QString CSMSettings::Setting::page() const
|
||||||
return property (Property_Page).at(0);
|
return property (Property_Page).at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setPrefix (const QString &value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Prefix, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::prefix() const
|
||||||
|
{
|
||||||
|
return property (Property_Prefix).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
void CSMSettings::Setting::setRowSpan (const int value)
|
void CSMSettings::Setting::setRowSpan (const int value)
|
||||||
{
|
{
|
||||||
setProperty (Property_RowSpan, value);
|
setProperty (Property_RowSpan, value);
|
||||||
|
@ -196,15 +224,106 @@ int CSMSettings::Setting::rowSpan () const
|
||||||
return property (Property_RowSpan).at(0).toInt();
|
return property (Property_RowSpan).at(0).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMSettings::Setting::setViewType (int vType)
|
void CSMSettings::Setting::setSingleStep (int value)
|
||||||
{
|
{
|
||||||
setProperty (Property_ViewType, vType);
|
setProperty (Property_SingleStep, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setSingleStep (double value)
|
||||||
|
{
|
||||||
|
setProperty (Property_SingleStep, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::singleStep() const
|
||||||
|
{
|
||||||
|
return property (Property_SingleStep).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setSuffix (const QString &value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Suffix, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::suffix() const
|
||||||
|
{
|
||||||
|
return property (Property_Suffix).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setTickInterval (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_TickInterval, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMSettings::Setting::tickInterval () const
|
||||||
|
{
|
||||||
|
return property (Property_TickInterval).at(0).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setTicksAbove (bool state)
|
||||||
|
{
|
||||||
|
setProperty (Property_TicksAbove, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Setting::ticksAbove() const
|
||||||
|
{
|
||||||
|
return (property (Property_TicksAbove).at(0) == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setTicksBelow (bool state)
|
||||||
|
{
|
||||||
|
setProperty (Property_TicksBelow, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Setting::ticksBelow() const
|
||||||
|
{
|
||||||
|
return (property (Property_TicksBelow).at(0) == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setType (int settingType)
|
||||||
|
{
|
||||||
|
setProperty (Property_SettingType, settingType);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMSettings::SettingType CSMSettings::Setting::type() const
|
||||||
|
{
|
||||||
|
return static_cast <CSMSettings::SettingType> ( property (
|
||||||
|
Property_SettingType).at(0).toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setMaximum (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Maximum, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setMaximum (double value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Maximum, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::maximum() const
|
||||||
|
{
|
||||||
|
return property (Property_Maximum).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setMinimum (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Minimum, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setMinimum (double value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Minimum, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::minimum() const
|
||||||
|
{
|
||||||
|
return property (Property_Minimum).at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVSettings::ViewType CSMSettings::Setting::viewType() const
|
CSVSettings::ViewType CSMSettings::Setting::viewType() const
|
||||||
{
|
{
|
||||||
return static_cast <CSVSettings::ViewType>
|
return static_cast <CSVSettings::ViewType> ( property (
|
||||||
(property(Property_ViewType).at(0).toInt());
|
Property_SettingType).at(0).toInt() / 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMSettings::Setting::setViewColumn (int value)
|
void CSMSettings::Setting::setViewColumn (int value)
|
||||||
|
@ -242,6 +361,17 @@ int CSMSettings::Setting::widgetWidth() const
|
||||||
{
|
{
|
||||||
return property (Property_WidgetWidth).at(0).toInt();
|
return property (Property_WidgetWidth).at(0).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setWrapping (bool state)
|
||||||
|
{
|
||||||
|
setProperty (Property_Wrapping, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Setting::wrapping() const
|
||||||
|
{
|
||||||
|
return (property (Property_Wrapping).at(0) == "true");
|
||||||
|
}
|
||||||
|
|
||||||
void CSMSettings::Setting::setProperty (SettingProperty prop, bool value)
|
void CSMSettings::Setting::setProperty (SettingProperty prop, bool value)
|
||||||
{
|
{
|
||||||
setProperty (prop, QStringList() << QVariant (value).toString());
|
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||||
|
@ -252,6 +382,11 @@ void CSMSettings::Setting::setProperty (SettingProperty prop, int value)
|
||||||
setProperty (prop, QStringList() << QVariant (value).toString());
|
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setProperty (SettingProperty prop, double value)
|
||||||
|
{
|
||||||
|
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||||
|
}
|
||||||
|
|
||||||
void CSMSettings::Setting::setProperty (SettingProperty prop,
|
void CSMSettings::Setting::setProperty (SettingProperty prop,
|
||||||
const QString &value)
|
const QString &value)
|
||||||
{
|
{
|
||||||
|
@ -264,18 +399,3 @@ void CSMSettings::Setting::setProperty (SettingProperty prop,
|
||||||
if (prop < mProperties.size())
|
if (prop < mProperties.size())
|
||||||
mProperties.replace (prop, value);
|
mProperties.replace (prop, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream &operator <<(QDataStream &stream, const CSMSettings::Setting& setting)
|
|
||||||
{
|
|
||||||
stream << setting.properties();
|
|
||||||
|
|
||||||
stream << setting.proxies();
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDataStream &operator >>(QDataStream& stream, CSMSettings::Setting& setting)
|
|
||||||
{
|
|
||||||
// stream >> setting.properties();
|
|
||||||
// stream >> setting.proxies();
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,12 +27,8 @@ namespace CSMSettings
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
explicit Setting();
|
|
||||||
|
|
||||||
explicit Setting(SettingType typ, const QString &settingName,
|
explicit Setting(SettingType typ, const QString &settingName,
|
||||||
const QString &pageName,
|
const QString &pageName);
|
||||||
const QStringList &values = QStringList());
|
|
||||||
|
|
||||||
void addProxy (const Setting *setting, const QStringList &vals);
|
void addProxy (const Setting *setting, const QStringList &vals);
|
||||||
void addProxy (const Setting *setting, const QList <QStringList> &list);
|
void addProxy (const Setting *setting, const QList <QStringList> &list);
|
||||||
|
@ -49,6 +45,8 @@ namespace CSMSettings
|
||||||
void setDefinedValues (QStringList list);
|
void setDefinedValues (QStringList list);
|
||||||
QStringList definedValues() const;
|
QStringList definedValues() const;
|
||||||
|
|
||||||
|
void setDefaultValue (int value);
|
||||||
|
void setDefaultValue (double value);
|
||||||
void setDefaultValue (const QString &value);
|
void setDefaultValue (const QString &value);
|
||||||
|
|
||||||
void setDefaultValues (const QStringList &values);
|
void setDefaultValues (const QStringList &values);
|
||||||
|
@ -66,12 +64,26 @@ namespace CSMSettings
|
||||||
void setIsMultiValue (bool state);
|
void setIsMultiValue (bool state);
|
||||||
bool isMultiValue() const;
|
bool isMultiValue() const;
|
||||||
|
|
||||||
|
void setMask (const QString &value);
|
||||||
|
QString mask() const;
|
||||||
|
|
||||||
|
void setMaximum (int value);
|
||||||
|
void setMaximum (double value);
|
||||||
|
QString maximum() const;
|
||||||
|
|
||||||
|
void setMinimum (int value);
|
||||||
|
void setMinimum (double value);
|
||||||
|
QString minimum() const;
|
||||||
|
|
||||||
void setName (const QString &value);
|
void setName (const QString &value);
|
||||||
QString name() const;
|
QString name() const;
|
||||||
|
|
||||||
void setPage (const QString &value);
|
void setPage (const QString &value);
|
||||||
QString page() const;
|
QString page() const;
|
||||||
|
|
||||||
|
void setPrefix (const QString &value);
|
||||||
|
QString prefix() const;
|
||||||
|
|
||||||
void setRowSpan (const int value);
|
void setRowSpan (const int value);
|
||||||
int rowSpan() const;
|
int rowSpan() const;
|
||||||
|
|
||||||
|
@ -80,6 +92,25 @@ namespace CSMSettings
|
||||||
void setSerializable (bool state);
|
void setSerializable (bool state);
|
||||||
bool serializable() const;
|
bool serializable() const;
|
||||||
|
|
||||||
|
void setSpecialValueText (const QString &text);
|
||||||
|
QString specialValueText() const;
|
||||||
|
|
||||||
|
void setSingleStep (int value);
|
||||||
|
void setSingleStep (double value);
|
||||||
|
QString singleStep() const;
|
||||||
|
|
||||||
|
void setSuffix (const QString &value);
|
||||||
|
QString suffix() const;
|
||||||
|
|
||||||
|
void setTickInterval (int value);
|
||||||
|
int tickInterval() const;
|
||||||
|
|
||||||
|
void setTicksAbove (bool state);
|
||||||
|
bool ticksAbove() const;
|
||||||
|
|
||||||
|
void setTicksBelow (bool state);
|
||||||
|
bool ticksBelow() const;
|
||||||
|
|
||||||
void setViewColumn (int value);
|
void setViewColumn (int value);
|
||||||
int viewColumn() const;
|
int viewColumn() const;
|
||||||
|
|
||||||
|
@ -88,9 +119,14 @@ namespace CSMSettings
|
||||||
void setViewRow (int value);
|
void setViewRow (int value);
|
||||||
int viewRow() const;
|
int viewRow() const;
|
||||||
|
|
||||||
void setViewType (int vType);
|
void setType (int settingType);
|
||||||
|
CSMSettings::SettingType type() const;
|
||||||
|
|
||||||
CSVSettings::ViewType viewType() const;
|
CSVSettings::ViewType viewType() const;
|
||||||
|
|
||||||
|
void setWrapping (bool state);
|
||||||
|
bool wrapping() const;
|
||||||
|
|
||||||
void setWidgetWidth (int value);
|
void setWidgetWidth (int value);
|
||||||
int widgetWidth() const;
|
int widgetWidth() const;
|
||||||
|
|
||||||
|
@ -100,6 +136,7 @@ namespace CSMSettings
|
||||||
///boilerplate code to convert setting values of common types
|
///boilerplate code to convert setting values of common types
|
||||||
void setProperty (SettingProperty prop, bool value);
|
void setProperty (SettingProperty prop, bool value);
|
||||||
void setProperty (SettingProperty prop, int value);
|
void setProperty (SettingProperty prop, int value);
|
||||||
|
void setProperty (SettingProperty prop, double value);
|
||||||
void setProperty (SettingProperty prop, const QString &value);
|
void setProperty (SettingProperty prop, const QString &value);
|
||||||
void setProperty (SettingProperty prop, const QStringList &value);
|
void setProperty (SettingProperty prop, const QStringList &value);
|
||||||
|
|
||||||
|
@ -111,9 +148,4 @@ namespace CSMSettings
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(CSMSettings::Setting)
|
|
||||||
|
|
||||||
QDataStream &operator <<(QDataStream &stream, const CSMSettings::Setting& setting);
|
|
||||||
QDataStream &operator >>(QDataStream &stream, CSMSettings::Setting& setting);
|
|
||||||
|
|
||||||
#endif // CSMSETTINGS_SETTING_HPP
|
#endif // CSMSETTINGS_SETTING_HPP
|
||||||
|
|
|
@ -30,8 +30,7 @@ void CSMSettings::SettingManager::dumpModel()
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMSettings::Setting *CSMSettings::SettingManager::createSetting
|
CSMSettings::Setting *CSMSettings::SettingManager::createSetting
|
||||||
(CSMSettings::SettingType typ, const QString &page, const QString &name,
|
(CSMSettings::SettingType typ, const QString &page, const QString &name)
|
||||||
const QStringList &values)
|
|
||||||
{
|
{
|
||||||
//get list of all settings for the current setting name
|
//get list of all settings for the current setting name
|
||||||
if (findSetting (page, name))
|
if (findSetting (page, name))
|
||||||
|
@ -41,7 +40,8 @@ CSMSettings::Setting *CSMSettings::SettingManager::createSetting
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Setting *setting = new Setting (typ, name, page, values);
|
Setting *setting = new Setting (typ, name, page);
|
||||||
|
|
||||||
|
|
||||||
//add declaration to the model
|
//add declaration to the model
|
||||||
mSettings.append (setting);
|
mSettings.append (setting);
|
||||||
|
|
|
@ -46,8 +46,7 @@ namespace CSMSettings
|
||||||
|
|
||||||
///add a new setting to the model and return it
|
///add a new setting to the model and return it
|
||||||
Setting *createSetting (CSMSettings::SettingType typ,
|
Setting *createSetting (CSMSettings::SettingType typ,
|
||||||
const QString &page, const QString &name,
|
const QString &page, const QString &name);
|
||||||
const QStringList &values = QStringList());
|
|
||||||
|
|
||||||
///add definitions to the settings specified in the page map
|
///add definitions to the settings specified in the page map
|
||||||
void addDefinitions (DefinitionPageMap &pageMap);
|
void addDefinitions (DefinitionPageMap &pageMap);
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace CSMSettings
|
||||||
{
|
{
|
||||||
Property_Name = 0,
|
Property_Name = 0,
|
||||||
Property_Page = 1,
|
Property_Page = 1,
|
||||||
Property_ViewType = 2,
|
Property_SettingType = 2,
|
||||||
Property_IsMultiValue = 3,
|
Property_IsMultiValue = 3,
|
||||||
Property_IsMultiLine = 4,
|
Property_IsMultiLine = 4,
|
||||||
Property_WidgetWidth = 5,
|
Property_WidgetWidth = 5,
|
||||||
|
@ -37,24 +37,49 @@ namespace CSMSettings
|
||||||
Property_Serializable = 9,
|
Property_Serializable = 9,
|
||||||
Property_ColumnSpan = 10,
|
Property_ColumnSpan = 10,
|
||||||
Property_RowSpan = 11,
|
Property_RowSpan = 11,
|
||||||
|
Property_Minimum = 12,
|
||||||
|
Property_Maximum = 13,
|
||||||
|
Property_SpecialValueText = 14,
|
||||||
|
Property_Prefix = 15,
|
||||||
|
Property_Suffix = 16,
|
||||||
|
Property_SingleStep = 17,
|
||||||
|
Property_Wrapping = 18,
|
||||||
|
Property_TickInterval = 19,
|
||||||
|
Property_TicksAbove = 20,
|
||||||
|
Property_TicksBelow = 21,
|
||||||
|
|
||||||
//Stringlists should always be the last items
|
//Stringlists should always be the last items
|
||||||
Property_DefaultValues = 12,
|
Property_DefaultValues = 22,
|
||||||
Property_DeclaredValues = 13,
|
Property_DeclaredValues = 23,
|
||||||
Property_DefinedValues = 14,
|
Property_DefinedValues = 24,
|
||||||
Property_Proxies = 15
|
Property_Proxies = 25
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SettingType
|
enum SettingType
|
||||||
{
|
{
|
||||||
Type_MultiBool = 0,
|
/*
|
||||||
Type_SingleBool = 1,
|
* 0 - 9 - Boolean widgets
|
||||||
Type_MultiList = 2,
|
* 10-19 - List widgets
|
||||||
Type_SingleList = 3,
|
* 21-29 - Range widgets
|
||||||
Type_MultiRange = 4,
|
* 31-39 - Text widgets
|
||||||
Type_SingleRange = 5,
|
*
|
||||||
Type_MultiText = 6,
|
* Each range corresponds to a View_Type enum by a factor of 10.
|
||||||
Type_SingleText = 7
|
*
|
||||||
|
* Even-numbered values are single-value widgets
|
||||||
|
* Odd-numbered values are multi-valued widgets
|
||||||
|
*/
|
||||||
|
|
||||||
|
Type_CheckBox = 0,
|
||||||
|
Type_RadioButton = 1,
|
||||||
|
Type_ListView = 10,
|
||||||
|
Type_ComboBox = 11,
|
||||||
|
Type_SpinBox = 21,
|
||||||
|
Type_DoubleSpinBox = 23,
|
||||||
|
Type_Slider = 25,
|
||||||
|
Type_Dial = 27,
|
||||||
|
Type_TextArea = 30,
|
||||||
|
Type_LineEdit = 31,
|
||||||
|
Type_Undefined = 40
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MergeMethod
|
enum MergeMethod
|
||||||
|
@ -84,7 +109,7 @@ namespace CSVSettings
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
namespace CSMSettings
|
namespace CSMSettings
|
||||||
{
|
{
|
||||||
struct PropertyDefaultValues
|
struct PropertyDefaultValues
|
||||||
|
@ -96,9 +121,11 @@ namespace CSMSettings
|
||||||
|
|
||||||
const QString sPropertyNames[] =
|
const QString sPropertyNames[] =
|
||||||
{
|
{
|
||||||
"name", "page", "view_type", "is_multi_value",
|
"name", "page", "setting_type", "is_multi_value",
|
||||||
"is_multi_line", "widget_width", "view_row", "view_column", "delimiter",
|
"is_multi_line", "widget_width", "view_row", "view_column", "delimiter",
|
||||||
"is_serializable","column_span", "row_span",
|
"is_serializable","column_span", "row_span", "minimum", "maximum",
|
||||||
|
"special_value_text", "prefix", "suffix", "single_step", "wrapping",
|
||||||
|
"tick_interval", "ticks_above", "ticks_below",
|
||||||
"defaults", "declarations", "definitions", "proxies"
|
"defaults", "declarations", "definitions", "proxies"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,16 +133,26 @@ namespace CSMSettings
|
||||||
{
|
{
|
||||||
"", //name
|
"", //name
|
||||||
"", //page
|
"", //page
|
||||||
"0", //view type
|
"40", //setting type
|
||||||
"false", //multivalue
|
"false", //multivalue
|
||||||
"false", //multiline
|
"false", //multiline
|
||||||
"0", //widget width
|
"7", //widget width
|
||||||
"-1", //view row
|
"-1", //view row
|
||||||
"-1", //view column
|
"-1", //view column
|
||||||
",", //delimiter
|
",", //delimiter
|
||||||
"true", //serialized
|
"true", //serialized
|
||||||
"1", //column span
|
"1", //column span
|
||||||
"1", //row span
|
"1", //row span
|
||||||
|
"0", //value range
|
||||||
|
"0", //value minimum
|
||||||
|
"0", //value maximum
|
||||||
|
"", //special text
|
||||||
|
"", //prefix
|
||||||
|
"", //suffix
|
||||||
|
"false", //wrapping
|
||||||
|
"1", //tick interval
|
||||||
|
"false", //ticks above
|
||||||
|
"true", //ticks below
|
||||||
"", //default values
|
"", //default values
|
||||||
"", //declared values
|
"", //declared values
|
||||||
"", //defined values
|
"", //defined values
|
||||||
|
|
|
@ -47,11 +47,11 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
{
|
{
|
||||||
QString section = "Window Size";
|
QString section = "Window Size";
|
||||||
{
|
{
|
||||||
Setting *width = createSetting (Type_SingleText, section, "Width");
|
Setting *width = createSetting (Type_LineEdit, section, "Width");
|
||||||
Setting *height = createSetting (Type_SingleText, section, "Height");
|
Setting *height = createSetting (Type_LineEdit, section, "Height");
|
||||||
|
|
||||||
width->setWidgetWidth (5);
|
width->setWidgetWidth (5);
|
||||||
height->setWidgetWidth (5);
|
height->setWidgetWidth (8);
|
||||||
|
|
||||||
width->setDefaultValues (QStringList() << "1024");
|
width->setDefaultValues (QStringList() << "1024");
|
||||||
height->setDefaultValues (QStringList() << "768");
|
height->setDefaultValues (QStringList() << "768");
|
||||||
|
@ -65,14 +65,11 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
/*
|
/*
|
||||||
*Create the proxy setting for predefined values
|
*Create the proxy setting for predefined values
|
||||||
*/
|
*/
|
||||||
Setting *preDefined = createSetting (Type_SingleList, section,
|
Setting *preDefined = createSetting (Type_ComboBox, section,
|
||||||
"Pre-Defined",
|
"Pre-Defined");
|
||||||
QStringList()
|
|
||||||
<< "640 x 480"
|
preDefined->setDeclaredValues (QStringList() << "640 x 480"
|
||||||
<< "800 x 600"
|
<< "800 x 600" << "1024 x 768" << "1440 x 900");
|
||||||
<< "1024 x 768"
|
|
||||||
<< "1440 x 900"
|
|
||||||
);
|
|
||||||
|
|
||||||
preDefined->setViewLocation (1, 1);
|
preDefined->setViewLocation (1, 1);
|
||||||
preDefined->setWidgetWidth (10);
|
preDefined->setWidgetWidth (10);
|
||||||
|
@ -94,13 +91,14 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
QStringList values = QStringList()
|
QStringList values = QStringList()
|
||||||
<< defaultValue << "Icon Only" << "Text Only";
|
<< defaultValue << "Icon Only" << "Text Only";
|
||||||
|
|
||||||
Setting *rsd = createSetting (Type_SingleBool,
|
Setting *rsd = createSetting (Type_RadioButton,
|
||||||
section, "Record Status Display",
|
section, "Record Status Display");
|
||||||
values);
|
|
||||||
|
|
||||||
Setting *ritd = createSetting (Type_SingleBool,
|
Setting *ritd = createSetting (Type_RadioButton,
|
||||||
section, "Referenceable ID Type Display",
|
section, "Referenceable ID Type Display");
|
||||||
values);
|
|
||||||
|
rsd->setDeclaredValues (values);
|
||||||
|
ritd->setDeclaredValues (values);
|
||||||
|
|
||||||
rsd->setEditorSetting (true);
|
rsd->setEditorSetting (true);
|
||||||
ritd->setEditorSetting (true);
|
ritd->setEditorSetting (true);
|
||||||
|
@ -108,44 +106,67 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
|
|
||||||
section = "Proxy Selection Test";
|
section = "Proxy Selection Test";
|
||||||
{
|
{
|
||||||
//create three setting objects, specifying the basic widget type,
|
/******************************************************************
|
||||||
//the setting view name, the page name, and the default value
|
* There are three types of values:
|
||||||
Setting *masterBoolean = createSetting (Type_SingleBool, section,
|
*
|
||||||
"Master Proxy",
|
* Declared values
|
||||||
QStringList()
|
*
|
||||||
|
* Pre-determined values, typically for
|
||||||
|
* combobox drop downs and boolean (radiobutton / checkbox) labels.
|
||||||
|
* These values represent the total possible list of values that
|
||||||
|
* may define a setting. No other values are allowed.
|
||||||
|
*
|
||||||
|
* Defined values
|
||||||
|
*
|
||||||
|
* Values which represent the actual, current value of
|
||||||
|
* a setting. For settings with declared values, this must be one or
|
||||||
|
* several declared values, as appropriate.
|
||||||
|
*
|
||||||
|
* Proxy values - values the proxy master updates the proxy slave when
|
||||||
|
* it's own definition is set / changed. These are definitions for
|
||||||
|
* proxy slave settings, but must match any declared values the proxy
|
||||||
|
* slave has, if any.
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
//create setting objects, specifying the basic widget type,
|
||||||
|
//the page name, and the view name
|
||||||
|
/*
|
||||||
|
Setting *masterBoolean = createSetting (Type_RadioButton, section,
|
||||||
|
"Master Proxy");
|
||||||
|
|
||||||
|
Setting *slaveBoolean = createSetting (Type_CheckBox, section,
|
||||||
|
"Proxy Checkboxes");
|
||||||
|
|
||||||
|
Setting *slaveSingleText = createSetting (Type_LineEdit, section,
|
||||||
|
"Proxy TextBox 1");
|
||||||
|
|
||||||
|
Setting *slaveMultiText = createSetting (Type_LineEdit, section,
|
||||||
|
"ProxyTextBox 2");
|
||||||
|
|
||||||
|
Setting *slaveAlphaSpinbox = createSetting (Type_SpinBox, section,
|
||||||
|
"Alpha Spinbox");
|
||||||
|
|
||||||
|
Setting *slaveIntegerSpinbox = createSetting (Type_SpinBox, section,
|
||||||
|
"Int Spinbox");
|
||||||
|
|
||||||
|
Setting *slaveDoubleSpinbox = createSetting (Type_DoubleSpinBox,
|
||||||
|
section, "Double Spinbox");
|
||||||
|
|
||||||
|
Setting *slaveSlider = createSetting (Type_Slider, section, "Slider");
|
||||||
|
|
||||||
|
Setting *slaveDial = createSetting (Type_Dial, section, "Dial");
|
||||||
|
|
||||||
|
//set declared values for selected views
|
||||||
|
masterBoolean->setDeclaredValues (QStringList()
|
||||||
<< "Profile One" << "Profile Two"
|
<< "Profile One" << "Profile Two"
|
||||||
<< "Profile Three" << "Profile Four"
|
<< "Profile Three" << "Profile Four");
|
||||||
);
|
|
||||||
|
|
||||||
Setting *slaveBoolean = createSetting (Type_MultiBool, section,
|
slaveBoolean->setDeclaredValues (QStringList()
|
||||||
"Proxy Checkboxes",
|
<< "One" << "Two" << "Three" << "Four" << "Five");
|
||||||
QStringList() << "One" << "Two"
|
|
||||||
<< "Three" << "Four" << "Five"
|
|
||||||
);
|
|
||||||
|
|
||||||
Setting *slaveSingleText = createSetting (Type_SingleText, section,
|
slaveAlphaSpinbox->setDeclaredValues (QStringList()
|
||||||
"Proxy TextBox 1"
|
<< "One" << "Two" << "Three" << "Four");
|
||||||
);
|
|
||||||
|
|
||||||
Setting *slaveMultiText = createSetting (Type_SingleText, section,
|
|
||||||
"ProxyTextBox 2"
|
|
||||||
);
|
|
||||||
|
|
||||||
// There are three types of values:
|
|
||||||
//
|
|
||||||
// Declared values - Pre-determined values, typically for
|
|
||||||
// combobox drop downs and boolean (radiobutton / checkbox) labels.
|
|
||||||
// These values represent the total possible list of values that may
|
|
||||||
// define a setting. No other values are allowed.
|
|
||||||
//
|
|
||||||
// Defined values - Values which represent the atual, current value of
|
|
||||||
// a setting. For settings with declared values, this must be one or
|
|
||||||
// several declared values, as appropriate.
|
|
||||||
//
|
|
||||||
// Proxy values - values the proxy master updates the proxy slave when
|
|
||||||
// it's own definition is set / changed. These are definitions for
|
|
||||||
// proxy slave settings, but must match any declared values the proxy
|
|
||||||
// slave has, if any.
|
|
||||||
|
|
||||||
masterBoolean->addProxy (slaveBoolean, QList <QStringList>()
|
masterBoolean->addProxy (slaveBoolean, QList <QStringList>()
|
||||||
<< (QStringList() << "One" << "Three")
|
<< (QStringList() << "One" << "Three")
|
||||||
|
@ -168,11 +189,47 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
<< (QStringList() << "Two" << "Four")
|
<< (QStringList() << "Two" << "Four")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveAlphaSpinbox, QList <QStringList>()
|
||||||
|
<< (QStringList() << "Four")
|
||||||
|
<< (QStringList() << "Three")
|
||||||
|
<< (QStringList() << "Two")
|
||||||
|
<< (QStringList() << "One"));
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveIntegerSpinbox, QList <QStringList> ()
|
||||||
|
<< (QStringList() << "0")
|
||||||
|
<< (QStringList() << "7")
|
||||||
|
<< (QStringList() << "14")
|
||||||
|
<< (QStringList() << "21"));
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveDoubleSpinbox, QList <QStringList> ()
|
||||||
|
<< (QStringList() << "0.17")
|
||||||
|
<< (QStringList() << "0.34")
|
||||||
|
<< (QStringList() << "0.51")
|
||||||
|
<< (QStringList() << "0.68"));
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveSlider, QList <QStringList> ()
|
||||||
|
<< (QStringList() << "25")
|
||||||
|
<< (QStringList() << "50")
|
||||||
|
<< (QStringList() << "75")
|
||||||
|
<< (QStringList() << "100")
|
||||||
|
);
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveDial, QList <QStringList> ()
|
||||||
|
<< (QStringList() << "25")
|
||||||
|
<< (QStringList() << "50")
|
||||||
|
<< (QStringList() << "75")
|
||||||
|
<< (QStringList() << "100")
|
||||||
|
);
|
||||||
|
|
||||||
//settings with proxies are not serialized by default
|
//settings with proxies are not serialized by default
|
||||||
//other settings non-serialized for demo purposes
|
//other settings non-serialized for demo purposes
|
||||||
slaveBoolean->setSerializable (false);
|
slaveBoolean->setSerializable (false);
|
||||||
slaveSingleText->setSerializable (false);
|
slaveSingleText->setSerializable (false);
|
||||||
slaveMultiText->setSerializable (false);
|
slaveMultiText->setSerializable (false);
|
||||||
|
slaveAlphaSpinbox->setSerializable (false);
|
||||||
|
slaveIntegerSpinbox->setSerializable (false);
|
||||||
|
slaveDoubleSpinbox->setSerializable (false);
|
||||||
|
slaveSlider->setSerializable (false);
|
||||||
|
|
||||||
slaveBoolean->setDefaultValues (QStringList()
|
slaveBoolean->setDefaultValues (QStringList()
|
||||||
<< "One" << "Three" << "Five");
|
<< "One" << "Three" << "Five");
|
||||||
|
@ -184,6 +241,38 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
|
|
||||||
slaveSingleText->setWidgetWidth (24);
|
slaveSingleText->setWidgetWidth (24);
|
||||||
slaveMultiText->setWidgetWidth (24);
|
slaveMultiText->setWidgetWidth (24);
|
||||||
|
|
||||||
|
slaveAlphaSpinbox->setDefaultValue ("Two");
|
||||||
|
slaveAlphaSpinbox->setWidgetWidth (20);
|
||||||
|
//slaveAlphaSpinbox->setPrefix ("No. ");
|
||||||
|
//slaveAlphaSpinbox->setSuffix ("!");
|
||||||
|
slaveAlphaSpinbox->setWrapping (true);
|
||||||
|
|
||||||
|
slaveIntegerSpinbox->setDefaultValue (14);
|
||||||
|
slaveIntegerSpinbox->setMinimum (0);
|
||||||
|
slaveIntegerSpinbox->setMaximum (58);
|
||||||
|
slaveIntegerSpinbox->setPrefix ("$");
|
||||||
|
slaveIntegerSpinbox->setSuffix (".00");
|
||||||
|
slaveIntegerSpinbox->setWidgetWidth (10);
|
||||||
|
slaveIntegerSpinbox->setSpecialValueText ("Nothing!");
|
||||||
|
|
||||||
|
slaveDoubleSpinbox->setDefaultValue (0.51);
|
||||||
|
slaveDoubleSpinbox->setSingleStep(0.17);
|
||||||
|
slaveDoubleSpinbox->setMaximum(4.0);
|
||||||
|
|
||||||
|
slaveSlider->setMinimum (0);
|
||||||
|
slaveSlider->setMaximum (100);
|
||||||
|
slaveSlider->setDefaultValue (75);
|
||||||
|
slaveSlider->setWidgetWidth (100);
|
||||||
|
slaveSlider->setTicksAbove (true);
|
||||||
|
slaveSlider->setTickInterval (25);
|
||||||
|
|
||||||
|
slaveDial->setMinimum (0);
|
||||||
|
slaveDial->setMaximum (100);
|
||||||
|
slaveDial->setSingleStep (5);
|
||||||
|
slaveDial->setDefaultValue (75);
|
||||||
|
slaveDial->setTickInterval (25);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,13 +284,13 @@ CSMSettings::UserSettings::~UserSettings()
|
||||||
void CSMSettings::UserSettings::loadSettings (const QString &fileName)
|
void CSMSettings::UserSettings::loadSettings (const QString &fileName)
|
||||||
{
|
{
|
||||||
mUserFilePath = QString::fromUtf8
|
mUserFilePath = QString::fromUtf8
|
||||||
(mCfgMgr.getUserConfigPath().c_str()) + fileName.toUtf8();
|
(mCfgMgr.getUserConfigPath().string().c_str()) + fileName.toUtf8();
|
||||||
|
|
||||||
QString global = QString::fromUtf8
|
QString global = QString::fromUtf8
|
||||||
(mCfgMgr.getGlobalPath().c_str()) + fileName.toUtf8();
|
(mCfgMgr.getGlobalPath().string().c_str()) + fileName.toUtf8();
|
||||||
|
|
||||||
QString local = QString::fromUtf8
|
QString local = QString::fromUtf8
|
||||||
(mCfgMgr.getLocalPath().c_str()) + fileName.toUtf8();
|
(mCfgMgr.getLocalPath().string().c_str()) + fileName.toUtf8();
|
||||||
|
|
||||||
//open user and global streams
|
//open user and global streams
|
||||||
QTextStream *userStream = openFilestream (mUserFilePath, true);
|
QTextStream *userStream = openFilestream (mUserFilePath, true);
|
||||||
|
|
|
@ -453,7 +453,7 @@ CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters()
|
||||||
return mFilters;
|
return mFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
|
QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
|
||||||
{
|
{
|
||||||
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include "tablemimedata.hpp"
|
#include "tablemimedata.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
|
@ -11,7 +14,7 @@ mDocument(document)
|
||||||
mObjectsFormats << QString::fromUtf8 (("tabledata/" + id.getTypeName()).c_str());
|
mObjectsFormats << QString::fromUtf8 (("tabledata/" + id.getTypeName()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) :
|
CSMWorld::TableMimeData::TableMimeData (const std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) :
|
||||||
mUniversalId (id), mDocument(document)
|
mUniversalId (id), mDocument(document)
|
||||||
{
|
{
|
||||||
for (std::vector<UniversalId>::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it)
|
for (std::vector<UniversalId>::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it)
|
||||||
|
@ -33,7 +36,8 @@ std::string CSMWorld::TableMimeData::getIcon() const
|
||||||
{
|
{
|
||||||
if (mUniversalId.empty())
|
if (mUniversalId.empty())
|
||||||
{
|
{
|
||||||
throw ("TableMimeData holds no UniversalId");
|
qDebug()<<"TableMimeData object does not hold any records!"; //because throwing in the event loop tends to be problematic
|
||||||
|
throw("TableMimeData object does not hold any records!");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tmpIcon;
|
std::string tmpIcon;
|
||||||
|
@ -50,7 +54,7 @@ std::string CSMWorld::TableMimeData::getIcon() const
|
||||||
|
|
||||||
if (tmpIcon != mUniversalId[i].getIcon())
|
if (tmpIcon != mUniversalId[i].getIcon())
|
||||||
{
|
{
|
||||||
return ":/multitype.png"; //icon stolen from gnome
|
return ":/multitype.png"; //icon stolen from gnome TODO: get new icon
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpIcon = mUniversalId[i].getIcon();
|
tmpIcon = mUniversalId[i].getIcon();
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace CSMWorld
|
||||||
public:
|
public:
|
||||||
TableMimeData(UniversalId id, const CSMDoc::Document& document);
|
TableMimeData(UniversalId id, const CSMDoc::Document& document);
|
||||||
|
|
||||||
TableMimeData(std::vector<UniversalId>& id, const CSMDoc::Document& document);
|
TableMimeData(const std::vector<UniversalId>& id, const CSMDoc::Document& document);
|
||||||
|
|
||||||
~TableMimeData();
|
~TableMimeData();
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ namespace CSMWorld
|
||||||
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
|
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
|
||||||
|
|
||||||
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);
|
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);
|
||||||
|
|
||||||
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
|
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
|
||||||
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
|
||||||
|
|
|
@ -60,6 +60,7 @@ namespace CSMWorld
|
||||||
Type_Spell,
|
Type_Spell,
|
||||||
Type_Cells,
|
Type_Cells,
|
||||||
Type_Cell,
|
Type_Cell,
|
||||||
|
Type_Cell_Missing, //For cells that does not exist yet.
|
||||||
Type_Referenceables,
|
Type_Referenceables,
|
||||||
Type_Referenceable,
|
Type_Referenceable,
|
||||||
Type_Activator,
|
Type_Activator,
|
||||||
|
|
|
@ -3,8 +3,12 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent)
|
#include <QtGui/qevent.h>
|
||||||
: WorldspaceWidget (parent)
|
|
||||||
|
#include <apps/opencs/model/world/tablemimedata.hpp>
|
||||||
|
|
||||||
|
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document)
|
||||||
|
: WorldspaceWidget (document, parent)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)
|
void CSVRender::PagedWorldspaceWidget::useViewHint (const std::string& hint)
|
||||||
|
@ -45,3 +49,44 @@ void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSel
|
||||||
mSelection = selection;
|
mSelection = selection;
|
||||||
emit cellSelectionChanged (mSelection);
|
emit cellSelectionChanged (mSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair< int, int > CSVRender::PagedWorldspaceWidget::getCoordinatesFromId (const std::string& record) const
|
||||||
|
{
|
||||||
|
std::istringstream stream (record.c_str());
|
||||||
|
char ignore;
|
||||||
|
int x, y;
|
||||||
|
stream >> ignore >> x >> y;
|
||||||
|
return std::make_pair(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
|
||||||
|
{
|
||||||
|
bool selectionChanged = false;
|
||||||
|
for (unsigned i = 0; i < data.size(); ++i)
|
||||||
|
{
|
||||||
|
std::pair<int, int> coordinates(getCoordinatesFromId(data[i].getId()));
|
||||||
|
if (mSelection.add(CSMWorld::CellCoordinates(coordinates.first, coordinates.second)))
|
||||||
|
{
|
||||||
|
selectionChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectionChanged)
|
||||||
|
{
|
||||||
|
emit cellSelectionChanged(mSelection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVRender::WorldspaceWidget::dropRequirments CSVRender::PagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case cellsExterior:
|
||||||
|
return canHandle;
|
||||||
|
|
||||||
|
case cellsInterior:
|
||||||
|
return needUnpaged;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ignored;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,17 +13,25 @@ namespace CSVRender
|
||||||
|
|
||||||
CSMWorld::CellSelection mSelection;
|
CSMWorld::CellSelection mSelection;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::pair<int, int> getCoordinatesFromId(const std::string& record) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PagedWorldspaceWidget (QWidget *parent);
|
PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document);
|
||||||
///< \note Sets the cell area selection to an invalid value to indicate that currently
|
///< \note Sets the cell area selection to an invalid value to indicate that currently
|
||||||
/// no cells are displayed. The cells to be displayed will be specified later through
|
/// no cells are displayed. The cells to be displayed will be specified later through
|
||||||
/// hint system.
|
/// hint system.
|
||||||
|
|
||||||
virtual void useViewHint (const std::string& hint);
|
void useViewHint (const std::string& hint);
|
||||||
|
|
||||||
void setCellSelection (const CSMWorld::CellSelection& selection);
|
void setCellSelection (const CSMWorld::CellSelection& selection);
|
||||||
|
|
||||||
|
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
|
||||||
|
|
||||||
|
virtual dropRequirments getDropRequirements(dropType type) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void cellSelectionChanged (const CSMWorld::CellSelection& selection);
|
void cellSelectionChanged (const CSMWorld::CellSelection& selection);
|
||||||
|
|
|
@ -320,7 +320,7 @@ namespace CSVRender
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mUpdate)
|
if (mUpdate && mWindow)
|
||||||
{
|
{
|
||||||
mUpdate = false;
|
mUpdate = false;
|
||||||
mWindow->update();
|
mWindow->update();
|
||||||
|
|
|
@ -3,10 +3,13 @@
|
||||||
|
|
||||||
#include <OgreColourValue.h>
|
#include <OgreColourValue.h>
|
||||||
|
|
||||||
|
#include <QtGui/qevent.h>
|
||||||
|
|
||||||
#include "../../model/doc/document.hpp"
|
#include "../../model/doc/document.hpp"
|
||||||
|
|
||||||
#include "../../model/world/data.hpp"
|
#include "../../model/world/data.hpp"
|
||||||
#include "../../model/world/idtable.hpp"
|
#include "../../model/world/idtable.hpp"
|
||||||
|
#include "../../model/world/tablemimedata.hpp"
|
||||||
|
|
||||||
void CSVRender::UnpagedWorldspaceWidget::update()
|
void CSVRender::UnpagedWorldspaceWidget::update()
|
||||||
{
|
{
|
||||||
|
@ -20,9 +23,8 @@ void CSVRender::UnpagedWorldspaceWidget::update()
|
||||||
/// \todo deal with mSunlight and mFog/mForDensity
|
/// \todo deal with mSunlight and mFog/mForDensity
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId,
|
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent)
|
||||||
CSMDoc::Document& document, QWidget *parent)
|
: WorldspaceWidget (document, parent), mCellId (cellId)
|
||||||
: WorldspaceWidget (parent), mCellId (cellId)
|
|
||||||
{
|
{
|
||||||
mCellsModel = &dynamic_cast<CSMWorld::IdTable&> (
|
mCellsModel = &dynamic_cast<CSMWorld::IdTable&> (
|
||||||
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
|
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
|
||||||
|
@ -64,3 +66,25 @@ void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelI
|
||||||
if (cellIndex.row()>=start && cellIndex.row()<=end)
|
if (cellIndex.row()>=start && cellIndex.row()<=end)
|
||||||
emit closeRequest();
|
emit closeRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
|
||||||
|
{
|
||||||
|
mCellId = data.begin()->getId();
|
||||||
|
update();
|
||||||
|
emit cellChanged(*data.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case cellsInterior:
|
||||||
|
return canHandle;
|
||||||
|
|
||||||
|
case cellsExterior:
|
||||||
|
return needPaged;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ignored;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -33,11 +33,19 @@ namespace CSVRender
|
||||||
UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document,
|
UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document,
|
||||||
QWidget *parent);
|
QWidget *parent);
|
||||||
|
|
||||||
|
virtual dropRequirments getDropRequirements(dropType type) const;
|
||||||
|
|
||||||
|
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
void cellRowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
void cellRowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void cellChanged(const CSMWorld::UniversalId& id);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,20 @@
|
||||||
#include <OgreSceneManager.h>
|
#include <OgreSceneManager.h>
|
||||||
#include <OgreEntity.h>
|
#include <OgreEntity.h>
|
||||||
|
|
||||||
#include "../world/scenetoolmode.hpp"
|
#include <QtGui/qevent.h>
|
||||||
|
|
||||||
CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent)
|
#include "../world/scenetoolmode.hpp"
|
||||||
: SceneWidget (parent)
|
#include <apps/opencs/model/world/universalid.hpp>
|
||||||
|
|
||||||
|
CSVRender::WorldspaceWidget::WorldspaceWidget (const CSMDoc::Document& document, QWidget* parent)
|
||||||
|
: SceneWidget (parent), mDocument(document)
|
||||||
{
|
{
|
||||||
Ogre::Entity* ent = getSceneManager()->createEntity("cube", Ogre::SceneManager::PT_CUBE);
|
Ogre::Entity* ent = getSceneManager()->createEntity("cube", Ogre::SceneManager::PT_CUBE);
|
||||||
ent->setMaterialName("BaseWhite");
|
ent->setMaterialName("BaseWhite");
|
||||||
|
|
||||||
getSceneManager()->getRootSceneNode()->attachObject(ent);
|
getSceneManager()->getRootSceneNode()->attachObject(ent);
|
||||||
|
|
||||||
|
setAcceptDrops(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
|
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
|
||||||
|
@ -47,3 +52,77 @@ CSVWorld::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
|
||||||
|
|
||||||
return tool;
|
return tool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSVRender::WorldspaceWidget::dropType CSVRender::WorldspaceWidget::getDropType (
|
||||||
|
const std::vector< CSMWorld::UniversalId >& data)
|
||||||
|
{
|
||||||
|
dropType output = notCells;
|
||||||
|
bool firstIteration = true;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < data.size(); ++i)
|
||||||
|
{
|
||||||
|
if (data[i].getType() == CSMWorld::UniversalId::Type_Cell ||
|
||||||
|
data[i].getType() == CSMWorld::UniversalId::Type_Cell_Missing)
|
||||||
|
{
|
||||||
|
if (*(data[i].getId().begin()) == '#') //exterior
|
||||||
|
{
|
||||||
|
if (firstIteration)
|
||||||
|
{
|
||||||
|
output = cellsExterior;
|
||||||
|
firstIteration = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output == cellsInterior)
|
||||||
|
{
|
||||||
|
output = cellsMixed;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
output = cellsInterior;
|
||||||
|
}
|
||||||
|
} else //interior
|
||||||
|
{
|
||||||
|
if (firstIteration)
|
||||||
|
{
|
||||||
|
output = cellsInterior;
|
||||||
|
firstIteration = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output == cellsExterior)
|
||||||
|
{
|
||||||
|
output = cellsMixed;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
output = cellsInterior;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output = notCells;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::WorldspaceWidget::dragEnterEvent (QDragEnterEvent* event)
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event)
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event)
|
||||||
|
{
|
||||||
|
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||||
|
|
||||||
|
if (mime->fromDocument (mDocument))
|
||||||
|
{
|
||||||
|
emit dataDropped(mime->getData());
|
||||||
|
} //not handling drops from different documents at the moment
|
||||||
|
}
|
|
@ -6,7 +6,13 @@
|
||||||
#include "navigation1st.hpp"
|
#include "navigation1st.hpp"
|
||||||
#include "navigationfree.hpp"
|
#include "navigationfree.hpp"
|
||||||
#include "navigationorbit.hpp"
|
#include "navigationorbit.hpp"
|
||||||
|
#include <apps/opencs/model/doc/document.hpp>
|
||||||
|
#include <apps/opencs/model/world/tablemimedata.hpp>
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class UniversalId;
|
||||||
|
}
|
||||||
namespace CSVWorld
|
namespace CSVWorld
|
||||||
{
|
{
|
||||||
class SceneToolMode;
|
class SceneToolMode;
|
||||||
|
@ -25,7 +31,23 @@ namespace CSVRender
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WorldspaceWidget (QWidget *parent = 0);
|
enum dropType
|
||||||
|
{
|
||||||
|
cellsMixed,
|
||||||
|
cellsInterior,
|
||||||
|
cellsExterior,
|
||||||
|
notCells
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dropRequirments
|
||||||
|
{
|
||||||
|
canHandle,
|
||||||
|
needPaged,
|
||||||
|
needUnpaged,
|
||||||
|
ignored //either mixed cells, or not cells
|
||||||
|
};
|
||||||
|
|
||||||
|
WorldspaceWidget (const CSMDoc::Document& document, QWidget *parent = 0);
|
||||||
|
|
||||||
CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent);
|
CSVWorld::SceneToolMode *makeNavigationSelector (CSVWorld::SceneToolbar *parent);
|
||||||
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
|
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
|
||||||
|
@ -33,9 +55,26 @@ namespace CSVRender
|
||||||
|
|
||||||
void selectDefaultNavigationMode();
|
void selectDefaultNavigationMode();
|
||||||
|
|
||||||
|
static dropType getDropType(const std::vector<CSMWorld::UniversalId>& data);
|
||||||
|
|
||||||
|
virtual dropRequirments getDropRequirements(dropType type) const = 0;
|
||||||
|
|
||||||
virtual void useViewHint (const std::string& hint);
|
virtual void useViewHint (const std::string& hint);
|
||||||
///< Default-implementation: ignored.
|
///< Default-implementation: ignored.
|
||||||
|
|
||||||
|
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const CSMDoc::Document& mDocument; //for checking if drop comes from same document
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void dragEnterEvent(QDragEnterEvent *event);
|
||||||
|
|
||||||
|
void dropEvent(QDropEvent* event);
|
||||||
|
|
||||||
|
void dragMoveEvent(QDragMoveEvent *event);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void selectNavigationMode (const std::string& mode);
|
void selectNavigationMode (const std::string& mode);
|
||||||
|
@ -43,6 +82,7 @@ namespace CSVRender
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void closeRequest();
|
void closeRequest();
|
||||||
|
void dataDropped(const std::vector<CSMWorld::UniversalId>& data);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,19 @@ CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting,
|
||||||
{
|
{
|
||||||
QAbstractButton *button = 0;
|
QAbstractButton *button = 0;
|
||||||
|
|
||||||
if (isMultiValue())
|
switch (setting->type())
|
||||||
|
{
|
||||||
|
case CSMSettings::Type_CheckBox:
|
||||||
button = new QCheckBox (value, this);
|
button = new QCheckBox (value, this);
|
||||||
else
|
break;
|
||||||
|
|
||||||
|
case CSMSettings::Type_RadioButton:
|
||||||
button = new QRadioButton (value, this);
|
button = new QRadioButton (value, this);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
connect (button, SIGNAL (clicked (bool)),
|
connect (button, SIGNAL (clicked (bool)),
|
||||||
this, SLOT (slotToggled (bool)));
|
this, SLOT (slotToggled (bool)));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef CSVSETTINGS_BOOLEANVIEW_HPP
|
#ifndef CSVSETTINGS_BOOLEANVIEW_HPP
|
||||||
#define CSVSETTINGS_BOOELANVIEW_HPP
|
#define CSVSETTINGS_BOOLEANVIEW_HPP
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QAbstractButton>
|
#include <QAbstractButton>
|
||||||
|
|
|
@ -123,10 +123,8 @@ void CSVSettings::Dialog::show()
|
||||||
{
|
{
|
||||||
if (pages().isEmpty())
|
if (pages().isEmpty())
|
||||||
buildPages();
|
buildPages();
|
||||||
|
|
||||||
QPoint screenCenter = QApplication::desktop()->screenGeometry().center();
|
QPoint screenCenter = QApplication::desktop()->screenGeometry().center();
|
||||||
|
|
||||||
move (screenCenter - geometry().center());
|
move (screenCenter - geometry().center());
|
||||||
|
|
||||||
QWidget::show();
|
QWidget::show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,9 +60,11 @@ void CSVSettings::Frame::showWidgets()
|
||||||
QWidget *widg = static_cast <QWidget *> (obj);
|
QWidget *widg = static_cast <QWidget *> (obj);
|
||||||
|
|
||||||
if (widg->property("sizePolicy").isValid())
|
if (widg->property("sizePolicy").isValid())
|
||||||
|
{
|
||||||
widg->setSizePolicy
|
widg->setSizePolicy
|
||||||
(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
layout()->activate();
|
layout()->activate();
|
||||||
setFixedSize(minimumSizeHint());
|
setFixedSize(minimumSizeHint());
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,12 @@
|
||||||
#include "booleanview.hpp"
|
#include "booleanview.hpp"
|
||||||
#include "textview.hpp"
|
#include "textview.hpp"
|
||||||
#include "listview.hpp"
|
#include "listview.hpp"
|
||||||
|
#include "rangeview.hpp"
|
||||||
|
|
||||||
#include "../../model/settings/usersettings.hpp"
|
#include "../../model/settings/usersettings.hpp"
|
||||||
#include "../../model/settings/connector.hpp"
|
#include "../../model/settings/connector.hpp"
|
||||||
|
#include "../../model/settings/support.hpp"
|
||||||
|
|
||||||
#include "settingwindow.hpp"
|
#include "settingwindow.hpp"
|
||||||
|
|
||||||
QMap <CSVSettings::ViewType, CSVSettings::IViewFactory *>
|
QMap <CSVSettings::ViewType, CSVSettings::IViewFactory *>
|
||||||
|
@ -85,4 +88,5 @@ void CSVSettings::Page::buildFactories()
|
||||||
mViewFactories[ViewType_Boolean] = new BooleanViewFactory (this);
|
mViewFactories[ViewType_Boolean] = new BooleanViewFactory (this);
|
||||||
mViewFactories[ViewType_Text] = new TextViewFactory (this);
|
mViewFactories[ViewType_Text] = new TextViewFactory (this);
|
||||||
mViewFactories[ViewType_List] = new ListViewFactory (this);
|
mViewFactories[ViewType_List] = new ListViewFactory (this);
|
||||||
|
mViewFactories[ViewType_Range] = new RangeViewFactory (this);
|
||||||
}
|
}
|
||||||
|
|
204
apps/opencs/view/settings/rangeview.cpp
Normal file
204
apps/opencs/view/settings/rangeview.cpp
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QAbstractSpinBox>
|
||||||
|
#include <QAbstractSlider>
|
||||||
|
#include <QDial>
|
||||||
|
#include <QSlider>
|
||||||
|
|
||||||
|
#include "rangeview.hpp"
|
||||||
|
#include "spinbox.hpp"
|
||||||
|
#include "../../model/settings/setting.hpp"
|
||||||
|
#include "../../model/settings/support.hpp"
|
||||||
|
|
||||||
|
CSVSettings::RangeView::RangeView (CSMSettings::Setting *setting,
|
||||||
|
Page *parent)
|
||||||
|
: mRangeWidget (0), mRangeType (setting->type()), View (setting, parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
mRangeWidget = 0;
|
||||||
|
|
||||||
|
if (isMultiValue())
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (mRangeType)
|
||||||
|
{
|
||||||
|
case CSMSettings::Type_SpinBox:
|
||||||
|
case CSMSettings::Type_DoubleSpinBox:
|
||||||
|
buildSpinBox (setting);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSMSettings::Type_Dial:
|
||||||
|
case CSMSettings::Type_Slider:
|
||||||
|
buildSlider (setting);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mRangeWidget->setFixedWidth (widgetWidth (setting->widgetWidth()));
|
||||||
|
mRangeWidget->setObjectName (setting->name());
|
||||||
|
|
||||||
|
addWidget (mRangeWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVSettings::RangeView::buildSlider (CSMSettings::Setting *setting)
|
||||||
|
{
|
||||||
|
switch (setting->type())
|
||||||
|
{
|
||||||
|
case CSMSettings::Type_Slider:
|
||||||
|
mRangeWidget = new QSlider (Qt::Horizontal, this);
|
||||||
|
mRangeWidget->setProperty ("tickInterval", setting->tickInterval());
|
||||||
|
|
||||||
|
if (setting->ticksAbove())
|
||||||
|
{
|
||||||
|
if (setting->ticksBelow())
|
||||||
|
mRangeWidget->setProperty ("tickPosition", QSlider::TicksBothSides);
|
||||||
|
else
|
||||||
|
mRangeWidget->setProperty ("tickPosition", QSlider::TicksAbove);
|
||||||
|
}
|
||||||
|
else if (setting->ticksBelow())
|
||||||
|
mRangeWidget->setProperty ("tickPosition", QSlider::TicksBelow);
|
||||||
|
else
|
||||||
|
mRangeWidget->setProperty ("tickPosition", QSlider::NoTicks);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSMSettings::Type_Dial:
|
||||||
|
mRangeWidget = new QDial (this);
|
||||||
|
mRangeWidget->setProperty ("wrapping", setting->wrapping());
|
||||||
|
mRangeWidget->setProperty ("notchesVisible",
|
||||||
|
(setting->ticksAbove() || setting->ticksBelow()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mRangeWidget->setProperty ("minimum", setting->minimum());
|
||||||
|
mRangeWidget->setProperty ("maximum", setting->maximum());
|
||||||
|
mRangeWidget->setProperty ("tracking", false);
|
||||||
|
mRangeWidget->setProperty ("singleStep", setting->singleStep());
|
||||||
|
|
||||||
|
connect (mRangeWidget, SIGNAL (valueChanged (int)),
|
||||||
|
this, SLOT (slotUpdateView (int)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVSettings::RangeView::buildSpinBox (CSMSettings::Setting *setting)
|
||||||
|
{
|
||||||
|
SpinBox *sb = 0;
|
||||||
|
|
||||||
|
switch (setting->type())
|
||||||
|
{
|
||||||
|
case CSMSettings::Type_SpinBox:
|
||||||
|
|
||||||
|
sb = new SpinBox (this);
|
||||||
|
|
||||||
|
if (!setting->declaredValues().isEmpty())
|
||||||
|
sb->setValueList (setting->declaredValues());
|
||||||
|
|
||||||
|
mRangeWidget = sb;
|
||||||
|
|
||||||
|
connect (mRangeWidget, SIGNAL (valueChanged (int)),
|
||||||
|
this, SLOT (slotUpdateView (int)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSMSettings::Type_DoubleSpinBox:
|
||||||
|
mRangeWidget = new QDoubleSpinBox (this);
|
||||||
|
|
||||||
|
connect (mRangeWidget, SIGNAL (valueChanged (double)),
|
||||||
|
this, SLOT (slotUpdateView (double)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//min / max values are set automatically in AlphaSpinBox
|
||||||
|
if (setting->declaredValues().isEmpty())
|
||||||
|
{
|
||||||
|
mRangeWidget->setProperty ("minimum", setting->minimum());
|
||||||
|
mRangeWidget->setProperty ("maximum", setting->maximum());
|
||||||
|
mRangeWidget->setProperty ("singleStep", setting->singleStep());
|
||||||
|
mRangeWidget->setProperty ("specialValueText",
|
||||||
|
setting->specialValueText());
|
||||||
|
}
|
||||||
|
|
||||||
|
mRangeWidget->setProperty ("prefix", setting->prefix());
|
||||||
|
mRangeWidget->setProperty ("suffix", setting->suffix());
|
||||||
|
mRangeWidget->setProperty ("wrapping", setting->wrapping());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVSettings::RangeView::slotUpdateView (int value)
|
||||||
|
{
|
||||||
|
QString textValue = "";
|
||||||
|
QStringList list;
|
||||||
|
|
||||||
|
switch (mRangeType)
|
||||||
|
{
|
||||||
|
case CSMSettings::Type_SpinBox:
|
||||||
|
list = static_cast <SpinBox *> (mRangeWidget)->valueList();
|
||||||
|
if (!list.isEmpty())
|
||||||
|
textValue = list.at(value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textValue.isEmpty())
|
||||||
|
textValue = QVariant (value).toString();
|
||||||
|
|
||||||
|
setSelectedValue (textValue, false);
|
||||||
|
|
||||||
|
View::updateView();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVSettings::RangeView::slotUpdateView (double value)
|
||||||
|
{
|
||||||
|
setSelectedValue (QVariant(value).toString(), false);
|
||||||
|
|
||||||
|
View::updateView();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVSettings::RangeView::updateView (bool signalUpdate) const
|
||||||
|
{
|
||||||
|
QString value;
|
||||||
|
|
||||||
|
if (!selectedValues().isEmpty())
|
||||||
|
value = selectedValues().at(0);
|
||||||
|
|
||||||
|
switch (mRangeType)
|
||||||
|
{
|
||||||
|
case CSMSettings::Type_SpinBox:
|
||||||
|
static_cast <SpinBox *> (mRangeWidget)->setValue (value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSMSettings::Type_DoubleSpinBox:
|
||||||
|
static_cast <QDoubleSpinBox *> (mRangeWidget)->setValue (value.toDouble());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSMSettings::Type_Slider:
|
||||||
|
case CSMSettings::Type_Dial:
|
||||||
|
mRangeWidget->setProperty ("value", value.toInt());
|
||||||
|
mRangeWidget->setProperty ("sliderPosition", value.toInt());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
View::updateView (signalUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVSettings::RangeView *CSVSettings::RangeViewFactory::createView
|
||||||
|
(CSMSettings::Setting *setting,
|
||||||
|
Page *parent)
|
||||||
|
{
|
||||||
|
return new RangeView (setting, parent);
|
||||||
|
}
|
49
apps/opencs/view/settings/rangeview.hpp
Normal file
49
apps/opencs/view/settings/rangeview.hpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef CSVSETTINGS_RANGEVIEW_HPP
|
||||||
|
#define CSVSETTINGS_RANGEVIEW_HPP
|
||||||
|
|
||||||
|
#include "view.hpp"
|
||||||
|
#include "../../model/settings/support.hpp"
|
||||||
|
|
||||||
|
class QStringListModel;
|
||||||
|
class QAbstractSpinBox;
|
||||||
|
|
||||||
|
namespace CSVSettings
|
||||||
|
{
|
||||||
|
class RangeView : public View
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
QWidget *mRangeWidget;
|
||||||
|
CSMSettings::SettingType mRangeType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RangeView (CSMSettings::Setting *setting,
|
||||||
|
Page *parent);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void updateView (bool signalUpdate = true) const;
|
||||||
|
|
||||||
|
void buildSlider (CSMSettings::Setting *setting);
|
||||||
|
void buildSpinBox (CSMSettings::Setting *setting);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void slotUpdateView (int value);
|
||||||
|
void slotUpdateView (double value);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class RangeViewFactory : public QObject, public IViewFactory
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RangeViewFactory (QWidget *parent = 0)
|
||||||
|
: QObject (parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
RangeView *createView (CSMSettings::Setting *setting,
|
||||||
|
Page *parent);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // CSVSETTINGS_RANGEVIEW_HPP
|
51
apps/opencs/view/settings/spinbox.cpp
Normal file
51
apps/opencs/view/settings/spinbox.cpp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#include "spinbox.hpp"
|
||||||
|
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QLineEdit>
|
||||||
|
|
||||||
|
CSVSettings::SpinBox::SpinBox(QWidget *parent)
|
||||||
|
: mValueList(QStringList()), QSpinBox(parent)
|
||||||
|
{
|
||||||
|
setRange (0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSVSettings::SpinBox::textFromValue(int val) const
|
||||||
|
{
|
||||||
|
if (mValueList.isEmpty())
|
||||||
|
return QVariant (val).toString();
|
||||||
|
|
||||||
|
QString value = "";
|
||||||
|
|
||||||
|
if (val < mValueList.size())
|
||||||
|
value = mValueList.at (val);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSVSettings::SpinBox::valueFromText(const QString &text) const
|
||||||
|
{
|
||||||
|
if (mValueList.isEmpty())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (mValueList.contains (text))
|
||||||
|
return mValueList.indexOf(text);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVSettings::SpinBox::setValue (const QString &value)
|
||||||
|
{
|
||||||
|
if (!mValueList.isEmpty())
|
||||||
|
{
|
||||||
|
lineEdit()->setText (value);
|
||||||
|
QSpinBox::setValue(valueFromText(value));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QSpinBox::setValue (value.toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVSettings::SpinBox::setValueList (const QStringList &list)
|
||||||
|
{
|
||||||
|
mValueList = list;
|
||||||
|
setMaximum (list.size() - 1);
|
||||||
|
}
|
31
apps/opencs/view/settings/spinbox.hpp
Normal file
31
apps/opencs/view/settings/spinbox.hpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef CSVSETTINGS_SPINBOX_HPP
|
||||||
|
#define CSVSETTINGS_SPINBOX_HPP
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QSpinBox>
|
||||||
|
|
||||||
|
namespace CSVSettings
|
||||||
|
{
|
||||||
|
class SpinBox : public QSpinBox
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
QStringList mValueList;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SpinBox(QWidget *parent = 0);
|
||||||
|
|
||||||
|
void setObjectName (const QString &name);
|
||||||
|
|
||||||
|
void setValue (const QString &value);
|
||||||
|
void setValueList (const QStringList &list);
|
||||||
|
const QStringList &valueList() const { return mValueList; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
QString textFromValue (int val) const;
|
||||||
|
int valueFromText (const QString &text) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // CSVSETTINGS_SPINBOX_HPP
|
|
@ -28,11 +28,6 @@ bool CSVSettings::TextView::isEquivalent
|
||||||
return (lhs.trimmed() == rhs.trimmed());
|
return (lhs.trimmed() == rhs.trimmed());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVSettings::TextView::setWidgetText (const QString &value) const
|
|
||||||
{
|
|
||||||
mTextWidget->setProperty ("text", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSVSettings::TextView::slotTextEdited (QString value)
|
void CSVSettings::TextView::slotTextEdited (QString value)
|
||||||
{
|
{
|
||||||
QStringList values = value.split (mDelimiter, QString::SkipEmptyParts);
|
QStringList values = value.split (mDelimiter, QString::SkipEmptyParts);
|
||||||
|
@ -51,19 +46,14 @@ void CSVSettings::TextView::updateView(bool signalUpdate) const
|
||||||
{
|
{
|
||||||
QString values = selectedValues().join (mDelimiter);
|
QString values = selectedValues().join (mDelimiter);
|
||||||
|
|
||||||
if (isEquivalent (widgetText(), values))
|
if (isEquivalent (mTextWidget->property("text").toString(), values))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setWidgetText (values);
|
mTextWidget->setProperty("text", values);
|
||||||
|
|
||||||
View::updateView (signalUpdate);
|
View::updateView (signalUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CSVSettings::TextView::widgetText() const
|
|
||||||
{
|
|
||||||
return mTextWidget->property("text").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
CSVSettings::TextView *CSVSettings::TextViewFactory::createView
|
CSVSettings::TextView *CSVSettings::TextViewFactory::createView
|
||||||
(CSMSettings::Setting *setting,
|
(CSMSettings::Setting *setting,
|
||||||
Page *parent)
|
Page *parent)
|
||||||
|
|
|
@ -32,12 +32,6 @@ namespace CSVSettings
|
||||||
///Comparison function that returns true if the trimmed() strings
|
///Comparison function that returns true if the trimmed() strings
|
||||||
///are equal
|
///are equal
|
||||||
bool isEquivalent (const QString &lhs, const QString &rhs) const;
|
bool isEquivalent (const QString &lhs, const QString &rhs) const;
|
||||||
|
|
||||||
///Convenience function to return the text of the widget
|
|
||||||
QString widgetText() const;
|
|
||||||
|
|
||||||
///Convenience function to set the text of the widget
|
|
||||||
void setWidgetText (const QString &value) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextViewFactory : public QObject, public IViewFactory
|
class TextViewFactory : public QObject, public IViewFactory
|
||||||
|
|
|
@ -192,6 +192,7 @@ bool CSVSettings::View::stringListsMatch (
|
||||||
QList <QStandardItem *> CSVSettings::View::toStandardItemList
|
QList <QStandardItem *> CSVSettings::View::toStandardItemList
|
||||||
(const QStringList &list) const
|
(const QStringList &list) const
|
||||||
{
|
{
|
||||||
|
|
||||||
QList <QStandardItem *> itemList;
|
QList <QStandardItem *> itemList;
|
||||||
|
|
||||||
foreach (const QString &value, list)
|
foreach (const QString &value, list)
|
||||||
|
|
|
@ -101,7 +101,7 @@ namespace CSVSettings
|
||||||
void showEvent ( QShowEvent * event );
|
void showEvent ( QShowEvent * event );
|
||||||
|
|
||||||
///Virtual for updating a specific View subclass
|
///Virtual for updating a specific View subclass
|
||||||
///bool indicates whether a signal is emitted that the view was updated
|
///bool indicates whether viewUpdated() signal is emitted
|
||||||
virtual void updateView (bool signalUpdate = true) const;
|
virtual void updateView (bool signalUpdate = true) const;
|
||||||
|
|
||||||
///Returns the pixel width corresponding to the specified number of
|
///Returns the pixel width corresponding to the specified number of
|
||||||
|
|
4
apps/opencs/view/world/datadisplaydelegate.cpp
Executable file → Normal file
4
apps/opencs/view/world/datadisplaydelegate.cpp
Executable file → Normal file
|
@ -25,7 +25,7 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values,
|
||||||
|
|
||||||
void CSVWorld::DataDisplayDelegate::buildPixmaps ()
|
void CSVWorld::DataDisplayDelegate::buildPixmaps ()
|
||||||
{
|
{
|
||||||
if (mPixmaps.size() > 0)
|
if (!mPixmaps.empty())
|
||||||
mPixmaps.clear();
|
mPixmaps.clear();
|
||||||
|
|
||||||
IconList::iterator it = mIcons.begin();
|
IconList::iterator it = mIcons.begin();
|
||||||
|
@ -33,7 +33,7 @@ void CSVWorld::DataDisplayDelegate::buildPixmaps ()
|
||||||
while (it != mIcons.end())
|
while (it != mIcons.end())
|
||||||
{
|
{
|
||||||
mPixmaps.push_back (std::make_pair (it->first, it->second.pixmap (mIconSize) ) );
|
mPixmaps.push_back (std::make_pair (it->first, it->second.pixmap (mIconSize) ) );
|
||||||
it++;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,7 @@ CSVWorld::CommandDelegate* CSVWorld::DialogueDelegateDispatcher::makeDelegate(CS
|
||||||
{
|
{
|
||||||
delegate = CommandDelegateFactoryCollection::get().makeDelegate (
|
delegate = CommandDelegateFactoryCollection::get().makeDelegate (
|
||||||
display, mUndoStack, mParent);
|
display, mUndoStack, mParent);
|
||||||
mDelegates.insert(std::make_pair<int, CommandDelegate*>(display, delegate));
|
mDelegates.insert(std::make_pair(display, delegate));
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
delegate = delegateIt->second;
|
delegate = delegateIt->second;
|
||||||
|
|
38
apps/opencs/view/world/dragrecordtable.cpp
Normal file
38
apps/opencs/view/world/dragrecordtable.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include <QDrag>
|
||||||
|
|
||||||
|
#include "../../model/world/tablemimedata.hpp"
|
||||||
|
#include "dragrecordtable.hpp"
|
||||||
|
|
||||||
|
void CSVWorld::DragRecordTable::startDrag (const CSVWorld::DragRecordTable& table)
|
||||||
|
{
|
||||||
|
CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDraggedRecords(), mDocument);
|
||||||
|
|
||||||
|
if (mime)
|
||||||
|
{
|
||||||
|
QDrag* drag = new QDrag (this);
|
||||||
|
drag->setMimeData (mime);
|
||||||
|
drag->setPixmap (QString::fromUtf8 (mime->getIcon().c_str()));
|
||||||
|
drag->exec (Qt::CopyAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document, QWidget* parent) :
|
||||||
|
mDocument(document),
|
||||||
|
QTableView(parent),
|
||||||
|
mEditLock(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void CSVWorld::DragRecordTable::setEditLock (bool locked)
|
||||||
|
{
|
||||||
|
mEditLock = locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::DragRecordTable::dragEnterEvent(QDragEnterEvent *event)
|
||||||
|
{
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::DragRecordTable::dragMoveEvent(QDragMoveEvent *event)
|
||||||
|
{
|
||||||
|
event->accept();
|
||||||
|
}
|
45
apps/opencs/view/world/dragrecordtable.hpp
Normal file
45
apps/opencs/view/world/dragrecordtable.hpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef CSV_WORLD_DRAGRECORDTABLE_H
|
||||||
|
#define CSV_WORLD_DRAGRECORDTABLE_H
|
||||||
|
|
||||||
|
#include <QTableView>
|
||||||
|
#include <QtGui/qevent.h>
|
||||||
|
|
||||||
|
class QWidget;
|
||||||
|
class QAction;
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class UniversalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSVWorld
|
||||||
|
{
|
||||||
|
class DragRecordTable : public QTableView
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
CSMDoc::Document& mDocument;
|
||||||
|
bool mEditLock;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DragRecordTable(CSMDoc::Document& document, QWidget* parent = NULL);
|
||||||
|
|
||||||
|
virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const = 0;
|
||||||
|
|
||||||
|
void setEditLock(bool locked);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void startDrag(const DragRecordTable& table);
|
||||||
|
|
||||||
|
void dragEnterEvent(QDragEnterEvent *event);
|
||||||
|
|
||||||
|
void dragMoveEvent(QDragMoveEvent *event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "../../model/world/idtable.hpp"
|
#include "../../model/world/idtable.hpp"
|
||||||
#include "../../model/world/commands.hpp"
|
#include "../../model/world/commands.hpp"
|
||||||
#include "../../model/world/columns.hpp"
|
#include "../../model/world/columns.hpp"
|
||||||
|
#include "../../model/world/tablemimedata.hpp"
|
||||||
|
|
||||||
void CSVWorld::RegionMap::contextMenuEvent (QContextMenuEvent *event)
|
void CSVWorld::RegionMap::contextMenuEvent (QContextMenuEvent *event)
|
||||||
{
|
{
|
||||||
|
@ -180,7 +181,7 @@ void CSVWorld::RegionMap::setRegion (const std::string& regionId)
|
||||||
|
|
||||||
CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId,
|
CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId,
|
||||||
CSMDoc::Document& document, QWidget *parent)
|
CSMDoc::Document& document, QWidget *parent)
|
||||||
: QTableView (parent), mEditLock (false), mDocument (document)
|
: DragRecordTable(document, parent)
|
||||||
{
|
{
|
||||||
verticalHeader()->hide();
|
verticalHeader()->hide();
|
||||||
horizontalHeader()->hide();
|
horizontalHeader()->hide();
|
||||||
|
@ -223,11 +224,8 @@ CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId,
|
||||||
mViewInTableAction = new QAction (tr ("View Cells in Table"), this);
|
mViewInTableAction = new QAction (tr ("View Cells in Table"), this);
|
||||||
connect (mViewInTableAction, SIGNAL (triggered()), this, SLOT (viewInTable()));
|
connect (mViewInTableAction, SIGNAL (triggered()), this, SLOT (viewInTable()));
|
||||||
addAction (mViewInTableAction);
|
addAction (mViewInTableAction);
|
||||||
}
|
|
||||||
|
|
||||||
void CSVWorld::RegionMap::setEditLock (bool locked)
|
setAcceptDrops(true);
|
||||||
{
|
|
||||||
mEditLock = locked;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::RegionMap::selectAll()
|
void CSVWorld::RegionMap::selectAll()
|
||||||
|
@ -344,3 +342,64 @@ void CSVWorld::RegionMap::viewInTable()
|
||||||
|
|
||||||
emit editRequest (CSMWorld::UniversalId::Type_Cells, hint.str());
|
emit editRequest (CSMWorld::UniversalId::Type_Cells, hint.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::RegionMap::mouseMoveEvent (QMouseEvent* event)
|
||||||
|
{
|
||||||
|
startDrag(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector< CSMWorld::UniversalId > CSVWorld::RegionMap::getDraggedRecords() const
|
||||||
|
{
|
||||||
|
QModelIndexList selected(getSelectedCells(true, false));
|
||||||
|
std::vector<CSMWorld::UniversalId> ids;
|
||||||
|
foreach (QModelIndex it, selected)
|
||||||
|
{
|
||||||
|
ids.push_back(
|
||||||
|
CSMWorld::UniversalId(
|
||||||
|
CSMWorld::UniversalId::Type_Cell,
|
||||||
|
model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData()));
|
||||||
|
}
|
||||||
|
selected = getSelectedCells(false, true);
|
||||||
|
foreach (QModelIndex it, selected)
|
||||||
|
{
|
||||||
|
ids.push_back(
|
||||||
|
CSMWorld::UniversalId(
|
||||||
|
CSMWorld::UniversalId::Type_Cell_Missing,
|
||||||
|
model()->data(it, CSMWorld::RegionMap::Role_CellId).toString().toUtf8().constData()));
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::RegionMap::dropEvent (QDropEvent* event)
|
||||||
|
{
|
||||||
|
QModelIndex index = indexAt (event->pos());
|
||||||
|
|
||||||
|
bool exists = QTableView::model()->data(index, Qt::BackgroundRole)!=QBrush (Qt::DiagCrossPattern);
|
||||||
|
|
||||||
|
if (!index.isValid() || !exists)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
|
||||||
|
if (mime->fromDocument(mDocument) && mime->holdsType(CSMWorld::UniversalId::Type_Region))
|
||||||
|
{
|
||||||
|
CSMWorld::UniversalId record (mime->returnMatching (CSMWorld::UniversalId::Type_Region));
|
||||||
|
|
||||||
|
QAbstractItemModel *regionModel = model();
|
||||||
|
|
||||||
|
CSMWorld::IdTable *cellsModel = &dynamic_cast<CSMWorld::IdTable&> (*
|
||||||
|
mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
|
||||||
|
|
||||||
|
std::string cellId(regionModel->data (index, CSMWorld::RegionMap::Role_CellId).
|
||||||
|
toString().toUtf8().constData());
|
||||||
|
|
||||||
|
QModelIndex index2(cellsModel->getModelIndex (cellId,
|
||||||
|
cellsModel->findColumnIndex (CSMWorld::Columns::ColumnId_Region)));
|
||||||
|
|
||||||
|
mDocument.getUndoStack().push(new CSMWorld::ModifyCommand
|
||||||
|
(*cellsModel, index2, QString::fromUtf8(record.getId().c_str())));
|
||||||
|
|
||||||
|
mRegionId = record.getId();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,14 @@
|
||||||
#ifndef CSV_WORLD_REGIONMAP_H
|
#ifndef CSV_WORLD_REGIONMAP_H
|
||||||
#define CSV_WORLD_REGIONMAP_H
|
#define CSV_WORLD_REGIONMAP_H
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
#include <QTableView>
|
#include <QTableView>
|
||||||
|
|
||||||
|
#include "./dragrecordtable.hpp"
|
||||||
|
|
||||||
class QAction;
|
class QAction;
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
|
@ -17,7 +23,7 @@ namespace CSMWorld
|
||||||
|
|
||||||
namespace CSVWorld
|
namespace CSVWorld
|
||||||
{
|
{
|
||||||
class RegionMap : public QTableView
|
class RegionMap : public DragRecordTable
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -29,8 +35,6 @@ namespace CSVWorld
|
||||||
QAction *mUnsetRegionAction;
|
QAction *mUnsetRegionAction;
|
||||||
QAction *mViewAction;
|
QAction *mViewAction;
|
||||||
QAction *mViewInTableAction;
|
QAction *mViewInTableAction;
|
||||||
bool mEditLock;
|
|
||||||
CSMDoc::Document& mDocument;
|
|
||||||
std::string mRegionId;
|
std::string mRegionId;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -50,12 +54,16 @@ namespace CSVWorld
|
||||||
void setRegion (const std::string& regionId);
|
void setRegion (const std::string& regionId);
|
||||||
///< Set region Id of selected cells.
|
///< Set region Id of selected cells.
|
||||||
|
|
||||||
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
|
|
||||||
|
void dropEvent(QDropEvent* event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document,
|
RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document,
|
||||||
QWidget *parent = 0);
|
QWidget *parent = 0);
|
||||||
|
|
||||||
void setEditLock (bool locked);
|
virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../model/doc/document.hpp"
|
#include "../../model/doc/document.hpp"
|
||||||
|
|
||||||
|
@ -18,11 +19,10 @@
|
||||||
|
|
||||||
#include "tablebottombox.hpp"
|
#include "tablebottombox.hpp"
|
||||||
#include "creator.hpp"
|
#include "creator.hpp"
|
||||||
#include "scenetoolbar.hpp"
|
|
||||||
#include "scenetoolmode.hpp"
|
#include "scenetoolmode.hpp"
|
||||||
|
|
||||||
CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
|
CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
|
||||||
: SubView (id)
|
: SubView (id), mLayout(new QHBoxLayout), mDocument(document), mScene(NULL), mToolbar(NULL)
|
||||||
{
|
{
|
||||||
QVBoxLayout *layout = new QVBoxLayout;
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
|
|
||||||
|
@ -32,33 +32,35 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
||||||
new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id,
|
new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id,
|
||||||
this), 0);
|
this), 0);
|
||||||
|
|
||||||
QHBoxLayout *layout2 = new QHBoxLayout;
|
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||||
|
|
||||||
layout2->setContentsMargins (QMargins (0, 0, 0, 0));
|
CSVRender::WorldspaceWidget* wordspaceWidget = NULL;
|
||||||
|
widgetType whatWidget;
|
||||||
SceneToolbar *toolbar = new SceneToolbar (48+6, this);
|
|
||||||
|
|
||||||
if (id.getId()=="sys::default")
|
if (id.getId()=="sys::default")
|
||||||
{
|
{
|
||||||
CSVRender::PagedWorldspaceWidget *widget = new CSVRender::PagedWorldspaceWidget (this);
|
whatWidget = widget_Paged;
|
||||||
mScene = widget;
|
|
||||||
connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)),
|
CSVRender::PagedWorldspaceWidget *newWidget = new CSVRender::PagedWorldspaceWidget (this, document);
|
||||||
this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&)));
|
|
||||||
|
wordspaceWidget = newWidget;
|
||||||
|
|
||||||
|
makeConnections(newWidget);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this);
|
{
|
||||||
|
whatWidget = widget_Unpaged;
|
||||||
|
|
||||||
SceneToolMode *navigationTool = mScene->makeNavigationSelector (toolbar);
|
CSVRender::UnpagedWorldspaceWidget *newWidget = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this);
|
||||||
toolbar->addTool (navigationTool);
|
|
||||||
|
|
||||||
SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar);
|
wordspaceWidget = newWidget;
|
||||||
toolbar->addTool (lightingTool);
|
|
||||||
|
|
||||||
layout2->addWidget (toolbar, 0);
|
makeConnections(newWidget);
|
||||||
|
}
|
||||||
|
|
||||||
layout2->addWidget (mScene, 1);
|
replaceToolbarAndWorldspace(wordspaceWidget, makeToolbar(wordspaceWidget, whatWidget));
|
||||||
|
|
||||||
layout->insertLayout (0, layout2, 1);
|
layout->insertLayout (0, mLayout, 1);
|
||||||
|
|
||||||
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
|
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
|
||||||
|
|
||||||
|
@ -69,10 +71,53 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
||||||
widget->setLayout (layout);
|
widget->setLayout (layout);
|
||||||
|
|
||||||
setWidget (widget);
|
setWidget (widget);
|
||||||
|
}
|
||||||
|
|
||||||
mScene->selectDefaultNavigationMode();
|
void CSVWorld::SceneSubView::makeConnections (CSVRender::UnpagedWorldspaceWidget* widget)
|
||||||
|
{
|
||||||
|
connect (widget, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
|
||||||
|
|
||||||
connect (mScene, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
|
connect(widget, SIGNAL(dataDropped(const std::vector<CSMWorld::UniversalId>&)),
|
||||||
|
this, SLOT(handleDrop(const std::vector<CSMWorld::UniversalId>&)));
|
||||||
|
|
||||||
|
connect(widget, SIGNAL(cellChanged(const CSMWorld::UniversalId&)),
|
||||||
|
this, SLOT(cellSelectionChanged(const CSMWorld::UniversalId&)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::SceneSubView::makeConnections (CSVRender::PagedWorldspaceWidget* widget)
|
||||||
|
{
|
||||||
|
connect (widget, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
|
||||||
|
|
||||||
|
connect(widget, SIGNAL(dataDropped(const std::vector<CSMWorld::UniversalId>&)),
|
||||||
|
this, SLOT(handleDrop(const std::vector<CSMWorld::UniversalId>&)));
|
||||||
|
|
||||||
|
connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)),
|
||||||
|
this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&)));
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVWorld::SceneToolbar* CSVWorld::SceneSubView::makeToolbar (CSVRender::WorldspaceWidget* widget, widgetType type)
|
||||||
|
{
|
||||||
|
CSVWorld::SceneToolbar* toolbar = new SceneToolbar (48+6, this);
|
||||||
|
|
||||||
|
SceneToolMode *navigationTool = widget->makeNavigationSelector (toolbar);
|
||||||
|
toolbar->addTool (navigationTool);
|
||||||
|
|
||||||
|
SceneToolMode *lightingTool = widget->makeLightingSelector (toolbar);
|
||||||
|
toolbar->addTool (lightingTool);
|
||||||
|
|
||||||
|
/* Add buttons specific to the type. For now no need for it.
|
||||||
|
*
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case widget_Paged:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case widget_Unpaged:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return toolbar;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::SceneSubView::setEditLock (bool locked)
|
void CSVWorld::SceneSubView::setEditLock (bool locked)
|
||||||
|
@ -102,8 +147,19 @@ void CSVWorld::SceneSubView::closeRequest()
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::UniversalId& id)
|
||||||
|
{
|
||||||
|
setUniversalId(id);
|
||||||
|
std::ostringstream stream;
|
||||||
|
stream << "Scene: " << getUniversalId().getId();
|
||||||
|
|
||||||
|
setWindowTitle (QString::fromUtf8 (stream.str().c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection& selection)
|
void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection& selection)
|
||||||
{
|
{
|
||||||
|
setUniversalId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Scene, "sys::default"));
|
||||||
int size = selection.getSize();
|
int size = selection.getSize();
|
||||||
|
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
|
@ -127,3 +183,61 @@ void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection
|
||||||
|
|
||||||
setWindowTitle (QString::fromUtf8 (stream.str().c_str()));
|
setWindowTitle (QString::fromUtf8 (stream.str().c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVWorld::SceneSubView::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
|
||||||
|
{
|
||||||
|
CSVRender::PagedWorldspaceWidget* pagedNewWidget = NULL;
|
||||||
|
CSVRender::UnpagedWorldspaceWidget* unPagedNewWidget = NULL;
|
||||||
|
SceneToolbar* toolbar = NULL;
|
||||||
|
|
||||||
|
switch (mScene->getDropRequirements(CSVRender::WorldspaceWidget::getDropType(data)))
|
||||||
|
{
|
||||||
|
case CSVRender::WorldspaceWidget::canHandle:
|
||||||
|
mScene->handleDrop(data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSVRender::WorldspaceWidget::needPaged:
|
||||||
|
pagedNewWidget = new CSVRender::PagedWorldspaceWidget(this, mDocument);
|
||||||
|
toolbar = makeToolbar(pagedNewWidget, widget_Paged);
|
||||||
|
makeConnections(pagedNewWidget);
|
||||||
|
replaceToolbarAndWorldspace(pagedNewWidget, toolbar);
|
||||||
|
mScene->handleDrop(data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSVRender::WorldspaceWidget::needUnpaged:
|
||||||
|
unPagedNewWidget = new CSVRender::UnpagedWorldspaceWidget(data.begin()->getId(), mDocument, this);
|
||||||
|
toolbar = makeToolbar(unPagedNewWidget, widget_Unpaged);
|
||||||
|
makeConnections(unPagedNewWidget);
|
||||||
|
replaceToolbarAndWorldspace(unPagedNewWidget, toolbar);
|
||||||
|
cellSelectionChanged(*(data.begin()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CSVRender::WorldspaceWidget::ignored:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceWidget* widget, CSVWorld::SceneToolbar* toolbar)
|
||||||
|
{
|
||||||
|
assert(mLayout);
|
||||||
|
|
||||||
|
if (mScene)
|
||||||
|
{
|
||||||
|
mLayout->removeWidget(mScene);
|
||||||
|
mScene->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mToolbar)
|
||||||
|
{
|
||||||
|
mLayout->removeWidget(mToolbar);
|
||||||
|
mToolbar->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
mScene = widget;
|
||||||
|
mToolbar = toolbar;
|
||||||
|
|
||||||
|
mLayout->addWidget (mToolbar, 0);
|
||||||
|
mLayout->addWidget (mScene, 1);
|
||||||
|
|
||||||
|
mScene->selectDefaultNavigationMode();
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
#ifndef CSV_WORLD_SCENESUBVIEW_H
|
#ifndef CSV_WORLD_SCENESUBVIEW_H
|
||||||
#define CSV_WORLD_SCENESUBVIEW_H
|
#define CSV_WORLD_SCENESUBVIEW_H
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
#include "../doc/subview.hpp"
|
#include "../doc/subview.hpp"
|
||||||
|
#include "scenetoolbar.hpp"
|
||||||
|
|
||||||
class QModelIndex;
|
class QModelIndex;
|
||||||
|
|
||||||
|
@ -18,6 +21,8 @@ namespace CSMDoc
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
class WorldspaceWidget;
|
class WorldspaceWidget;
|
||||||
|
class PagedWorldspaceWidget;
|
||||||
|
class UnpagedWorldspaceWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CSVWorld
|
namespace CSVWorld
|
||||||
|
@ -32,6 +37,9 @@ namespace CSVWorld
|
||||||
|
|
||||||
TableBottomBox *mBottom;
|
TableBottomBox *mBottom;
|
||||||
CSVRender::WorldspaceWidget *mScene;
|
CSVRender::WorldspaceWidget *mScene;
|
||||||
|
QHBoxLayout* mLayout;
|
||||||
|
CSMDoc::Document& mDocument;
|
||||||
|
SceneToolbar* mToolbar;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -45,11 +53,30 @@ namespace CSVWorld
|
||||||
|
|
||||||
virtual void useHint (const std::string& hint);
|
virtual void useHint (const std::string& hint);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void makeConnections(CSVRender::PagedWorldspaceWidget* widget);
|
||||||
|
|
||||||
|
void makeConnections(CSVRender::UnpagedWorldspaceWidget* widget);
|
||||||
|
|
||||||
|
void replaceToolbarAndWorldspace(CSVRender::WorldspaceWidget* widget, SceneToolbar* toolbar);
|
||||||
|
|
||||||
|
enum widgetType
|
||||||
|
{
|
||||||
|
widget_Paged,
|
||||||
|
widget_Unpaged
|
||||||
|
};
|
||||||
|
SceneToolbar* makeToolbar(CSVRender::WorldspaceWidget* widget, widgetType type);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void closeRequest();
|
void closeRequest();
|
||||||
|
|
||||||
void cellSelectionChanged (const CSMWorld::CellSelection& selection);
|
void cellSelectionChanged (const CSMWorld::CellSelection& selection);
|
||||||
|
|
||||||
|
void cellSelectionChanged (const CSMWorld::UniversalId& id);
|
||||||
|
|
||||||
|
void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,8 +188,8 @@ std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
|
||||||
|
|
||||||
CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
||||||
bool createAndDelete, bool sorting, CSMDoc::Document& document)
|
bool createAndDelete, bool sorting, CSMDoc::Document& document)
|
||||||
: mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0),
|
: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0),
|
||||||
mDocument (document)
|
DragRecordTable(document)
|
||||||
{
|
{
|
||||||
mModel = &dynamic_cast<CSMWorld::IdTable&> (*mDocument.getData().getTableModel (id));
|
mModel = &dynamic_cast<CSMWorld::IdTable&> (*mDocument.getData().getTableModel (id));
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ void CSVWorld::Table::setEditLock (bool locked)
|
||||||
for (std::vector<CommandDelegate *>::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter)
|
for (std::vector<CommandDelegate *>::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter)
|
||||||
(*iter)->setEditLock (locked);
|
(*iter)->setEditLock (locked);
|
||||||
|
|
||||||
mEditLock = locked;
|
DragRecordTable::setEditLock(locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
|
CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
|
||||||
|
@ -298,7 +298,7 @@ void CSVWorld::Table::revertRecord()
|
||||||
{
|
{
|
||||||
std::vector<std::string> revertableIds = listRevertableSelectedIds();
|
std::vector<std::string> revertableIds = listRevertableSelectedIds();
|
||||||
|
|
||||||
if (revertableIds.size()>0)
|
if (!revertableIds.empty())
|
||||||
{
|
{
|
||||||
if (revertableIds.size()>1)
|
if (revertableIds.size()>1)
|
||||||
mDocument.getUndoStack().beginMacro (tr ("Revert multiple records"));
|
mDocument.getUndoStack().beginMacro (tr ("Revert multiple records"));
|
||||||
|
@ -318,7 +318,7 @@ void CSVWorld::Table::deleteRecord()
|
||||||
{
|
{
|
||||||
std::vector<std::string> deletableIds = listDeletableSelectedIds();
|
std::vector<std::string> deletableIds = listDeletableSelectedIds();
|
||||||
|
|
||||||
if (deletableIds.size()>0)
|
if (!deletableIds.empty())
|
||||||
{
|
{
|
||||||
if (deletableIds.size()>1)
|
if (deletableIds.size()>1)
|
||||||
mDocument.getUndoStack().beginMacro (tr ("Delete multiple records"));
|
mDocument.getUndoStack().beginMacro (tr ("Delete multiple records"));
|
||||||
|
@ -518,42 +518,8 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event)
|
||||||
{
|
{
|
||||||
if (event->buttons() & Qt::LeftButton)
|
if (event->buttons() & Qt::LeftButton)
|
||||||
{
|
{
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
startDrag(*this);
|
||||||
|
|
||||||
if (selectedRows.size() == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QDrag* drag = new QDrag (this);
|
|
||||||
CSMWorld::TableMimeData* mime = NULL;
|
|
||||||
|
|
||||||
if (selectedRows.size() == 1)
|
|
||||||
{
|
|
||||||
mime = new CSMWorld::TableMimeData (getUniversalId (selectedRows.begin()->row()), mDocument);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::vector<CSMWorld::UniversalId> idToDrag;
|
|
||||||
|
|
||||||
foreach (QModelIndex it, selectedRows) //I had a dream. Dream where you could use C++11 in OpenMW.
|
|
||||||
{
|
|
||||||
idToDrag.push_back (getUniversalId (it.row()));
|
|
||||||
}
|
|
||||||
|
|
||||||
mime = new CSMWorld::TableMimeData (idToDrag, mDocument);
|
|
||||||
}
|
|
||||||
|
|
||||||
drag->setMimeData (mime);
|
|
||||||
drag->setPixmap (QString::fromUtf8 (mime->getIcon().c_str()));
|
|
||||||
drag->exec(Qt::CopyAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSVWorld::Table::dragEnterEvent(QDragEnterEvent *event)
|
|
||||||
{
|
|
||||||
event->acceptProposedAction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::Table::dropEvent(QDropEvent *event)
|
void CSVWorld::Table::dropEvent(QDropEvent *event)
|
||||||
|
@ -583,11 +549,6 @@ void CSVWorld::Table::dropEvent(QDropEvent *event)
|
||||||
} //TODO handle drops from different document
|
} //TODO handle drops from different document
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::Table::dragMoveEvent(QDragMoveEvent *event)
|
|
||||||
{
|
|
||||||
event->accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const
|
std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const
|
||||||
{
|
{
|
||||||
const int count = mModel->columnCount();
|
const int count = mModel->columnCount();
|
||||||
|
@ -605,3 +566,18 @@ std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column
|
||||||
}
|
}
|
||||||
return titles;
|
return titles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const
|
||||||
|
{
|
||||||
|
|
||||||
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
|
std::vector<CSMWorld::UniversalId> idToDrag;
|
||||||
|
|
||||||
|
foreach (QModelIndex it, selectedRows) //I had a dream. Dream where you could use C++11 in OpenMW.
|
||||||
|
{
|
||||||
|
idToDrag.push_back (getUniversalId (it.row()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return idToDrag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <QTableView>
|
|
||||||
#include <QtGui/qevent.h>
|
#include <QtGui/qevent.h>
|
||||||
|
|
||||||
#include "../../model/filter/node.hpp"
|
#include "../../model/filter/node.hpp"
|
||||||
#include "../../model/world/columnbase.hpp"
|
#include "../../model/world/columnbase.hpp"
|
||||||
|
#include "dragrecordtable.hpp"
|
||||||
|
|
||||||
class QUndoStack;
|
class QUndoStack;
|
||||||
class QAction;
|
class QAction;
|
||||||
|
@ -31,7 +31,7 @@ namespace CSVWorld
|
||||||
class CommandDelegate;
|
class CommandDelegate;
|
||||||
|
|
||||||
///< Table widget
|
///< Table widget
|
||||||
class Table : public QTableView
|
class Table : public DragRecordTable
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -47,9 +47,7 @@ namespace CSVWorld
|
||||||
QAction *mPreviewAction;
|
QAction *mPreviewAction;
|
||||||
CSMWorld::IdTableProxyModel *mProxyModel;
|
CSMWorld::IdTableProxyModel *mProxyModel;
|
||||||
CSMWorld::IdTable *mModel;
|
CSMWorld::IdTable *mModel;
|
||||||
bool mEditLock;
|
|
||||||
int mRecordStatusDisplay;
|
int mRecordStatusDisplay;
|
||||||
CSMDoc::Document& mDocument;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -61,10 +59,6 @@ namespace CSVWorld
|
||||||
|
|
||||||
void mouseMoveEvent(QMouseEvent *event);
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
|
|
||||||
void dragEnterEvent(QDragEnterEvent *event);
|
|
||||||
|
|
||||||
void dragMoveEvent(QDragMoveEvent *event);
|
|
||||||
|
|
||||||
void dropEvent(QDropEvent *event);
|
void dropEvent(QDropEvent *event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -74,12 +68,14 @@ namespace CSVWorld
|
||||||
///< \param createAndDelete Allow creation and deletion of records.
|
///< \param createAndDelete Allow creation and deletion of records.
|
||||||
/// \param sorting Allow changing order of rows in the view via column headers.
|
/// \param sorting Allow changing order of rows in the view via column headers.
|
||||||
|
|
||||||
void setEditLock (bool locked);
|
virtual void setEditLock (bool locked);
|
||||||
|
|
||||||
CSMWorld::UniversalId getUniversalId (int row) const;
|
CSMWorld::UniversalId getUniversalId (int row) const;
|
||||||
|
|
||||||
std::vector<std::string> getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const;
|
std::vector<std::string> getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const;
|
||||||
|
|
||||||
|
virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void editRequest (const CSMWorld::UniversalId& id, const std::string& hint);
|
void editRequest (const CSMWorld::UniversalId& id, const std::string& hint);
|
||||||
|
@ -92,6 +88,7 @@ namespace CSVWorld
|
||||||
/// \param modified Number of added and modified records
|
/// \param modified Number of added and modified records
|
||||||
|
|
||||||
void createRequest();
|
void createRequest();
|
||||||
|
|
||||||
void cloneRequest(const CSMWorld::UniversalId&);
|
void cloneRequest(const CSMWorld::UniversalId&);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
@ -48,7 +48,7 @@ add_openmw_dir (mwscript
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwsound
|
add_openmw_dir (mwsound
|
||||||
soundmanagerimp openal_output audiere_decoder mpgsnd_decoder ffmpeg_decoder
|
soundmanagerimp openal_output ffmpeg_decoder
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwworld
|
add_openmw_dir (mwworld
|
||||||
|
@ -67,7 +67,7 @@ add_openmw_dir (mwclass
|
||||||
|
|
||||||
add_openmw_dir (mwmechanics
|
add_openmw_dir (mwmechanics
|
||||||
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
mechanicsmanagerimp stat character creaturestats magiceffects movement actors objects
|
||||||
drawstate spells activespells npcstats aipackage aisequence aipersue alchemy aiwander aitravel aifollow
|
drawstate spells activespells npcstats aipackage aisequence aipursue alchemy aiwander aitravel aifollow
|
||||||
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
|
aiescort aiactivate aicombat repair enchanting pathfinding pathgrid security spellsuccess spellcasting
|
||||||
disease pickpocket levelledlist combat steering obstacle
|
disease pickpocket levelledlist combat steering obstacle
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace Loading
|
||||||
|
{
|
||||||
|
class Listener;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
class ESMReader;
|
class ESMReader;
|
||||||
|
@ -45,9 +50,6 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void goodbye() = 0;
|
virtual void goodbye() = 0;
|
||||||
|
|
||||||
virtual MWWorld::Ptr getActor() const = 0;
|
|
||||||
///< Return the actor the player is currently talking to.
|
|
||||||
|
|
||||||
virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const = 0;
|
virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const = 0;
|
||||||
|
|
||||||
//calbacks for the GUI
|
//calbacks for the GUI
|
||||||
|
@ -63,7 +65,7 @@ namespace MWBase
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const = 0;
|
virtual int countSavedGameRecords() const = 0;
|
||||||
|
|
||||||
virtual void write (ESM::ESMWriter& writer) const = 0;
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0;
|
||||||
|
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
#include "../mwdialogue/topic.hpp"
|
#include "../mwdialogue/topic.hpp"
|
||||||
#include "../mwdialogue/quest.hpp"
|
#include "../mwdialogue/quest.hpp"
|
||||||
|
|
||||||
|
namespace Loading
|
||||||
|
{
|
||||||
|
class Listener;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
class ESMReader;
|
class ESMReader;
|
||||||
|
@ -80,7 +85,7 @@ namespace MWBase
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const = 0;
|
virtual int countSavedGameRecords() const = 0;
|
||||||
|
|
||||||
virtual void write (ESM::ESMWriter& writer) const = 0;
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0;
|
||||||
|
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,6 +55,8 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void endGame() = 0;
|
virtual void endGame() = 0;
|
||||||
|
|
||||||
|
virtual void deleteGame (const MWState::Character *character, const MWState::Slot *slot) = 0;
|
||||||
|
|
||||||
virtual void saveGame (const std::string& description, const MWState::Slot *slot = 0) = 0;
|
virtual void saveGame (const std::string& description, const MWState::Slot *slot = 0) = 0;
|
||||||
///< Write a saved game to \a slot or create a new slot if \a slot == 0.
|
///< Write a saved game to \a slot or create a new slot if \a slot == 0.
|
||||||
///
|
///
|
||||||
|
|
|
@ -156,8 +156,9 @@ namespace MWBase
|
||||||
virtual void setValue (const std::string& id, int value) = 0;
|
virtual void setValue (const std::string& id, int value) = 0;
|
||||||
|
|
||||||
/// Set time left for the player to start drowning (update the drowning bar)
|
/// Set time left for the player to start drowning (update the drowning bar)
|
||||||
/// @param time value from [0,20]
|
/// @param time time left to start drowning
|
||||||
virtual void setDrowningTimeLeft (float time) =0;
|
/// @param maxTime how long we can be underwater (in total) until drowning starts
|
||||||
|
virtual void setDrowningTimeLeft (float time, float maxTime) = 0;
|
||||||
|
|
||||||
virtual void setPlayerClass (const ESM::Class &class_) = 0;
|
virtual void setPlayerClass (const ESM::Class &class_) = 0;
|
||||||
///< set current class of player
|
///< set current class of player
|
||||||
|
@ -302,8 +303,12 @@ namespace MWBase
|
||||||
/// Clear all savegame-specific data
|
/// Clear all savegame-specific data
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
|
|
||||||
virtual void write (ESM::ESMWriter& writer) = 0;
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) = 0;
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||||
|
virtual int countSavedGameRecords() const = 0;
|
||||||
|
|
||||||
|
/// Does the current stack of GUI-windows permit saving?
|
||||||
|
virtual bool isSavingAllowed() const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ namespace MWBase
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const = 0;
|
virtual int countSavedGameRecords() const = 0;
|
||||||
|
|
||||||
virtual void write (ESM::ESMWriter& writer) const = 0;
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const = 0;
|
||||||
|
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type,
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type,
|
||||||
const std::map<int, int>& contentFileMap) = 0;
|
const std::map<int, int>& contentFileMap) = 0;
|
||||||
|
@ -407,6 +407,8 @@ namespace MWBase
|
||||||
virtual bool getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) = 0;
|
virtual bool getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc) = 0;
|
||||||
///< get Line of Sight (morrowind stupid implementation)
|
///< get Line of Sight (morrowind stupid implementation)
|
||||||
|
|
||||||
|
virtual float getDistToNearestRayHit(const Ogre::Vector3& from, const Ogre::Vector3& dir, float maxDist) = 0;
|
||||||
|
|
||||||
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0;
|
virtual void enableActorCollision(const MWWorld::Ptr& actor, bool enable) = 0;
|
||||||
|
|
||||||
virtual int canRest() = 0;
|
virtual int canRest() = 0;
|
||||||
|
|
|
@ -624,6 +624,8 @@ namespace MWClass
|
||||||
if (!attacker.isEmpty() && ptr.getClass().isNpc() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30)
|
if (!attacker.isEmpty() && ptr.getClass().isNpc() && ptr.getClass().getCreatureStats(ptr).getAiSetting(MWMechanics::CreatureStats::AI_Fight).getModified() <= 30)
|
||||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
|
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
|
||||||
|
|
||||||
|
getCreatureStats(ptr).setAttacked(true);
|
||||||
|
|
||||||
if(!successful)
|
if(!successful)
|
||||||
{
|
{
|
||||||
// TODO: Handle HitAttemptOnMe script function
|
// TODO: Handle HitAttemptOnMe script function
|
||||||
|
@ -659,7 +661,6 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
||||||
}
|
}
|
||||||
getCreatureStats(ptr).setAttacked(true);
|
|
||||||
|
|
||||||
// Check for knockdown
|
// Check for knockdown
|
||||||
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat();
|
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat();
|
||||||
|
|
|
@ -170,6 +170,14 @@ namespace MWClass
|
||||||
virtual int getBaseGold(const MWWorld::Ptr& ptr) const;
|
virtual int getBaseGold(const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
virtual bool isClass(const MWWorld::Ptr& ptr, const std::string &className) const;
|
virtual bool isClass(const MWWorld::Ptr& ptr, const std::string &className) const;
|
||||||
|
|
||||||
|
virtual bool canSwim (const MWWorld::Ptr &ptr) const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool canWalk (const MWWorld::Ptr &ptr) const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -468,11 +468,6 @@ namespace MWDialogue
|
||||||
mIsInChoice = true;
|
mIsInChoice = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr DialogueManager::getActor() const
|
|
||||||
{
|
|
||||||
return mActor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DialogueManager::goodbye()
|
void DialogueManager::goodbye()
|
||||||
{
|
{
|
||||||
mIsInChoice = true;
|
mIsInChoice = true;
|
||||||
|
@ -614,7 +609,7 @@ namespace MWDialogue
|
||||||
return 1; // known topics
|
return 1; // known topics
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::write (ESM::ESMWriter& writer) const
|
void DialogueManager::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
|
||||||
{
|
{
|
||||||
ESM::DialogueState state;
|
ESM::DialogueState state;
|
||||||
|
|
||||||
|
@ -626,6 +621,7 @@ namespace MWDialogue
|
||||||
writer.startRecord (ESM::REC_DIAS);
|
writer.startRecord (ESM::REC_DIAS);
|
||||||
state.save (writer);
|
state.save (writer);
|
||||||
writer.endRecord (ESM::REC_DIAS);
|
writer.endRecord (ESM::REC_DIAS);
|
||||||
|
progress.increaseProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogueManager::readRecord (ESM::ESMReader& reader, int32_t type)
|
void DialogueManager::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||||
|
|
|
@ -68,9 +68,6 @@ namespace MWDialogue
|
||||||
|
|
||||||
virtual void goodbye();
|
virtual void goodbye();
|
||||||
|
|
||||||
virtual MWWorld::Ptr getActor() const;
|
|
||||||
///< Return the actor the player is currently talking to.
|
|
||||||
|
|
||||||
virtual bool checkServiceRefused ();
|
virtual bool checkServiceRefused ();
|
||||||
|
|
||||||
virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const;
|
virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const;
|
||||||
|
@ -86,7 +83,7 @@ namespace MWDialogue
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const;
|
virtual int countSavedGameRecords() const;
|
||||||
|
|
||||||
virtual void write (ESM::ESMWriter& writer) const;
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||||
|
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
};
|
};
|
||||||
|
|
|
@ -111,8 +111,14 @@ bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const
|
||||||
|
|
||||||
// check cell
|
// check cell
|
||||||
if (!info.mCell.empty())
|
if (!info.mCell.empty())
|
||||||
if (!Misc::StringUtils::ciEqual(player.getCell()->getCell()->mName, info.mCell))
|
{
|
||||||
|
// supports partial matches, just like getPcCell
|
||||||
|
const std::string& playerCell = player.getCell()->getCell()->mName;
|
||||||
|
bool match = playerCell.length()>=info.mCell.length() &&
|
||||||
|
Misc::StringUtils::ciEqual(playerCell.substr (0, info.mCell.length()), info.mCell);
|
||||||
|
if (!match)
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,7 @@ namespace MWDialogue
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Journal::write (ESM::ESMWriter& writer) const
|
void Journal::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
|
||||||
{
|
{
|
||||||
for (TQuestIter iter (mQuests.begin()); iter!=mQuests.end(); ++iter)
|
for (TQuestIter iter (mQuests.begin()); iter!=mQuests.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
@ -178,6 +178,7 @@ namespace MWDialogue
|
||||||
writer.startRecord (ESM::REC_QUES);
|
writer.startRecord (ESM::REC_QUES);
|
||||||
state.save (writer);
|
state.save (writer);
|
||||||
writer.endRecord (ESM::REC_QUES);
|
writer.endRecord (ESM::REC_QUES);
|
||||||
|
progress.increaseProgress();
|
||||||
|
|
||||||
for (Topic::TEntryIter iter (quest.begin()); iter!=quest.end(); ++iter)
|
for (Topic::TEntryIter iter (quest.begin()); iter!=quest.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
@ -188,6 +189,7 @@ namespace MWDialogue
|
||||||
writer.startRecord (ESM::REC_JOUR);
|
writer.startRecord (ESM::REC_JOUR);
|
||||||
entry.save (writer);
|
entry.save (writer);
|
||||||
writer.endRecord (ESM::REC_JOUR);
|
writer.endRecord (ESM::REC_JOUR);
|
||||||
|
progress.increaseProgress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +201,7 @@ namespace MWDialogue
|
||||||
writer.startRecord (ESM::REC_JOUR);
|
writer.startRecord (ESM::REC_JOUR);
|
||||||
entry.save (writer);
|
entry.save (writer);
|
||||||
writer.endRecord (ESM::REC_JOUR);
|
writer.endRecord (ESM::REC_JOUR);
|
||||||
|
progress.increaseProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TTopicIter iter (mTopics.begin()); iter!=mTopics.end(); ++iter)
|
for (TTopicIter iter (mTopics.begin()); iter!=mTopics.end(); ++iter)
|
||||||
|
@ -214,6 +217,7 @@ namespace MWDialogue
|
||||||
writer.startRecord (ESM::REC_JOUR);
|
writer.startRecord (ESM::REC_JOUR);
|
||||||
entry.save (writer);
|
entry.save (writer);
|
||||||
writer.endRecord (ESM::REC_JOUR);
|
writer.endRecord (ESM::REC_JOUR);
|
||||||
|
progress.increaseProgress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace MWDialogue
|
||||||
|
|
||||||
virtual int countSavedGameRecords() const;
|
virtual int countSavedGameRecords() const;
|
||||||
|
|
||||||
virtual void write (ESM::ESMWriter& writer) const;
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||||
|
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
};
|
};
|
||||||
|
|
|
@ -188,12 +188,13 @@ namespace MWGui
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GM_ClassCreate:
|
case GM_ClassCreate:
|
||||||
MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog);
|
if (!mCreateClassDialog)
|
||||||
mCreateClassDialog = 0;
|
{
|
||||||
mCreateClassDialog = new CreateClassDialog();
|
mCreateClassDialog = new CreateClassDialog();
|
||||||
mCreateClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
|
|
||||||
mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
|
mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
|
||||||
mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
|
mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
|
||||||
|
}
|
||||||
|
mCreateClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
|
||||||
mCreateClassDialog->setVisible(true);
|
mCreateClassDialog->setVisible(true);
|
||||||
if (mCreationStage < CSE_RaceChosen)
|
if (mCreationStage < CSE_RaceChosen)
|
||||||
mCreationStage = CSE_RaceChosen;
|
mCreationStage = CSE_RaceChosen;
|
||||||
|
@ -531,8 +532,8 @@ namespace MWGui
|
||||||
mPlayerClass = klass;
|
mPlayerClass = klass;
|
||||||
MWBase::Environment::get().getWindowManager()->setPlayerClass(klass);
|
MWBase::Environment::get().getWindowManager()->setPlayerClass(klass);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog);
|
// Do not delete dialog, so that choices are rembered in case we want to go back and adjust them later
|
||||||
mCreateClassDialog = 0;
|
mCreateClassDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePlayerHealth();
|
updatePlayerHealth();
|
||||||
|
@ -554,8 +555,8 @@ namespace MWGui
|
||||||
|
|
||||||
void CharacterCreation::onCreateClassDialogBack()
|
void CharacterCreation::onCreateClassDialogBack()
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog);
|
// Do not delete dialog, so that choices are rembered in case we want to go back and adjust them later
|
||||||
mCreateClassDialog = 0;
|
mCreateClassDialog->setVisible(false);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(GM_Class);
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompanionItemModel::copyItem (const ItemStack& item, size_t count)
|
void CompanionItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner=false)
|
||||||
{
|
{
|
||||||
if (mActor.getClass().isNpc())
|
if (mActor.getClass().isNpc())
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,7 @@ namespace MWGui
|
||||||
stats.modifyProfit(MWWorld::Class::get(item.mBase).getValue(item.mBase) * count);
|
stats.modifyProfit(MWWorld::Class::get(item.mBase).getValue(item.mBase) * count);
|
||||||
}
|
}
|
||||||
|
|
||||||
InventoryItemModel::copyItem(item, count);
|
InventoryItemModel::copyItem(item, count, setNewOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompanionItemModel::removeItem (const ItemStack& item, size_t count)
|
void CompanionItemModel::removeItem (const ItemStack& item, size_t count)
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace MWGui
|
||||||
public:
|
public:
|
||||||
CompanionItemModel (const MWWorld::Ptr& actor);
|
CompanionItemModel (const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
virtual void copyItem (const ItemStack& item, size_t count);
|
virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner);
|
||||||
virtual void removeItem (const ItemStack& item, size_t count);
|
virtual void removeItem (const ItemStack& item, size_t count);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -215,16 +215,22 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
std::vector<std::string> matches;
|
std::vector<std::string> matches;
|
||||||
listNames();
|
listNames();
|
||||||
mCommandLine->setCaption(complete( mCommandLine->getOnlyText(), matches ));
|
std::string oldCaption = mCommandLine->getCaption();
|
||||||
#if 0
|
std::string newCaption = complete( mCommandLine->getOnlyText(), matches );
|
||||||
|
mCommandLine->setCaption(newCaption);
|
||||||
|
|
||||||
|
// List candidates if repeatedly pressing tab
|
||||||
|
if (oldCaption == newCaption && matches.size())
|
||||||
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
printOK("");
|
||||||
for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); ++it,++i )
|
for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); ++it,++i )
|
||||||
{
|
{
|
||||||
printOK( *it );
|
printOK( *it );
|
||||||
if( i == 50 )
|
if( i == 50 )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mCommandHistory.empty()) return;
|
if(mCommandHistory.empty()) return;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "../mwworld/containerstore.hpp"
|
#include "../mwworld/containerstore.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/pickpocket.hpp"
|
#include "../mwmechanics/pickpocket.hpp"
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
#include "countdialog.hpp"
|
#include "countdialog.hpp"
|
||||||
#include "tradewindow.hpp"
|
#include "tradewindow.hpp"
|
||||||
|
@ -84,8 +85,7 @@ namespace MWGui
|
||||||
// otherwise, do the transfer
|
// otherwise, do the transfer
|
||||||
if (targetModel != mSourceModel)
|
if (targetModel != mSourceModel)
|
||||||
{
|
{
|
||||||
targetModel->copyItem(mItem, mDraggedCount);
|
mSourceModel->moveItem(mItem, mDraggedCount, targetModel);
|
||||||
mSourceModel->removeItem(mItem, mDraggedCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mSourceModel->update();
|
mSourceModel->update();
|
||||||
|
@ -292,8 +292,7 @@ namespace MWGui
|
||||||
if (!onTakeItem(item, item.mCount))
|
if (!onTakeItem(item, item.mCount))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
playerModel->copyItem(item, item.mCount);
|
mModel->moveItem(item, item.mCount, playerModel);
|
||||||
mModel->removeItem(item, item.mCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
||||||
|
@ -341,6 +340,10 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Looting a dead corpse is considered OK
|
||||||
|
if (mPtr.getClass().isActor() && mPtr.getClass().getCreatureStats(mPtr).isDead())
|
||||||
|
return true;
|
||||||
|
else
|
||||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, count);
|
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, count);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -71,7 +71,7 @@ ItemModel::ModelIndex ContainerItemModel::getIndex (ItemStack item)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainerItemModel::copyItem (const ItemStack& item, size_t count)
|
void ContainerItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner)
|
||||||
{
|
{
|
||||||
const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1];
|
const MWWorld::Ptr& source = mItemSources[mItemSources.size()-1];
|
||||||
if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source))
|
if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source))
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace MWGui
|
||||||
virtual ModelIndex getIndex (ItemStack item);
|
virtual ModelIndex getIndex (ItemStack item);
|
||||||
virtual size_t getItemCount();
|
virtual size_t getItemCount();
|
||||||
|
|
||||||
virtual void copyItem (const ItemStack& item, size_t count);
|
virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
|
||||||
virtual void removeItem (const ItemStack& item, size_t count);
|
virtual void removeItem (const ItemStack& item, size_t count);
|
||||||
|
|
||||||
virtual void update();
|
virtual void update();
|
||||||
|
|
|
@ -196,6 +196,16 @@ namespace MWGui
|
||||||
bitmapFile->read(&textureData[0], width*height*4);
|
bitmapFile->read(&textureData[0], width*height*4);
|
||||||
bitmapFile->close();
|
bitmapFile->close();
|
||||||
|
|
||||||
|
std::string resourceName;
|
||||||
|
if (name.size() >= 5 && Misc::StringUtils::ciEqual(name.substr(0, 5), "magic"))
|
||||||
|
resourceName = "Magic Cards";
|
||||||
|
else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "century"))
|
||||||
|
resourceName = "Century Gothic";
|
||||||
|
else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "daedric"))
|
||||||
|
resourceName = "Daedric";
|
||||||
|
else
|
||||||
|
return; // no point in loading it, since there is no way of using additional fonts
|
||||||
|
|
||||||
std::string textureName = name;
|
std::string textureName = name;
|
||||||
Ogre::Image image;
|
Ogre::Image image;
|
||||||
image.loadDynamicImage(&textureData[0], width, height, Ogre::PF_BYTE_RGBA);
|
image.loadDynamicImage(&textureData[0], width, height, Ogre::PF_BYTE_RGBA);
|
||||||
|
@ -208,18 +218,11 @@ namespace MWGui
|
||||||
// Register the font with MyGUI
|
// Register the font with MyGUI
|
||||||
MyGUI::ResourceManualFont* font = static_cast<MyGUI::ResourceManualFont*>(
|
MyGUI::ResourceManualFont* font = static_cast<MyGUI::ResourceManualFont*>(
|
||||||
MyGUI::FactoryManager::getInstance().createObject("Resource", "ResourceManualFont"));
|
MyGUI::FactoryManager::getInstance().createObject("Resource", "ResourceManualFont"));
|
||||||
|
|
||||||
// We need to emulate loading from XML because the data members are private as of mygui 3.2.0
|
// We need to emulate loading from XML because the data members are private as of mygui 3.2.0
|
||||||
MyGUI::xml::Document xmlDocument;
|
MyGUI::xml::Document xmlDocument;
|
||||||
MyGUI::xml::ElementPtr root = xmlDocument.createRoot("ResourceManualFont");
|
MyGUI::xml::ElementPtr root = xmlDocument.createRoot("ResourceManualFont");
|
||||||
|
root->addAttribute("name", resourceName);
|
||||||
if (name.size() >= 5 && Misc::StringUtils::ciEqual(name.substr(0, 5), "magic"))
|
|
||||||
root->addAttribute("name", "Magic Cards");
|
|
||||||
else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "century"))
|
|
||||||
root->addAttribute("name", "Century Gothic");
|
|
||||||
else if (name.size() >= 7 && Misc::StringUtils::ciEqual(name.substr(0, 7), "daedric"))
|
|
||||||
root->addAttribute("name", "Daedric");
|
|
||||||
else
|
|
||||||
return; // no point in loading it, since there is no way of using additional fonts
|
|
||||||
|
|
||||||
MyGUI::xml::ElementPtr defaultHeight = root->createChild("Property");
|
MyGUI::xml::ElementPtr defaultHeight = root->createChild("Property");
|
||||||
defaultHeight->addAttribute("key", "DefaultHeight");
|
defaultHeight->addAttribute("key", "DefaultHeight");
|
||||||
|
@ -285,6 +288,7 @@ namespace MWGui
|
||||||
|
|
||||||
font->deserialization(root, MyGUI::Version(3,2,0));
|
font->deserialization(root, MyGUI::Version(3,2,0));
|
||||||
|
|
||||||
|
MyGUI::ResourceManager::getInstance().removeByName(font->getResourceName());
|
||||||
MyGUI::ResourceManager::getInstance().addResource(font);
|
MyGUI::ResourceManager::getInstance().addResource(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace MWGui
|
||||||
, mWeaponVisible(true)
|
, mWeaponVisible(true)
|
||||||
, mSpellVisible(true)
|
, mSpellVisible(true)
|
||||||
, mWorldMouseOver(false)
|
, mWorldMouseOver(false)
|
||||||
, mEnemyHealthTimer(0)
|
, mEnemyHealthTimer(-1)
|
||||||
, mIsDrowning(false)
|
, mIsDrowning(false)
|
||||||
, mWeaponSpellTimer(0.f)
|
, mWeaponSpellTimer(0.f)
|
||||||
, mDrowningFlashTheta(0.f)
|
, mDrowningFlashTheta(0.f)
|
||||||
|
@ -203,9 +203,9 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HUD::setDrowningTimeLeft(float time)
|
void HUD::setDrowningTimeLeft(float time, float maxTime)
|
||||||
{
|
{
|
||||||
size_t progress = time/20.0*200.0;
|
size_t progress = time/maxTime*200.0;
|
||||||
mDrowning->setProgressPosition(progress);
|
mDrowning->setProgressPosition(progress);
|
||||||
|
|
||||||
bool isDrowning = (progress == 0);
|
bool isDrowning = (progress == 0);
|
||||||
|
@ -625,7 +625,7 @@ namespace MWGui
|
||||||
if (mIsDrowning)
|
if (mIsDrowning)
|
||||||
{
|
{
|
||||||
float intensity = (cos(mDrowningFlashTheta) + 1.0f) / 2.0f;
|
float intensity = (cos(mDrowningFlashTheta) + 1.0f) / 2.0f;
|
||||||
mDrowningFlash->setColour(MyGUI::Colour(intensity, intensity, intensity));
|
mDrowningFlash->setColour(MyGUI::Colour(intensity, 0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,4 +639,10 @@ namespace MWGui
|
||||||
updateEnemyHealthBar();
|
updateEnemyHealthBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HUD::resetEnemy()
|
||||||
|
{
|
||||||
|
mEnemy = MWWorld::Ptr();
|
||||||
|
mEnemyHealthTimer = -1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,9 @@ namespace MWGui
|
||||||
void setBatchCount(unsigned int count);
|
void setBatchCount(unsigned int count);
|
||||||
|
|
||||||
/// Set time left for the player to start drowning
|
/// Set time left for the player to start drowning
|
||||||
/// @param time value from [0,20]
|
/// @param time time left to start drowning
|
||||||
void setDrowningTimeLeft(float time);
|
/// @param maxTime how long we can be underwater (in total) until drowning starts
|
||||||
|
void setDrowningTimeLeft(float time, float maxTime);
|
||||||
void setDrowningBarVisible(bool visible);
|
void setDrowningBarVisible(bool visible);
|
||||||
|
|
||||||
void setHmsVisible(bool visible);
|
void setHmsVisible(bool visible);
|
||||||
|
@ -56,6 +57,7 @@ namespace MWGui
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
void setEnemy(const MWWorld::Ptr& enemy);
|
void setEnemy(const MWWorld::Ptr& enemy);
|
||||||
|
void resetEnemy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning;
|
MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/creaturestats.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -38,11 +40,11 @@ ItemModel::ModelIndex InventoryItemModel::getIndex (ItemStack item)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryItemModel::copyItem (const ItemStack& item, size_t count)
|
void InventoryItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner)
|
||||||
{
|
{
|
||||||
if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor))
|
if (item.mBase.getContainerStore() == &mActor.getClass().getContainerStore(mActor))
|
||||||
throw std::runtime_error("Item to copy needs to be from a different container!");
|
throw std::runtime_error("Item to copy needs to be from a different container!");
|
||||||
mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor);
|
mActor.getClass().getContainerStore(mActor).add(item.mBase, count, mActor, setNewOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,6 +59,18 @@ void InventoryItemModel::removeItem (const ItemStack& item, size_t count)
|
||||||
throw std::runtime_error("Not enough items in the stack to remove");
|
throw std::runtime_error("Not enough items in the stack to remove");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InventoryItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel)
|
||||||
|
{
|
||||||
|
bool setNewOwner = false;
|
||||||
|
|
||||||
|
// Are you dead? Then you wont need that anymore
|
||||||
|
if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead())
|
||||||
|
setNewOwner = true;
|
||||||
|
|
||||||
|
otherModel->copyItem(item, count, setNewOwner);
|
||||||
|
removeItem(item, count);
|
||||||
|
}
|
||||||
|
|
||||||
void InventoryItemModel::update()
|
void InventoryItemModel::update()
|
||||||
{
|
{
|
||||||
MWWorld::ContainerStore& store = MWWorld::Class::get(mActor).getContainerStore(mActor);
|
MWWorld::ContainerStore& store = MWWorld::Class::get(mActor).getContainerStore(mActor);
|
||||||
|
|
|
@ -15,9 +15,12 @@ namespace MWGui
|
||||||
virtual ModelIndex getIndex (ItemStack item);
|
virtual ModelIndex getIndex (ItemStack item);
|
||||||
virtual size_t getItemCount();
|
virtual size_t getItemCount();
|
||||||
|
|
||||||
virtual void copyItem (const ItemStack& item, size_t count);
|
virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
|
||||||
virtual void removeItem (const ItemStack& item, size_t count);
|
virtual void removeItem (const ItemStack& item, size_t count);
|
||||||
|
|
||||||
|
/// Move items from this model to \a otherModel.
|
||||||
|
virtual void moveItem (const ItemStack& item, size_t count, ItemModel* otherModel);
|
||||||
|
|
||||||
virtual void update();
|
virtual void update();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace MWGui
|
||||||
, mTrading(false)
|
, mTrading(false)
|
||||||
, mLastXSize(0)
|
, mLastXSize(0)
|
||||||
, mLastYSize(0)
|
, mLastYSize(0)
|
||||||
, mPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr())
|
, mPreview(new MWRender::InventoryPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr()))
|
||||||
, mPreviewDirty(true)
|
, mPreviewDirty(true)
|
||||||
, mDragAndDrop(dragAndDrop)
|
, mDragAndDrop(dragAndDrop)
|
||||||
, mSelectedItem(-1)
|
, mSelectedItem(-1)
|
||||||
|
@ -91,8 +91,8 @@ namespace MWGui
|
||||||
mTradeModel = new TradeItemModel(new InventoryItemModel(mPtr), MWWorld::Ptr());
|
mTradeModel = new TradeItemModel(new InventoryItemModel(mPtr), MWWorld::Ptr());
|
||||||
mSortModel = new SortFilterItemModel(mTradeModel);
|
mSortModel = new SortFilterItemModel(mTradeModel);
|
||||||
mItemView->setModel(mSortModel);
|
mItemView->setModel(mSortModel);
|
||||||
mPreview = MWRender::InventoryPreview(mPtr);
|
mPreview.reset(new MWRender::InventoryPreview(mPtr));
|
||||||
mPreview.setup();
|
mPreview->setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryWindow::setGuiMode(GuiMode mode)
|
void InventoryWindow::setGuiMode(GuiMode mode)
|
||||||
|
@ -444,7 +444,7 @@ namespace MWGui
|
||||||
|
|
||||||
MWWorld::Ptr InventoryWindow::getAvatarSelectedItem(int x, int y)
|
MWWorld::Ptr InventoryWindow::getAvatarSelectedItem(int x, int y)
|
||||||
{
|
{
|
||||||
int slot = mPreview.getSlotSelected (x, y);
|
int slot = mPreview->getSlotSelected (x, y);
|
||||||
|
|
||||||
if (slot == -1)
|
if (slot == -1)
|
||||||
return MWWorld::Ptr();
|
return MWWorld::Ptr();
|
||||||
|
@ -493,7 +493,7 @@ namespace MWGui
|
||||||
mPreviewDirty = false;
|
mPreviewDirty = false;
|
||||||
MyGUI::IntSize size = mAvatarImage->getSize();
|
MyGUI::IntSize size = mAvatarImage->getSize();
|
||||||
|
|
||||||
mPreview.update (size.width, size.height);
|
mPreview->update (size.width, size.height);
|
||||||
|
|
||||||
mAvatarImage->setImageTexture("CharacterPreview");
|
mAvatarImage->setImageTexture("CharacterPreview");
|
||||||
mAvatarImage->setImageCoord(MyGUI::IntCoord(0, 0, std::min(512, size.width), std::min(1024, size.height)));
|
mAvatarImage->setImageCoord(MyGUI::IntCoord(0, 0, std::min(512, size.width), std::min(1024, size.height)));
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace MWGui
|
||||||
MWWorld::Ptr getAvatarSelectedItem(int x, int y);
|
MWWorld::Ptr getAvatarSelectedItem(int x, int y);
|
||||||
|
|
||||||
void rebuildAvatar() {
|
void rebuildAvatar() {
|
||||||
mPreview.rebuild();
|
mPreview->rebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
TradeItemModel* getTradeModel();
|
TradeItemModel* getTradeModel();
|
||||||
|
@ -81,7 +81,7 @@ namespace MWGui
|
||||||
int mLastXSize;
|
int mLastXSize;
|
||||||
int mLastYSize;
|
int mLastYSize;
|
||||||
|
|
||||||
MWRender::InventoryPreview mPreview;
|
std::auto_ptr<MWRender::InventoryPreview> mPreview;
|
||||||
|
|
||||||
bool mTrading;
|
bool mTrading;
|
||||||
|
|
||||||
|
|
|
@ -71,16 +71,22 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ItemModel::moveItem(const ItemStack &item, size_t count, ItemModel *otherModel)
|
||||||
|
{
|
||||||
|
otherModel->copyItem(item, count);
|
||||||
|
removeItem(item, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ProxyItemModel::~ProxyItemModel()
|
ProxyItemModel::~ProxyItemModel()
|
||||||
{
|
{
|
||||||
delete mSourceModel;
|
delete mSourceModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyItemModel::copyItem (const ItemStack& item, size_t count)
|
void ProxyItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner)
|
||||||
{
|
{
|
||||||
// no need to use mapToSource since itemIndex refers to an index in the sourceModel
|
// no need to use mapToSource since itemIndex refers to an index in the sourceModel
|
||||||
mSourceModel->copyItem (item, count);
|
mSourceModel->copyItem (item, count, setNewOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyItemModel::removeItem (const ItemStack& item, size_t count)
|
void ProxyItemModel::removeItem (const ItemStack& item, size_t count)
|
||||||
|
|
|
@ -55,7 +55,11 @@ namespace MWGui
|
||||||
|
|
||||||
virtual void update() = 0;
|
virtual void update() = 0;
|
||||||
|
|
||||||
virtual void copyItem (const ItemStack& item, size_t count) = 0;
|
/// Move items from this model to \a otherModel.
|
||||||
|
virtual void moveItem (const ItemStack& item, size_t count, ItemModel* otherModel);
|
||||||
|
|
||||||
|
/// @param setNewOwner Set the copied item's owner to the actor we are copying to, or keep the original owner?
|
||||||
|
virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) = 0;
|
||||||
virtual void removeItem (const ItemStack& item, size_t count) = 0;
|
virtual void removeItem (const ItemStack& item, size_t count) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -69,7 +73,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~ProxyItemModel();
|
virtual ~ProxyItemModel();
|
||||||
virtual void copyItem (const ItemStack& item, size_t count);
|
virtual void copyItem (const ItemStack& item, size_t count, bool setNewOwner=false);
|
||||||
virtual void removeItem (const ItemStack& item, size_t count);
|
virtual void removeItem (const ItemStack& item, size_t count);
|
||||||
virtual ModelIndex getIndex (ItemStack item);
|
virtual ModelIndex getIndex (ItemStack item);
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ namespace MWGui
|
||||||
|
|
||||||
void MWList::redraw(bool scrollbarShown)
|
void MWList::redraw(bool scrollbarShown)
|
||||||
{
|
{
|
||||||
const int _scrollBarWidth = 24; // fetch this from skin?
|
const int _scrollBarWidth = 20; // fetch this from skin?
|
||||||
const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0;
|
const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0;
|
||||||
const int spacing = 3;
|
const int spacing = 3;
|
||||||
size_t scrollbarPosition = mScrollView->getScrollPosition();
|
size_t scrollbarPosition = mScrollView->getScrollPosition();
|
||||||
|
@ -83,7 +83,7 @@ namespace MWGui
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MyGUI::ImageBox* separator = mScrollView->createWidget<MyGUI::ImageBox>("MW_HLine",
|
MyGUI::ImageBox* separator = mScrollView->createWidget<MyGUI::ImageBox>("MW_HLine",
|
||||||
MyGUI::IntCoord(2, mItemHeight, mScrollView->getWidth()-4, 18),
|
MyGUI::IntCoord(2, mItemHeight, mScrollView->getWidth() - scrollBarWidth - 4, 18),
|
||||||
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
|
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
|
||||||
separator->setNeedMouseFocus(false);
|
separator->setNeedMouseFocus(false);
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
mScrollView->setCanvasSize(mClient->getSize().width + (_scrollBarWidth-scrollBarWidth), std::max(mItemHeight, mClient->getSize().height));
|
mScrollView->setCanvasSize(mClient->getSize().width, std::max(mItemHeight, mClient->getSize().height));
|
||||||
|
|
||||||
if (!scrollbarShown && mItemHeight > mClient->getSize().height)
|
if (!scrollbarShown && mItemHeight > mClient->getSize().height)
|
||||||
redraw(true);
|
redraw(true);
|
||||||
|
|
|
@ -160,7 +160,6 @@ namespace MWGui
|
||||||
|
|
||||||
void LoadingScreen::setProgress (size_t value)
|
void LoadingScreen::setProgress (size_t value)
|
||||||
{
|
{
|
||||||
assert(value < mProgressBar->getScrollRange());
|
|
||||||
if (value - mProgress < mProgressBar->getScrollRange()/100.f)
|
if (value - mProgress < mProgressBar->getScrollRange()/100.f)
|
||||||
return;
|
return;
|
||||||
mProgress = value;
|
mProgress = value;
|
||||||
|
@ -174,7 +173,6 @@ namespace MWGui
|
||||||
mProgressBar->setScrollPosition(0);
|
mProgressBar->setScrollPosition(0);
|
||||||
size_t value = mProgress + increase;
|
size_t value = mProgress + increase;
|
||||||
mProgress = value;
|
mProgress = value;
|
||||||
assert(mProgress < mProgressBar->getScrollRange());
|
|
||||||
mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize());
|
mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize());
|
||||||
draw();
|
draw();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace MWGui
|
||||||
|
|
||||||
virtual void setProgressRange (size_t range);
|
virtual void setProgressRange (size_t range);
|
||||||
virtual void setProgress (size_t value);
|
virtual void setProgress (size_t value);
|
||||||
virtual void increaseProgress (size_t increase);
|
virtual void increaseProgress (size_t increase=1);
|
||||||
|
|
||||||
virtual void setVisible(bool visible);
|
virtual void setVisible(bool visible);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
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 available
|
// adding info about git hash if available
|
||||||
std::string rev = OPENMW_VERSION_COMMITHASH;
|
std::string rev = OPENMW_VERSION_COMMITHASH;
|
||||||
|
@ -36,7 +36,7 @@ namespace MWGui
|
||||||
if (!rev.empty() && !tag.empty())
|
if (!rev.empty() && !tag.empty())
|
||||||
{
|
{
|
||||||
rev = rev.substr(0,10);
|
rev = rev.substr(0,10);
|
||||||
sstream << "\nrevision: " << rev;
|
sstream << "\nRevision: " << rev;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string output = sstream.str();
|
std::string output = sstream.str();
|
||||||
|
@ -170,7 +170,8 @@ namespace MWGui
|
||||||
buttons.push_back("loadgame");
|
buttons.push_back("loadgame");
|
||||||
|
|
||||||
if (state==MWBase::StateManager::State_Running &&
|
if (state==MWBase::StateManager::State_Running &&
|
||||||
MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1)
|
MWBase::Environment::get().getWorld()->getGlobalInt ("chargenstate")==-1 &&
|
||||||
|
MWBase::Environment::get().getWindowManager()->isSavingAllowed())
|
||||||
buttons.push_back("savegame");
|
buttons.push_back("savegame");
|
||||||
|
|
||||||
buttons.push_back("options");
|
buttons.push_back("options");
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "../mwrender/globalmap.hpp"
|
#include "../mwrender/globalmap.hpp"
|
||||||
|
|
||||||
|
#include "../components/esm/globalmap.hpp"
|
||||||
|
|
||||||
#include "widgets.hpp"
|
#include "widgets.hpp"
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
|
@ -436,7 +438,6 @@ namespace MWGui
|
||||||
worldY * mGlobalMapRender->getHeight()+6,
|
worldY * mGlobalMapRender->getHeight()+6,
|
||||||
12, 12);
|
12, 12);
|
||||||
|
|
||||||
|
|
||||||
static int _counter=0;
|
static int _counter=0;
|
||||||
MyGUI::Button* markerWidget = mGlobalMapOverlay->createWidget<MyGUI::Button>("ButtonImage",
|
MyGUI::Button* markerWidget = mGlobalMapOverlay->createWidget<MyGUI::Button>("ButtonImage",
|
||||||
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
|
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
|
||||||
|
@ -452,6 +453,11 @@ namespace MWGui
|
||||||
markerWidget->setUserString("ToolTipType", "Layout");
|
markerWidget->setUserString("ToolTipType", "Layout");
|
||||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||||
markerWidget->setUserString("Caption_TextOneLine", name);
|
markerWidget->setUserString("Caption_TextOneLine", name);
|
||||||
|
|
||||||
|
CellId cell;
|
||||||
|
cell.first = x;
|
||||||
|
cell.second = y;
|
||||||
|
mMarkers.push_back(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWindow::cellExplored(int x, int y)
|
void MapWindow::cellExplored(int x, int y)
|
||||||
|
@ -580,6 +586,7 @@ namespace MWGui
|
||||||
|
|
||||||
void MapWindow::clear()
|
void MapWindow::clear()
|
||||||
{
|
{
|
||||||
|
mMarkers.clear();
|
||||||
mGlobalMapRender->clear();
|
mGlobalMapRender->clear();
|
||||||
|
|
||||||
while (mEventBoxGlobal->getChildCount())
|
while (mEventBoxGlobal->getChildCount())
|
||||||
|
@ -588,21 +595,34 @@ namespace MWGui
|
||||||
MyGUI::Gui::getInstance().destroyWidget(mGlobalMapOverlay->getChildAt(0));
|
MyGUI::Gui::getInstance().destroyWidget(mGlobalMapOverlay->getChildAt(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWindow::write(ESM::ESMWriter &writer)
|
void MapWindow::write(ESM::ESMWriter &writer, Loading::Listener& progress)
|
||||||
{
|
{
|
||||||
mGlobalMapRender->write(writer);
|
ESM::GlobalMap map;
|
||||||
|
mGlobalMapRender->write(map);
|
||||||
|
|
||||||
|
map.mMarkers = mMarkers;
|
||||||
|
|
||||||
|
writer.startRecord(ESM::REC_GMAP);
|
||||||
|
map.save(writer);
|
||||||
|
writer.endRecord(ESM::REC_GMAP);
|
||||||
|
progress.increaseProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWindow::readRecord(ESM::ESMReader &reader, int32_t type)
|
void MapWindow::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<int, int> > exploredCells;
|
if (type == ESM::REC_GMAP)
|
||||||
mGlobalMapRender->readRecord(reader, type, exploredCells);
|
{
|
||||||
|
ESM::GlobalMap map;
|
||||||
|
map.load(reader);
|
||||||
|
|
||||||
for (std::vector<std::pair<int, int> >::iterator it = exploredCells.begin(); it != exploredCells.end(); ++it)
|
mGlobalMapRender->read(map);
|
||||||
|
|
||||||
|
for (std::vector<ESM::GlobalMap::CellId>::iterator it = map.mMarkers.begin(); it != map.mMarkers.end(); ++it)
|
||||||
{
|
{
|
||||||
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>().search(it->first, it->second);
|
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>().search(it->first, it->second);
|
||||||
if (cell && !cell->mName.empty())
|
if (cell && !cell->mName.empty())
|
||||||
addVisitedLocation(cell->mName, it->first, it->second);
|
addVisitedLocation(cell->mName, it->first, it->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,9 @@ namespace MWGui
|
||||||
bool mChanged;
|
bool mChanged;
|
||||||
bool mFogOfWar;
|
bool mFogOfWar;
|
||||||
|
|
||||||
|
typedef std::pair<int, int> CellId;
|
||||||
|
std::vector<CellId> mMarkers;
|
||||||
|
|
||||||
std::vector<MyGUI::ImageBox*> mMapWidgets;
|
std::vector<MyGUI::ImageBox*> mMapWidgets;
|
||||||
std::vector<MyGUI::ImageBox*> mFogWidgets;
|
std::vector<MyGUI::ImageBox*> mFogWidgets;
|
||||||
|
|
||||||
|
@ -105,7 +108,7 @@ namespace MWGui
|
||||||
/// Clear all savegame-specific data
|
/// Clear all savegame-specific data
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void write (ESM::ESMWriter& writer);
|
void write (ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||||
void readRecord (ESM::ESMReader& reader, int32_t type);
|
void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#include <components/esm/quickkeys.hpp>
|
||||||
|
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
@ -55,6 +57,14 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuickKeysMenu::clear()
|
||||||
|
{
|
||||||
|
for (int i=0; i<10; ++i)
|
||||||
|
{
|
||||||
|
unassign(mQuickKeyButtons[i], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QuickKeysMenu::~QuickKeysMenu()
|
QuickKeysMenu::~QuickKeysMenu()
|
||||||
{
|
{
|
||||||
delete mAssignDialog;
|
delete mAssignDialog;
|
||||||
|
@ -154,8 +164,6 @@ namespace MWGui
|
||||||
frame->setUserString ("ToolTipType", "ItemPtr");
|
frame->setUserString ("ToolTipType", "ItemPtr");
|
||||||
frame->setUserData(item);
|
frame->setUserData(item);
|
||||||
frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked);
|
frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked);
|
||||||
|
|
||||||
|
|
||||||
MyGUI::ImageBox* image = frame->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
|
MyGUI::ImageBox* image = frame->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
|
||||||
std::string path = std::string("icons\\");
|
std::string path = std::string("icons\\");
|
||||||
path += MWWorld::Class::get(item).getInventoryIcon(item);
|
path += MWWorld::Class::get(item).getInventoryIcon(item);
|
||||||
|
@ -165,6 +173,7 @@ namespace MWGui
|
||||||
image->setImageTexture (path);
|
image->setImageTexture (path);
|
||||||
image->setNeedMouseFocus (false);
|
image->setNeedMouseFocus (false);
|
||||||
|
|
||||||
|
if (mItemSelectionDialog)
|
||||||
mItemSelectionDialog->setVisible(false);
|
mItemSelectionDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,6 +207,7 @@ namespace MWGui
|
||||||
image->setImageTexture (path);
|
image->setImageTexture (path);
|
||||||
image->setNeedMouseFocus (false);
|
image->setNeedMouseFocus (false);
|
||||||
|
|
||||||
|
if (mMagicSelectionDialog)
|
||||||
mMagicSelectionDialog->setVisible(false);
|
mMagicSelectionDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,6 +249,7 @@ namespace MWGui
|
||||||
image->setImageTexture (path);
|
image->setImageTexture (path);
|
||||||
image->setNeedMouseFocus (false);
|
image->setNeedMouseFocus (false);
|
||||||
|
|
||||||
|
if (mMagicSelectionDialog)
|
||||||
mMagicSelectionDialog->setVisible(false);
|
mMagicSelectionDialog->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +336,6 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
store.setSelectedEnchantItem(it);
|
store.setSelectedEnchantItem(it);
|
||||||
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,6 +385,110 @@ namespace MWGui
|
||||||
center();
|
center();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuickKeysMenu::write(ESM::ESMWriter &writer)
|
||||||
|
{
|
||||||
|
writer.startRecord(ESM::REC_KEYS);
|
||||||
|
|
||||||
|
ESM::QuickKeys keys;
|
||||||
|
|
||||||
|
for (int i=0; i<10; ++i)
|
||||||
|
{
|
||||||
|
MyGUI::Button* button = mQuickKeyButtons[i];
|
||||||
|
|
||||||
|
int type = *button->getUserData<QuickKeyType>();
|
||||||
|
|
||||||
|
ESM::QuickKeys::QuickKey key;
|
||||||
|
key.mType = type;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Type_Unassigned:
|
||||||
|
break;
|
||||||
|
case Type_Item:
|
||||||
|
case Type_MagicItem:
|
||||||
|
{
|
||||||
|
MWWorld::Ptr item = *button->getChildAt(0)->getUserData<MWWorld::Ptr>();
|
||||||
|
key.mId = item.getCellRef().mRefID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type_Magic:
|
||||||
|
std::string spellId = button->getChildAt(0)->getUserString("Spell");
|
||||||
|
key.mId = spellId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
keys.mKeys.push_back(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
keys.save(writer);
|
||||||
|
|
||||||
|
writer.endRecord(ESM::REC_KEYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKeysMenu::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||||
|
{
|
||||||
|
if (type != ESM::REC_KEYS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ESM::QuickKeys keys;
|
||||||
|
keys.load(reader);
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
for (std::vector<ESM::QuickKeys::QuickKey>::const_iterator it = keys.mKeys.begin(); it != keys.mKeys.end(); ++it)
|
||||||
|
{
|
||||||
|
if (i >= 10)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mSelectedIndex = i;
|
||||||
|
int keyType = it->mType;
|
||||||
|
std::string id = it->mId;
|
||||||
|
MyGUI::Button* button = mQuickKeyButtons[i];
|
||||||
|
|
||||||
|
switch (keyType)
|
||||||
|
{
|
||||||
|
case Type_Magic:
|
||||||
|
onAssignMagic(id);
|
||||||
|
break;
|
||||||
|
case Type_Item:
|
||||||
|
case Type_MagicItem:
|
||||||
|
{
|
||||||
|
// Find the item by id
|
||||||
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
|
MWWorld::InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||||
|
MWWorld::Ptr item;
|
||||||
|
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||||
|
{
|
||||||
|
if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, id))
|
||||||
|
{
|
||||||
|
if (item.isEmpty() ||
|
||||||
|
// Prefer the stack with the lowest remaining uses
|
||||||
|
(it->getCellRef().mCharge != -1 && (item.getCellRef().mCharge == -1 || it->getCellRef().mCharge < item.getCellRef().mCharge) ))
|
||||||
|
{
|
||||||
|
item = *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.isEmpty())
|
||||||
|
unassign(button, i);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (keyType == Type_Item)
|
||||||
|
onAssignItem(item);
|
||||||
|
else if (keyType == Type_MagicItem)
|
||||||
|
onAssignMagicItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Type_Unassigned:
|
||||||
|
unassign(button, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,11 @@ namespace MWGui
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void write (ESM::ESMWriter& writer);
|
||||||
|
void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MyGUI::EditBox* mInstructionLabel;
|
MyGUI::EditBox* mInstructionLabel;
|
||||||
MyGUI::Button* mOkButton;
|
MyGUI::Button* mOkButton;
|
||||||
|
|
|
@ -17,6 +17,8 @@ namespace MWGui
|
||||||
|
|
||||||
void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable
|
void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable
|
||||||
|
|
||||||
|
void resetReference() { mPtr = MWWorld::Ptr(); mCurrentPlayerCell = NULL; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void onReferenceUnavailable() = 0; ///< called when reference has become unavailable
|
virtual void onReferenceUnavailable() = 0; ///< called when reference has become unavailable
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace MWGui
|
||||||
: WindowModal("openmw_savegame_dialog.layout")
|
: WindowModal("openmw_savegame_dialog.layout")
|
||||||
, mSaving(true)
|
, mSaving(true)
|
||||||
, mCurrentCharacter(NULL)
|
, mCurrentCharacter(NULL)
|
||||||
|
, mCurrentSlot(NULL)
|
||||||
{
|
{
|
||||||
getWidget(mScreenshot, "Screenshot");
|
getWidget(mScreenshot, "Screenshot");
|
||||||
getWidget(mCharacterSelection, "SelectCharacter");
|
getWidget(mCharacterSelection, "SelectCharacter");
|
||||||
|
@ -36,6 +37,7 @@ namespace MWGui
|
||||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SaveGameDialog::onCancelButtonClicked);
|
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SaveGameDialog::onCancelButtonClicked);
|
||||||
mCharacterSelection->eventComboChangePosition += MyGUI::newDelegate(this, &SaveGameDialog::onCharacterSelected);
|
mCharacterSelection->eventComboChangePosition += MyGUI::newDelegate(this, &SaveGameDialog::onCharacterSelected);
|
||||||
mSaveList->eventListChangePosition += MyGUI::newDelegate(this, &SaveGameDialog::onSlotSelected);
|
mSaveList->eventListChangePosition += MyGUI::newDelegate(this, &SaveGameDialog::onSlotSelected);
|
||||||
|
mSaveList->eventListMouseItemActivate += MyGUI::newDelegate(this, &SaveGameDialog::onSlotMouseClick);
|
||||||
mSaveList->eventListSelectAccept += MyGUI::newDelegate(this, &SaveGameDialog::onSlotActivated);
|
mSaveList->eventListSelectAccept += MyGUI::newDelegate(this, &SaveGameDialog::onSlotActivated);
|
||||||
mSaveNameEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &SaveGameDialog::onEditSelectAccept);
|
mSaveNameEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &SaveGameDialog::onEditSelectAccept);
|
||||||
mSaveNameEdit->eventEditTextChange += MyGUI::newDelegate(this, &SaveGameDialog::onSaveNameChanged);
|
mSaveNameEdit->eventEditTextChange += MyGUI::newDelegate(this, &SaveGameDialog::onSaveNameChanged);
|
||||||
|
@ -47,6 +49,37 @@ namespace MWGui
|
||||||
accept();
|
accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SaveGameDialog::onSlotMouseClick(MyGUI::ListBox* sender, size_t pos)
|
||||||
|
{
|
||||||
|
onSlotSelected(sender, pos);
|
||||||
|
|
||||||
|
if (pos != MyGUI::ITEM_NONE && MyGUI::InputManager::getInstance().isShiftPressed())
|
||||||
|
{
|
||||||
|
ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
|
||||||
|
dialog->open("#{sMessage3}");
|
||||||
|
dialog->eventOkClicked.clear();
|
||||||
|
dialog->eventOkClicked += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteSlotConfirmed);
|
||||||
|
dialog->eventCancelClicked.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveGameDialog::onDeleteSlotConfirmed()
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getStateManager()->deleteGame (mCurrentCharacter, mCurrentSlot);
|
||||||
|
mSaveList->removeItemAt(mSaveList->getIndexSelected());
|
||||||
|
onSlotSelected(mSaveList, MyGUI::ITEM_NONE);
|
||||||
|
|
||||||
|
// The character might be deleted now
|
||||||
|
size_t previousIndex = mCharacterSelection->getIndexSelected();
|
||||||
|
open();
|
||||||
|
if (mCharacterSelection->getItemCount())
|
||||||
|
{
|
||||||
|
size_t nextCharacter = std::min(previousIndex, mCharacterSelection->getItemCount()-1);
|
||||||
|
mCharacterSelection->setIndexSelected(nextCharacter);
|
||||||
|
onCharacterSelected(mCharacterSelection, nextCharacter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SaveGameDialog::onSaveNameChanged(MyGUI::EditBox *sender)
|
void SaveGameDialog::onSaveNameChanged(MyGUI::EditBox *sender)
|
||||||
{
|
{
|
||||||
// This might have previously been a save slot from the list. If so, that is no longer the case
|
// This might have previously been a save slot from the list. If so, that is no longer the case
|
||||||
|
@ -69,6 +102,12 @@ namespace MWGui
|
||||||
|
|
||||||
center();
|
center();
|
||||||
|
|
||||||
|
mCharacterSelection->setCaption("");
|
||||||
|
mCharacterSelection->removeAllItems();
|
||||||
|
mCurrentCharacter = NULL;
|
||||||
|
mCurrentSlot = NULL;
|
||||||
|
mSaveList->removeAllItems();
|
||||||
|
|
||||||
MWBase::StateManager* mgr = MWBase::Environment::get().getStateManager();
|
MWBase::StateManager* mgr = MWBase::Environment::get().getStateManager();
|
||||||
if (mgr->characterBegin() == mgr->characterEnd())
|
if (mgr->characterBegin() == mgr->characterEnd())
|
||||||
return;
|
return;
|
||||||
|
@ -78,8 +117,6 @@ namespace MWGui
|
||||||
std::string directory =
|
std::string directory =
|
||||||
Misc::StringUtils::lowerCase (Settings::Manager::getString ("character", "Saves"));
|
Misc::StringUtils::lowerCase (Settings::Manager::getString ("character", "Saves"));
|
||||||
|
|
||||||
mCharacterSelection->removeAllItems();
|
|
||||||
|
|
||||||
int selectedIndex = MyGUI::ITEM_NONE;
|
int selectedIndex = MyGUI::ITEM_NONE;
|
||||||
|
|
||||||
for (MWBase::StateManager::CharacterIterator it = mgr->characterBegin(); it != mgr->characterEnd(); ++it)
|
for (MWBase::StateManager::CharacterIterator it = mgr->characterBegin(); it != mgr->characterEnd(); ++it)
|
||||||
|
@ -152,23 +189,10 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(NULL);
|
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(NULL);
|
||||||
|
|
||||||
// Get the selected slot, if any
|
|
||||||
unsigned int i=0;
|
|
||||||
const MWState::Slot* slot = NULL;
|
|
||||||
|
|
||||||
if (mCurrentCharacter)
|
|
||||||
{
|
|
||||||
for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it,++i)
|
|
||||||
{
|
|
||||||
if (i == mSaveList->getIndexSelected())
|
|
||||||
slot = &*it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSaving)
|
if (mSaving)
|
||||||
{
|
{
|
||||||
// If overwriting an existing slot, ask for confirmation first
|
// If overwriting an existing slot, ask for confirmation first
|
||||||
if (slot != NULL && !reallySure)
|
if (mCurrentSlot != NULL && !reallySure)
|
||||||
{
|
{
|
||||||
ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
|
ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
|
||||||
dialog->open("#{sMessage4}");
|
dialog->open("#{sMessage4}");
|
||||||
|
@ -182,18 +206,22 @@ namespace MWGui
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage65}");
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage65}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MWBase::Environment::get().getStateManager()->saveGame (mSaveNameEdit->getCaption(), slot);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mCurrentCharacter && slot)
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot);
|
|
||||||
MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu);
|
||||||
|
|
||||||
|
if (mSaving)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getStateManager()->saveGame (mSaveNameEdit->getCaption(), mCurrentSlot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mCurrentCharacter && mCurrentSlot)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, mCurrentSlot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (MWBase::Environment::get().getStateManager()->getState()==
|
if (MWBase::Environment::get().getStateManager()->getState()==
|
||||||
MWBase::StateManager::State_NoGame)
|
MWBase::StateManager::State_NoGame)
|
||||||
|
@ -221,6 +249,7 @@ namespace MWGui
|
||||||
assert(character && "Can't find selected character");
|
assert(character && "Can't find selected character");
|
||||||
|
|
||||||
mCurrentCharacter = character;
|
mCurrentCharacter = character;
|
||||||
|
mCurrentSlot = NULL;
|
||||||
fillSaveList();
|
fillSaveList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,6 +269,7 @@ namespace MWGui
|
||||||
{
|
{
|
||||||
if (pos == MyGUI::ITEM_NONE)
|
if (pos == MyGUI::ITEM_NONE)
|
||||||
{
|
{
|
||||||
|
mCurrentSlot = NULL;
|
||||||
mInfoText->setCaption("");
|
mInfoText->setCaption("");
|
||||||
mScreenshot->setImageTexture("");
|
mScreenshot->setImageTexture("");
|
||||||
return;
|
return;
|
||||||
|
@ -248,17 +278,17 @@ namespace MWGui
|
||||||
if (mSaving)
|
if (mSaving)
|
||||||
mSaveNameEdit->setCaption(sender->getItemNameAt(pos));
|
mSaveNameEdit->setCaption(sender->getItemNameAt(pos));
|
||||||
|
|
||||||
const MWState::Slot* slot = NULL;
|
mCurrentSlot = NULL;
|
||||||
unsigned int i=0;
|
unsigned int i=0;
|
||||||
for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it, ++i)
|
for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it, ++i)
|
||||||
{
|
{
|
||||||
if (i == pos)
|
if (i == pos)
|
||||||
slot = &*it;
|
mCurrentSlot = &*it;
|
||||||
}
|
}
|
||||||
assert(slot && "Can't find selected slot");
|
assert(mCurrentSlot && "Can't find selected slot");
|
||||||
|
|
||||||
std::stringstream text;
|
std::stringstream text;
|
||||||
time_t time = slot->mTimeStamp;
|
time_t time = mCurrentSlot->mTimeStamp;
|
||||||
struct tm* timeinfo;
|
struct tm* timeinfo;
|
||||||
timeinfo = localtime(&time);
|
timeinfo = localtime(&time);
|
||||||
|
|
||||||
|
@ -269,24 +299,24 @@ namespace MWGui
|
||||||
char buffer[size];
|
char buffer[size];
|
||||||
if (std::strftime(buffer, size, "%x %X", timeinfo) > 0)
|
if (std::strftime(buffer, size, "%x %X", timeinfo) > 0)
|
||||||
text << buffer << "\n";
|
text << buffer << "\n";
|
||||||
text << "Level " << slot->mProfile.mPlayerLevel << "\n";
|
text << "Level " << mCurrentSlot->mProfile.mPlayerLevel << "\n";
|
||||||
text << slot->mProfile.mPlayerCell << "\n";
|
text << mCurrentSlot->mProfile.mPlayerCell << "\n";
|
||||||
// text << "Time played: " << slot->mProfile.mTimePlayed << "\n";
|
// text << "Time played: " << slot->mProfile.mTimePlayed << "\n";
|
||||||
|
|
||||||
int hour = int(slot->mProfile.mInGameTime.mGameHour);
|
int hour = int(mCurrentSlot->mProfile.mInGameTime.mGameHour);
|
||||||
bool pm = hour >= 12;
|
bool pm = hour >= 12;
|
||||||
if (hour >= 13) hour -= 12;
|
if (hour >= 13) hour -= 12;
|
||||||
if (hour == 0) hour = 12;
|
if (hour == 0) hour = 12;
|
||||||
|
|
||||||
text
|
text
|
||||||
<< slot->mProfile.mInGameTime.mDay << " "
|
<< mCurrentSlot->mProfile.mInGameTime.mDay << " "
|
||||||
<< MWBase::Environment::get().getWorld()->getMonthName(slot->mProfile.mInGameTime.mMonth)
|
<< MWBase::Environment::get().getWorld()->getMonthName(mCurrentSlot->mProfile.mInGameTime.mMonth)
|
||||||
<< " " << hour << " " << (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}");
|
<< " " << hour << " " << (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}");
|
||||||
|
|
||||||
mInfoText->setCaptionWithReplacing(text.str());
|
mInfoText->setCaptionWithReplacing(text.str());
|
||||||
|
|
||||||
// Decode screenshot
|
// Decode screenshot
|
||||||
std::vector<char> data = slot->mProfile.mScreenshot; // MemoryDataStream doesn't work with const data :(
|
std::vector<char> data = mCurrentSlot->mProfile.mScreenshot; // MemoryDataStream doesn't work with const data :(
|
||||||
Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size()));
|
Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream(&data[0], data.size()));
|
||||||
Ogre::Image image;
|
Ogre::Image image;
|
||||||
image.load(stream, "jpg");
|
image.load(stream, "jpg");
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
namespace MWState
|
namespace MWState
|
||||||
{
|
{
|
||||||
class Character;
|
class Character;
|
||||||
|
class Slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
|
@ -24,8 +25,15 @@ namespace MWGui
|
||||||
void onCancelButtonClicked (MyGUI::Widget* sender);
|
void onCancelButtonClicked (MyGUI::Widget* sender);
|
||||||
void onOkButtonClicked (MyGUI::Widget* sender);
|
void onOkButtonClicked (MyGUI::Widget* sender);
|
||||||
void onCharacterSelected (MyGUI::ComboBox* sender, size_t pos);
|
void onCharacterSelected (MyGUI::ComboBox* sender, size_t pos);
|
||||||
|
// Slot selected (mouse click or arrow keys)
|
||||||
void onSlotSelected (MyGUI::ListBox* sender, size_t pos);
|
void onSlotSelected (MyGUI::ListBox* sender, size_t pos);
|
||||||
|
// Slot activated (double click or enter key)
|
||||||
void onSlotActivated (MyGUI::ListBox* sender, size_t pos);
|
void onSlotActivated (MyGUI::ListBox* sender, size_t pos);
|
||||||
|
// Slot clicked with mouse
|
||||||
|
void onSlotMouseClick(MyGUI::ListBox* sender, size_t pos);
|
||||||
|
|
||||||
|
void onDeleteSlotConfirmed();
|
||||||
|
|
||||||
void onEditSelectAccept (MyGUI::EditBox* sender);
|
void onEditSelectAccept (MyGUI::EditBox* sender);
|
||||||
void onSaveNameChanged (MyGUI::EditBox* sender);
|
void onSaveNameChanged (MyGUI::EditBox* sender);
|
||||||
void onConfirmationGiven();
|
void onConfirmationGiven();
|
||||||
|
@ -46,6 +54,7 @@ namespace MWGui
|
||||||
MyGUI::Widget* mSpacer;
|
MyGUI::Widget* mSpacer;
|
||||||
|
|
||||||
const MWState::Character* mCurrentCharacter;
|
const MWState::Character* mCurrentCharacter;
|
||||||
|
const MWState::Slot* mCurrentSlot;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -322,7 +322,6 @@ namespace MWGui
|
||||||
}
|
}
|
||||||
|
|
||||||
store.setSelectedEnchantItem(it);
|
store.setSelectedEnchantItem(it);
|
||||||
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item);
|
|
||||||
|
|
||||||
updateSpells();
|
updateSpells();
|
||||||
}
|
}
|
||||||
|
|
|
@ -475,7 +475,7 @@ namespace MWGui
|
||||||
text += std::string("#DDC79E") + faction->mName;
|
text += std::string("#DDC79E") + faction->mName;
|
||||||
|
|
||||||
if (expelled.find(it->first) != expelled.end())
|
if (expelled.find(it->first) != expelled.end())
|
||||||
text += "\n#{sExpelled}";
|
text += "\n#BF9959#{sExpelled}";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
text += std::string("\n#BF9959") + faction->mRanks[it->second];
|
text += std::string("\n#BF9959") + faction->mRanks[it->second];
|
||||||
|
|
|
@ -120,14 +120,11 @@ namespace MWGui
|
||||||
if (i == sourceModel->getItemCount())
|
if (i == sourceModel->getItemCount())
|
||||||
throw std::runtime_error("The borrowed item disappeared");
|
throw std::runtime_error("The borrowed item disappeared");
|
||||||
|
|
||||||
// reset owner before copying
|
// reset owner while copying, but only for items bought by the player
|
||||||
|
bool setNewOwner = (mMerchant.isEmpty());
|
||||||
const ItemStack& item = sourceModel->getItem(i);
|
const ItemStack& item = sourceModel->getItem(i);
|
||||||
std::string owner = item.mBase.getCellRef().mOwner;
|
|
||||||
if (mMerchant.isEmpty()) // only for items bought by player
|
|
||||||
item.mBase.getCellRef().mOwner = "";
|
|
||||||
// copy the borrowed items to our model
|
// copy the borrowed items to our model
|
||||||
copyItem(item, it->mCount);
|
copyItem(item, it->mCount, setNewOwner);
|
||||||
item.mBase.getCellRef().mOwner = owner;
|
|
||||||
// then remove them from the source model
|
// then remove them from the source model
|
||||||
sourceModel->removeItem(item, it->mCount);
|
sourceModel->removeItem(item, it->mCount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -245,7 +245,7 @@ namespace MWGui
|
||||||
// were there any items traded at all?
|
// were there any items traded at all?
|
||||||
std::vector<ItemStack> playerBought = playerItemModel->getItemsBorrowedToUs();
|
std::vector<ItemStack> playerBought = playerItemModel->getItemsBorrowedToUs();
|
||||||
std::vector<ItemStack> merchantBought = mTradeModel->getItemsBorrowedToUs();
|
std::vector<ItemStack> merchantBought = mTradeModel->getItemsBorrowedToUs();
|
||||||
if (!playerBought.size() && !merchantBought.size())
|
if (playerBought.empty() && merchantBought.empty())
|
||||||
{
|
{
|
||||||
// user notification
|
// user notification
|
||||||
MWBase::Environment::get().getWindowManager()->
|
MWBase::Environment::get().getWindowManager()->
|
||||||
|
|
|
@ -187,7 +187,7 @@ namespace MWGui
|
||||||
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
|
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
|
||||||
|
|
||||||
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
|
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
|
||||||
SDL_ShowCursor(false);
|
//SDL_ShowCursor(false);
|
||||||
|
|
||||||
mCursorManager->setEnabled(true);
|
mCursorManager->setEnabled(true);
|
||||||
|
|
||||||
|
@ -289,6 +289,10 @@ namespace MWGui
|
||||||
|
|
||||||
void WindowManager::setNewGame(bool newgame)
|
void WindowManager::setNewGame(bool newgame)
|
||||||
{
|
{
|
||||||
|
// This method will always be called after loading a savegame or starting a new game
|
||||||
|
// Reset enemy, it could be a dangling pointer from a previous game
|
||||||
|
mHud->resetEnemy();
|
||||||
|
|
||||||
if (newgame)
|
if (newgame)
|
||||||
{
|
{
|
||||||
disallowAll();
|
disallowAll();
|
||||||
|
@ -621,9 +625,9 @@ namespace MWGui
|
||||||
mStatsWindow->setValue (id, value);
|
mStatsWindow->setValue (id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::setDrowningTimeLeft (float time)
|
void WindowManager::setDrowningTimeLeft (float time, float maxTime)
|
||||||
{
|
{
|
||||||
mHud->setDrowningTimeLeft(time);
|
mHud->setDrowningTimeLeft(time, maxTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::setPlayerClass (const ESM::Class &class_)
|
void WindowManager::setPlayerClass (const ESM::Class &class_)
|
||||||
|
@ -1401,16 +1405,49 @@ namespace MWGui
|
||||||
void WindowManager::clear()
|
void WindowManager::clear()
|
||||||
{
|
{
|
||||||
mMap->clear();
|
mMap->clear();
|
||||||
|
mQuickKeysMenu->clear();
|
||||||
|
|
||||||
|
mTrainingWindow->resetReference();
|
||||||
|
mDialogueWindow->resetReference();
|
||||||
|
mTradeWindow->resetReference();
|
||||||
|
mSpellBuyingWindow->resetReference();
|
||||||
|
mSpellCreationDialog->resetReference();
|
||||||
|
mEnchantingDialog->resetReference();
|
||||||
|
mContainerWindow->resetReference();
|
||||||
|
mCompanionWindow->resetReference();
|
||||||
|
mConsole->resetReference();
|
||||||
|
|
||||||
|
mGuiModes.clear();
|
||||||
|
updateVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::write(ESM::ESMWriter &writer)
|
void WindowManager::write(ESM::ESMWriter &writer, Loading::Listener& progress)
|
||||||
{
|
{
|
||||||
mMap->write(writer);
|
mMap->write(writer, progress);
|
||||||
|
|
||||||
|
mQuickKeysMenu->write(writer);
|
||||||
|
progress.increaseProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type)
|
void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||||
{
|
{
|
||||||
|
if (type == ESM::REC_GMAP)
|
||||||
mMap->readRecord(reader, type);
|
mMap->readRecord(reader, type);
|
||||||
|
else if (type == ESM::REC_KEYS)
|
||||||
|
mQuickKeysMenu->readRecord(reader, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WindowManager::countSavedGameRecords() const
|
||||||
|
{
|
||||||
|
return 1 // Global map
|
||||||
|
+ 1; // QuickKeysMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WindowManager::isSavingAllowed() const
|
||||||
|
{
|
||||||
|
return !MyGUI::InputManager::getInstance().isModalAny()
|
||||||
|
// TODO: remove this, once we have properly serialized the state of open windows
|
||||||
|
&& (!isGuiMode() || (mGuiModes.size() == 1 && getMode() == GM_MainMenu));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::playVideo(const std::string &name, bool allowSkipping)
|
void WindowManager::playVideo(const std::string &name, bool allowSkipping)
|
||||||
|
|
|
@ -166,8 +166,9 @@ namespace MWGui
|
||||||
virtual void setValue (const std::string& id, int value);
|
virtual void setValue (const std::string& id, int value);
|
||||||
|
|
||||||
/// Set time left for the player to start drowning (update the drowning bar)
|
/// Set time left for the player to start drowning (update the drowning bar)
|
||||||
/// @param time value from [0,20]
|
/// @param time time left to start drowning
|
||||||
virtual void setDrowningTimeLeft (float time);
|
/// @param maxTime how long we can be underwater (in total) until drowning starts
|
||||||
|
virtual void setDrowningTimeLeft (float time, float maxTime);
|
||||||
|
|
||||||
virtual void setPlayerClass (const ESM::Class &class_); ///< set current class of player
|
virtual void setPlayerClass (const ESM::Class &class_); ///< set current class of player
|
||||||
virtual void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group.
|
virtual void configureSkills (const SkillList& major, const SkillList& minor); ///< configure skill groups, each set contains the skill ID for that group.
|
||||||
|
@ -290,8 +291,12 @@ namespace MWGui
|
||||||
/// Clear all savegame-specific data
|
/// Clear all savegame-specific data
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
virtual void write (ESM::ESMWriter& writer);
|
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
|
virtual int countSavedGameRecords() const;
|
||||||
|
|
||||||
|
/// Does the current stack of GUI-windows permit saving?
|
||||||
|
virtual bool isSavingAllowed() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mConsoleOnlyScripts;
|
bool mConsoleOnlyScripts;
|
||||||
|
|
|
@ -114,6 +114,7 @@ namespace MWInput
|
||||||
, mTimeIdle(0.f)
|
, mTimeIdle(0.f)
|
||||||
, mOverencumberedMessageDelay(0.f)
|
, mOverencumberedMessageDelay(0.f)
|
||||||
, mAlwaysRunActive(false)
|
, mAlwaysRunActive(false)
|
||||||
|
, mControlsDisabled(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
Ogre::RenderWindow* window = ogre.getWindow ();
|
Ogre::RenderWindow* window = ogre.getWindow ();
|
||||||
|
@ -265,19 +266,20 @@ namespace MWInput
|
||||||
|
|
||||||
void InputManager::update(float dt, bool disableControls, bool disableEvents)
|
void InputManager::update(float dt, bool disableControls, bool disableEvents)
|
||||||
{
|
{
|
||||||
|
mControlsDisabled = disableControls;
|
||||||
|
|
||||||
mInputManager->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible());
|
mInputManager->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible());
|
||||||
|
|
||||||
mInputManager->capture(disableEvents);
|
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)
|
if (mControlsDisabled)
|
||||||
if (!disableControls)
|
|
||||||
mInputBinder->update(dt);
|
|
||||||
|
|
||||||
if (disableControls)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// update values of channels (as a result of pressed keys)
|
||||||
|
mInputBinder->update(dt);
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
@ -484,7 +486,7 @@ namespace MWInput
|
||||||
|
|
||||||
if (text)
|
if (text)
|
||||||
{
|
{
|
||||||
edit->addText(MyGUI::UString(text));
|
edit->insertText(MyGUI::UString(text), edit->getTextCursor());
|
||||||
SDL_free(text);
|
SDL_free(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,6 +511,7 @@ namespace MWInput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mControlsDisabled)
|
||||||
mInputBinder->keyPressed (arg);
|
mInputBinder->keyPressed (arg);
|
||||||
|
|
||||||
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
|
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
|
||||||
|
|
|
@ -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 disableControls, bool disableEvents=false);
|
virtual void update(float dt, bool disableControls=false, bool disableEvents=false);
|
||||||
|
|
||||||
void setPlayer (MWWorld::Player* player) { mPlayer = player; }
|
void setPlayer (MWWorld::Player* player) { mPlayer = player; }
|
||||||
|
|
||||||
|
@ -145,6 +145,8 @@ namespace MWInput
|
||||||
|
|
||||||
bool mInvertY;
|
bool mInvertY;
|
||||||
|
|
||||||
|
bool mControlsDisabled;
|
||||||
|
|
||||||
float mCameraSensitivity;
|
float mCameraSensitivity;
|
||||||
float mUISensitivity;
|
float mUISensitivity;
|
||||||
float mCameraYMultiplier;
|
float mCameraYMultiplier;
|
||||||
|
|
|
@ -206,7 +206,7 @@ namespace MWMechanics
|
||||||
if (effectIt->mKey.mId == effectId)
|
if (effectIt->mKey.mId == effectId)
|
||||||
effectIt = it->second.mEffects.erase(effectIt);
|
effectIt = it->second.mEffects.erase(effectIt);
|
||||||
else
|
else
|
||||||
effectIt++;
|
++effectIt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mSpellsChanged = true;
|
mSpellsChanged = true;
|
||||||
|
@ -224,7 +224,7 @@ namespace MWMechanics
|
||||||
&& it->second.mCasterHandle == actorHandle)
|
&& it->second.mCasterHandle == actorHandle)
|
||||||
effectIt = it->second.mEffects.erase(effectIt);
|
effectIt = it->second.mEffects.erase(effectIt);
|
||||||
else
|
else
|
||||||
effectIt++;
|
++effectIt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mSpellsChanged = true;
|
mSpellsChanged = true;
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include "aicombat.hpp"
|
#include "aicombat.hpp"
|
||||||
#include "aifollow.hpp"
|
#include "aifollow.hpp"
|
||||||
#include "aipersue.hpp"
|
#include "aipursue.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -194,21 +194,11 @@ namespace MWMechanics
|
||||||
+(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1])
|
+(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1])
|
||||||
+(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2]));
|
+(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2]));
|
||||||
float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified();
|
float fight = ptr.getClass().getCreatureStats(ptr).getAiSetting(CreatureStats::AI_Fight).getModified();
|
||||||
float disp = 100; //creatures don't have disposition, so set it to 100 by default
|
|
||||||
if(ptr.getTypeName() == typeid(ESM::NPC).name())
|
|
||||||
{
|
|
||||||
disp = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (fight == 100 )
|
if( (fight == 100 )
|
||||||
|| (fight >= 95 && d <= 3000)
|
|| (fight >= 95 && d <= 3000)
|
||||||
|| (fight >= 90 && d <= 2000)
|
|| (fight >= 90 && d <= 2000)
|
||||||
|| (fight >= 80 && d <= 1000)
|
|| (fight >= 80 && d <= 1000)
|
||||||
|| (fight >= 80 && disp <= 40)
|
|
||||||
|| (fight >= 70 && disp <= 35 && d <= 1000)
|
|
||||||
|| (fight >= 60 && disp <= 30 && d <= 1000)
|
|
||||||
|| (fight >= 50 && disp == 0)
|
|
||||||
|| (fight >= 40 && disp <= 10 && d <= 500)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,player)
|
bool LOS = MWBase::Environment::get().getWorld()->getLOS(ptr,player)
|
||||||
|
@ -216,7 +206,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (LOS)
|
if (LOS)
|
||||||
{
|
{
|
||||||
creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr()));
|
creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr()), ptr);
|
||||||
creatureStats.setHostile(true);
|
creatureStats.setHostile(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -548,7 +538,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
// TODO: Add AI to follow player and fight for him
|
// TODO: Add AI to follow player and fight for him
|
||||||
AiFollow package(ptr.getRefData().getHandle());
|
AiFollow package(ptr.getRefData().getHandle());
|
||||||
MWWorld::Class::get (ref.getPtr()).getCreatureStats (ref.getPtr()).getAiSequence().stack(package);
|
MWWorld::Class::get (ref.getPtr()).getCreatureStats (ref.getPtr()).getAiSequence().stack(package, ptr);
|
||||||
// TODO: VFX_SummonStart, VFX_SummonEnd
|
// TODO: VFX_SummonStart, VFX_SummonEnd
|
||||||
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first,
|
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first,
|
||||||
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos).getRefData().getHandle()));
|
MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(),store,ipos).getRefData().getHandle()));
|
||||||
|
@ -751,34 +741,33 @@ namespace MWMechanics
|
||||||
CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr);
|
CreatureStats& creatureStats = MWWorld::Class::get(ptr).getCreatureStats(ptr);
|
||||||
NpcStats& npcStats = MWWorld::Class::get(ptr).getNpcStats(ptr);
|
NpcStats& npcStats = MWWorld::Class::get(ptr).getNpcStats(ptr);
|
||||||
|
|
||||||
// If I'm a guard and I'm not hostile
|
if (ptr.getClass().isClass(ptr, "Guard") && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPursue && !creatureStats.isHostile())
|
||||||
if (ptr.getClass().isClass(ptr, "Guard") && !creatureStats.isHostile())
|
|
||||||
{
|
{
|
||||||
/// \todo Move me! I shouldn't be here...
|
/// \todo Move me! I shouldn't be here...
|
||||||
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
|
||||||
float cutoff = float(esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt()) *
|
float cutoff = float(esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt());
|
||||||
float(esmStore.get<ESM::GameSetting>().find("iCrimeThresholdMultiplier")->getInt()) *
|
// Force dialogue on sight if bounty is greater than the cutoff
|
||||||
esmStore.get<ESM::GameSetting>().find("fCrimeGoldDiscountMult")->getFloat();
|
// In vanilla morrowind, the greeting dialogue is scripted to either arrest the player (< 5000 bounty) or attack (>= 5000 bounty)
|
||||||
// Attack on sight if bounty is greater than the cutoff
|
|
||||||
if ( player.getClass().getNpcStats(player).getBounty() >= cutoff
|
if ( player.getClass().getNpcStats(player).getBounty() >= cutoff
|
||||||
|
// TODO: do not run these two every frame. keep an Aware state for each actor and update it every 0.2 s or so?
|
||||||
&& MWBase::Environment::get().getWorld()->getLOS(ptr, player)
|
&& MWBase::Environment::get().getWorld()->getLOS(ptr, player)
|
||||||
&& MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr))
|
&& MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr))
|
||||||
{
|
{
|
||||||
creatureStats.getAiSequence().stack(AiCombat(player));
|
creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
|
||||||
creatureStats.setHostile(true);
|
creatureStats.setAlarmed(true);
|
||||||
npcStats.setCrimeId( MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() );
|
npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if I was a witness to a crime
|
// if I was a witness to a crime
|
||||||
if (npcStats.getCrimeId() != -1)
|
if (npcStats.getCrimeId() != -1)
|
||||||
{
|
{
|
||||||
// if you've payed for your crimes and I havent noticed
|
// if you've paid for your crimes and I havent noticed
|
||||||
if( npcStats.getCrimeId() <= MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() )
|
if( npcStats.getCrimeId() <= MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() )
|
||||||
{
|
{
|
||||||
// Calm witness down
|
// Calm witness down
|
||||||
if (ptr.getClass().isClass(ptr, "Guard"))
|
if (ptr.getClass().isClass(ptr, "Guard"))
|
||||||
creatureStats.getAiSequence().stopPersue();
|
creatureStats.getAiSequence().stopPursuit();
|
||||||
creatureStats.getAiSequence().stopCombat();
|
creatureStats.getAiSequence().stopCombat();
|
||||||
|
|
||||||
// Reset factors to attack
|
// Reset factors to attack
|
||||||
|
@ -793,17 +782,16 @@ namespace MWMechanics
|
||||||
else if (!creatureStats.isHostile())
|
else if (!creatureStats.isHostile())
|
||||||
{
|
{
|
||||||
if (ptr.getClass().isClass(ptr, "Guard"))
|
if (ptr.getClass().isClass(ptr, "Guard"))
|
||||||
creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)));
|
creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
|
||||||
else
|
else
|
||||||
creatureStats.getAiSequence().stack(AiCombat(player));
|
creatureStats.getAiSequence().stack(AiCombat(player), ptr);
|
||||||
creatureStats.setHostile(true);
|
creatureStats.setHostile(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if I didn't report a crime was I attacked?
|
// if I didn't report a crime was I attacked?
|
||||||
else if (creatureStats.getAttacked() && !creatureStats.isHostile())
|
else if (creatureStats.getAttacked() && !creatureStats.isHostile())
|
||||||
{
|
{
|
||||||
creatureStats.getAiSequence().stack(AiCombat(player));
|
creatureStats.getAiSequence().stack(AiCombat(player), ptr);
|
||||||
creatureStats.setHostile(true);
|
creatureStats.setHostile(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -911,12 +899,23 @@ namespace MWMechanics
|
||||||
iter->second->update(duration);
|
iter->second->update(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill dead actors
|
// Kill dead actors, update some variables
|
||||||
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++)
|
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++)
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = MWWorld::Class::get(iter->first);
|
const MWWorld::Class &cls = MWWorld::Class::get(iter->first);
|
||||||
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
||||||
|
|
||||||
|
//KnockedOutOneFrameLogic
|
||||||
|
//Used for "OnKnockedOut" command
|
||||||
|
//Put here to ensure that it's run for PRECISELY one frame.
|
||||||
|
if(stats.getKnockedDown() && !stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Start it for one frame if nessesary
|
||||||
|
stats.setKnockedDownOneFrame(true);
|
||||||
|
}
|
||||||
|
else if (stats.getKnockedDownOneFrame() && !stats.getKnockedDownOverOneFrame()) { //Turn off KnockedOutOneframe
|
||||||
|
stats.setKnockedDownOneFrame(false);
|
||||||
|
stats.setKnockedDownOverOneFrame(true);
|
||||||
|
}
|
||||||
|
|
||||||
if(!stats.isDead())
|
if(!stats.isDead())
|
||||||
{
|
{
|
||||||
if(iter->second->isDead())
|
if(iter->second->isDead())
|
||||||
|
@ -1050,8 +1049,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = MWWorld::Class::get(iter->first);
|
const MWWorld::Class &cls = MWWorld::Class::get(iter->first);
|
||||||
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
||||||
|
if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow)
|
||||||
if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow)
|
|
||||||
{
|
{
|
||||||
MWMechanics::AiFollow* package = static_cast<MWMechanics::AiFollow*>(stats.getAiSequence().getActivePackage());
|
MWMechanics::AiFollow* package = static_cast<MWMechanics::AiFollow*>(stats.getAiSequence().getActivePackage());
|
||||||
if(package->getFollowedActor() == actor.getCellRef().mRefID)
|
if(package->getFollowedActor() == actor.getCellRef().mRefID)
|
||||||
|
@ -1072,8 +1070,7 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
const MWWorld::Class &cls = MWWorld::Class::get(*iter);
|
const MWWorld::Class &cls = MWWorld::Class::get(*iter);
|
||||||
CreatureStats &stats = cls.getCreatureStats(*iter);
|
CreatureStats &stats = cls.getCreatureStats(*iter);
|
||||||
|
if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat)
|
||||||
if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat)
|
|
||||||
{
|
{
|
||||||
MWMechanics::AiCombat* package = static_cast<MWMechanics::AiCombat*>(stats.getAiSequence().getActivePackage());
|
MWMechanics::AiCombat* package = static_cast<MWMechanics::AiCombat*>(stats.getAiSequence().getActivePackage());
|
||||||
if(package->getTargetId() == actor.getCellRef().mRefID)
|
if(package->getTargetId() == actor.getCellRef().mRefID)
|
||||||
|
|
|
@ -31,10 +31,52 @@ namespace
|
||||||
|
|
||||||
//chooses an attack depending on probability to avoid uniformity
|
//chooses an attack depending on probability to avoid uniformity
|
||||||
void chooseBestAttack(const ESM::Weapon* weapon, MWMechanics::Movement &movement);
|
void chooseBestAttack(const ESM::Weapon* weapon, MWMechanics::Movement &movement);
|
||||||
|
|
||||||
|
float getZAngleToDir(const Ogre::Vector3& dir, float dirLen = 0.0f)
|
||||||
|
{
|
||||||
|
float len = (dirLen > 0.0f)? dirLen : dir.length();
|
||||||
|
return Ogre::Radian( Ogre::Math::ACos(dir.y / len) * sgn(Ogre::Math::ASin(dir.x / len)) ).valueDegrees();
|
||||||
|
}
|
||||||
|
|
||||||
|
float getXAngleToDir(const Ogre::Vector3& dir, float dirLen = 0.0f)
|
||||||
|
{
|
||||||
|
float len = (dirLen > 0.0f)? dirLen : dir.length();
|
||||||
|
return Ogre::Radian(-Ogre::Math::ASin(dir.z / len)).valueDegrees();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const float PATHFIND_Z_REACH = 50.0f;
|
||||||
|
// distance at which actor pays more attention to decide whether to shortcut or stick to pathgrid
|
||||||
|
const float PATHFIND_CAUTION_DIST = 500.0f;
|
||||||
|
// distance after which actor (failed previously to shortcut) will try again
|
||||||
|
const float PATHFIND_SHORTCUT_RETRY_DIST = 300.0f;
|
||||||
|
|
||||||
|
// cast up-down ray with some offset from actor position to check for pits/obstacles on the way to target;
|
||||||
|
// magnitude of pits/obstacles is defined by PATHFIND_Z_REACH
|
||||||
|
bool checkWayIsClear(const Ogre::Vector3& from, const Ogre::Vector3& to, float offset)
|
||||||
|
{
|
||||||
|
if((to - from).length() >= PATHFIND_CAUTION_DIST || abs(from.z - to.z) <= PATHFIND_Z_REACH)
|
||||||
|
{
|
||||||
|
Ogre::Vector3 dir = to - from;
|
||||||
|
dir.z = 0;
|
||||||
|
dir.normalise();
|
||||||
|
float verticalOffset = 200; // instead of '200' here we want the height of the actor
|
||||||
|
Ogre::Vector3 _from = from + dir*offset + Ogre::Vector3::UNIT_Z * verticalOffset;
|
||||||
|
|
||||||
|
// cast up-down ray and find height in world space of hit
|
||||||
|
float h = _from.z - MWBase::Environment::get().getWorld()->getDistToNearestRayHit(_from, -Ogre::Vector3::UNIT_Z, verticalOffset + PATHFIND_Z_REACH + 1);
|
||||||
|
|
||||||
|
if(abs(from.z - h) <= PATHFIND_Z_REACH)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
|
static const float MAX_ATTACK_DURATION = 0.35f;
|
||||||
static const float DOOR_CHECK_INTERVAL = 1.5f; // same as AiWander
|
static const float DOOR_CHECK_INTERVAL = 1.5f; // same as AiWander
|
||||||
// NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp
|
// NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp
|
||||||
|
|
||||||
|
@ -45,16 +87,16 @@ namespace MWMechanics
|
||||||
mTimerCombatMove(0),
|
mTimerCombatMove(0),
|
||||||
mFollowTarget(false),
|
mFollowTarget(false),
|
||||||
mReadyToAttack(false),
|
mReadyToAttack(false),
|
||||||
mStrike(false),
|
mAttack(false),
|
||||||
mCombatMove(false),
|
mCombatMove(false),
|
||||||
mBackOffDoor(false),
|
|
||||||
mRotate(false),
|
|
||||||
mMovement(),
|
mMovement(),
|
||||||
|
mForceNoShortcut(false),
|
||||||
|
mShortcutFailPos(),
|
||||||
|
mBackOffDoor(false),
|
||||||
mCell(NULL),
|
mCell(NULL),
|
||||||
mDoorIter(actor.getCell()->get<ESM::Door>().mList.end()),
|
mDoorIter(actor.getCell()->get<ESM::Door>().mList.end()),
|
||||||
mDoors(actor.getCell()->get<ESM::Door>()),
|
mDoors(actor.getCell()->get<ESM::Door>()),
|
||||||
mDoorCheckDuration(0),
|
mDoorCheckDuration(0)
|
||||||
mTargetAngle(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,15 +169,21 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
actor.getClass().getMovementSettings(actor) = mMovement;
|
actor.getClass().getMovementSettings(actor) = mMovement;
|
||||||
|
actor.getClass().getMovementSettings(actor).mRotation[0] = 0;
|
||||||
|
actor.getClass().getMovementSettings(actor).mRotation[2] = 0;
|
||||||
|
|
||||||
if (mRotate)
|
if(mMovement.mRotation[2] != 0)
|
||||||
{
|
{
|
||||||
if (zTurn(actor, Ogre::Degree(mTargetAngle)))
|
if(zTurn(actor, Ogre::Degree(mMovement.mRotation[2]))) mMovement.mRotation[2] = 0;
|
||||||
mRotate = false;
|
}
|
||||||
|
|
||||||
|
if(mMovement.mRotation[0] != 0)
|
||||||
|
{
|
||||||
|
if(smoothTurn(actor, Ogre::Degree(mMovement.mRotation[0]), 0)) mMovement.mRotation[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mTimerAttack -= duration;
|
mTimerAttack -= duration;
|
||||||
actor.getClass().getCreatureStats(actor).setAttackingOrSpell(mStrike);
|
actor.getClass().getCreatureStats(actor).setAttackingOrSpell(mAttack);
|
||||||
|
|
||||||
float tReaction = 0.25f;
|
float tReaction = 0.25f;
|
||||||
if(mTimerReact < tReaction)
|
if(mTimerReact < tReaction)
|
||||||
|
@ -156,16 +204,16 @@ namespace MWMechanics
|
||||||
|
|
||||||
//actual attacking logic
|
//actual attacking logic
|
||||||
//TODO: Some skills affect period of strikes.For berserk-like style period ~ 0.25f
|
//TODO: Some skills affect period of strikes.For berserk-like style period ~ 0.25f
|
||||||
float attackPeriod = 1.0f;
|
float attacksPeriod = 1.0f;
|
||||||
if(mReadyToAttack)
|
if(mReadyToAttack)
|
||||||
{
|
{
|
||||||
if(mTimerAttack <= -attackPeriod)
|
if(mTimerAttack <= -attacksPeriod)
|
||||||
{
|
{
|
||||||
//TODO: should depend on time between 'start' to 'min attack'
|
//TODO: should depend on time between 'start' to 'min attack'
|
||||||
//for better controlling of NPCs' attack strength.
|
//for better controlling of NPCs' attack strength.
|
||||||
//Also it seems that this time is different for slash/thrust/chop
|
//Also it seems that this time is different for slash/thrust/chop
|
||||||
mTimerAttack = 0.35f * static_cast<float>(rand())/RAND_MAX;
|
mTimerAttack = MAX_ATTACK_DURATION * static_cast<float>(rand())/RAND_MAX;
|
||||||
mStrike = true;
|
mAttack = true;
|
||||||
|
|
||||||
//say a provoking combat phrase
|
//say a provoking combat phrase
|
||||||
if (actor.getClass().isNpc())
|
if (actor.getClass().isNpc())
|
||||||
|
@ -180,30 +228,31 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mTimerAttack <= 0)
|
else if (mTimerAttack <= 0)
|
||||||
mStrike = false;
|
mAttack = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mTimerAttack = -attackPeriod;
|
mTimerAttack = -attacksPeriod;
|
||||||
mStrike = false;
|
mAttack = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MWWorld::Class &cls = actor.getClass();
|
const MWWorld::Class &actorCls = actor.getClass();
|
||||||
const ESM::Weapon *weapon = NULL;
|
const ESM::Weapon *weapon = NULL;
|
||||||
MWMechanics::WeaponType weaptype;
|
MWMechanics::WeaponType weaptype;
|
||||||
float weapRange, weapSpeed = 1.0f;
|
float weapRange, weapSpeed = 1.0f;
|
||||||
|
|
||||||
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
|
actorCls.getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true);
|
||||||
|
|
||||||
if (actor.getClass().hasInventoryStore(actor))
|
// Get weapon characteristics
|
||||||
|
if (actorCls.hasInventoryStore(actor))
|
||||||
{
|
{
|
||||||
MWMechanics::DrawState_ state = actor.getClass().getCreatureStats(actor).getDrawState();
|
MWMechanics::DrawState_ state = actorCls.getCreatureStats(actor).getDrawState();
|
||||||
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
|
if (state == MWMechanics::DrawState_Spell || state == MWMechanics::DrawState_Nothing)
|
||||||
actor.getClass().getCreatureStats(actor).setDrawState(MWMechanics::DrawState_Weapon);
|
actorCls.getCreatureStats(actor).setDrawState(MWMechanics::DrawState_Weapon);
|
||||||
|
|
||||||
//Get weapon speed and range
|
//Get weapon speed and range
|
||||||
MWWorld::ContainerStoreIterator weaponSlot =
|
MWWorld::ContainerStoreIterator weaponSlot =
|
||||||
MWMechanics::getActiveWeapon(cls.getCreatureStats(actor), cls.getInventoryStore(actor), &weaptype);
|
MWMechanics::getActiveWeapon(actorCls.getCreatureStats(actor), actorCls.getInventoryStore(actor), &weaptype);
|
||||||
|
|
||||||
if (weaptype == WeapType_HandToHand)
|
if (weaptype == WeapType_HandToHand)
|
||||||
{
|
{
|
||||||
|
@ -225,36 +274,27 @@ namespace MWMechanics
|
||||||
weapRange = 150; //TODO: use true attack range (the same problem in Creature::hit)
|
weapRange = 150; //TODO: use true attack range (the same problem in Creature::hit)
|
||||||
}
|
}
|
||||||
|
|
||||||
ESM::Position pos = actor.getRefData().getPosition();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some notes on meanings of variables:
|
* Some notes on meanings of variables:
|
||||||
*
|
*
|
||||||
* rangeMelee:
|
* rangeAttack:
|
||||||
*
|
*
|
||||||
* - Distance where attack using the actor's weapon is possible
|
* - Distance where attack using the actor's weapon is possible:
|
||||||
* - longer for ranged weapons (obviously?) vs. melee weapons
|
* longer for ranged weapons (obviously?) vs. melee weapons
|
||||||
|
* - Determined by weapon's reach parameter; hardcoded value
|
||||||
|
* for ranged weapon and for creatures
|
||||||
* - Once within this distance mFollowTarget is triggered
|
* - Once within this distance mFollowTarget is triggered
|
||||||
* (TODO: check whether the follow logic still works for ranged
|
|
||||||
* weapons, since rangeCloseup is set to zero)
|
|
||||||
* - TODO: The variable name is confusing. It was ok when AiCombat only
|
|
||||||
* had melee weapons but now that ranged weapons are supported that is
|
|
||||||
* no longer the case. It should really be renamed to something
|
|
||||||
* like rangeStrike - alternatively, keep this name for melee
|
|
||||||
* weapons and use a different variable for tracking ranged weapon
|
|
||||||
* distance (rangeRanged maybe?)
|
|
||||||
*
|
*
|
||||||
* rangeCloseup:
|
* rangeFollow:
|
||||||
*
|
*
|
||||||
* - Applies to melee weapons or hand to hand only (or creatures without
|
* - Applies to melee weapons or hand to hand only (or creatures without
|
||||||
* weapons)
|
* weapons)
|
||||||
* - Distance a little further away from the actor's weapon strike
|
* - Distance a little further away than the actor's weapon reach
|
||||||
* i.e. rangeCloseup > rangeMelee for melee weapons
|
* i.e. rangeFollow > rangeAttack for melee weapons
|
||||||
* (the variable names make this simple concept counter-intuitive,
|
* - Hardcoded value (0 for ranged weapons)
|
||||||
* something like rangeMelee > rangeStrike may be better)
|
|
||||||
* - Once the target gets beyond this distance mFollowTarget is cleared
|
* - Once the target gets beyond this distance mFollowTarget is cleared
|
||||||
* and a path to the target needs to be found
|
* and a path to the target needs to be found
|
||||||
* - TODO: Possibly rename this variable to rangeMelee or even rangeFollow
|
|
||||||
*
|
*
|
||||||
* mFollowTarget:
|
* mFollowTarget:
|
||||||
*
|
*
|
||||||
|
@ -263,58 +303,72 @@ namespace MWMechanics
|
||||||
* available, since the default path without pathgrids is direct to
|
* available, since the default path without pathgrids is direct to
|
||||||
* target even if LOS is not achieved)
|
* target even if LOS is not achieved)
|
||||||
*/
|
*/
|
||||||
float rangeMelee;
|
|
||||||
float rangeCloseUp;
|
float rangeAttack;
|
||||||
|
float rangeFollow;
|
||||||
bool distantCombat = false;
|
bool distantCombat = false;
|
||||||
if (weaptype==WeapType_BowAndArrow || weaptype==WeapType_Crossbow || weaptype==WeapType_Thrown)
|
if (weaptype == WeapType_BowAndArrow || weaptype == WeapType_Crossbow || weaptype == WeapType_Thrown)
|
||||||
{
|
{
|
||||||
rangeMelee = 1000; // TODO: should depend on archer skill
|
rangeAttack = 1000; // TODO: should depend on archer skill
|
||||||
rangeCloseUp = 0; //doesn't needed when attacking from distance
|
rangeFollow = 0; // not needed in ranged combat
|
||||||
distantCombat = true;
|
distantCombat = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rangeMelee = weapRange;
|
rangeAttack = weapRange;
|
||||||
rangeCloseUp = 300;
|
rangeFollow = 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ogre::Vector3 vStart(pos.pos[0], pos.pos[1], pos.pos[2]);
|
ESM::Position pos = actor.getRefData().getPosition();
|
||||||
ESM::Position targetPos = mTarget.getRefData().getPosition();
|
Ogre::Vector3 vActorPos(pos.pos);
|
||||||
Ogre::Vector3 vDest(targetPos.pos[0], targetPos.pos[1], targetPos.pos[2]);
|
Ogre::Vector3 vTargetPos(mTarget.getRefData().getPosition().pos);
|
||||||
Ogre::Vector3 vDir = vDest - vStart;
|
Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos;
|
||||||
float distBetween = vDir.length();
|
|
||||||
|
bool isStuck = false;
|
||||||
|
float speed = 0.0f;
|
||||||
|
if(mMovement.mPosition[1] && (Ogre::Vector3(mLastPos.pos) - vActorPos).length() < (speed = actorCls.getSpeed(actor)) / 10.0f)
|
||||||
|
isStuck = true;
|
||||||
|
|
||||||
|
mLastPos = pos;
|
||||||
|
|
||||||
|
// check if actor can move along z-axis
|
||||||
|
bool canMoveByZ = (actorCls.canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(actor))
|
||||||
|
|| MWBase::Environment::get().getWorld()->isFlying(actor);
|
||||||
|
|
||||||
|
// determine vertical angle to target
|
||||||
|
// if actor can move along z-axis it will control movement dir
|
||||||
|
// if can't - it will control correct aiming
|
||||||
|
mMovement.mRotation[0] = getXAngleToDir(vDirToTarget);
|
||||||
|
|
||||||
|
vDirToTarget.z = 0;
|
||||||
|
float distToTarget = vDirToTarget.length();
|
||||||
|
|
||||||
// (within strike dist) || (not quite strike dist while following)
|
// (within strike dist) || (not quite strike dist while following)
|
||||||
if(distBetween < rangeMelee || (distBetween <= rangeCloseUp && mFollowTarget) )
|
if(distToTarget < rangeAttack || (distToTarget <= rangeFollow && mFollowTarget && !isStuck) )
|
||||||
{
|
{
|
||||||
//Melee and Close-up combat
|
//Melee and Close-up combat
|
||||||
vDir.z = 0;
|
mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget);
|
||||||
float dirLen = vDir.length();
|
|
||||||
mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / dirLen) * sgn(Ogre::Math::ASin(vDir.x / dirLen)) ).valueDegrees();
|
|
||||||
mRotate = true;
|
|
||||||
|
|
||||||
//bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget);
|
|
||||||
// (not quite strike dist while following)
|
// (not quite strike dist while following)
|
||||||
if (mFollowTarget && distBetween > rangeMelee)
|
if (mFollowTarget && distToTarget > rangeAttack)
|
||||||
{
|
{
|
||||||
//Close-up combat: just run up on target
|
//Close-up combat: just run up on target
|
||||||
mMovement.mPosition[1] = 1;
|
mMovement.mPosition[1] = 1;
|
||||||
}
|
}
|
||||||
else // (within strike dist)
|
else // (within strike dist)
|
||||||
{
|
{
|
||||||
//Melee: stop running and attack
|
|
||||||
mMovement.mPosition[1] = 0;
|
mMovement.mPosition[1] = 0;
|
||||||
|
|
||||||
// When attacking with a weapon, choose between slash, thrust or chop
|
// set slash/thrust/chop attack
|
||||||
if (actor.getClass().hasInventoryStore(actor))
|
if (mAttack && !distantCombat) chooseBestAttack(weapon, mMovement);
|
||||||
chooseBestAttack(weapon, mMovement);
|
|
||||||
|
|
||||||
if(mMovement.mPosition[0] || mMovement.mPosition[1])
|
if(mMovement.mPosition[0] || mMovement.mPosition[1])
|
||||||
{
|
{
|
||||||
mTimerCombatMove = 0.1f + 0.1f * static_cast<float>(rand())/RAND_MAX;
|
mTimerCombatMove = 0.1f + 0.1f * static_cast<float>(rand())/RAND_MAX;
|
||||||
mCombatMove = true;
|
mCombatMove = true;
|
||||||
}
|
}
|
||||||
else if(actor.getClass().isNpc() && (!distantCombat || (distantCombat && rangeMelee/5)))
|
// only NPCs are smart enough to use dodge movements
|
||||||
|
else if(actorCls.isNpc() && (!distantCombat || (distantCombat && distToTarget < rangeAttack/2)))
|
||||||
{
|
{
|
||||||
//apply sideway movement (kind of dodging) with some probability
|
//apply sideway movement (kind of dodging) with some probability
|
||||||
if(static_cast<float>(rand())/RAND_MAX < 0.25)
|
if(static_cast<float>(rand())/RAND_MAX < 0.25)
|
||||||
|
@ -325,7 +379,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(distantCombat && distBetween < rangeMelee/4)
|
if(distantCombat && distToTarget < rangeAttack/4)
|
||||||
{
|
{
|
||||||
mMovement.mPosition[1] = -1;
|
mMovement.mPosition[1] = -1;
|
||||||
}
|
}
|
||||||
|
@ -335,56 +389,105 @@ namespace MWMechanics
|
||||||
mFollowTarget = true;
|
mFollowTarget = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // remote pathfinding
|
||||||
{
|
{
|
||||||
//target is at far distance: build path to target
|
bool preferShortcut = false;
|
||||||
|
bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget);
|
||||||
|
|
||||||
|
if(mReadyToAttack) isStuck = false;
|
||||||
|
|
||||||
|
// check if shortcut is available
|
||||||
|
if(!isStuck
|
||||||
|
&& (!mForceNoShortcut
|
||||||
|
|| (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST)
|
||||||
|
&& inLOS)
|
||||||
|
{
|
||||||
|
if(speed == 0.0f) speed = actorCls.getSpeed(actor);
|
||||||
|
// maximum dist before pit/obstacle for actor to avoid them depending on his speed
|
||||||
|
float maxAvoidDist = tReaction * speed + speed / MAX_VEL_ANGULAR.valueRadians() * 2; // *2 - for reliability
|
||||||
|
preferShortcut = checkWayIsClear(vActorPos, vTargetPos, distToTarget > maxAvoidDist*1.5? maxAvoidDist : maxAvoidDist/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't use pathgrid when actor can move in 3 dimensions
|
||||||
|
if(canMoveByZ) preferShortcut = true;
|
||||||
|
|
||||||
|
if(preferShortcut)
|
||||||
|
{
|
||||||
|
mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget);
|
||||||
|
mForceNoShortcut = false;
|
||||||
|
mShortcutFailPos.pos[0] = mShortcutFailPos.pos[1] = mShortcutFailPos.pos[2] = 0;
|
||||||
|
mPathFinder.clearPath();
|
||||||
|
}
|
||||||
|
else // if shortcut failed stick to path grid
|
||||||
|
{
|
||||||
|
if(!isStuck && mShortcutFailPos.pos[0] == 0.0f && mShortcutFailPos.pos[1] == 0.0f && mShortcutFailPos.pos[2] == 0.0f)
|
||||||
|
{
|
||||||
|
mForceNoShortcut = true;
|
||||||
|
mShortcutFailPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
mFollowTarget = false;
|
mFollowTarget = false;
|
||||||
|
|
||||||
buildNewPath(actor); //may fail to build a path, check before use
|
buildNewPath(actor); //may fail to build a path, check before use
|
||||||
|
|
||||||
//delete visited path node
|
//delete visited path node
|
||||||
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
|
mPathFinder.checkWaypoint(pos.pos[0],pos.pos[1],pos.pos[2]);
|
||||||
|
|
||||||
//if no new path leave mTargetAngle unchanged
|
// This works on the borders between the path grid and areas with no waypoints.
|
||||||
if(!mPathFinder.getPath().empty())
|
if(inLOS && mPathFinder.getPath().size() > 1)
|
||||||
{
|
{
|
||||||
//try shortcut
|
// get point just before target
|
||||||
if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))
|
std::list<ESM::Pathgrid::Point>::const_iterator pntIter = --mPathFinder.getPath().end();
|
||||||
mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees();
|
--pntIter;
|
||||||
|
Ogre::Vector3 vBeforeTarget = Ogre::Vector3(pntIter->mX, pntIter->mY, pntIter->mZ);
|
||||||
|
|
||||||
|
// if current actor pos is closer to target then last point of path (excluding target itself) then go straight on target
|
||||||
|
if(distToTarget <= (vTargetPos - vBeforeTarget).length())
|
||||||
|
{
|
||||||
|
mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget);
|
||||||
|
preferShortcut = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is no new path, then go straight on target
|
||||||
|
if(!preferShortcut)
|
||||||
|
{
|
||||||
|
if(!mPathFinder.getPath().empty())
|
||||||
|
mMovement.mRotation[2] = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||||
else
|
else
|
||||||
mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget);
|
||||||
mRotate = true;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mMovement.mPosition[1] = 1;
|
mMovement.mPosition[1] = 1;
|
||||||
mReadyToAttack = false;
|
mReadyToAttack = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(distBetween > rangeMelee)
|
if(distToTarget > rangeAttack && !distantCombat)
|
||||||
{
|
{
|
||||||
//special run attack; it shouldn't affect melee combat tactics
|
//special run attack; it shouldn't affect melee combat tactics
|
||||||
if(actor.getClass().getMovementSettings(actor).mPosition[1] == 1)
|
if(actorCls.getMovementSettings(actor).mPosition[1] == 1)
|
||||||
{
|
{
|
||||||
//check if actor can overcome the distance = distToTarget - attackerWeapRange
|
//check if actor can overcome the distance = distToTarget - attackerWeapRange
|
||||||
//less than in time of playing weapon anim from 'start' to 'hit' tags (t_swing)
|
//less than in time of playing weapon anim from 'start' to 'hit' tags (t_swing)
|
||||||
//then start attacking
|
//then start attacking
|
||||||
float speed1 = cls.getSpeed(actor);
|
float speed1 = actorCls.getSpeed(actor);
|
||||||
float speed2 = mTarget.getClass().getSpeed(mTarget);
|
float speed2 = mTarget.getClass().getSpeed(mTarget);
|
||||||
if(mTarget.getClass().getMovementSettings(mTarget).mPosition[0] == 0
|
if(mTarget.getClass().getMovementSettings(mTarget).mPosition[0] == 0
|
||||||
&& mTarget.getClass().getMovementSettings(mTarget).mPosition[1] == 0)
|
&& mTarget.getClass().getMovementSettings(mTarget).mPosition[1] == 0)
|
||||||
speed2 = 0;
|
speed2 = 0;
|
||||||
|
|
||||||
float s1 = distBetween - weapRange;
|
float s1 = distToTarget - weapRange;
|
||||||
float t = s1/speed1;
|
float t = s1/speed1;
|
||||||
float s2 = speed2 * t;
|
float s2 = speed2 * t;
|
||||||
float t_swing = 0.17f/weapSpeed;//instead of 0.17 should be the time of playing weapon anim from 'start' to 'hit' tags
|
float t_swing = (MAX_ATTACK_DURATION/2) / weapSpeed;//instead of 0.17 should be the time of playing weapon anim from 'start' to 'hit' tags
|
||||||
if (t + s2/speed1 <= t_swing)
|
if (t + s2/speed1 <= t_swing)
|
||||||
{
|
{
|
||||||
mReadyToAttack = true;
|
mReadyToAttack = true;
|
||||||
if(mTimerAttack <= -attackPeriod)
|
if(mTimerAttack <= -attacksPeriod)
|
||||||
{
|
{
|
||||||
mTimerAttack = 0.3f*static_cast<float>(rand())/RAND_MAX;
|
mTimerAttack = MAX_ATTACK_DURATION * static_cast<float>(rand())/RAND_MAX;
|
||||||
mStrike = true;
|
mAttack = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,7 +497,7 @@ namespace MWMechanics
|
||||||
// coded at 250ms or 1/4 second
|
// coded at 250ms or 1/4 second
|
||||||
//
|
//
|
||||||
// TODO: Add a parameter to vary DURATION_SAME_SPOT?
|
// TODO: Add a parameter to vary DURATION_SAME_SPOT?
|
||||||
if((distBetween > rangeMelee || mFollowTarget) &&
|
if((distToTarget > rangeAttack || mFollowTarget) &&
|
||||||
mObstacleCheck.check(actor, tReaction)) // check if evasive action needed
|
mObstacleCheck.check(actor, tReaction)) // check if evasive action needed
|
||||||
{
|
{
|
||||||
// first check if we're walking into a door
|
// first check if we're walking into a door
|
||||||
|
@ -406,12 +509,11 @@ namespace MWMechanics
|
||||||
// Check all the doors in this cell
|
// Check all the doors in this cell
|
||||||
mDoors = cell->get<ESM::Door>(); // update
|
mDoors = cell->get<ESM::Door>(); // update
|
||||||
mDoorIter = mDoors.mList.begin();
|
mDoorIter = mDoors.mList.begin();
|
||||||
Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos);
|
|
||||||
for (; mDoorIter != mDoors.mList.end(); ++mDoorIter)
|
for (; mDoorIter != mDoors.mList.end(); ++mDoorIter)
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Door>& ref = *mDoorIter;
|
MWWorld::LiveCellRef<ESM::Door>& ref = *mDoorIter;
|
||||||
float minSqr = 1.3*1.3*MIN_DIST_TO_DOOR_SQUARED; // for legibility
|
float minSqr = 1.3*1.3*MIN_DIST_TO_DOOR_SQUARED; // for legibility
|
||||||
if(actorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr &&
|
if(vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr &&
|
||||||
ref.mData.getLocalRotation().rot[2] < 0.4f) // even small opening
|
ref.mData.getLocalRotation().rot[2] < 0.4f) // even small opening
|
||||||
{
|
{
|
||||||
//std::cout<<"closed door id \""<<ref.mRef.mRefID<<"\""<<std::endl;
|
//std::cout<<"closed door id \""<<ref.mRef.mRefID<<"\""<<std::endl;
|
||||||
|
@ -441,11 +543,10 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::LiveCellRef<ESM::Door>& ref = *mDoorIter;
|
MWWorld::LiveCellRef<ESM::Door>& ref = *mDoorIter;
|
||||||
Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos);
|
|
||||||
float minSqr = 1.6 * 1.6 * MIN_DIST_TO_DOOR_SQUARED; // for legibility
|
float minSqr = 1.6 * 1.6 * MIN_DIST_TO_DOOR_SQUARED; // for legibility
|
||||||
// TODO: add reaction to checking open doors
|
// TODO: add reaction to checking open doors
|
||||||
if(mBackOffDoor &&
|
if(mBackOffDoor &&
|
||||||
actorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr)
|
vActorPos.squaredDistance(Ogre::Vector3(ref.mRef.mPos.pos)) < minSqr)
|
||||||
{
|
{
|
||||||
mMovement.mPosition[1] = -0.2; // back off, but slowly
|
mMovement.mPosition[1] = -0.2; // back off, but slowly
|
||||||
}
|
}
|
||||||
|
@ -458,43 +559,34 @@ namespace MWMechanics
|
||||||
//std::cout<<"open door id \""<<ref.mRef.mRefID<<"\""<<std::endl;
|
//std::cout<<"open door id \""<<ref.mRef.mRefID<<"\""<<std::endl;
|
||||||
mMovement.mPosition[1] = 1;
|
mMovement.mPosition[1] = 1;
|
||||||
}
|
}
|
||||||
else
|
// these lines break ranged combat distance keeping
|
||||||
{
|
//else
|
||||||
mMovement.mPosition[1] = 1; // FIXME: oscillation?
|
//{
|
||||||
}
|
// mMovement.mPosition[1] = 1; // FIXME: oscillation?
|
||||||
|
//}
|
||||||
actor.getClass().getMovementSettings(actor) = mMovement;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiCombat::buildNewPath(const MWWorld::Ptr& actor)
|
void AiCombat::buildNewPath(const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
//Construct path to target
|
Ogre::Vector3 newPathTarget = Ogre::Vector3(mTarget.getRefData().getPosition().pos);
|
||||||
ESM::Pathgrid::Point dest;
|
|
||||||
dest.mX = mTarget.getRefData().getPosition().pos[0];
|
float dist;
|
||||||
dest.mY = mTarget.getRefData().getPosition().pos[1];
|
|
||||||
dest.mZ = mTarget.getRefData().getPosition().pos[2];
|
|
||||||
Ogre::Vector3 newPathTarget = Ogre::Vector3(dest.mX, dest.mY, dest.mZ);
|
|
||||||
|
|
||||||
float dist = -1; //hack to indicate first time, to construct a new path
|
|
||||||
if(!mPathFinder.getPath().empty())
|
if(!mPathFinder.getPath().empty())
|
||||||
{
|
{
|
||||||
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back();
|
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back();
|
||||||
Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ);
|
Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ);
|
||||||
dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length());
|
dist = (newPathTarget - currPathTarget).length();
|
||||||
}
|
}
|
||||||
|
else dist = 1e+38F; // necessarily construct a new path
|
||||||
|
|
||||||
float targetPosThreshold;
|
float targetPosThreshold = (actor.getCell()->getCell()->isExterior())? 300 : 100;
|
||||||
bool isOutside = actor.getCell()->getCell()->isExterior();
|
|
||||||
if (isOutside)
|
|
||||||
targetPosThreshold = 300;
|
|
||||||
else
|
|
||||||
targetPosThreshold = 100;
|
|
||||||
|
|
||||||
if((dist < 0) || (dist > targetPosThreshold))
|
//construct new path only if target has moved away more than on [targetPosThreshold]
|
||||||
|
if(dist > targetPosThreshold)
|
||||||
{
|
{
|
||||||
//construct new path only if target has moved away more than on <targetPosThreshold>
|
|
||||||
ESM::Position pos = actor.getRefData().getPosition();
|
ESM::Position pos = actor.getRefData().getPosition();
|
||||||
|
|
||||||
ESM::Pathgrid::Point start;
|
ESM::Pathgrid::Point start;
|
||||||
|
@ -502,17 +594,18 @@ namespace MWMechanics
|
||||||
start.mY = pos.pos[1];
|
start.mY = pos.pos[1];
|
||||||
start.mZ = pos.pos[2];
|
start.mZ = pos.pos[2];
|
||||||
|
|
||||||
|
ESM::Pathgrid::Point dest;
|
||||||
|
dest.mX = newPathTarget.x;
|
||||||
|
dest.mY = newPathTarget.y;
|
||||||
|
dest.mZ = newPathTarget.z;
|
||||||
|
|
||||||
if(!mPathFinder.isPathConstructed())
|
if(!mPathFinder.isPathConstructed())
|
||||||
mPathFinder.buildPath(start, dest, actor.getCell(), isOutside);
|
mPathFinder.buildPath(start, dest, actor.getCell(), false);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PathFinder newPathFinder;
|
PathFinder newPathFinder;
|
||||||
newPathFinder.buildPath(start, dest, actor.getCell(), isOutside);
|
newPathFinder.buildPath(start, dest, actor.getCell(), false);
|
||||||
|
|
||||||
//TO EXPLORE:
|
|
||||||
//maybe here is a mistake (?): PathFinder::getPathSize() returns number of grid points in the path,
|
|
||||||
//not the actual path length. Here we should know if the new path is actually more effective.
|
|
||||||
//if(pathFinder2.getPathSize() < mPathFinder.getPathSize())
|
|
||||||
if(!mPathFinder.getPath().empty())
|
if(!mPathFinder.getPath().empty())
|
||||||
{
|
{
|
||||||
newPathFinder.syncStart(mPathFinder.getPath());
|
newPathFinder.syncStart(mPathFinder.getPath());
|
||||||
|
|
|
@ -39,17 +39,16 @@ namespace MWMechanics
|
||||||
// when mCombatMove is true
|
// when mCombatMove is true
|
||||||
float mTimerCombatMove;
|
float mTimerCombatMove;
|
||||||
|
|
||||||
// the z rotation angle (degrees) we want to reach
|
|
||||||
// used every frame when mRotate is true
|
|
||||||
float mTargetAngle;
|
|
||||||
|
|
||||||
// AiCombat states
|
// AiCombat states
|
||||||
bool mReadyToAttack, mStrike;
|
bool mReadyToAttack, mAttack;
|
||||||
bool mFollowTarget;
|
bool mFollowTarget;
|
||||||
bool mCombatMove;
|
bool mCombatMove;
|
||||||
bool mBackOffDoor;
|
bool mBackOffDoor;
|
||||||
bool mRotate;
|
|
||||||
|
|
||||||
|
bool mForceNoShortcut;
|
||||||
|
ESM::Position mShortcutFailPos;
|
||||||
|
|
||||||
|
ESM::Position mLastPos;
|
||||||
MWMechanics::Movement mMovement;
|
MWMechanics::Movement mMovement;
|
||||||
MWWorld::Ptr mTarget;
|
MWWorld::Ptr mTarget;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace MWMechanics
|
||||||
TypeIdFollow = 3,
|
TypeIdFollow = 3,
|
||||||
TypeIdActivate = 4,
|
TypeIdActivate = 4,
|
||||||
TypeIdCombat = 5,
|
TypeIdCombat = 5,
|
||||||
TypeIdPersue = 6
|
TypeIdPursue = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~AiPackage();
|
virtual ~AiPackage();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue