mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-20 18:53:54 +00:00
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
|
||||
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
|
||||
option(OPENMW_OSX_DEPLOYMENT OFF)
|
||||
|
@ -171,27 +169,6 @@ if (USE_FFMPEG)
|
|||
endif (FFMPEG_FOUND)
|
||||
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)
|
||||
message(WARNING "--------------------")
|
||||
message(WARNING "Failed to find any sound input packages")
|
||||
|
@ -434,7 +411,6 @@ IF(NOT WIN32 AND NOT APPLE)
|
|||
|
||||
# Install licenses
|
||||
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" )
|
||||
ENDIF (DPKG_PROGRAM)
|
||||
|
||||
|
|
|
@ -333,7 +333,7 @@ int load(Arguments& info)
|
|||
|
||||
// Is the user interested in this record type?
|
||||
bool interested = true;
|
||||
if (info.types.size() > 0)
|
||||
if (!info.types.empty())
|
||||
{
|
||||
std::vector<std::string>::iterator match;
|
||||
match = std::find(info.types.begin(), info.types.end(),
|
||||
|
|
|
@ -124,7 +124,7 @@ void printEffectList(ESM::EffectList effects)
|
|||
{
|
||||
int i = 0;
|
||||
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)
|
||||
<< " (" << eit->mEffectID << ")" << std::endl;
|
||||
|
|
|
@ -214,13 +214,13 @@ QStringList Launcher::GraphicsPage::getAvailableOptions(const QString &key, Ogre
|
|||
uint row = 0;
|
||||
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;
|
||||
uint idx = 0;
|
||||
|
||||
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) {
|
||||
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
|
||||
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
||||
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
|
||||
scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap
|
||||
scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable
|
||||
)
|
||||
|
||||
opencs_units (view/render
|
||||
|
@ -95,7 +95,9 @@ opencs_units (view/settings
|
|||
booleanview
|
||||
textview
|
||||
listview
|
||||
rangeview
|
||||
resizeablestackedwidget
|
||||
spinbox
|
||||
)
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -1,29 +1,22 @@
|
|||
#include "setting.hpp"
|
||||
#include "support.hpp"
|
||||
|
||||
CSMSettings::Setting::Setting()
|
||||
{
|
||||
buildDefaultSetting();
|
||||
}
|
||||
|
||||
CSMSettings::Setting::Setting(SettingType typ, const QString &settingName,
|
||||
const QString &pageName, const QStringList &values)
|
||||
const QString &pageName)
|
||||
: mIsEditorSetting (false)
|
||||
{
|
||||
buildDefaultSetting();
|
||||
|
||||
int vType = static_cast <int> (typ);
|
||||
int settingType = static_cast <int> (typ);
|
||||
|
||||
if ((vType % 2) == 0)
|
||||
setProperty (Property_IsMultiValue,
|
||||
QVariant(true).toString());
|
||||
else
|
||||
vType--;
|
||||
//even-numbered setting types are multi-valued
|
||||
if ((settingType % 2) == 0)
|
||||
setProperty (Property_IsMultiValue, QVariant(true).toString());
|
||||
|
||||
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_Name, settingName);
|
||||
setProperty (Property_DeclaredValues, values);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::buildDefaultSetting()
|
||||
|
@ -74,6 +67,11 @@ int CSMSettings::Setting::columnSpan() const
|
|||
return property (Property_ColumnSpan).at(0).toInt();
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setDeclaredValues (QStringList list)
|
||||
{
|
||||
setProperty (Property_DeclaredValues, list);
|
||||
}
|
||||
|
||||
QStringList CSMSettings::Setting::declaredValues() const
|
||||
{
|
||||
return property (Property_DeclaredValues);
|
||||
|
@ -97,6 +95,16 @@ QStringList CSMSettings::Setting::property (SettingProperty prop) const
|
|||
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)
|
||||
{
|
||||
setDefaultValues (QStringList() << value);
|
||||
|
@ -166,6 +174,16 @@ bool CSMSettings::Setting::serializable() const
|
|||
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)
|
||||
{
|
||||
setProperty (Property_Name, value);
|
||||
|
@ -186,6 +204,16 @@ QString CSMSettings::Setting::page() const
|
|||
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)
|
||||
{
|
||||
setProperty (Property_RowSpan, value);
|
||||
|
@ -196,15 +224,106 @@ int CSMSettings::Setting::rowSpan () const
|
|||
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
|
||||
{
|
||||
return static_cast <CSVSettings::ViewType>
|
||||
(property(Property_ViewType).at(0).toInt());
|
||||
return static_cast <CSVSettings::ViewType> ( property (
|
||||
Property_SettingType).at(0).toInt() / 10);
|
||||
}
|
||||
|
||||
void CSMSettings::Setting::setViewColumn (int value)
|
||||
|
@ -242,6 +361,17 @@ int CSMSettings::Setting::widgetWidth() const
|
|||
{
|
||||
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)
|
||||
{
|
||||
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||
|
@ -252,6 +382,11 @@ void CSMSettings::Setting::setProperty (SettingProperty prop, int value)
|
|||
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,
|
||||
const QString &value)
|
||||
{
|
||||
|
@ -264,18 +399,3 @@ void CSMSettings::Setting::setProperty (SettingProperty prop,
|
|||
if (prop < mProperties.size())
|
||||
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:
|
||||
|
||||
|
||||
explicit Setting();
|
||||
|
||||
explicit Setting(SettingType typ, const QString &settingName,
|
||||
const QString &pageName,
|
||||
const QStringList &values = QStringList());
|
||||
const QString &pageName);
|
||||
|
||||
void addProxy (const Setting *setting, const QStringList &vals);
|
||||
void addProxy (const Setting *setting, const QList <QStringList> &list);
|
||||
|
@ -49,6 +45,8 @@ namespace CSMSettings
|
|||
void setDefinedValues (QStringList list);
|
||||
QStringList definedValues() const;
|
||||
|
||||
void setDefaultValue (int value);
|
||||
void setDefaultValue (double value);
|
||||
void setDefaultValue (const QString &value);
|
||||
|
||||
void setDefaultValues (const QStringList &values);
|
||||
|
@ -66,12 +64,26 @@ namespace CSMSettings
|
|||
void setIsMultiValue (bool state);
|
||||
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);
|
||||
QString name() const;
|
||||
|
||||
void setPage (const QString &value);
|
||||
QString page() const;
|
||||
|
||||
void setPrefix (const QString &value);
|
||||
QString prefix() const;
|
||||
|
||||
void setRowSpan (const int value);
|
||||
int rowSpan() const;
|
||||
|
||||
|
@ -80,6 +92,25 @@ namespace CSMSettings
|
|||
void setSerializable (bool state);
|
||||
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);
|
||||
int viewColumn() const;
|
||||
|
||||
|
@ -88,9 +119,14 @@ namespace CSMSettings
|
|||
void setViewRow (int value);
|
||||
int viewRow() const;
|
||||
|
||||
void setViewType (int vType);
|
||||
void setType (int settingType);
|
||||
CSMSettings::SettingType type() const;
|
||||
|
||||
CSVSettings::ViewType viewType() const;
|
||||
|
||||
void setWrapping (bool state);
|
||||
bool wrapping() const;
|
||||
|
||||
void setWidgetWidth (int value);
|
||||
int widgetWidth() const;
|
||||
|
||||
|
@ -100,6 +136,7 @@ namespace CSMSettings
|
|||
///boilerplate code to convert setting values of common types
|
||||
void setProperty (SettingProperty prop, bool 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 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
|
||||
|
|
|
@ -30,8 +30,7 @@ void CSMSettings::SettingManager::dumpModel()
|
|||
}
|
||||
|
||||
CSMSettings::Setting *CSMSettings::SettingManager::createSetting
|
||||
(CSMSettings::SettingType typ, const QString &page, const QString &name,
|
||||
const QStringList &values)
|
||||
(CSMSettings::SettingType typ, const QString &page, const QString &name)
|
||||
{
|
||||
//get list of all settings for the current setting name
|
||||
if (findSetting (page, name))
|
||||
|
@ -41,7 +40,8 @@ CSMSettings::Setting *CSMSettings::SettingManager::createSetting
|
|||
return 0;
|
||||
}
|
||||
|
||||
Setting *setting = new Setting (typ, name, page, values);
|
||||
Setting *setting = new Setting (typ, name, page);
|
||||
|
||||
|
||||
//add declaration to the model
|
||||
mSettings.append (setting);
|
||||
|
|
|
@ -46,8 +46,7 @@ namespace CSMSettings
|
|||
|
||||
///add a new setting to the model and return it
|
||||
Setting *createSetting (CSMSettings::SettingType typ,
|
||||
const QString &page, const QString &name,
|
||||
const QStringList &values = QStringList());
|
||||
const QString &page, const QString &name);
|
||||
|
||||
///add definitions to the settings specified in the page map
|
||||
void addDefinitions (DefinitionPageMap &pageMap);
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace CSMSettings
|
|||
{
|
||||
Property_Name = 0,
|
||||
Property_Page = 1,
|
||||
Property_ViewType = 2,
|
||||
Property_SettingType = 2,
|
||||
Property_IsMultiValue = 3,
|
||||
Property_IsMultiLine = 4,
|
||||
Property_WidgetWidth = 5,
|
||||
|
@ -37,24 +37,49 @@ namespace CSMSettings
|
|||
Property_Serializable = 9,
|
||||
Property_ColumnSpan = 10,
|
||||
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
|
||||
Property_DefaultValues = 12,
|
||||
Property_DeclaredValues = 13,
|
||||
Property_DefinedValues = 14,
|
||||
Property_Proxies = 15
|
||||
Property_DefaultValues = 22,
|
||||
Property_DeclaredValues = 23,
|
||||
Property_DefinedValues = 24,
|
||||
Property_Proxies = 25
|
||||
};
|
||||
|
||||
enum SettingType
|
||||
{
|
||||
Type_MultiBool = 0,
|
||||
Type_SingleBool = 1,
|
||||
Type_MultiList = 2,
|
||||
Type_SingleList = 3,
|
||||
Type_MultiRange = 4,
|
||||
Type_SingleRange = 5,
|
||||
Type_MultiText = 6,
|
||||
Type_SingleText = 7
|
||||
/*
|
||||
* 0 - 9 - Boolean widgets
|
||||
* 10-19 - List widgets
|
||||
* 21-29 - Range widgets
|
||||
* 31-39 - Text widgets
|
||||
*
|
||||
* Each range corresponds to a View_Type enum by a factor of 10.
|
||||
*
|
||||
* 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
|
||||
|
@ -84,7 +109,7 @@ namespace CSVSettings
|
|||
};
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
namespace CSMSettings
|
||||
{
|
||||
struct PropertyDefaultValues
|
||||
|
@ -96,9 +121,11 @@ namespace CSMSettings
|
|||
|
||||
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_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"
|
||||
};
|
||||
|
||||
|
@ -106,16 +133,26 @@ namespace CSMSettings
|
|||
{
|
||||
"", //name
|
||||
"", //page
|
||||
"0", //view type
|
||||
"40", //setting type
|
||||
"false", //multivalue
|
||||
"false", //multiline
|
||||
"0", //widget width
|
||||
"7", //widget width
|
||||
"-1", //view row
|
||||
"-1", //view column
|
||||
",", //delimiter
|
||||
"true", //serialized
|
||||
"1", //column 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
|
||||
"", //declared values
|
||||
"", //defined values
|
||||
|
|
|
@ -47,11 +47,11 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
{
|
||||
QString section = "Window Size";
|
||||
{
|
||||
Setting *width = createSetting (Type_SingleText, section, "Width");
|
||||
Setting *height = createSetting (Type_SingleText, section, "Height");
|
||||
Setting *width = createSetting (Type_LineEdit, section, "Width");
|
||||
Setting *height = createSetting (Type_LineEdit, section, "Height");
|
||||
|
||||
width->setWidgetWidth (5);
|
||||
height->setWidgetWidth (5);
|
||||
height->setWidgetWidth (8);
|
||||
|
||||
width->setDefaultValues (QStringList() << "1024");
|
||||
height->setDefaultValues (QStringList() << "768");
|
||||
|
@ -65,14 +65,11 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
/*
|
||||
*Create the proxy setting for predefined values
|
||||
*/
|
||||
Setting *preDefined = createSetting (Type_SingleList, section,
|
||||
"Pre-Defined",
|
||||
QStringList()
|
||||
<< "640 x 480"
|
||||
<< "800 x 600"
|
||||
<< "1024 x 768"
|
||||
<< "1440 x 900"
|
||||
);
|
||||
Setting *preDefined = createSetting (Type_ComboBox, section,
|
||||
"Pre-Defined");
|
||||
|
||||
preDefined->setDeclaredValues (QStringList() << "640 x 480"
|
||||
<< "800 x 600" << "1024 x 768" << "1440 x 900");
|
||||
|
||||
preDefined->setViewLocation (1, 1);
|
||||
preDefined->setWidgetWidth (10);
|
||||
|
@ -94,13 +91,14 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
QStringList values = QStringList()
|
||||
<< defaultValue << "Icon Only" << "Text Only";
|
||||
|
||||
Setting *rsd = createSetting (Type_SingleBool,
|
||||
section, "Record Status Display",
|
||||
values);
|
||||
Setting *rsd = createSetting (Type_RadioButton,
|
||||
section, "Record Status Display");
|
||||
|
||||
Setting *ritd = createSetting (Type_SingleBool,
|
||||
section, "Referenceable ID Type Display",
|
||||
values);
|
||||
Setting *ritd = createSetting (Type_RadioButton,
|
||||
section, "Referenceable ID Type Display");
|
||||
|
||||
rsd->setDeclaredValues (values);
|
||||
ritd->setDeclaredValues (values);
|
||||
|
||||
rsd->setEditorSetting (true);
|
||||
ritd->setEditorSetting (true);
|
||||
|
@ -108,44 +106,67 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
|
||||
section = "Proxy Selection Test";
|
||||
{
|
||||
//create three setting objects, specifying the basic widget type,
|
||||
//the setting view name, the page name, and the default value
|
||||
Setting *masterBoolean = createSetting (Type_SingleBool, section,
|
||||
"Master Proxy",
|
||||
QStringList()
|
||||
<< "Profile One" << "Profile Two"
|
||||
<< "Profile Three" << "Profile Four"
|
||||
);
|
||||
/******************************************************************
|
||||
* 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 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.
|
||||
*******************************************************************/
|
||||
|
||||
Setting *slaveBoolean = createSetting (Type_MultiBool, section,
|
||||
"Proxy Checkboxes",
|
||||
QStringList() << "One" << "Two"
|
||||
<< "Three" << "Four" << "Five"
|
||||
);
|
||||
//create setting objects, specifying the basic widget type,
|
||||
//the page name, and the view name
|
||||
/*
|
||||
Setting *masterBoolean = createSetting (Type_RadioButton, section,
|
||||
"Master Proxy");
|
||||
|
||||
Setting *slaveSingleText = createSetting (Type_SingleText, section,
|
||||
"Proxy TextBox 1"
|
||||
);
|
||||
Setting *slaveBoolean = createSetting (Type_CheckBox, section,
|
||||
"Proxy Checkboxes");
|
||||
|
||||
Setting *slaveMultiText = createSetting (Type_SingleText, section,
|
||||
"ProxyTextBox 2"
|
||||
);
|
||||
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 Three" << "Profile Four");
|
||||
|
||||
slaveBoolean->setDeclaredValues (QStringList()
|
||||
<< "One" << "Two" << "Three" << "Four" << "Five");
|
||||
|
||||
slaveAlphaSpinbox->setDeclaredValues (QStringList()
|
||||
<< "One" << "Two" << "Three" << "Four");
|
||||
|
||||
// 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>()
|
||||
<< (QStringList() << "One" << "Three")
|
||||
|
@ -168,11 +189,47 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
<< (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
|
||||
//other settings non-serialized for demo purposes
|
||||
slaveBoolean->setSerializable (false);
|
||||
slaveSingleText->setSerializable (false);
|
||||
slaveMultiText->setSerializable (false);
|
||||
slaveAlphaSpinbox->setSerializable (false);
|
||||
slaveIntegerSpinbox->setSerializable (false);
|
||||
slaveDoubleSpinbox->setSerializable (false);
|
||||
slaveSlider->setSerializable (false);
|
||||
|
||||
slaveBoolean->setDefaultValues (QStringList()
|
||||
<< "One" << "Three" << "Five");
|
||||
|
@ -184,7 +241,39 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
|
||||
slaveSingleText->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);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
CSMSettings::UserSettings::~UserSettings()
|
||||
|
@ -195,13 +284,13 @@ CSMSettings::UserSettings::~UserSettings()
|
|||
void CSMSettings::UserSettings::loadSettings (const QString &fileName)
|
||||
{
|
||||
mUserFilePath = QString::fromUtf8
|
||||
(mCfgMgr.getUserConfigPath().c_str()) + fileName.toUtf8();
|
||||
(mCfgMgr.getUserConfigPath().string().c_str()) + fileName.toUtf8();
|
||||
|
||||
QString global = QString::fromUtf8
|
||||
(mCfgMgr.getGlobalPath().c_str()) + fileName.toUtf8();
|
||||
(mCfgMgr.getGlobalPath().string().c_str()) + fileName.toUtf8();
|
||||
|
||||
QString local = QString::fromUtf8
|
||||
(mCfgMgr.getLocalPath().c_str()) + fileName.toUtf8();
|
||||
(mCfgMgr.getLocalPath().string().c_str()) + fileName.toUtf8();
|
||||
|
||||
//open user and global streams
|
||||
QTextStream *userStream = openFilestream (mUserFilePath, true);
|
||||
|
|
|
@ -453,7 +453,7 @@ CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters()
|
|||
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());
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "tablemimedata.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "universalid.hpp"
|
||||
#include "columnbase.hpp"
|
||||
|
||||
|
@ -11,7 +14,7 @@ mDocument(document)
|
|||
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)
|
||||
{
|
||||
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())
|
||||
{
|
||||
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;
|
||||
|
@ -50,7 +54,7 @@ std::string CSMWorld::TableMimeData::getIcon() const
|
|||
|
||||
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();
|
||||
|
@ -531,4 +535,4 @@ CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::U
|
|||
const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const
|
||||
{
|
||||
return &mDocument;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace CSMWorld
|
|||
public:
|
||||
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();
|
||||
|
||||
|
@ -56,6 +56,7 @@ namespace CSMWorld
|
|||
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
|
||||
|
||||
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);
|
||||
|
||||
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
|
||||
|
||||
private:
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace
|
|||
{ 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_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_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace CSMWorld
|
|||
Type_Spell,
|
||||
Type_Cells,
|
||||
Type_Cell,
|
||||
Type_Cell_Missing, //For cells that does not exist yet.
|
||||
Type_Referenceables,
|
||||
Type_Referenceable,
|
||||
Type_Activator,
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget *parent)
|
||||
: WorldspaceWidget (parent)
|
||||
#include <QtGui/qevent.h>
|
||||
|
||||
#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)
|
||||
|
@ -44,4 +48,45 @@ void CSVRender::PagedWorldspaceWidget::setCellSelection (const CSMWorld::CellSel
|
|||
{
|
||||
mSelection = selection;
|
||||
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;
|
||||
|
||||
private:
|
||||
|
||||
std::pair<int, int> getCoordinatesFromId(const std::string& record) const;
|
||||
|
||||
public:
|
||||
|
||||
PagedWorldspaceWidget (QWidget *parent);
|
||||
PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document);
|
||||
///< \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
|
||||
/// hint system.
|
||||
|
||||
virtual void useViewHint (const std::string& hint);
|
||||
void useViewHint (const std::string& hint);
|
||||
|
||||
void setCellSelection (const CSMWorld::CellSelection& selection);
|
||||
|
||||
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
|
||||
|
||||
virtual dropRequirments getDropRequirements(dropType type) const;
|
||||
|
||||
signals:
|
||||
|
||||
void cellSelectionChanged (const CSMWorld::CellSelection& selection);
|
||||
|
|
|
@ -320,7 +320,7 @@ namespace CSVRender
|
|||
|
||||
}
|
||||
|
||||
if (mUpdate)
|
||||
if (mUpdate && mWindow)
|
||||
{
|
||||
mUpdate = false;
|
||||
mWindow->update();
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace CSVRender
|
|||
SceneWidget(QWidget *parent);
|
||||
virtual ~SceneWidget();
|
||||
|
||||
QPaintEngine* paintEngine() const;
|
||||
QPaintEngine* paintEngine() const;
|
||||
|
||||
CSVWorld::SceneToolMode *makeLightingSelector (CSVWorld::SceneToolbar *parent);
|
||||
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
|
||||
|
|
|
@ -3,10 +3,13 @@
|
|||
|
||||
#include <OgreColourValue.h>
|
||||
|
||||
#include <QtGui/qevent.h>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/idtable.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
|
||||
void CSVRender::UnpagedWorldspaceWidget::update()
|
||||
{
|
||||
|
@ -20,9 +23,8 @@ void CSVRender::UnpagedWorldspaceWidget::update()
|
|||
/// \todo deal with mSunlight and mFog/mForDensity
|
||||
}
|
||||
|
||||
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId,
|
||||
CSMDoc::Document& document, QWidget *parent)
|
||||
: WorldspaceWidget (parent), mCellId (cellId)
|
||||
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent)
|
||||
: WorldspaceWidget (document, parent), mCellId (cellId)
|
||||
{
|
||||
mCellsModel = &dynamic_cast<CSMWorld::IdTable&> (
|
||||
*document.getData().getTableModel (CSMWorld::UniversalId::Type_Cells));
|
||||
|
@ -63,4 +65,26 @@ void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelI
|
|||
|
||||
if (cellIndex.row()>=start && cellIndex.row()<=end)
|
||||
emit closeRequest();
|
||||
}
|
||||
}
|
||||
|
||||
void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data)
|
||||
{
|
||||
mCellId = data.begin()->getId();
|
||||
update();
|
||||
emit cellChanged(*data.begin());
|
||||
}
|
||||
|
||||
CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case cellsInterior:
|
||||
return canHandle;
|
||||
|
||||
case cellsExterior:
|
||||
return needPaged;
|
||||
|
||||
default:
|
||||
return ignored;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,13 +31,21 @@ namespace CSVRender
|
|||
public:
|
||||
|
||||
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:
|
||||
|
||||
void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||
|
||||
void cellRowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||
|
||||
signals:
|
||||
|
||||
void cellChanged(const CSMWorld::UniversalId& id);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,15 +5,20 @@
|
|||
#include <OgreSceneManager.h>
|
||||
#include <OgreEntity.h>
|
||||
|
||||
#include "../world/scenetoolmode.hpp"
|
||||
#include <QtGui/qevent.h>
|
||||
|
||||
CSVRender::WorldspaceWidget::WorldspaceWidget (QWidget *parent)
|
||||
: SceneWidget (parent)
|
||||
#include "../world/scenetoolmode.hpp"
|
||||
#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);
|
||||
ent->setMaterialName("BaseWhite");
|
||||
|
||||
getSceneManager()->getRootSceneNode()->attachObject(ent);
|
||||
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
|
||||
|
@ -46,4 +51,78 @@ CSVWorld::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
|
|||
this, SLOT (selectNavigationMode (const std::string&)));
|
||||
|
||||
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 "navigationfree.hpp"
|
||||
#include "navigationorbit.hpp"
|
||||
#include <apps/opencs/model/doc/document.hpp>
|
||||
#include <apps/opencs/model/world/tablemimedata.hpp>
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class UniversalId;
|
||||
}
|
||||
namespace CSVWorld
|
||||
{
|
||||
class SceneToolMode;
|
||||
|
@ -25,7 +31,23 @@ namespace CSVRender
|
|||
|
||||
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);
|
||||
///< \attention The created tool is not added to the toolbar (via addTool). Doing that
|
||||
|
@ -33,9 +55,26 @@ namespace CSVRender
|
|||
|
||||
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);
|
||||
///< 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:
|
||||
|
||||
void selectNavigationMode (const std::string& mode);
|
||||
|
@ -43,6 +82,7 @@ namespace CSVRender
|
|||
signals:
|
||||
|
||||
void closeRequest();
|
||||
void dataDropped(const std::vector<CSMWorld::UniversalId>& data);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -18,10 +18,19 @@ CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting,
|
|||
{
|
||||
QAbstractButton *button = 0;
|
||||
|
||||
if (isMultiValue())
|
||||
switch (setting->type())
|
||||
{
|
||||
case CSMSettings::Type_CheckBox:
|
||||
button = new QCheckBox (value, this);
|
||||
else
|
||||
break;
|
||||
|
||||
case CSMSettings::Type_RadioButton:
|
||||
button = new QRadioButton (value, this);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
connect (button, SIGNAL (clicked (bool)),
|
||||
this, SLOT (slotToggled (bool)));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef CSVSETTINGS_BOOLEANVIEW_HPP
|
||||
#define CSVSETTINGS_BOOELANVIEW_HPP
|
||||
#define CSVSETTINGS_BOOLEANVIEW_HPP
|
||||
|
||||
#include <QWidget>
|
||||
#include <QAbstractButton>
|
||||
|
|
|
@ -123,10 +123,8 @@ void CSVSettings::Dialog::show()
|
|||
{
|
||||
if (pages().isEmpty())
|
||||
buildPages();
|
||||
|
||||
QPoint screenCenter = QApplication::desktop()->screenGeometry().center();
|
||||
|
||||
move (screenCenter - geometry().center());
|
||||
|
||||
QWidget::show();
|
||||
}
|
||||
|
|
|
@ -60,8 +60,10 @@ void CSVSettings::Frame::showWidgets()
|
|||
QWidget *widg = static_cast <QWidget *> (obj);
|
||||
|
||||
if (widg->property("sizePolicy").isValid())
|
||||
{
|
||||
widg->setSizePolicy
|
||||
(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
}
|
||||
}
|
||||
layout()->activate();
|
||||
setFixedSize(minimumSizeHint());
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
#include "booleanview.hpp"
|
||||
#include "textview.hpp"
|
||||
#include "listview.hpp"
|
||||
#include "rangeview.hpp"
|
||||
|
||||
#include "../../model/settings/usersettings.hpp"
|
||||
#include "../../model/settings/connector.hpp"
|
||||
#include "../../model/settings/support.hpp"
|
||||
|
||||
#include "settingwindow.hpp"
|
||||
|
||||
QMap <CSVSettings::ViewType, CSVSettings::IViewFactory *>
|
||||
|
@ -85,4 +88,5 @@ void CSVSettings::Page::buildFactories()
|
|||
mViewFactories[ViewType_Boolean] = new BooleanViewFactory (this);
|
||||
mViewFactories[ViewType_Text] = new TextViewFactory (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
|
|
@ -19,7 +19,7 @@ void CSVSettings::SettingWindow::createPages()
|
|||
QList <CSMSettings::Setting *> connectedSettings;
|
||||
|
||||
foreach (const QString &pageName, pageMap.keys())
|
||||
{
|
||||
{
|
||||
QList <CSMSettings::Setting *> pageSettings = pageMap.value (pageName);
|
||||
|
||||
mPages.append (new Page (pageName, pageSettings, this));
|
||||
|
|
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());
|
||||
}
|
||||
|
||||
void CSVSettings::TextView::setWidgetText (const QString &value) const
|
||||
{
|
||||
mTextWidget->setProperty ("text", value);
|
||||
}
|
||||
|
||||
void CSVSettings::TextView::slotTextEdited (QString value)
|
||||
{
|
||||
QStringList values = value.split (mDelimiter, QString::SkipEmptyParts);
|
||||
|
@ -51,19 +46,14 @@ void CSVSettings::TextView::updateView(bool signalUpdate) const
|
|||
{
|
||||
QString values = selectedValues().join (mDelimiter);
|
||||
|
||||
if (isEquivalent (widgetText(), values))
|
||||
if (isEquivalent (mTextWidget->property("text").toString(), values))
|
||||
return;
|
||||
|
||||
setWidgetText (values);
|
||||
mTextWidget->setProperty("text", values);
|
||||
|
||||
View::updateView (signalUpdate);
|
||||
}
|
||||
|
||||
QString CSVSettings::TextView::widgetText() const
|
||||
{
|
||||
return mTextWidget->property("text").toString();
|
||||
}
|
||||
|
||||
CSVSettings::TextView *CSVSettings::TextViewFactory::createView
|
||||
(CSMSettings::Setting *setting,
|
||||
Page *parent)
|
||||
|
|
|
@ -32,12 +32,6 @@ namespace CSVSettings
|
|||
///Comparison function that returns true if the trimmed() strings
|
||||
///are equal
|
||||
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
|
||||
|
|
|
@ -192,6 +192,7 @@ bool CSVSettings::View::stringListsMatch (
|
|||
QList <QStandardItem *> CSVSettings::View::toStandardItemList
|
||||
(const QStringList &list) const
|
||||
{
|
||||
|
||||
QList <QStandardItem *> itemList;
|
||||
|
||||
foreach (const QString &value, list)
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace CSVSettings
|
|||
void showEvent ( QShowEvent * event );
|
||||
|
||||
///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;
|
||||
|
||||
///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 ()
|
||||
{
|
||||
if (mPixmaps.size() > 0)
|
||||
if (!mPixmaps.empty())
|
||||
mPixmaps.clear();
|
||||
|
||||
IconList::iterator it = mIcons.begin();
|
||||
|
@ -33,7 +33,7 @@ void CSVWorld::DataDisplayDelegate::buildPixmaps ()
|
|||
while (it != mIcons.end())
|
||||
{
|
||||
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 (
|
||||
display, mUndoStack, mParent);
|
||||
mDelegates.insert(std::make_pair<int, CommandDelegate*>(display, delegate));
|
||||
mDelegates.insert(std::make_pair(display, delegate));
|
||||
} else
|
||||
{
|
||||
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/commands.hpp"
|
||||
#include "../../model/world/columns.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
|
||||
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,
|
||||
CSMDoc::Document& document, QWidget *parent)
|
||||
: QTableView (parent), mEditLock (false), mDocument (document)
|
||||
: DragRecordTable(document, parent)
|
||||
{
|
||||
verticalHeader()->hide();
|
||||
horizontalHeader()->hide();
|
||||
|
@ -223,11 +224,8 @@ CSVWorld::RegionMap::RegionMap (const CSMWorld::UniversalId& universalId,
|
|||
mViewInTableAction = new QAction (tr ("View Cells in Table"), this);
|
||||
connect (mViewInTableAction, SIGNAL (triggered()), this, SLOT (viewInTable()));
|
||||
addAction (mViewInTableAction);
|
||||
}
|
||||
|
||||
void CSVWorld::RegionMap::setEditLock (bool locked)
|
||||
{
|
||||
mEditLock = locked;
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
void CSVWorld::RegionMap::selectAll()
|
||||
|
@ -343,4 +341,65 @@ void CSVWorld::RegionMap::viewInTable()
|
|||
hint << ")";
|
||||
|
||||
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
|
||||
#define CSV_WORLD_REGIONMAP_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <QObject>
|
||||
#include <QTableView>
|
||||
|
||||
#include "./dragrecordtable.hpp"
|
||||
|
||||
class QAction;
|
||||
|
||||
namespace CSMDoc
|
||||
|
@ -17,7 +23,7 @@ namespace CSMWorld
|
|||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class RegionMap : public QTableView
|
||||
class RegionMap : public DragRecordTable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -29,8 +35,6 @@ namespace CSVWorld
|
|||
QAction *mUnsetRegionAction;
|
||||
QAction *mViewAction;
|
||||
QAction *mViewInTableAction;
|
||||
bool mEditLock;
|
||||
CSMDoc::Document& mDocument;
|
||||
std::string mRegionId;
|
||||
|
||||
private:
|
||||
|
@ -50,12 +54,16 @@ namespace CSVWorld
|
|||
void setRegion (const std::string& regionId);
|
||||
///< Set region Id of selected cells.
|
||||
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
|
||||
void dropEvent(QDropEvent* event);
|
||||
|
||||
public:
|
||||
|
||||
RegionMap (const CSMWorld::UniversalId& universalId, CSMDoc::Document& document,
|
||||
QWidget *parent = 0);
|
||||
|
||||
void setEditLock (bool locked);
|
||||
virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const;
|
||||
|
||||
signals:
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <cassert>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
||||
|
@ -18,11 +19,10 @@
|
|||
|
||||
#include "tablebottombox.hpp"
|
||||
#include "creator.hpp"
|
||||
#include "scenetoolbar.hpp"
|
||||
#include "scenetoolmode.hpp"
|
||||
|
||||
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;
|
||||
|
||||
|
@ -32,33 +32,35 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
|||
new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id,
|
||||
this), 0);
|
||||
|
||||
QHBoxLayout *layout2 = new QHBoxLayout;
|
||||
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||
|
||||
layout2->setContentsMargins (QMargins (0, 0, 0, 0));
|
||||
|
||||
SceneToolbar *toolbar = new SceneToolbar (48+6, this);
|
||||
CSVRender::WorldspaceWidget* wordspaceWidget = NULL;
|
||||
widgetType whatWidget;
|
||||
|
||||
if (id.getId()=="sys::default")
|
||||
{
|
||||
CSVRender::PagedWorldspaceWidget *widget = new CSVRender::PagedWorldspaceWidget (this);
|
||||
mScene = widget;
|
||||
connect (widget, SIGNAL (cellSelectionChanged (const CSMWorld::CellSelection&)),
|
||||
this, SLOT (cellSelectionChanged (const CSMWorld::CellSelection&)));
|
||||
whatWidget = widget_Paged;
|
||||
|
||||
CSVRender::PagedWorldspaceWidget *newWidget = new CSVRender::PagedWorldspaceWidget (this, document);
|
||||
|
||||
wordspaceWidget = newWidget;
|
||||
|
||||
makeConnections(newWidget);
|
||||
}
|
||||
else
|
||||
mScene = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this);
|
||||
{
|
||||
whatWidget = widget_Unpaged;
|
||||
|
||||
SceneToolMode *navigationTool = mScene->makeNavigationSelector (toolbar);
|
||||
toolbar->addTool (navigationTool);
|
||||
CSVRender::UnpagedWorldspaceWidget *newWidget = new CSVRender::UnpagedWorldspaceWidget (id.getId(), document, this);
|
||||
|
||||
SceneToolMode *lightingTool = mScene->makeLightingSelector (toolbar);
|
||||
toolbar->addTool (lightingTool);
|
||||
wordspaceWidget = newWidget;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -69,10 +71,53 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D
|
|||
widget->setLayout (layout);
|
||||
|
||||
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)
|
||||
|
@ -102,8 +147,19 @@ void CSVWorld::SceneSubView::closeRequest()
|
|||
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)
|
||||
{
|
||||
setUniversalId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Scene, "sys::default"));
|
||||
int size = selection.getSize();
|
||||
|
||||
std::ostringstream stream;
|
||||
|
@ -126,4 +182,62 @@ void CSVWorld::SceneSubView::cellSelectionChanged (const CSMWorld::CellSelection
|
|||
}
|
||||
|
||||
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
|
||||
#define CSV_WORLD_SCENESUBVIEW_H
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include "../doc/subview.hpp"
|
||||
#include "scenetoolbar.hpp"
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
|
@ -18,6 +21,8 @@ namespace CSMDoc
|
|||
namespace CSVRender
|
||||
{
|
||||
class WorldspaceWidget;
|
||||
class PagedWorldspaceWidget;
|
||||
class UnpagedWorldspaceWidget;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
|
@ -32,6 +37,9 @@ namespace CSVWorld
|
|||
|
||||
TableBottomBox *mBottom;
|
||||
CSVRender::WorldspaceWidget *mScene;
|
||||
QHBoxLayout* mLayout;
|
||||
CSMDoc::Document& mDocument;
|
||||
SceneToolbar* mToolbar;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -45,11 +53,30 @@ namespace CSVWorld
|
|||
|
||||
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:
|
||||
|
||||
void closeRequest();
|
||||
|
||||
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,
|
||||
bool createAndDelete, bool sorting, CSMDoc::Document& document)
|
||||
: mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0),
|
||||
mDocument (document)
|
||||
: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0),
|
||||
DragRecordTable(document)
|
||||
{
|
||||
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)
|
||||
(*iter)->setEditLock (locked);
|
||||
|
||||
mEditLock = locked;
|
||||
DragRecordTable::setEditLock(locked);
|
||||
}
|
||||
|
||||
CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
|
||||
|
@ -298,7 +298,7 @@ void CSVWorld::Table::revertRecord()
|
|||
{
|
||||
std::vector<std::string> revertableIds = listRevertableSelectedIds();
|
||||
|
||||
if (revertableIds.size()>0)
|
||||
if (!revertableIds.empty())
|
||||
{
|
||||
if (revertableIds.size()>1)
|
||||
mDocument.getUndoStack().beginMacro (tr ("Revert multiple records"));
|
||||
|
@ -318,7 +318,7 @@ void CSVWorld::Table::deleteRecord()
|
|||
{
|
||||
std::vector<std::string> deletableIds = listDeletableSelectedIds();
|
||||
|
||||
if (deletableIds.size()>0)
|
||||
if (!deletableIds.empty())
|
||||
{
|
||||
if (deletableIds.size()>1)
|
||||
mDocument.getUndoStack().beginMacro (tr ("Delete multiple records"));
|
||||
|
@ -518,42 +518,8 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event)
|
|||
{
|
||||
if (event->buttons() & Qt::LeftButton)
|
||||
{
|
||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||
|
||||
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);
|
||||
startDrag(*this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CSVWorld::Table::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void CSVWorld::Table::dropEvent(QDropEvent *event)
|
||||
|
@ -583,11 +549,6 @@ void CSVWorld::Table::dropEvent(QDropEvent *event)
|
|||
} //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
|
||||
{
|
||||
const int count = mModel->columnCount();
|
||||
|
@ -605,3 +566,18 @@ std::vector<std::string> CSVWorld::Table::getColumnsWithDisplay(CSMWorld::Column
|
|||
}
|
||||
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 <string>
|
||||
|
||||
#include <QTableView>
|
||||
#include <QtGui/qevent.h>
|
||||
|
||||
#include "../../model/filter/node.hpp"
|
||||
#include "../../model/world/columnbase.hpp"
|
||||
#include "dragrecordtable.hpp"
|
||||
|
||||
class QUndoStack;
|
||||
class QAction;
|
||||
|
@ -31,7 +31,7 @@ namespace CSVWorld
|
|||
class CommandDelegate;
|
||||
|
||||
///< Table widget
|
||||
class Table : public QTableView
|
||||
class Table : public DragRecordTable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -47,9 +47,7 @@ namespace CSVWorld
|
|||
QAction *mPreviewAction;
|
||||
CSMWorld::IdTableProxyModel *mProxyModel;
|
||||
CSMWorld::IdTable *mModel;
|
||||
bool mEditLock;
|
||||
int mRecordStatusDisplay;
|
||||
CSMDoc::Document& mDocument;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -61,10 +59,6 @@ namespace CSVWorld
|
|||
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
|
||||
void dropEvent(QDropEvent *event);
|
||||
|
||||
public:
|
||||
|
@ -74,12 +68,14 @@ namespace CSVWorld
|
|||
///< \param createAndDelete Allow creation and deletion of records.
|
||||
/// \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;
|
||||
|
||||
std::vector<std::string> getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const;
|
||||
|
||||
virtual std::vector<CSMWorld::UniversalId> getDraggedRecords() const;
|
||||
|
||||
signals:
|
||||
|
||||
void editRequest (const CSMWorld::UniversalId& id, const std::string& hint);
|
||||
|
@ -92,6 +88,7 @@ namespace CSVWorld
|
|||
/// \param modified Number of added and modified records
|
||||
|
||||
void createRequest();
|
||||
|
||||
void cloneRequest(const CSMWorld::UniversalId&);
|
||||
|
||||
private slots:
|
||||
|
|
|
@ -48,7 +48,7 @@ add_openmw_dir (mwscript
|
|||
)
|
||||
|
||||
add_openmw_dir (mwsound
|
||||
soundmanagerimp openal_output audiere_decoder mpgsnd_decoder ffmpeg_decoder
|
||||
soundmanagerimp openal_output ffmpeg_decoder
|
||||
)
|
||||
|
||||
add_openmw_dir (mwworld
|
||||
|
@ -67,7 +67,7 @@ add_openmw_dir (mwclass
|
|||
|
||||
add_openmw_dir (mwmechanics
|
||||
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
|
||||
disease pickpocket levelledlist combat steering obstacle
|
||||
)
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Loading
|
||||
{
|
||||
class Listener;
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
|
@ -45,9 +50,6 @@ namespace MWBase
|
|||
|
||||
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;
|
||||
|
||||
//calbacks for the GUI
|
||||
|
@ -63,7 +65,7 @@ namespace MWBase
|
|||
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -11,6 +11,11 @@
|
|||
#include "../mwdialogue/topic.hpp"
|
||||
#include "../mwdialogue/quest.hpp"
|
||||
|
||||
namespace Loading
|
||||
{
|
||||
class Listener;
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
|
@ -80,7 +85,7 @@ namespace MWBase
|
|||
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -55,6 +55,8 @@ namespace MWBase
|
|||
|
||||
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;
|
||||
///< 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;
|
||||
|
||||
/// Set time left for the player to start drowning (update the drowning bar)
|
||||
/// @param time value from [0,20]
|
||||
virtual void setDrowningTimeLeft (float time) =0;
|
||||
/// @param time time left to start drowning
|
||||
/// @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;
|
||||
///< set current class of player
|
||||
|
@ -302,8 +303,12 @@ namespace MWBase
|
|||
/// Clear all savegame-specific data
|
||||
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 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 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,
|
||||
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;
|
||||
///< 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 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)
|
||||
MWBase::Environment::get().getMechanicsManager()->commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
|
||||
|
||||
getCreatureStats(ptr).setAttacked(true);
|
||||
|
||||
if(!successful)
|
||||
{
|
||||
// TODO: Handle HitAttemptOnMe script function
|
||||
|
@ -659,7 +661,6 @@ namespace MWClass
|
|||
{
|
||||
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
||||
}
|
||||
getCreatureStats(ptr).setAttacked(true);
|
||||
|
||||
// Check for knockdown
|
||||
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 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;
|
||||
}
|
||||
|
||||
MWWorld::Ptr DialogueManager::getActor() const
|
||||
{
|
||||
return mActor;
|
||||
}
|
||||
|
||||
void DialogueManager::goodbye()
|
||||
{
|
||||
mIsInChoice = true;
|
||||
|
@ -614,7 +609,7 @@ namespace MWDialogue
|
|||
return 1; // known topics
|
||||
}
|
||||
|
||||
void DialogueManager::write (ESM::ESMWriter& writer) const
|
||||
void DialogueManager::write (ESM::ESMWriter& writer, Loading::Listener& progress) const
|
||||
{
|
||||
ESM::DialogueState state;
|
||||
|
||||
|
@ -626,6 +621,7 @@ namespace MWDialogue
|
|||
writer.startRecord (ESM::REC_DIAS);
|
||||
state.save (writer);
|
||||
writer.endRecord (ESM::REC_DIAS);
|
||||
progress.increaseProgress();
|
||||
}
|
||||
|
||||
void DialogueManager::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||
|
|
|
@ -68,9 +68,6 @@ namespace MWDialogue
|
|||
|
||||
virtual void goodbye();
|
||||
|
||||
virtual MWWorld::Ptr getActor() const;
|
||||
///< Return the actor the player is currently talking to.
|
||||
|
||||
virtual bool checkServiceRefused ();
|
||||
|
||||
virtual void say(const MWWorld::Ptr &actor, const std::string &topic) const;
|
||||
|
@ -86,7 +83,7 @@ namespace MWDialogue
|
|||
|
||||
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);
|
||||
};
|
||||
|
|
|
@ -111,8 +111,14 @@ bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const
|
|||
|
||||
// check cell
|
||||
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 true;
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace MWDialogue
|
|||
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)
|
||||
{
|
||||
|
@ -178,6 +178,7 @@ namespace MWDialogue
|
|||
writer.startRecord (ESM::REC_QUES);
|
||||
state.save (writer);
|
||||
writer.endRecord (ESM::REC_QUES);
|
||||
progress.increaseProgress();
|
||||
|
||||
for (Topic::TEntryIter iter (quest.begin()); iter!=quest.end(); ++iter)
|
||||
{
|
||||
|
@ -188,6 +189,7 @@ namespace MWDialogue
|
|||
writer.startRecord (ESM::REC_JOUR);
|
||||
entry.save (writer);
|
||||
writer.endRecord (ESM::REC_JOUR);
|
||||
progress.increaseProgress();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,6 +201,7 @@ namespace MWDialogue
|
|||
writer.startRecord (ESM::REC_JOUR);
|
||||
entry.save (writer);
|
||||
writer.endRecord (ESM::REC_JOUR);
|
||||
progress.increaseProgress();
|
||||
}
|
||||
|
||||
for (TTopicIter iter (mTopics.begin()); iter!=mTopics.end(); ++iter)
|
||||
|
@ -214,6 +217,7 @@ namespace MWDialogue
|
|||
writer.startRecord (ESM::REC_JOUR);
|
||||
entry.save (writer);
|
||||
writer.endRecord (ESM::REC_JOUR);
|
||||
progress.increaseProgress();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace MWDialogue
|
|||
|
||||
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);
|
||||
};
|
||||
|
|
|
@ -188,12 +188,13 @@ namespace MWGui
|
|||
break;
|
||||
|
||||
case GM_ClassCreate:
|
||||
MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog);
|
||||
mCreateClassDialog = 0;
|
||||
mCreateClassDialog = new CreateClassDialog();
|
||||
if (!mCreateClassDialog)
|
||||
{
|
||||
mCreateClassDialog = new CreateClassDialog();
|
||||
mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
|
||||
mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
|
||||
}
|
||||
mCreateClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
|
||||
mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
|
||||
mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
|
||||
mCreateClassDialog->setVisible(true);
|
||||
if (mCreationStage < CSE_RaceChosen)
|
||||
mCreationStage = CSE_RaceChosen;
|
||||
|
@ -531,8 +532,8 @@ namespace MWGui
|
|||
mPlayerClass = klass;
|
||||
MWBase::Environment::get().getWindowManager()->setPlayerClass(klass);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog);
|
||||
mCreateClassDialog = 0;
|
||||
// Do not delete dialog, so that choices are rembered in case we want to go back and adjust them later
|
||||
mCreateClassDialog->setVisible(false);
|
||||
}
|
||||
|
||||
updatePlayerHealth();
|
||||
|
@ -554,8 +555,8 @@ namespace MWGui
|
|||
|
||||
void CharacterCreation::onCreateClassDialogBack()
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->removeDialog(mCreateClassDialog);
|
||||
mCreateClassDialog = 0;
|
||||
// Do not delete dialog, so that choices are rembered in case we want to go back and adjust them later
|
||||
mCreateClassDialog->setVisible(false);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->popGuiMode();
|
||||
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())
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ namespace MWGui
|
|||
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)
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace MWGui
|
|||
public:
|
||||
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);
|
||||
};
|
||||
|
||||
|
|
|
@ -215,16 +215,22 @@ namespace MWGui
|
|||
{
|
||||
std::vector<std::string> matches;
|
||||
listNames();
|
||||
mCommandLine->setCaption(complete( mCommandLine->getOnlyText(), matches ));
|
||||
#if 0
|
||||
int i = 0;
|
||||
for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); ++it,++i )
|
||||
std::string oldCaption = mCommandLine->getCaption();
|
||||
std::string newCaption = complete( mCommandLine->getOnlyText(), matches );
|
||||
mCommandLine->setCaption(newCaption);
|
||||
|
||||
// List candidates if repeatedly pressing tab
|
||||
if (oldCaption == newCaption && matches.size())
|
||||
{
|
||||
printOK( *it );
|
||||
if( i == 50 )
|
||||
break;
|
||||
int i = 0;
|
||||
printOK("");
|
||||
for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); ++it,++i )
|
||||
{
|
||||
printOK( *it );
|
||||
if( i == 50 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if(mCommandHistory.empty()) return;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "../mwworld/containerstore.hpp"
|
||||
|
||||
#include "../mwmechanics/pickpocket.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
#include "countdialog.hpp"
|
||||
#include "tradewindow.hpp"
|
||||
|
@ -84,8 +85,7 @@ namespace MWGui
|
|||
// otherwise, do the transfer
|
||||
if (targetModel != mSourceModel)
|
||||
{
|
||||
targetModel->copyItem(mItem, mDraggedCount);
|
||||
mSourceModel->removeItem(mItem, mDraggedCount);
|
||||
mSourceModel->moveItem(mItem, mDraggedCount, targetModel);
|
||||
}
|
||||
|
||||
mSourceModel->update();
|
||||
|
@ -292,8 +292,7 @@ namespace MWGui
|
|||
if (!onTakeItem(item, item.mCount))
|
||||
break;
|
||||
|
||||
playerModel->copyItem(item, item.mCount);
|
||||
mModel->removeItem(item, item.mCount);
|
||||
mModel->moveItem(item, item.mCount, playerModel);
|
||||
}
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Container);
|
||||
|
@ -341,7 +340,11 @@ namespace MWGui
|
|||
}
|
||||
else
|
||||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, count);
|
||||
// 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);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ ItemModel::ModelIndex ContainerItemModel::getIndex (ItemStack item)
|
|||
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];
|
||||
if (item.mBase.getContainerStore() == &source.getClass().getContainerStore(source))
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace MWGui
|
|||
virtual ModelIndex getIndex (ItemStack item);
|
||||
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 update();
|
||||
|
|
|
@ -196,6 +196,16 @@ namespace MWGui
|
|||
bitmapFile->read(&textureData[0], width*height*4);
|
||||
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;
|
||||
Ogre::Image image;
|
||||
image.loadDynamicImage(&textureData[0], width, height, Ogre::PF_BYTE_RGBA);
|
||||
|
@ -208,18 +218,11 @@ namespace MWGui
|
|||
// Register the font with MyGUI
|
||||
MyGUI::ResourceManualFont* font = static_cast<MyGUI::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
|
||||
MyGUI::xml::Document xmlDocument;
|
||||
MyGUI::xml::ElementPtr root = xmlDocument.createRoot("ResourceManualFont");
|
||||
|
||||
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
|
||||
root->addAttribute("name", resourceName);
|
||||
|
||||
MyGUI::xml::ElementPtr defaultHeight = root->createChild("Property");
|
||||
defaultHeight->addAttribute("key", "DefaultHeight");
|
||||
|
@ -285,6 +288,7 @@ namespace MWGui
|
|||
|
||||
font->deserialization(root, MyGUI::Version(3,2,0));
|
||||
|
||||
MyGUI::ResourceManager::getInstance().removeByName(font->getResourceName());
|
||||
MyGUI::ResourceManager::getInstance().addResource(font);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace MWGui
|
|||
, mWeaponVisible(true)
|
||||
, mSpellVisible(true)
|
||||
, mWorldMouseOver(false)
|
||||
, mEnemyHealthTimer(0)
|
||||
, mEnemyHealthTimer(-1)
|
||||
, mIsDrowning(false)
|
||||
, mWeaponSpellTimer(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);
|
||||
|
||||
bool isDrowning = (progress == 0);
|
||||
|
@ -625,7 +625,7 @@ namespace MWGui
|
|||
if (mIsDrowning)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
void HUD::resetEnemy()
|
||||
{
|
||||
mEnemy = MWWorld::Ptr();
|
||||
mEnemyHealthTimer = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,8 +22,9 @@ namespace MWGui
|
|||
void setBatchCount(unsigned int count);
|
||||
|
||||
/// Set time left for the player to start drowning
|
||||
/// @param time value from [0,20]
|
||||
void setDrowningTimeLeft(float time);
|
||||
/// @param time time left to start drowning
|
||||
/// @param maxTime how long we can be underwater (in total) until drowning starts
|
||||
void setDrowningTimeLeft(float time, float maxTime);
|
||||
void setDrowningBarVisible(bool visible);
|
||||
|
||||
void setHmsVisible(bool visible);
|
||||
|
@ -56,6 +57,7 @@ namespace MWGui
|
|||
void update();
|
||||
|
||||
void setEnemy(const MWWorld::Ptr& enemy);
|
||||
void resetEnemy();
|
||||
|
||||
private:
|
||||
MyGUI::ProgressBar *mHealth, *mMagicka, *mStamina, *mEnemyHealth, *mDrowning;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
|
@ -38,11 +40,11 @@ ItemModel::ModelIndex InventoryItemModel::getIndex (ItemStack item)
|
|||
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))
|
||||
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");
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get(mActor).getContainerStore(mActor);
|
||||
|
|
|
@ -15,9 +15,12 @@ namespace MWGui
|
|||
virtual ModelIndex getIndex (ItemStack item);
|
||||
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);
|
||||
|
||||
/// Move items from this model to \a otherModel.
|
||||
virtual void moveItem (const ItemStack& item, size_t count, ItemModel* otherModel);
|
||||
|
||||
virtual void update();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace MWGui
|
|||
, mTrading(false)
|
||||
, mLastXSize(0)
|
||||
, mLastYSize(0)
|
||||
, mPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr())
|
||||
, mPreview(new MWRender::InventoryPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr()))
|
||||
, mPreviewDirty(true)
|
||||
, mDragAndDrop(dragAndDrop)
|
||||
, mSelectedItem(-1)
|
||||
|
@ -91,8 +91,8 @@ namespace MWGui
|
|||
mTradeModel = new TradeItemModel(new InventoryItemModel(mPtr), MWWorld::Ptr());
|
||||
mSortModel = new SortFilterItemModel(mTradeModel);
|
||||
mItemView->setModel(mSortModel);
|
||||
mPreview = MWRender::InventoryPreview(mPtr);
|
||||
mPreview.setup();
|
||||
mPreview.reset(new MWRender::InventoryPreview(mPtr));
|
||||
mPreview->setup();
|
||||
}
|
||||
|
||||
void InventoryWindow::setGuiMode(GuiMode mode)
|
||||
|
@ -444,7 +444,7 @@ namespace MWGui
|
|||
|
||||
MWWorld::Ptr InventoryWindow::getAvatarSelectedItem(int x, int y)
|
||||
{
|
||||
int slot = mPreview.getSlotSelected (x, y);
|
||||
int slot = mPreview->getSlotSelected (x, y);
|
||||
|
||||
if (slot == -1)
|
||||
return MWWorld::Ptr();
|
||||
|
@ -493,7 +493,7 @@ namespace MWGui
|
|||
mPreviewDirty = false;
|
||||
MyGUI::IntSize size = mAvatarImage->getSize();
|
||||
|
||||
mPreview.update (size.width, size.height);
|
||||
mPreview->update (size.width, size.height);
|
||||
|
||||
mAvatarImage->setImageTexture("CharacterPreview");
|
||||
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);
|
||||
|
||||
void rebuildAvatar() {
|
||||
mPreview.rebuild();
|
||||
mPreview->rebuild();
|
||||
}
|
||||
|
||||
TradeItemModel* getTradeModel();
|
||||
|
@ -81,7 +81,7 @@ namespace MWGui
|
|||
int mLastXSize;
|
||||
int mLastYSize;
|
||||
|
||||
MWRender::InventoryPreview mPreview;
|
||||
std::auto_ptr<MWRender::InventoryPreview> mPreview;
|
||||
|
||||
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()
|
||||
{
|
||||
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
|
||||
mSourceModel->copyItem (item, count);
|
||||
mSourceModel->copyItem (item, count, setNewOwner);
|
||||
}
|
||||
|
||||
void ProxyItemModel::removeItem (const ItemStack& item, size_t count)
|
||||
|
|
|
@ -55,7 +55,11 @@ namespace MWGui
|
|||
|
||||
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;
|
||||
|
||||
private:
|
||||
|
@ -69,7 +73,7 @@ namespace MWGui
|
|||
{
|
||||
public:
|
||||
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 ModelIndex getIndex (ItemStack item);
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace MWGui
|
|||
|
||||
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 spacing = 3;
|
||||
size_t scrollbarPosition = mScrollView->getScrollPosition();
|
||||
|
@ -83,7 +83,7 @@ namespace MWGui
|
|||
else
|
||||
{
|
||||
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);
|
||||
separator->setNeedMouseFocus(false);
|
||||
|
||||
|
@ -91,7 +91,7 @@ namespace MWGui
|
|||
}
|
||||
++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)
|
||||
redraw(true);
|
||||
|
|
|
@ -160,7 +160,6 @@ namespace MWGui
|
|||
|
||||
void LoadingScreen::setProgress (size_t value)
|
||||
{
|
||||
assert(value < mProgressBar->getScrollRange());
|
||||
if (value - mProgress < mProgressBar->getScrollRange()/100.f)
|
||||
return;
|
||||
mProgress = value;
|
||||
|
@ -174,7 +173,6 @@ namespace MWGui
|
|||
mProgressBar->setScrollPosition(0);
|
||||
size_t value = mProgress + increase;
|
||||
mProgress = value;
|
||||
assert(mProgress < mProgressBar->getScrollRange());
|
||||
mProgressBar->setTrackSize(value / (float)(mProgressBar->getScrollRange()) * mProgressBar->getLineSize());
|
||||
draw();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace MWGui
|
|||
|
||||
virtual void setProgressRange (size_t range);
|
||||
virtual void setProgress (size_t value);
|
||||
virtual void increaseProgress (size_t increase);
|
||||
virtual void increaseProgress (size_t increase=1);
|
||||
|
||||
virtual void setVisible(bool visible);
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace MWGui
|
|||
{
|
||||
getWidget(mVersionText, "VersionText");
|
||||
std::stringstream sstream;
|
||||
sstream << "OpenMW version: " << OPENMW_VERSION;
|
||||
sstream << "OpenMW Version: " << OPENMW_VERSION;
|
||||
|
||||
// adding info about git hash if available
|
||||
std::string rev = OPENMW_VERSION_COMMITHASH;
|
||||
|
@ -36,7 +36,7 @@ namespace MWGui
|
|||
if (!rev.empty() && !tag.empty())
|
||||
{
|
||||
rev = rev.substr(0,10);
|
||||
sstream << "\nrevision: " << rev;
|
||||
sstream << "\nRevision: " << rev;
|
||||
}
|
||||
|
||||
std::string output = sstream.str();
|
||||
|
@ -170,7 +170,8 @@ namespace MWGui
|
|||
buttons.push_back("loadgame");
|
||||
|
||||
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("options");
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "../mwrender/globalmap.hpp"
|
||||
|
||||
#include "../components/esm/globalmap.hpp"
|
||||
|
||||
#include "widgets.hpp"
|
||||
|
||||
namespace MWGui
|
||||
|
@ -436,7 +438,6 @@ namespace MWGui
|
|||
worldY * mGlobalMapRender->getHeight()+6,
|
||||
12, 12);
|
||||
|
||||
|
||||
static int _counter=0;
|
||||
MyGUI::Button* markerWidget = mGlobalMapOverlay->createWidget<MyGUI::Button>("ButtonImage",
|
||||
widgetCoord, MyGUI::Align::Default, "Door" + boost::lexical_cast<std::string>(_counter));
|
||||
|
@ -452,6 +453,11 @@ namespace MWGui
|
|||
markerWidget->setUserString("ToolTipType", "Layout");
|
||||
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
|
||||
markerWidget->setUserString("Caption_TextOneLine", name);
|
||||
|
||||
CellId cell;
|
||||
cell.first = x;
|
||||
cell.second = y;
|
||||
mMarkers.push_back(cell);
|
||||
}
|
||||
|
||||
void MapWindow::cellExplored(int x, int y)
|
||||
|
@ -580,6 +586,7 @@ namespace MWGui
|
|||
|
||||
void MapWindow::clear()
|
||||
{
|
||||
mMarkers.clear();
|
||||
mGlobalMapRender->clear();
|
||||
|
||||
while (mEventBoxGlobal->getChildCount())
|
||||
|
@ -588,21 +595,34 @@ namespace MWGui
|
|||
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)
|
||||
{
|
||||
std::vector<std::pair<int, int> > exploredCells;
|
||||
mGlobalMapRender->readRecord(reader, type, exploredCells);
|
||||
|
||||
for (std::vector<std::pair<int, int> >::iterator it = exploredCells.begin(); it != exploredCells.end(); ++it)
|
||||
if (type == ESM::REC_GMAP)
|
||||
{
|
||||
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>().search(it->first, it->second);
|
||||
if (cell && !cell->mName.empty())
|
||||
addVisitedLocation(cell->mName, it->first, it->second);
|
||||
ESM::GlobalMap map;
|
||||
map.load(reader);
|
||||
|
||||
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);
|
||||
if (cell && !cell->mName.empty())
|
||||
addVisitedLocation(cell->mName, it->first, it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,9 @@ namespace MWGui
|
|||
bool mChanged;
|
||||
bool mFogOfWar;
|
||||
|
||||
typedef std::pair<int, int> CellId;
|
||||
std::vector<CellId> mMarkers;
|
||||
|
||||
std::vector<MyGUI::ImageBox*> mMapWidgets;
|
||||
std::vector<MyGUI::ImageBox*> mFogWidgets;
|
||||
|
||||
|
@ -105,7 +108,7 @@ namespace MWGui
|
|||
/// Clear all savegame-specific data
|
||||
void clear();
|
||||
|
||||
void write (ESM::ESMWriter& writer);
|
||||
void write (ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||
void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
|
||||
private:
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <components/esm/quickkeys.hpp>
|
||||
|
||||
#include "../mwworld/inventorystore.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()
|
||||
{
|
||||
delete mAssignDialog;
|
||||
|
@ -154,8 +164,6 @@ namespace MWGui
|
|||
frame->setUserString ("ToolTipType", "ItemPtr");
|
||||
frame->setUserData(item);
|
||||
frame->eventMouseButtonClick += MyGUI::newDelegate(this, &QuickKeysMenu::onQuickKeyButtonClicked);
|
||||
|
||||
|
||||
MyGUI::ImageBox* image = frame->createWidget<MyGUI::ImageBox>("ImageBox", MyGUI::IntCoord(5, 5, 32, 32), MyGUI::Align::Default);
|
||||
std::string path = std::string("icons\\");
|
||||
path += MWWorld::Class::get(item).getInventoryIcon(item);
|
||||
|
@ -165,7 +173,8 @@ namespace MWGui
|
|||
image->setImageTexture (path);
|
||||
image->setNeedMouseFocus (false);
|
||||
|
||||
mItemSelectionDialog->setVisible(false);
|
||||
if (mItemSelectionDialog)
|
||||
mItemSelectionDialog->setVisible(false);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onAssignItemCancel()
|
||||
|
@ -198,7 +207,8 @@ namespace MWGui
|
|||
image->setImageTexture (path);
|
||||
image->setNeedMouseFocus (false);
|
||||
|
||||
mMagicSelectionDialog->setVisible(false);
|
||||
if (mMagicSelectionDialog)
|
||||
mMagicSelectionDialog->setVisible(false);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onAssignMagic (const std::string& spellId)
|
||||
|
@ -239,7 +249,8 @@ namespace MWGui
|
|||
image->setImageTexture (path);
|
||||
image->setNeedMouseFocus (false);
|
||||
|
||||
mMagicSelectionDialog->setVisible(false);
|
||||
if (mMagicSelectionDialog)
|
||||
mMagicSelectionDialog->setVisible(false);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::onAssignMagicCancel ()
|
||||
|
@ -325,7 +336,6 @@ namespace MWGui
|
|||
}
|
||||
|
||||
store.setSelectedEnchantItem(it);
|
||||
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,6 +385,110 @@ namespace MWGui
|
|||
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:
|
||||
MyGUI::EditBox* mInstructionLabel;
|
||||
MyGUI::Button* mOkButton;
|
||||
|
|
|
@ -17,6 +17,8 @@ namespace MWGui
|
|||
|
||||
void checkReferenceAvailable(); ///< closes the window, if the MW-reference has become unavailable
|
||||
|
||||
void resetReference() { mPtr = MWWorld::Ptr(); mCurrentPlayerCell = NULL; }
|
||||
|
||||
protected:
|
||||
virtual void onReferenceUnavailable() = 0; ///< called when reference has become unavailable
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace MWGui
|
|||
: WindowModal("openmw_savegame_dialog.layout")
|
||||
, mSaving(true)
|
||||
, mCurrentCharacter(NULL)
|
||||
, mCurrentSlot(NULL)
|
||||
{
|
||||
getWidget(mScreenshot, "Screenshot");
|
||||
getWidget(mCharacterSelection, "SelectCharacter");
|
||||
|
@ -36,6 +37,7 @@ namespace MWGui
|
|||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SaveGameDialog::onCancelButtonClicked);
|
||||
mCharacterSelection->eventComboChangePosition += MyGUI::newDelegate(this, &SaveGameDialog::onCharacterSelected);
|
||||
mSaveList->eventListChangePosition += MyGUI::newDelegate(this, &SaveGameDialog::onSlotSelected);
|
||||
mSaveList->eventListMouseItemActivate += MyGUI::newDelegate(this, &SaveGameDialog::onSlotMouseClick);
|
||||
mSaveList->eventListSelectAccept += MyGUI::newDelegate(this, &SaveGameDialog::onSlotActivated);
|
||||
mSaveNameEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &SaveGameDialog::onEditSelectAccept);
|
||||
mSaveNameEdit->eventEditTextChange += MyGUI::newDelegate(this, &SaveGameDialog::onSaveNameChanged);
|
||||
|
@ -47,6 +49,37 @@ namespace MWGui
|
|||
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)
|
||||
{
|
||||
// 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();
|
||||
|
||||
mCharacterSelection->setCaption("");
|
||||
mCharacterSelection->removeAllItems();
|
||||
mCurrentCharacter = NULL;
|
||||
mCurrentSlot = NULL;
|
||||
mSaveList->removeAllItems();
|
||||
|
||||
MWBase::StateManager* mgr = MWBase::Environment::get().getStateManager();
|
||||
if (mgr->characterBegin() == mgr->characterEnd())
|
||||
return;
|
||||
|
@ -78,8 +117,6 @@ namespace MWGui
|
|||
std::string directory =
|
||||
Misc::StringUtils::lowerCase (Settings::Manager::getString ("character", "Saves"));
|
||||
|
||||
mCharacterSelection->removeAllItems();
|
||||
|
||||
int selectedIndex = MyGUI::ITEM_NONE;
|
||||
|
||||
for (MWBase::StateManager::CharacterIterator it = mgr->characterBegin(); it != mgr->characterEnd(); ++it)
|
||||
|
@ -152,23 +189,10 @@ namespace MWGui
|
|||
{
|
||||
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 overwriting an existing slot, ask for confirmation first
|
||||
if (slot != NULL && !reallySure)
|
||||
if (mCurrentSlot != NULL && !reallySure)
|
||||
{
|
||||
ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
|
||||
dialog->open("#{sMessage4}");
|
||||
|
@ -182,18 +206,22 @@ namespace MWGui
|
|||
MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage65}");
|
||||
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);
|
||||
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()==
|
||||
MWBase::StateManager::State_NoGame)
|
||||
|
@ -221,6 +249,7 @@ namespace MWGui
|
|||
assert(character && "Can't find selected character");
|
||||
|
||||
mCurrentCharacter = character;
|
||||
mCurrentSlot = NULL;
|
||||
fillSaveList();
|
||||
}
|
||||
|
||||
|
@ -240,6 +269,7 @@ namespace MWGui
|
|||
{
|
||||
if (pos == MyGUI::ITEM_NONE)
|
||||
{
|
||||
mCurrentSlot = NULL;
|
||||
mInfoText->setCaption("");
|
||||
mScreenshot->setImageTexture("");
|
||||
return;
|
||||
|
@ -248,17 +278,17 @@ namespace MWGui
|
|||
if (mSaving)
|
||||
mSaveNameEdit->setCaption(sender->getItemNameAt(pos));
|
||||
|
||||
const MWState::Slot* slot = NULL;
|
||||
mCurrentSlot = NULL;
|
||||
unsigned int i=0;
|
||||
for (MWState::Character::SlotIterator it = mCurrentCharacter->begin(); it != mCurrentCharacter->end(); ++it, ++i)
|
||||
{
|
||||
if (i == pos)
|
||||
slot = &*it;
|
||||
mCurrentSlot = &*it;
|
||||
}
|
||||
assert(slot && "Can't find selected slot");
|
||||
assert(mCurrentSlot && "Can't find selected slot");
|
||||
|
||||
std::stringstream text;
|
||||
time_t time = slot->mTimeStamp;
|
||||
time_t time = mCurrentSlot->mTimeStamp;
|
||||
struct tm* timeinfo;
|
||||
timeinfo = localtime(&time);
|
||||
|
||||
|
@ -269,24 +299,24 @@ namespace MWGui
|
|||
char buffer[size];
|
||||
if (std::strftime(buffer, size, "%x %X", timeinfo) > 0)
|
||||
text << buffer << "\n";
|
||||
text << "Level " << slot->mProfile.mPlayerLevel << "\n";
|
||||
text << slot->mProfile.mPlayerCell << "\n";
|
||||
text << "Level " << mCurrentSlot->mProfile.mPlayerLevel << "\n";
|
||||
text << mCurrentSlot->mProfile.mPlayerCell << "\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;
|
||||
if (hour >= 13) hour -= 12;
|
||||
if (hour == 0) hour = 12;
|
||||
|
||||
text
|
||||
<< slot->mProfile.mInGameTime.mDay << " "
|
||||
<< MWBase::Environment::get().getWorld()->getMonthName(slot->mProfile.mInGameTime.mMonth)
|
||||
<< mCurrentSlot->mProfile.mInGameTime.mDay << " "
|
||||
<< MWBase::Environment::get().getWorld()->getMonthName(mCurrentSlot->mProfile.mInGameTime.mMonth)
|
||||
<< " " << hour << " " << (pm ? "#{sSaveMenuHelp05}" : "#{sSaveMenuHelp04}");
|
||||
|
||||
mInfoText->setCaptionWithReplacing(text.str());
|
||||
|
||||
// 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::Image image;
|
||||
image.load(stream, "jpg");
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
namespace MWState
|
||||
{
|
||||
class Character;
|
||||
class Slot;
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
|
@ -24,8 +25,15 @@ namespace MWGui
|
|||
void onCancelButtonClicked (MyGUI::Widget* sender);
|
||||
void onOkButtonClicked (MyGUI::Widget* sender);
|
||||
void onCharacterSelected (MyGUI::ComboBox* sender, size_t pos);
|
||||
// Slot selected (mouse click or arrow keys)
|
||||
void onSlotSelected (MyGUI::ListBox* sender, size_t pos);
|
||||
// Slot activated (double click or enter key)
|
||||
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 onSaveNameChanged (MyGUI::EditBox* sender);
|
||||
void onConfirmationGiven();
|
||||
|
@ -46,6 +54,7 @@ namespace MWGui
|
|||
MyGUI::Widget* mSpacer;
|
||||
|
||||
const MWState::Character* mCurrentCharacter;
|
||||
const MWState::Slot* mCurrentSlot;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -322,7 +322,6 @@ namespace MWGui
|
|||
}
|
||||
|
||||
store.setSelectedEnchantItem(it);
|
||||
MWBase::Environment::get().getWindowManager()->setSelectedEnchantItem(item);
|
||||
|
||||
updateSpells();
|
||||
}
|
||||
|
|
|
@ -475,7 +475,7 @@ namespace MWGui
|
|||
text += std::string("#DDC79E") + faction->mName;
|
||||
|
||||
if (expelled.find(it->first) != expelled.end())
|
||||
text += "\n#{sExpelled}";
|
||||
text += "\n#BF9959#{sExpelled}";
|
||||
else
|
||||
{
|
||||
text += std::string("\n#BF9959") + faction->mRanks[it->second];
|
||||
|
|
|
@ -120,14 +120,11 @@ namespace MWGui
|
|||
if (i == sourceModel->getItemCount())
|
||||
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);
|
||||
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
|
||||
copyItem(item, it->mCount);
|
||||
item.mBase.getCellRef().mOwner = owner;
|
||||
copyItem(item, it->mCount, setNewOwner);
|
||||
// then remove them from the source model
|
||||
sourceModel->removeItem(item, it->mCount);
|
||||
}
|
||||
|
|
|
@ -78,13 +78,13 @@ namespace MWGui
|
|||
}
|
||||
|
||||
void TradeWindow::startTrade(const MWWorld::Ptr& actor)
|
||||
{
|
||||
{
|
||||
mPtr = actor;
|
||||
|
||||
mCurrentBalance = 0;
|
||||
mCurrentMerchantOffer = 0;
|
||||
|
||||
checkTradeTime();
|
||||
checkTradeTime();
|
||||
|
||||
std::vector<MWWorld::Ptr> itemSources;
|
||||
MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources);
|
||||
|
@ -245,7 +245,7 @@ namespace MWGui
|
|||
// were there any items traded at all?
|
||||
std::vector<ItemStack> playerBought = playerItemModel->getItemsBorrowedToUs();
|
||||
std::vector<ItemStack> merchantBought = mTradeModel->getItemsBorrowedToUs();
|
||||
if (!playerBought.size() && !merchantBought.size())
|
||||
if (playerBought.empty() && merchantBought.empty())
|
||||
{
|
||||
// user notification
|
||||
MWBase::Environment::get().getWindowManager()->
|
||||
|
@ -476,7 +476,7 @@ namespace MWGui
|
|||
}
|
||||
|
||||
// Relates to NPC gold reset delay
|
||||
void TradeWindow::checkTradeTime()
|
||||
void TradeWindow::checkTradeTime()
|
||||
{
|
||||
MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
double delay = boost::lexical_cast<double>(MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->getInt());
|
||||
|
@ -488,14 +488,14 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void TradeWindow::updateTradeTime()
|
||||
void TradeWindow::updateTradeTime()
|
||||
{
|
||||
MWWorld::ContainerStore store = mPtr.getClass().getContainerStore(mPtr);
|
||||
MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
|
||||
double delay = boost::lexical_cast<double>(MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->getInt());
|
||||
|
||||
// If trade timestamp is within reset delay don't set
|
||||
if ( ! (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getTradeTime() &&
|
||||
if ( ! (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getTradeTime() &&
|
||||
MWBase::Environment::get().getWorld()->getTimeStamp() < sellerStats.getTradeTime() + delay) )
|
||||
{
|
||||
sellerStats.setTradeTime(MWBase::Environment::get().getWorld()->getTimeStamp());
|
||||
|
|
|
@ -187,7 +187,7 @@ namespace MWGui
|
|||
MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged);
|
||||
|
||||
onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer());
|
||||
SDL_ShowCursor(false);
|
||||
//SDL_ShowCursor(false);
|
||||
|
||||
mCursorManager->setEnabled(true);
|
||||
|
||||
|
@ -289,6 +289,10 @@ namespace MWGui
|
|||
|
||||
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)
|
||||
{
|
||||
disallowAll();
|
||||
|
@ -621,9 +625,9 @@ namespace MWGui
|
|||
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_)
|
||||
|
@ -1401,16 +1405,49 @@ namespace MWGui
|
|||
void WindowManager::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)
|
||||
{
|
||||
mMap->readRecord(reader, type);
|
||||
if (type == ESM::REC_GMAP)
|
||||
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)
|
||||
|
|
|
@ -166,8 +166,9 @@ namespace MWGui
|
|||
virtual void setValue (const std::string& id, int value);
|
||||
|
||||
/// Set time left for the player to start drowning (update the drowning bar)
|
||||
/// @param time value from [0,20]
|
||||
virtual void setDrowningTimeLeft (float time);
|
||||
/// @param time time left to start drowning
|
||||
/// @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 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
|
||||
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 int countSavedGameRecords() const;
|
||||
|
||||
/// Does the current stack of GUI-windows permit saving?
|
||||
virtual bool isSavingAllowed() const;
|
||||
|
||||
private:
|
||||
bool mConsoleOnlyScripts;
|
||||
|
|
|
@ -114,6 +114,7 @@ namespace MWInput
|
|||
, mTimeIdle(0.f)
|
||||
, mOverencumberedMessageDelay(0.f)
|
||||
, mAlwaysRunActive(false)
|
||||
, mControlsDisabled(false)
|
||||
{
|
||||
|
||||
Ogre::RenderWindow* window = ogre.getWindow ();
|
||||
|
@ -265,19 +266,20 @@ namespace MWInput
|
|||
|
||||
void InputManager::update(float dt, bool disableControls, bool disableEvents)
|
||||
{
|
||||
mControlsDisabled = disableControls;
|
||||
|
||||
mInputManager->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible());
|
||||
|
||||
mInputManager->capture(disableEvents);
|
||||
// inject some fake mouse movement to force updating MyGUI's widget states
|
||||
MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel);
|
||||
|
||||
// update values of channels (as a result of pressed keys)
|
||||
if (!disableControls)
|
||||
mInputBinder->update(dt);
|
||||
|
||||
if (disableControls)
|
||||
if (mControlsDisabled)
|
||||
return;
|
||||
|
||||
// update values of channels (as a result of pressed keys)
|
||||
mInputBinder->update(dt);
|
||||
|
||||
bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)
|
||||
&& MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console;
|
||||
|
||||
|
@ -484,7 +486,7 @@ namespace MWInput
|
|||
|
||||
if (text)
|
||||
{
|
||||
edit->addText(MyGUI::UString(text));
|
||||
edit->insertText(MyGUI::UString(text), edit->getTextCursor());
|
||||
SDL_free(text);
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +511,8 @@ namespace MWInput
|
|||
}
|
||||
}
|
||||
|
||||
mInputBinder->keyPressed (arg);
|
||||
if (!mControlsDisabled)
|
||||
mInputBinder->keyPressed (arg);
|
||||
|
||||
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace MWInput
|
|||
/// Clear all savegame-specific data
|
||||
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; }
|
||||
|
||||
|
@ -145,6 +145,8 @@ namespace MWInput
|
|||
|
||||
bool mInvertY;
|
||||
|
||||
bool mControlsDisabled;
|
||||
|
||||
float mCameraSensitivity;
|
||||
float mUISensitivity;
|
||||
float mCameraYMultiplier;
|
||||
|
|
|
@ -206,7 +206,7 @@ namespace MWMechanics
|
|||
if (effectIt->mKey.mId == effectId)
|
||||
effectIt = it->second.mEffects.erase(effectIt);
|
||||
else
|
||||
effectIt++;
|
||||
++effectIt;
|
||||
}
|
||||
}
|
||||
mSpellsChanged = true;
|
||||
|
@ -224,7 +224,7 @@ namespace MWMechanics
|
|||
&& it->second.mCasterHandle == actorHandle)
|
||||
effectIt = it->second.mEffects.erase(effectIt);
|
||||
else
|
||||
effectIt++;
|
||||
++effectIt;
|
||||
}
|
||||
}
|
||||
mSpellsChanged = true;
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include "aicombat.hpp"
|
||||
#include "aifollow.hpp"
|
||||
#include "aipersue.hpp"
|
||||
#include "aipursue.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -194,21 +194,11 @@ namespace MWMechanics
|
|||
+(actorpos.pos[1] - playerpos.pos[1])*(actorpos.pos[1] - playerpos.pos[1])
|
||||
+(actorpos.pos[2] - playerpos.pos[2])*(actorpos.pos[2] - playerpos.pos[2]));
|
||||
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 )
|
||||
|| (fight >= 95 && d <= 3000)
|
||||
|| (fight >= 90 && d <= 2000)
|
||||
|| (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)
|
||||
|
@ -216,7 +206,7 @@ namespace MWMechanics
|
|||
|
||||
if (LOS)
|
||||
{
|
||||
creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr()));
|
||||
creatureStats.getAiSequence().stack(AiCombat(MWBase::Environment::get().getWorld()->getPlayerPtr()), ptr);
|
||||
creatureStats.setHostile(true);
|
||||
}
|
||||
}
|
||||
|
@ -548,7 +538,7 @@ namespace MWMechanics
|
|||
|
||||
// TODO: Add AI to follow player and fight for him
|
||||
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
|
||||
creatureStats.mSummonedCreatures.insert(std::make_pair(it->first,
|
||||
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);
|
||||
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.isHostile())
|
||||
if (ptr.getClass().isClass(ptr, "Guard") && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPursue && !creatureStats.isHostile())
|
||||
{
|
||||
/// \todo Move me! I shouldn't be here...
|
||||
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
|
||||
float cutoff = float(esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt()) *
|
||||
float(esmStore.get<ESM::GameSetting>().find("iCrimeThresholdMultiplier")->getInt()) *
|
||||
esmStore.get<ESM::GameSetting>().find("fCrimeGoldDiscountMult")->getFloat();
|
||||
// Attack on sight if bounty is greater than the cutoff
|
||||
float cutoff = float(esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt());
|
||||
// Force dialogue on sight if bounty is greater than the cutoff
|
||||
// In vanilla morrowind, the greeting dialogue is scripted to either arrest the player (< 5000 bounty) or attack (>= 5000 bounty)
|
||||
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().getMechanicsManager()->awarenessCheck(player, ptr))
|
||||
{
|
||||
creatureStats.getAiSequence().stack(AiCombat(player));
|
||||
creatureStats.setHostile(true);
|
||||
npcStats.setCrimeId( MWBase::Environment::get().getWorld()->getPlayer().getCrimeId() );
|
||||
creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
|
||||
creatureStats.setAlarmed(true);
|
||||
npcStats.setCrimeId(MWBase::Environment::get().getWorld()->getPlayer().getNewCrimeId());
|
||||
}
|
||||
}
|
||||
|
||||
// if I was a witness to a crime
|
||||
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() )
|
||||
{
|
||||
// Calm witness down
|
||||
if (ptr.getClass().isClass(ptr, "Guard"))
|
||||
creatureStats.getAiSequence().stopPersue();
|
||||
creatureStats.getAiSequence().stopPursuit();
|
||||
creatureStats.getAiSequence().stopCombat();
|
||||
|
||||
// Reset factors to attack
|
||||
|
@ -793,17 +782,16 @@ namespace MWMechanics
|
|||
else if (!creatureStats.isHostile())
|
||||
{
|
||||
if (ptr.getClass().isClass(ptr, "Guard"))
|
||||
creatureStats.getAiSequence().stack(AiPersue(player.getClass().getId(player)));
|
||||
creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
|
||||
else
|
||||
creatureStats.getAiSequence().stack(AiCombat(player));
|
||||
creatureStats.getAiSequence().stack(AiCombat(player), ptr);
|
||||
creatureStats.setHostile(true);
|
||||
}
|
||||
}
|
||||
|
||||
// if I didn't report a crime was I attacked?
|
||||
else if (creatureStats.getAttacked() && !creatureStats.isHostile())
|
||||
{
|
||||
creatureStats.getAiSequence().stack(AiCombat(player));
|
||||
creatureStats.getAiSequence().stack(AiCombat(player), ptr);
|
||||
creatureStats.setHostile(true);
|
||||
}
|
||||
}
|
||||
|
@ -911,12 +899,23 @@ namespace MWMechanics
|
|||
iter->second->update(duration);
|
||||
}
|
||||
|
||||
// Kill dead actors
|
||||
// Kill dead actors, update some variables
|
||||
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++)
|
||||
{
|
||||
const MWWorld::Class &cls = MWWorld::Class::get(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(iter->second->isDead())
|
||||
|
@ -1050,8 +1049,7 @@ namespace MWMechanics
|
|||
{
|
||||
const MWWorld::Class &cls = MWWorld::Class::get(iter->first);
|
||||
CreatureStats &stats = cls.getCreatureStats(iter->first);
|
||||
|
||||
if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow)
|
||||
if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdFollow)
|
||||
{
|
||||
MWMechanics::AiFollow* package = static_cast<MWMechanics::AiFollow*>(stats.getAiSequence().getActivePackage());
|
||||
if(package->getFollowedActor() == actor.getCellRef().mRefID)
|
||||
|
@ -1072,8 +1070,7 @@ namespace MWMechanics
|
|||
{
|
||||
const MWWorld::Class &cls = MWWorld::Class::get(*iter);
|
||||
CreatureStats &stats = cls.getCreatureStats(*iter);
|
||||
|
||||
if(stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat)
|
||||
if(!stats.isDead() && stats.getAiSequence().getTypeId() == AiPackage::TypeIdCombat)
|
||||
{
|
||||
MWMechanics::AiCombat* package = static_cast<MWMechanics::AiCombat*>(stats.getAiSequence().getActivePackage());
|
||||
if(package->getTargetId() == actor.getCellRef().mRefID)
|
||||
|
|
|
@ -31,10 +31,52 @@ namespace
|
|||
|
||||
//chooses an attack depending on probability to avoid uniformity
|
||||
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
|
||||
{
|
||||
static const float MAX_ATTACK_DURATION = 0.35f;
|
||||
static const float DOOR_CHECK_INTERVAL = 1.5f; // same as AiWander
|
||||
// NOTE: MIN_DIST_TO_DOOR_SQUARED is defined in obstacle.hpp
|
||||
|
||||
|
@ -45,16 +87,16 @@ namespace MWMechanics
|
|||
mTimerCombatMove(0),
|
||||
mFollowTarget(false),
|
||||
mReadyToAttack(false),
|
||||
mStrike(false),
|
||||
mAttack(false),
|
||||
mCombatMove(false),
|
||||
mBackOffDoor(false),
|
||||
mRotate(false),
|
||||
mMovement(),
|
||||
mForceNoShortcut(false),
|
||||
mShortcutFailPos(),
|
||||
mBackOffDoor(false),
|
||||
mCell(NULL),
|
||||
mDoorIter(actor.getCell()->get<ESM::Door>().mList.end()),
|
||||
mDoors(actor.getCell()->get<ESM::Door>()),
|
||||
mDoorCheckDuration(0),
|
||||
mTargetAngle(0)
|
||||
mDoorCheckDuration(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -125,17 +167,23 @@ namespace MWMechanics
|
|||
mCombatMove = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)))
|
||||
mRotate = false;
|
||||
if(zTurn(actor, Ogre::Degree(mMovement.mRotation[2]))) mMovement.mRotation[2] = 0;
|
||||
}
|
||||
|
||||
if(mMovement.mRotation[0] != 0)
|
||||
{
|
||||
if(smoothTurn(actor, Ogre::Degree(mMovement.mRotation[0]), 0)) mMovement.mRotation[0] = 0;
|
||||
}
|
||||
|
||||
mTimerAttack -= duration;
|
||||
actor.getClass().getCreatureStats(actor).setAttackingOrSpell(mStrike);
|
||||
actor.getClass().getCreatureStats(actor).setAttackingOrSpell(mAttack);
|
||||
|
||||
float tReaction = 0.25f;
|
||||
if(mTimerReact < tReaction)
|
||||
|
@ -145,7 +193,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
//Update with period = tReaction
|
||||
|
||||
|
||||
mTimerReact = 0;
|
||||
|
||||
bool cellChange = mCell && (actor.getCell() != mCell);
|
||||
|
@ -156,16 +204,16 @@ namespace MWMechanics
|
|||
|
||||
//actual attacking logic
|
||||
//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(mTimerAttack <= -attackPeriod)
|
||||
if(mTimerAttack <= -attacksPeriod)
|
||||
{
|
||||
//TODO: should depend on time between 'start' to 'min attack'
|
||||
//for better controlling of NPCs' attack strength.
|
||||
//Also it seems that this time is different for slash/thrust/chop
|
||||
mTimerAttack = 0.35f * static_cast<float>(rand())/RAND_MAX;
|
||||
mStrike = true;
|
||||
mTimerAttack = MAX_ATTACK_DURATION * static_cast<float>(rand())/RAND_MAX;
|
||||
mAttack = true;
|
||||
|
||||
//say a provoking combat phrase
|
||||
if (actor.getClass().isNpc())
|
||||
|
@ -180,30 +228,31 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
else if (mTimerAttack <= 0)
|
||||
mStrike = false;
|
||||
mAttack = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mTimerAttack = -attackPeriod;
|
||||
mStrike = false;
|
||||
mTimerAttack = -attacksPeriod;
|
||||
mAttack = false;
|
||||
}
|
||||
|
||||
const MWWorld::Class &cls = actor.getClass();
|
||||
const MWWorld::Class &actorCls = actor.getClass();
|
||||
const ESM::Weapon *weapon = NULL;
|
||||
MWMechanics::WeaponType weaptype;
|
||||
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)
|
||||
actor.getClass().getCreatureStats(actor).setDrawState(MWMechanics::DrawState_Weapon);
|
||||
actorCls.getCreatureStats(actor).setDrawState(MWMechanics::DrawState_Weapon);
|
||||
|
||||
//Get weapon speed and range
|
||||
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)
|
||||
{
|
||||
|
@ -225,36 +274,27 @@ namespace MWMechanics
|
|||
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:
|
||||
*
|
||||
* rangeMelee:
|
||||
* rangeAttack:
|
||||
*
|
||||
* - Distance where attack using the actor's weapon is possible
|
||||
* - longer for ranged weapons (obviously?) vs. melee weapons
|
||||
* - Distance where attack using the actor's weapon is possible:
|
||||
* 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
|
||||
* (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
|
||||
* weapons)
|
||||
* - Distance a little further away from the actor's weapon strike
|
||||
* i.e. rangeCloseup > rangeMelee for melee weapons
|
||||
* (the variable names make this simple concept counter-intuitive,
|
||||
* something like rangeMelee > rangeStrike may be better)
|
||||
* - Distance a little further away than the actor's weapon reach
|
||||
* i.e. rangeFollow > rangeAttack for melee weapons
|
||||
* - Hardcoded value (0 for ranged weapons)
|
||||
* - Once the target gets beyond this distance mFollowTarget is cleared
|
||||
* and a path to the target needs to be found
|
||||
* - TODO: Possibly rename this variable to rangeMelee or even rangeFollow
|
||||
*
|
||||
* mFollowTarget:
|
||||
*
|
||||
|
@ -263,58 +303,72 @@ namespace MWMechanics
|
|||
* available, since the default path without pathgrids is direct to
|
||||
* target even if LOS is not achieved)
|
||||
*/
|
||||
float rangeMelee;
|
||||
float rangeCloseUp;
|
||||
|
||||
float rangeAttack;
|
||||
float rangeFollow;
|
||||
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
|
||||
rangeCloseUp = 0; //doesn't needed when attacking from distance
|
||||
rangeAttack = 1000; // TODO: should depend on archer skill
|
||||
rangeFollow = 0; // not needed in ranged combat
|
||||
distantCombat = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
rangeMelee = weapRange;
|
||||
rangeCloseUp = 300;
|
||||
rangeAttack = weapRange;
|
||||
rangeFollow = 300;
|
||||
}
|
||||
|
||||
ESM::Position pos = actor.getRefData().getPosition();
|
||||
Ogre::Vector3 vActorPos(pos.pos);
|
||||
Ogre::Vector3 vTargetPos(mTarget.getRefData().getPosition().pos);
|
||||
Ogre::Vector3 vDirToTarget = vTargetPos - vActorPos;
|
||||
|
||||
Ogre::Vector3 vStart(pos.pos[0], pos.pos[1], pos.pos[2]);
|
||||
ESM::Position targetPos = mTarget.getRefData().getPosition();
|
||||
Ogre::Vector3 vDest(targetPos.pos[0], targetPos.pos[1], targetPos.pos[2]);
|
||||
Ogre::Vector3 vDir = vDest - vStart;
|
||||
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)
|
||||
if(distBetween < rangeMelee || (distBetween <= rangeCloseUp && mFollowTarget) )
|
||||
if(distToTarget < rangeAttack || (distToTarget <= rangeFollow && mFollowTarget && !isStuck) )
|
||||
{
|
||||
//Melee and Close-up combat
|
||||
vDir.z = 0;
|
||||
float dirLen = vDir.length();
|
||||
mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / dirLen) * sgn(Ogre::Math::ASin(vDir.x / dirLen)) ).valueDegrees();
|
||||
mRotate = true;
|
||||
mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget);
|
||||
|
||||
//bool LOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget);
|
||||
// (not quite strike dist while following)
|
||||
if (mFollowTarget && distBetween > rangeMelee)
|
||||
if (mFollowTarget && distToTarget > rangeAttack)
|
||||
{
|
||||
//Close-up combat: just run up on target
|
||||
mMovement.mPosition[1] = 1;
|
||||
}
|
||||
else // (within strike dist)
|
||||
{
|
||||
//Melee: stop running and attack
|
||||
mMovement.mPosition[1] = 0;
|
||||
|
||||
// When attacking with a weapon, choose between slash, thrust or chop
|
||||
if (actor.getClass().hasInventoryStore(actor))
|
||||
chooseBestAttack(weapon, mMovement);
|
||||
// set slash/thrust/chop attack
|
||||
if (mAttack && !distantCombat) chooseBestAttack(weapon, mMovement);
|
||||
|
||||
if(mMovement.mPosition[0] || mMovement.mPosition[1])
|
||||
{
|
||||
mTimerCombatMove = 0.1f + 0.1f * static_cast<float>(rand())/RAND_MAX;
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
@ -335,56 +389,105 @@ namespace MWMechanics
|
|||
mFollowTarget = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
else // remote pathfinding
|
||||
{
|
||||
//target is at far distance: build path to target
|
||||
mFollowTarget = false;
|
||||
bool preferShortcut = false;
|
||||
bool inLOS = MWBase::Environment::get().getWorld()->getLOS(actor, mTarget);
|
||||
|
||||
buildNewPath(actor); //may fail to build a path, check before use
|
||||
|
||||
//delete visited path node
|
||||
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
|
||||
|
||||
//if no new path leave mTargetAngle unchanged
|
||||
if(!mPathFinder.getPath().empty())
|
||||
if(mReadyToAttack) isStuck = false;
|
||||
|
||||
// check if shortcut is available
|
||||
if(!isStuck
|
||||
&& (!mForceNoShortcut
|
||||
|| (Ogre::Vector3(mShortcutFailPos.pos) - vActorPos).length() >= PATHFIND_SHORTCUT_RETRY_DIST)
|
||||
&& inLOS)
|
||||
{
|
||||
//try shortcut
|
||||
if(vDir.length() < mPathFinder.getDistToNext(pos.pos[0],pos.pos[1],pos.pos[2]) && MWBase::Environment::get().getWorld()->getLOS(actor, mTarget))
|
||||
mTargetAngle = Ogre::Radian( Ogre::Math::ACos(vDir.y / vDir.length()) * sgn(Ogre::Math::ASin(vDir.x / vDir.length())) ).valueDegrees();
|
||||
else
|
||||
mTargetAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
|
||||
mRotate = true;
|
||||
if(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;
|
||||
|
||||
buildNewPath(actor); //may fail to build a path, check before use
|
||||
|
||||
//delete visited path node
|
||||
mPathFinder.checkWaypoint(pos.pos[0],pos.pos[1],pos.pos[2]);
|
||||
|
||||
// This works on the borders between the path grid and areas with no waypoints.
|
||||
if(inLOS && mPathFinder.getPath().size() > 1)
|
||||
{
|
||||
// get point just before target
|
||||
std::list<ESM::Pathgrid::Point>::const_iterator pntIter = --mPathFinder.getPath().end();
|
||||
--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
|
||||
mMovement.mRotation[2] = getZAngleToDir(vDirToTarget, distToTarget);
|
||||
}
|
||||
}
|
||||
|
||||
mMovement.mPosition[1] = 1;
|
||||
mReadyToAttack = false;
|
||||
}
|
||||
|
||||
if(distBetween > rangeMelee)
|
||||
if(distToTarget > rangeAttack && !distantCombat)
|
||||
{
|
||||
//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
|
||||
//less than in time of playing weapon anim from 'start' to 'hit' tags (t_swing)
|
||||
//then start attacking
|
||||
float speed1 = cls.getSpeed(actor);
|
||||
float speed1 = actorCls.getSpeed(actor);
|
||||
float speed2 = mTarget.getClass().getSpeed(mTarget);
|
||||
if(mTarget.getClass().getMovementSettings(mTarget).mPosition[0] == 0
|
||||
&& mTarget.getClass().getMovementSettings(mTarget).mPosition[1] == 0)
|
||||
speed2 = 0;
|
||||
|
||||
float s1 = distBetween - weapRange;
|
||||
float s1 = distToTarget - weapRange;
|
||||
float t = s1/speed1;
|
||||
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)
|
||||
{
|
||||
mReadyToAttack = true;
|
||||
if(mTimerAttack <= -attackPeriod)
|
||||
if(mTimerAttack <= -attacksPeriod)
|
||||
{
|
||||
mTimerAttack = 0.3f*static_cast<float>(rand())/RAND_MAX;
|
||||
mStrike = true;
|
||||
mTimerAttack = MAX_ATTACK_DURATION * static_cast<float>(rand())/RAND_MAX;
|
||||
mAttack = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -394,7 +497,7 @@ namespace MWMechanics
|
|||
// coded at 250ms or 1/4 second
|
||||
//
|
||||
// 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
|
||||
{
|
||||
// first check if we're walking into a door
|
||||
|
@ -406,12 +509,11 @@ namespace MWMechanics
|
|||
// Check all the doors in this cell
|
||||
mDoors = cell->get<ESM::Door>(); // update
|
||||
mDoorIter = mDoors.mList.begin();
|
||||
Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos);
|
||||
for (; mDoorIter != mDoors.mList.end(); ++mDoorIter)
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Door>& ref = *mDoorIter;
|
||||
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
|
||||
{
|
||||
//std::cout<<"closed door id \""<<ref.mRef.mRefID<<"\""<<std::endl;
|
||||
|
@ -441,11 +543,10 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
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
|
||||
// TODO: add reaction to checking open doors
|
||||
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
|
||||
}
|
||||
|
@ -454,47 +555,38 @@ namespace MWMechanics
|
|||
ref.mData.getLocalRotation().rot[2] >= 1)
|
||||
{
|
||||
mDoorIter = mDoors.mList.end();
|
||||
mBackOffDoor = false;
|
||||
mBackOffDoor = false;
|
||||
//std::cout<<"open door id \""<<ref.mRef.mRefID<<"\""<<std::endl;
|
||||
mMovement.mPosition[1] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMovement.mPosition[1] = 1; // FIXME: oscillation?
|
||||
}
|
||||
|
||||
actor.getClass().getMovementSettings(actor) = mMovement;
|
||||
// these lines break ranged combat distance keeping
|
||||
//else
|
||||
//{
|
||||
// mMovement.mPosition[1] = 1; // FIXME: oscillation?
|
||||
//}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AiCombat::buildNewPath(const MWWorld::Ptr& actor)
|
||||
{
|
||||
//Construct path to target
|
||||
ESM::Pathgrid::Point dest;
|
||||
dest.mX = mTarget.getRefData().getPosition().pos[0];
|
||||
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);
|
||||
Ogre::Vector3 newPathTarget = Ogre::Vector3(mTarget.getRefData().getPosition().pos);
|
||||
|
||||
float dist = -1; //hack to indicate first time, to construct a new path
|
||||
float dist;
|
||||
|
||||
if(!mPathFinder.getPath().empty())
|
||||
{
|
||||
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back();
|
||||
Ogre::Vector3 currPathTarget(lastPt.mX, lastPt.mY, lastPt.mZ);
|
||||
dist = Ogre::Math::Abs((newPathTarget - currPathTarget).length());
|
||||
dist = (newPathTarget - currPathTarget).length();
|
||||
}
|
||||
else dist = 1e+38F; // necessarily construct a new path
|
||||
|
||||
float targetPosThreshold;
|
||||
bool isOutside = actor.getCell()->getCell()->isExterior();
|
||||
if (isOutside)
|
||||
targetPosThreshold = 300;
|
||||
else
|
||||
targetPosThreshold = 100;
|
||||
float targetPosThreshold = (actor.getCell()->getCell()->isExterior())? 300 : 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::Pathgrid::Point start;
|
||||
|
@ -502,17 +594,18 @@ namespace MWMechanics
|
|||
start.mY = pos.pos[1];
|
||||
start.mZ = pos.pos[2];
|
||||
|
||||
ESM::Pathgrid::Point dest;
|
||||
dest.mX = newPathTarget.x;
|
||||
dest.mY = newPathTarget.y;
|
||||
dest.mZ = newPathTarget.z;
|
||||
|
||||
if(!mPathFinder.isPathConstructed())
|
||||
mPathFinder.buildPath(start, dest, actor.getCell(), isOutside);
|
||||
mPathFinder.buildPath(start, dest, actor.getCell(), false);
|
||||
else
|
||||
{
|
||||
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())
|
||||
{
|
||||
newPathFinder.syncStart(mPathFinder.getPath());
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue