Merge remote-tracking branch 'upstream/master' into osx-ogre-19

actorid
Nikolay Kasyanov 11 years ago
commit 3993c34739

@ -167,6 +167,7 @@ if(USE_SYSTEM_TINYXML)
find_library(TINYXML_LIBRARIES tinyxml)
find_path(TINYXML_INCLUDE_DIR tinyxml.h)
message(STATUS "Found TinyXML: ${TINYXML_LIBRARIES} ${TINYXML_INCLUDE_DIR}")
add_definitions (-DTIXML_USE_STL)
if(TINYXML_LIBRARIES AND TINYXML_INCLUDE_DIR)
include_directories(${TINYXML_INCLUDE_DIR})
message(STATUS "Using system TinyXML library.")

@ -77,6 +77,8 @@ namespace
ini.insert(loc, setting + "=" + val + "\r\n");
}
#define FIX(setting) add_setting(category, setting, get_setting(category, setting, inx), ini)
void bloodmoon_fix_ini(std::string& ini, const bfs::path inxPath)
{
std::string inx = read_to_string(inxPath);
@ -88,95 +90,94 @@ namespace
ini.erase(start, end-start);
std::string category;
std::string setting;
category = "General";
{
setting = "Werewolf FOV"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Werewolf FOV");
}
category = "Moons";
{
setting = "Script Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Script Color");
}
category = "Weather";
{
setting = "Snow Ripples"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Ripple Radius"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Ripples Per Flake"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Ripple Scale"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Ripple Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Gravity Scale"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow High Kill"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Low Kill"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Snow Ripples");
FIX("Snow Ripple Radius");
FIX("Snow Ripples Per Flake");
FIX("Snow Ripple Scale");
FIX("Snow Ripple Speed");
FIX("Snow Gravity Scale");
FIX("Snow High Kill");
FIX("Snow Low Kill");
}
category = "Weather Blight";
{
setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Ambient Loop Sound ID");
}
category = "Weather Snow";
{
setting = "Sky Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Disc Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Transition Delta"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Land Fog Day Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Land Fog Night Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Clouds Maximum Percent"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Wind Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Cloud Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Glare View"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Cloud Texture"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Threshold"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Diameter"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Height Min"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Height Max"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Snow Entrance Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Max Snowflakes"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Sky Sunrise Color");
FIX("Sky Day Color");
FIX("Sky Sunset Color");
FIX("Sky Night Color");
FIX("Fog Sunrise Color");
FIX("Fog Day Color");
FIX("Fog Sunset Color");
FIX("Fog Night Color");
FIX("Ambient Sunrise Color");
FIX("Ambient Day Color");
FIX("Ambient Sunset Color");
FIX("Ambient Night Color");
FIX("Sun Sunrise Color");
FIX("Sun Day Color");
FIX("Sun Sunset Color");
FIX("Sun Night Color");
FIX("Sun Disc Sunset Color");
FIX("Transition Delta");
FIX("Land Fog Day Depth");
FIX("Land Fog Night Depth");
FIX("Clouds Maximum Percent");
FIX("Wind Speed");
FIX("Cloud Speed");
FIX("Glare View");
FIX("Cloud Texture");
FIX("Ambient Loop Sound ID");
FIX("Snow Threshold");
FIX("Snow Diameter");
FIX("Snow Height Min");
FIX("Snow Height Max");
FIX("Snow Entrance Speed");
FIX("Max Snowflakes");
}
category = "Weather Blizzard";
{
setting = "Sky Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sky Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Fog Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Sunrise Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Day Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Night Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Sun Disc Sunset Color"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Transition Delta"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Land Fog Day Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Land Fog Night Depth"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Clouds Maximum Percent"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Wind Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Cloud Speed"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Glare View"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Cloud Texture"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Ambient Loop Sound ID"; add_setting(category, setting, get_setting(category, setting, inx), ini);
setting = "Storm Threshold"; add_setting(category, setting, get_setting(category, setting, inx), ini);
FIX("Sky Sunrise Color");
FIX("Sky Day Color");
FIX("Sky Sunset Color");
FIX("Sky Night Color");
FIX("Fog Sunrise Color");
FIX("Fog Day Color");
FIX("Fog Sunset Color");
FIX("Fog Night Color");
FIX("Ambient Sunrise Color");
FIX("Ambient Day Color");
FIX("Ambient Sunset Color");
FIX("Ambient Night Color");
FIX("Sun Sunrise Color");
FIX("Sun Day Color");
FIX("Sun Sunset Color");
FIX("Sun Night Color");
FIX("Sun Disc Sunset Color");
FIX("Transition Delta");
FIX("Land Fog Day Depth");
FIX("Land Fog Night Depth");
FIX("Clouds Maximum Percent");
FIX("Wind Speed");
FIX("Cloud Speed");
FIX("Glare View");
FIX("Cloud Texture");
FIX("Ambient Loop Sound ID");
FIX("Storm Threshold");
}
}
@ -268,6 +269,27 @@ namespace
strptime(time, "%d %B %Y", &tms);
return mktime(&tms);
}
// Some cds have cab files which have the Data Files subfolders outside the Data Files folder
void install_dfiles_outside(const bfs::path& from, const bfs::path& dFiles)
{
bfs::path fonts = findFile(from, "fonts", false);
if(fonts.string() != "")
installToPath(fonts, dFiles / "Fonts");
bfs::path music = findFile(from, "music", false);
if(music.string() != "")
installToPath(music, dFiles / "Music");
bfs::path sound = findFile(from, "sound", false);
if(sound.string() != "")
installToPath(sound, dFiles / "Sound");
bfs::path splash = findFile(from, "splash", false);
if(splash.string() != "")
installToPath(splash, dFiles / "Splash");
}
}
bool UnshieldThread::SetMorrowindPath(const std::string& path)
@ -365,6 +387,8 @@ bool UnshieldThread::extract()
installToPath(dFilesDir, outputDataFilesDir);
install_dfiles_outside(mwExtractPath, outputDataFilesDir);
// Videos are often kept uncompressed on the cd
bfs::path videosPath = findFile(mMorrowindPath.parent_path(), "video", false);
if(videosPath.string() != "")
@ -399,6 +423,8 @@ bool UnshieldThread::extract()
installToPath(dFilesDir, outputDataFilesDir);
install_dfiles_outside(tbExtractPath, outputDataFilesDir);
// Mt GOTY CD has Sounds in a seperate folder from the rest of the data files
bfs::path soundsPath = findFile(tbExtractPath, "sounds", false);
if(soundsPath.string() != "")
@ -426,6 +452,8 @@ bool UnshieldThread::extract()
bfs::path dFilesDir = findFile(bmExtractPath, "bloodmoon.esm").parent_path();
installToPath(dFilesDir, outputDataFilesDir);
install_dfiles_outside(bmExtractPath, outputDataFilesDir);
// My GOTY CD contains a folder within cab files called Tribunal patch,
// which contains Tribunal.esm

@ -18,12 +18,12 @@ opencs_hdrs_noqt (model/doc
opencs_units (model/world
idtable idtableproxymodel regionmap
idtable idtableproxymodel regionmap data
)
opencs_units_noqt (model/world
universalid data record commands columnbase scriptcontext cell refidcollection
universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns
)
@ -59,12 +59,13 @@ opencs_hdrs_noqt (view/doc
opencs_units (view/world
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
cellcreator referenceablecreator referencecreator
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
scenetoolmode
)
opencs_units_noqt (view/world
dialoguesubview subviews
enumdelegate vartypedelegate recordstatusdelegate refidtypedelegate datadisplaydelegate
enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
scripthighlighter idvalidator
)

@ -34,7 +34,7 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row,
{
string = data.toString();
}
else if (data.type()==QVariant::Int || data.type()==QVariant::UInt ||
else if ((data.type()==QVariant::Int || data.type()==QVariant::UInt) &&
CSMWorld::Columns::hasEnums (static_cast<CSMWorld::Columns::ColumnId> (mColumnId)))
{
int value = data.toInt();
@ -47,8 +47,10 @@ bool CSMFilter::TextNode::test (const CSMWorld::IdTable& table, int row,
}
else if (data.type()==QVariant::Bool)
{
string = data.toBool() ? "true" : " false";
string = data.toBool() ? "true" : "false";
}
else if (mText.empty() && !data.isValid())
return true;
else
return false;

@ -17,7 +17,7 @@ bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row,
const std::map<int, int>::const_iterator iter = columns.find (mColumnId);
if (iter==columns.end())
throw std::logic_error ("invalid column in test value test");
throw std::logic_error ("invalid column in value node test");
if (iter->second==-1)
return true;
@ -27,7 +27,7 @@ bool CSMFilter::ValueNode::test (const CSMWorld::IdTable& table, int row,
QVariant data = table.data (index);
if (data.type()!=QVariant::Double && data.type()!=QVariant::Bool && data.type()!=QVariant::Int &&
data.type()!=QVariant::UInt)
data.type()!=QVariant::UInt && data.type()!=static_cast<QVariant::Type> (QMetaType::Float))
return false;
double value = data.toDouble();
@ -68,7 +68,7 @@ std::string CSMFilter::ValueNode::toString (bool numericColumns) const
<< CSMWorld::Columns::getName (static_cast<CSMWorld::Columns::ColumnId> (mColumnId))
<< "\"";
stream << ", \"";
stream << ", ";
if (mLower==mUpper && mLowerType!=Type_Infinite && mUpperType!=Type_Infinite)
stream << mLower;

@ -19,7 +19,12 @@ int CSMTools::BirthsignCheckStage::setup()
void CSMTools::BirthsignCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::BirthSign& birthsign = mBirthsigns.getRecord (stage).get();
const CSMWorld::Record<ESM::BirthSign>& record = mBirthsigns.getRecord (stage);
if (record.isDeleted())
return;
const ESM::BirthSign& birthsign = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Birthsign, birthsign.mId);

@ -20,7 +20,12 @@ int CSMTools::ClassCheckStage::setup()
void CSMTools::ClassCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Class& class_= mClasses.getRecord (stage).get();
const CSMWorld::Record<ESM::Class>& record = mClasses.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Class& class_ = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Class, class_.mId);

@ -20,7 +20,12 @@ int CSMTools::FactionCheckStage::setup()
void CSMTools::FactionCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Faction& faction = mFactions.getRecord (stage).get();
const CSMWorld::Record<ESM::Faction>& record = mFactions.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Faction& faction = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Faction, faction.mId);

@ -9,7 +9,12 @@
void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector<std::string>& messages)
{
const ESM::Race& race = mRaces.getRecord (stage).get();
const CSMWorld::Record<ESM::Race>& record = mRaces.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Race& race = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Race, race.mId);

@ -19,7 +19,12 @@ int CSMTools::RegionCheckStage::setup()
void CSMTools::RegionCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Region& region = mRegions.getRecord (stage).get();
const CSMWorld::Record<ESM::Region>& record = mRegions.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Region& region = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Region, region.mId);

@ -18,7 +18,12 @@ int CSMTools::SkillCheckStage::setup()
void CSMTools::SkillCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Skill& skill = mSkills.getRecord (stage).get();
const CSMWorld::Record<ESM::Skill>& record = mSkills.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Skill& skill = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Skill, skill.mId);

@ -18,7 +18,12 @@ int CSMTools::SoundCheckStage::setup()
void CSMTools::SoundCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Sound& sound = mSounds.getRecord (stage).get();
const CSMWorld::Record<ESM::Sound>& record = mSounds.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Sound& sound = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId);

@ -19,7 +19,12 @@ int CSMTools::SpellCheckStage::setup()
void CSMTools::SpellCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Spell& spell = mSpells.getRecord (stage).get();
const CSMWorld::Record<ESM::Spell>& record = mSpells.getRecord (stage);
if (record.isDeleted())
return;
const ESM::Spell& spell = record.get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Spell, spell.mId);

@ -107,6 +107,11 @@ namespace CSMWorld
virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const;
///< \param type Will be ignored, unless the collection supports multiple record types
virtual std::vector<std::string> getIds (bool listDeleted = true) const;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
void addColumn (Column<ESXRecordT> *column);
void setRecord (int index, const Record<ESXRecordT>& record);
@ -293,6 +298,21 @@ namespace CSMWorld
return static_cast<int> (mRecords.size());
}
template<typename ESXRecordT, typename IdAccessorT>
std::vector<std::string> Collection<ESXRecordT, IdAccessorT>::getIds (bool listDeleted) const
{
std::vector<std::string> ids;
for (typename std::map<std::string, int>::const_iterator iter = mIndex.begin();
iter!=mIndex.end(); ++iter)
{
if (listDeleted || !mRecords[iter->second].isDeleted())
ids.push_back (IdAccessorT().getId (mRecords[iter->second].get()));
}
return ids;
}
template<typename ESXRecordT, typename IdAccessorT>
const Record<ESXRecordT>& Collection<ESXRecordT, IdAccessorT>::getRecord (const std::string& id) const
{

@ -78,8 +78,12 @@ namespace CSMWorld
virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const = 0;
///< \param type Will be ignored, unless the collection supports multiple record types
};
virtual std::vector<std::string> getIds (bool listDeleted = true) const = 0;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
};
}
#endif

@ -1216,6 +1216,74 @@ namespace CSMWorld
return true;
}
};
template<typename ESXRecordT>
struct PosColumn : public Column<ESXRecordT>
{
ESM::Position ESXRecordT::* mPosition;
int mIndex;
PosColumn (ESM::Position ESXRecordT::* position, int index, bool door)
: Column<ESXRecordT> (
(door ? Columns::ColumnId_DoorPositionXPos : Columns::ColumnId_PositionXPos)+index,
ColumnBase::Display_Float), mPosition (position), mIndex (index) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
const ESM::Position& position = record.get().*mPosition;
return position.pos[mIndex];
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
ESM::Position& position = record.get().*mPosition;
position.pos[mIndex] = data.toFloat();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct RotColumn : public Column<ESXRecordT>
{
ESM::Position ESXRecordT::* mPosition;
int mIndex;
RotColumn (ESM::Position ESXRecordT::* position, int index, bool door)
: Column<ESXRecordT> (
(door ? Columns::ColumnId_DoorPositionXRot : Columns::ColumnId_PositionXRot)+index,
ColumnBase::Display_Float), mPosition (position), mIndex (index) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
const ESM::Position& position = record.get().*mPosition;
return position.rot[mIndex];
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
ESM::Position& position = record.get().*mPosition;
position.rot[mIndex] = data.toFloat();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
}
#endif

@ -51,7 +51,7 @@ namespace CSMWorld
{ ColumnId_FactionIndex, "Faction Index" },
{ ColumnId_Charges, "Charges" },
{ ColumnId_Enchantment, "Enchantment" },
{ ColumnId_Value, "Coin Value" },
{ ColumnId_CoinValue, "Coin Value" },
{ ColumnId_Teleport, "Teleport" },
{ ColumnId_TeleportCell, "Teleport Cell" },
{ ColumnId_LockLevel, "Lock Level" },
@ -147,6 +147,18 @@ namespace CSMWorld
{ ColumnId_Magical, "Magical" },
{ ColumnId_Silver, "Silver" },
{ ColumnId_Filter, "Filter" },
{ ColumnId_PositionXPos, "Pos X" },
{ ColumnId_PositionYPos, "Pos Y" },
{ ColumnId_PositionZPos, "Pos Z" },
{ ColumnId_PositionXRot, "Rot X" },
{ ColumnId_PositionYRot, "Rot Y" },
{ ColumnId_PositionZRot, "Rot Z" },
{ ColumnId_DoorPositionXPos, "Teleport Pos X" },
{ ColumnId_DoorPositionYPos, "Teleport Pos Y" },
{ ColumnId_DoorPositionZPos, "Teleport Pos Z" },
{ ColumnId_DoorPositionXRot, "Teleport Rot X" },
{ ColumnId_DoorPositionYRot, "Teleport Rot Y" },
{ ColumnId_DoorPositionZRot, "Teleport Rot Z" },
{ ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" },

@ -45,101 +45,113 @@ namespace CSMWorld
ColumnId_Charges = 32,
ColumnId_Enchantment = 33,
ColumnId_CoinValue = 34,
ColumnId_Teleport = 25,
ColumnId_TeleportCell = 26,
ColumnId_LockLevel = 27,
ColumnId_Key = 28,
ColumnId_Trap = 29,
ColumnId_BeastRace = 30,
ColumnId_AutoCalc = 31,
ColumnId_StarterSpell = 32,
ColumnId_AlwaysSucceeds = 33,
ColumnId_SleepForbidden = 34,
ColumnId_InteriorWater = 35,
ColumnId_InteriorSky = 36,
ColumnId_Model = 37,
ColumnId_Script = 38,
ColumnId_Icon = 39,
ColumnId_Weight = 40,
ColumnId_EnchantmentPoints = 31,
ColumnId_Quality = 32,
ColumnId_Ai = 33,
ColumnId_AiHello = 34,
ColumnId_AiFlee = 35,
ColumnId_AiFight = 36,
ColumnId_AiAlarm = 37,
ColumnId_BuysWeapons = 38,
ColumnId_BuysArmor = 39,
ColumnId_BuysClothing = 40,
ColumnId_BuysBooks = 41,
ColumnId_BuysIngredients = 42,
ColumnId_BuysLockpicks = 43,
ColumnId_BuysProbes = 44,
ColumnId_BuysLights = 45,
ColumnId_BuysApparati = 46,
ColumnId_BuysRepairItems = 47,
ColumnId_BuysMiscItems = 48,
ColumnId_BuysPotions = 49,
ColumnId_BuysMagicItems = 50,
ColumnId_SellsSpells = 51,
ColumnId_Trainer = 52,
ColumnId_Spellmaking = 53,
ColumnId_EnchantingService = 54,
ColumnId_RepairService = 55,
ColumnId_ApparatusType = 56,
ColumnId_ArmorType = 57,
ColumnId_Health = 58,
ColumnId_ArmorValue = 59,
ColumnId_Scroll = 60,
ColumnId_ClothingType = 61,
ColumnId_WeightCapacity = 62,
ColumnId_OrganicContainer = 63,
ColumnId_Respawn = 64,
ColumnId_CreatureType = 65,
ColumnId_SoulPoints = 66,
ColumnId_OriginalCreature = 67,
ColumnId_Biped = 68,
ColumnId_HasWeapon = 69,
ColumnId_NoMovement = 70,
ColumnId_Swims = 71,
ColumnId_Flies = 72,
ColumnId_Walks = 73,
ColumnId_Essential = 74,
ColumnId_SkeletonBlood = 75,
ColumnId_MetalBlood = 76,
ColumnId_OpenSound = 77,
ColumnId_CloseSound = 78,
ColumnId_Duration = 79,
ColumnId_Radius = 80,
ColumnId_Colour = 81,
ColumnId_Sound = 82,
ColumnId_Dynamic = 83,
ColumnId_Portable = 84,
ColumnId_NegativeLight = 85,
ColumnId_Flickering = 86,
ColumnId_SlowFlickering = 87,
ColumnId_Pulsing = 88,
ColumnId_SlowPulsing = 89,
ColumnId_Fire = 90,
ColumnId_OffByDefault = 91,
ColumnId_IsKey = 92,
ColumnId_Race = 93,
ColumnId_Class = 94,
Columnid_Hair = 95,
ColumnId_Head = 96,
ColumnId_Female = 97,
ColumnId_WeaponType = 98,
ColumnId_WeaponSpeed = 99,
ColumnId_WeaponReach = 100,
ColumnId_MinChop = 101,
ColumnId_MaxChip = 102,
Columnid_MinSlash = 103,
ColumnId_MaxSlash = 104,
ColumnId_MinThrust = 105,
ColumnId_MaxThrust = 106,
ColumnId_Magical = 107,
ColumnId_Silver = 108,
ColumnId_Filter = 109,
ColumnId_Teleport = 35,
ColumnId_TeleportCell = 36,
ColumnId_LockLevel = 37,
ColumnId_Key = 38,
ColumnId_Trap = 39,
ColumnId_BeastRace = 40,
ColumnId_AutoCalc = 41,
ColumnId_StarterSpell = 42,
ColumnId_AlwaysSucceeds = 43,
ColumnId_SleepForbidden = 44,
ColumnId_InteriorWater = 45,
ColumnId_InteriorSky = 46,
ColumnId_Model = 47,
ColumnId_Script = 48,
ColumnId_Icon = 49,
ColumnId_Weight = 50,
ColumnId_EnchantmentPoints = 51,
ColumnId_Quality = 52,
ColumnId_Ai = 53,
ColumnId_AiHello = 54,
ColumnId_AiFlee = 55,
ColumnId_AiFight = 56,
ColumnId_AiAlarm = 57,
ColumnId_BuysWeapons = 58,
ColumnId_BuysArmor = 59,
ColumnId_BuysClothing = 60,
ColumnId_BuysBooks = 61,
ColumnId_BuysIngredients = 62,
ColumnId_BuysLockpicks = 63,
ColumnId_BuysProbes = 64,
ColumnId_BuysLights = 65,
ColumnId_BuysApparati = 66,
ColumnId_BuysRepairItems = 67,
ColumnId_BuysMiscItems = 68,
ColumnId_BuysPotions = 69,
ColumnId_BuysMagicItems = 70,
ColumnId_SellsSpells = 71,
ColumnId_Trainer = 72,
ColumnId_Spellmaking = 73,
ColumnId_EnchantingService = 74,
ColumnId_RepairService = 75,
ColumnId_ApparatusType = 76,
ColumnId_ArmorType = 77,
ColumnId_Health = 78,
ColumnId_ArmorValue = 79,
ColumnId_Scroll = 80,
ColumnId_ClothingType = 81,
ColumnId_WeightCapacity = 82,
ColumnId_OrganicContainer = 83,
ColumnId_Respawn = 84,
ColumnId_CreatureType = 85,
ColumnId_SoulPoints = 86,
ColumnId_OriginalCreature = 87,
ColumnId_Biped = 88,
ColumnId_HasWeapon = 89,
ColumnId_NoMovement = 90,
ColumnId_Swims = 91,
ColumnId_Flies = 92,
ColumnId_Walks = 93,
ColumnId_Essential = 94,
ColumnId_SkeletonBlood = 95,
ColumnId_MetalBlood = 96,
ColumnId_OpenSound = 97,
ColumnId_CloseSound = 98,
ColumnId_Duration = 99,
ColumnId_Radius = 100,
ColumnId_Colour = 101,
ColumnId_Sound = 102,
ColumnId_Dynamic = 103,
ColumnId_Portable = 104,
ColumnId_NegativeLight = 105,
ColumnId_Flickering = 106,
ColumnId_SlowFlickering = 107,
ColumnId_Pulsing = 108,
ColumnId_SlowPulsing = 109,
ColumnId_Fire = 110,
ColumnId_OffByDefault = 111,
ColumnId_IsKey = 112,
ColumnId_Race = 113,
ColumnId_Class = 114,
Columnid_Hair = 115,
ColumnId_Head = 116,
ColumnId_Female = 117,
ColumnId_WeaponType = 118,
ColumnId_WeaponSpeed = 119,
ColumnId_WeaponReach = 120,
ColumnId_MinChop = 121,
ColumnId_MaxChip = 122,
Columnid_MinSlash = 123,
ColumnId_MaxSlash = 124,
ColumnId_MinThrust = 125,
ColumnId_MaxThrust = 126,
ColumnId_Magical = 127,
ColumnId_Silver = 128,
ColumnId_Filter = 129,
ColumnId_PositionXPos = 130,
ColumnId_PositionYPos = 131,
ColumnId_PositionZPos = 132,
ColumnId_PositionXRot = 133,
ColumnId_PositionYRot = 134,
ColumnId_PositionZRot = 135,
ColumnId_DoorPositionXPos = 136,
ColumnId_DoorPositionYPos = 137,
ColumnId_DoorPositionZPos = 138,
ColumnId_DoorPositionXRot = 139,
ColumnId_DoorPositionYRot = 140,
ColumnId_DoorPositionZRot = 141,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.

@ -2,12 +2,14 @@
#include "data.hpp"
#include <stdexcept>
#include <algorithm>
#include <QAbstractItemModel>
#include <components/esm/esmreader.hpp>
#include <components/esm/defs.hpp>
#include <components/esm/loadglob.hpp>
#include <components/esm/cellref.hpp>
#include "idtable.hpp"
#include "columnimp.hpp"
@ -15,13 +17,31 @@
#include "columns.hpp"
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2)
UniversalId::Type type2, bool update)
{
mModels.push_back (model);
mModelIndex.insert (std::make_pair (type1, model));
if (type2!=UniversalId::Type_None)
mModelIndex.insert (std::make_pair (type2, model));
if (update)
{
connect (model, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (dataChanged (const QModelIndex&, const QModelIndex&)));
connect (model, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (rowsChanged (const QModelIndex&, int, int)));
connect (model, SIGNAL (rowsRemoved (const QModelIndex&, int, int)),
this, SLOT (rowsChanged (const QModelIndex&, int, int)));
}
}
void CSMWorld::Data::appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
bool listDeleted)
{
std::vector<std::string> ids2 = collection.getIds (listDeleted);
ids.insert (ids.end(), ids2.begin(), ids2.end());
}
CSMWorld::Data::Data() : mRefs (mCells)
@ -134,6 +154,12 @@ CSMWorld::Data::Data() : mRefs (mCells)
mRefs.addColumn (new RecordStateColumn<CellRef>);
mRefs.addColumn (new CellColumn<CellRef>);
mRefs.addColumn (new IdColumn<CellRef>);
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mPos, 0, false));
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mPos, 1, false));
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mPos, 2, false));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mPos, 0, false));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mPos, 1, false));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mPos, 2, false));
mRefs.addColumn (new ScaleColumn<CellRef>);
mRefs.addColumn (new OwnerColumn<CellRef>);
mRefs.addColumn (new SoulColumn<CellRef>);
@ -144,6 +170,12 @@ CSMWorld::Data::Data() : mRefs (mCells)
mRefs.addColumn (new GoldValueColumn<CellRef>);
mRefs.addColumn (new TeleportColumn<CellRef>);
mRefs.addColumn (new TeleportCellColumn<CellRef>);
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mDoorDest, 0, true));
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mDoorDest, 1, true));
mRefs.addColumn (new PosColumn<CellRef> (&CellRef::mDoorDest, 2, true));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mDoorDest, 0, true));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mDoorDest, 1, true));
mRefs.addColumn (new RotColumn<CellRef> (&CellRef::mDoorDest, 2, true));
mRefs.addColumn (new LockLevelColumn<CellRef>);
mRefs.addColumn (new KeyColumn<CellRef>);
mRefs.addColumn (new TrapColumn<CellRef>);
@ -155,7 +187,7 @@ CSMWorld::Data::Data() : mRefs (mCells)
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill, false);
addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class);
addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction);
addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race);
@ -167,8 +199,8 @@ CSMWorld::Data::Data() : mRefs (mCells)
addModel (new IdTable (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs), UniversalId::Type_References, UniversalId::Type_Reference);
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter);
addModel (new IdTable (&mRefs), UniversalId::Type_References, UniversalId::Type_Reference, false);
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false);
}
CSMWorld::Data::~Data()
@ -341,7 +373,7 @@ QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{
RegionMap *table = 0;
addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap,
UniversalId::Type_None);
UniversalId::Type_None, false);
return table;
}
throw std::logic_error ("No table model available for " + id.toString());
@ -440,3 +472,36 @@ bool CSMWorld::Data::hasId (const std::string& id) const
getCells().searchId (id)!=-1 ||
getReferenceables().searchId (id)!=-1;
}
std::vector<std::string> CSMWorld::Data::getIds (bool listDeleted) const
{
std::vector<std::string> ids;
appendIds (ids, mGlobals, listDeleted);
appendIds (ids, mGmsts, listDeleted);
appendIds (ids, mClasses, listDeleted);
appendIds (ids, mFactions, listDeleted);
appendIds (ids, mRaces, listDeleted);
appendIds (ids, mSounds, listDeleted);
appendIds (ids, mScripts, listDeleted);
appendIds (ids, mRegions, listDeleted);
appendIds (ids, mBirthsigns, listDeleted);
appendIds (ids, mSpells, listDeleted);
appendIds (ids, mCells, listDeleted);
appendIds (ids, mReferenceables, listDeleted);
std::sort (ids.begin(), ids.end());
return ids;
}
void CSMWorld::Data::dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
{
if (topLeft.column()<=0)
emit idListChanged();
}
void CSMWorld::Data::rowsChanged (const QModelIndex& parent, int start, int end)
{
emit idListChanged();
}

@ -6,6 +6,9 @@
#include <boost/filesystem/path.hpp>
#include <QObject>
#include <QModelIndex>
#include <components/esm/loadglob.hpp>
#include <components/esm/loadgmst.hpp>
#include <components/esm/loadskil.hpp>
@ -30,8 +33,10 @@ class QAbstractItemModel;
namespace CSMWorld
{
class Data
class Data : public QObject
{
Q_OBJECT
IdCollection<ESM::Global> mGlobals;
IdCollection<ESM::GameSetting> mGmsts;
IdCollection<ESM::Skill> mSkills;
@ -55,13 +60,17 @@ namespace CSMWorld
Data& operator= (const Data&);
void addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2 = UniversalId::Type_None);
UniversalId::Type type2 = UniversalId::Type_None, bool update = true);
static void appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
bool listDeleted);
///< Append all IDs from collection to \a ids.
public:
Data();
~Data();
virtual ~Data();
const IdCollection<ESM::Global>& getGlobals() const;
@ -136,6 +145,21 @@ namespace CSMWorld
///< Merging content of a file into base or modified.
bool hasId (const std::string& id) const;
std::vector<std::string> getIds (bool listDeleted = true) const;
///< Return a sorted collection of all IDs that are not internal to the editor.
///
/// \param listDeleted include deleted record in the list
signals:
void idListChanged();
private slots:
void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void rowsChanged (const QModelIndex& parent, int start, int end);
};
}

@ -534,3 +534,8 @@ int CSMWorld::RefIdCollection::getAppendIndex (UniversalId::Type type) const
{
return mData.getAppendIndex (type);
}
std::vector<std::string> CSMWorld::RefIdCollection::getIds (bool listDeleted) const
{
return mData.getIds (listDeleted);
}

@ -89,6 +89,11 @@ namespace CSMWorld
virtual int getAppendIndex (UniversalId::Type type) const;
///< \param type Will be ignored, unless the collection supports multiple record types
virtual std::vector<std::string> getIds (bool listDeleted) const;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
};
}

@ -196,3 +196,25 @@ int CSMWorld::RefIdData::getSize() const
{
return mIndex.size();
}
std::vector<std::string> CSMWorld::RefIdData::getIds (bool listDeleted) const
{
std::vector<std::string> ids;
for (std::map<std::string, LocalIndex>::const_iterator iter (mIndex.begin()); iter!=mIndex.end();
++iter)
{
if (listDeleted || !getRecord (iter->second).isDeleted())
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator container =
mRecordContainers.find (iter->second.second);
if (container==mRecordContainers.end())
throw std::logic_error ("Invalid referenceable ID type");
ids.push_back (container->second->getId (iter->second.first));
}
}
return ids;
}

@ -182,6 +182,11 @@ namespace CSMWorld
void load (const LocalIndex& index, ESM::ESMReader& reader, bool base);
int getSize() const;
std::vector<std::string> getIds (bool listDeleted = true) const;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
};
}

@ -1,6 +1,14 @@
#include "scriptcontext.hpp"
#include <algorithm>
#include <components/misc/stringops.hpp>
#include "data.hpp"
CSMWorld::ScriptContext::ScriptContext (const Data& data) : mData (data), mIdsUpdated (false) {}
bool CSMWorld::ScriptContext::canDeclareLocals() const
{
return false;
@ -18,5 +26,19 @@ char CSMWorld::ScriptContext::getMemberType (const std::string& name, const std:
bool CSMWorld::ScriptContext::isId (const std::string& name) const
{
return false;
if (!mIdsUpdated)
{
mIds = mData.getIds();
std::for_each (mIds.begin(), mIds.end(), &Misc::StringUtils::lowerCase);
mIdsUpdated = true;
}
return std::binary_search (mIds.begin(), mIds.end(), Misc::StringUtils::lowerCase (name));
}
void CSMWorld::ScriptContext::invalidateIds()
{
mIdsUpdated = false;
}

@ -1,14 +1,25 @@
#ifndef CSM_WORLD_SCRIPTCONTEXT_H
#define CSM_WORLD_SCRIPTCONTEXT_H
#include <string>
#include <vector>
#include <components/compiler/context.hpp>
namespace CSMWorld
{
class Data;
class ScriptContext : public Compiler::Context
{
const Data& mData;
mutable std::vector<std::string> mIds;
mutable bool mIdsUpdated;
public:
ScriptContext (const Data& data);
virtual bool canDeclareLocals() const;
///< Is the compiler allowed to declare local variables?
@ -20,6 +31,8 @@ namespace CSMWorld
virtual bool isId (const std::string& name) const;
///< Does \a name match an ID, that can be referenced?
void invalidateIds();
};
}

@ -43,18 +43,18 @@ namespace
static const TypeData sIdArg[] =
{
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", ":./globvar.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", ":./GMST.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", ":./skill.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", ":./class.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", ":./faction.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", ":./race.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", ":./sound.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", ":./script.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", ":./land.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", ":./birthsign.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "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" },
@ -80,13 +80,14 @@ namespace
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", 0 },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};
static const TypeData sIndexArg[] =
{
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};

@ -86,10 +86,11 @@ namespace CSMWorld
Type_Reference,
Type_RegionMap,
Type_Filter,
Type_Filters
Type_Filters,
Type_Scene
};
enum { NumberOfTypes = Type_Filters+1 };
enum { NumberOfTypes = Type_Scene+1 };
private:

@ -1,6 +0,0 @@
#include "ocspropertywidget.hpp"
OcsPropertyWidget::OcsPropertyWidget(QObject *parent) :
QObject(parent)
{
}

@ -1,18 +0,0 @@
#ifndef OCSPROPERTYWIDGET_HPP
#define OCSPROPERTYWIDGET_HPP
#include <QObject>
class OcsPropertyWidget : public QObject
{
Q_OBJECT
public:
explicit OcsPropertyWidget(QObject *parent = 0);
signals:
public slots:
};
#endif // OCSPROPERTYWIDGET_HPP

@ -61,7 +61,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
if (path.parent_path().string()==mLocalData.string())
{
// path already points to the local data directory
message = QString::fromUtf8 (("Will be saved as: " + path.native()).c_str());
message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str());
mResultPath = path;
mValid = true;
}
@ -70,7 +70,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
// path points somewhere else or is a leaf name.
path = mLocalData / path.filename();
message = QString::fromUtf8 (("Will be saved as: " + path.native()).c_str());
message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str());
mResultPath = path;
mValid = true;

@ -115,6 +115,10 @@ void CSVDoc::View::setupWorldMenu()
world->addSeparator(); // items that don't represent single record lists follow here
QAction *scene = new QAction (tr ("Scene"), this);
connect (scene, SIGNAL (triggered()), this, SLOT (addSceneSubView()));
world->addAction (scene);
QAction *regionMap = new QAction (tr ("Region Map"), this);
connect (regionMap, SIGNAL (triggered()), this, SLOT (addRegionMapSubView()));
world->addAction (regionMap);
@ -403,6 +407,11 @@ void CSVDoc::View::addFiltersSubView()
addSubView (CSMWorld::UniversalId::Type_Filters);
}
void CSVDoc::View::addSceneSubView()
{
addSubView (CSMWorld::UniversalId::Type_Scene);
}
void CSVDoc::View::abortOperation (int type)
{
mDocument->abortOperation (type);

@ -164,6 +164,8 @@ namespace CSVDoc
void addFiltersSubView();
void addSceneSubView();
void toggleShowStatusBar (bool show);
};
}

@ -14,7 +14,7 @@
#include "../world/enumdelegate.hpp"
#include "../world/vartypedelegate.hpp"
#include "../world/recordstatusdelegate.hpp"
#include "../world/refidtypedelegate.hpp"
#include "../world/idtypedelegate.hpp"
#include "../settings/usersettingsdialog.hpp"
#include "view.hpp"
@ -56,7 +56,7 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
new CSVWorld::RecordStatusDelegateFactory());
mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType,
new CSVWorld::RefIdTypeDelegateFactory());
new CSVWorld::IdTypeDelegateFactory());
struct Mapping
{

@ -6,6 +6,8 @@
#include "../../model/tools/reportmodel.hpp"
#include "../../view/world/idtypedelegate.hpp"
CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: CSVDoc::SubView (id), mModel (document.getReport (id))
{
@ -18,6 +20,11 @@ CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc:
mTable->setSelectionBehavior (QAbstractItemView::SelectRows);
mTable->setSelectionMode (QAbstractItemView::ExtendedSelection);
mIdTypeDelegate = CSVWorld::IdTypeDelegateFactory().makeDelegate (
document.getUndoStack(), this);
mTable->setItemDelegateForColumn (0, mIdTypeDelegate);
connect (mTable, SIGNAL (doubleClicked (const QModelIndex&)), this, SLOT (show (const QModelIndex&)));
}
@ -26,6 +33,11 @@ void CSVTools::ReportSubView::setEditLock (bool locked)
// ignored. We don't change document state anyway.
}
void CSVTools::ReportSubView::updateEditorSetting (const QString& key, const QString& value)
{
mIdTypeDelegate->updateEditorSetting (key, value);
}
void CSVTools::ReportSubView::show (const QModelIndex& index)
{
focusId (mModel->getUniversalId (index.row()));

@ -16,6 +16,11 @@ namespace CSMTools
class ReportModel;
}
namespace CSVWorld
{
class CommandDelegate;
}
namespace CSVTools
{
class Table;
@ -26,6 +31,7 @@ namespace CSVTools
CSMTools::ReportModel *mModel;
QTableView *mTable;
CSVWorld::CommandDelegate *mIdTypeDelegate;
public:
@ -33,6 +39,8 @@ namespace CSVTools
virtual void setEditLock (bool locked);
virtual void updateEditorSetting (const QString&, const QString&);
private slots:
void show (const QModelIndex& index);

@ -0,0 +1,46 @@
#include "idtypedelegate.hpp"
#include "../../model/world/universalid.hpp"
CSVWorld::IdTypeDelegate::IdTypeDelegate
(const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent)
: DataDisplayDelegate (values, icons, undoStack, parent)
{}
bool CSVWorld::IdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue)
{
/// \todo make the setting key a member variable, that is initialised from a constructor argument
if (settingName == "Referenceable ID Type Display")
{
if (settingValue == "Icon and Text")
mDisplayMode = Mode_IconAndText;
else if (settingValue == "Icon Only")
mDisplayMode = Mode_IconOnly;
else if (settingValue == "Text Only")
mDisplayMode = Mode_TextOnly;
return true;
}
return false;
}
CSVWorld::IdTypeDelegateFactory::IdTypeDelegateFactory()
{
for (int i=0; i<CSMWorld::UniversalId::NumberOfTypes; ++i)
{
CSMWorld::UniversalId id (static_cast<CSMWorld::UniversalId::Type> (i));
DataDisplayDelegateFactory::add (id.getType(), QString::fromUtf8 (id.getTypeName().c_str()),
QString::fromUtf8 (id.getIcon().c_str()));
}
}
CSVWorld::CommandDelegate *CSVWorld::IdTypeDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{
return new IdTypeDelegate (mValues, mIcons, undoStack, parent);
}

@ -1,5 +1,5 @@
#ifndef REFIDTYPEDELEGATE_HPP
#define REFIDTYPEDELEGATE_HPP
#ifndef IDTYPEDELEGATE_HPP
#define IDTYPEDELEGATE_HPP
#include "enumdelegate.hpp"
#include "util.hpp"
@ -8,29 +8,23 @@
namespace CSVWorld
{
class RefIdTypeDelegate : public DataDisplayDelegate
class IdTypeDelegate : public DataDisplayDelegate
{
public:
RefIdTypeDelegate (const ValueList &mValues, const IconList &icons, QUndoStack& undoStack, QObject *parent);
IdTypeDelegate (const ValueList &mValues, const IconList &icons, QUndoStack& undoStack, QObject *parent);
virtual bool updateEditorSetting (const QString &settingName, const QString &settingValue);
};
class RefIdTypeDelegateFactory : public DataDisplayDelegateFactory
class IdTypeDelegateFactory : public DataDisplayDelegateFactory
{
typedef std::vector < std::pair <CSMWorld::UniversalId::Type, QString> > UidTypeList;
public:
RefIdTypeDelegateFactory();
IdTypeDelegateFactory();
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
private:
UidTypeList buildUidTypeList () const;
};
}

@ -1,62 +0,0 @@
#include "refidtypedelegate.hpp"
#include "../../model/world/universalid.hpp"
CSVWorld::RefIdTypeDelegate::RefIdTypeDelegate
(const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent)
: DataDisplayDelegate (values, icons, undoStack, parent)
{}
bool CSVWorld::RefIdTypeDelegate::updateEditorSetting (const QString &settingName, const QString &settingValue)
{
if (settingName == "Referenceable ID Type Display")
{
if (settingValue == "Icon and Text")
mDisplayMode = Mode_IconAndText;
else if (settingValue == "Icon Only")
mDisplayMode = Mode_IconOnly;
else if (settingValue == "Text Only")
mDisplayMode = Mode_TextOnly;
return true;
}
return false;
}
CSVWorld::RefIdTypeDelegateFactory::RefIdTypeDelegateFactory()
{
UidTypeList uIdList = buildUidTypeList();
for (UidTypeList::const_iterator it = uIdList.begin(); it != uIdList.end(); it++)
{
int i = it->first;
DataDisplayDelegateFactory::add (i, QString::fromStdString(CSMWorld::UniversalId(it->first, "").getTypeName()), it->second);
}
}
CSVWorld::CommandDelegate *CSVWorld::RefIdTypeDelegateFactory::makeDelegate (QUndoStack& undoStack,
QObject *parent) const
{
return new RefIdTypeDelegate (mValues, mIcons, undoStack, parent);
}
CSVWorld::RefIdTypeDelegateFactory::UidTypeList CSVWorld::RefIdTypeDelegateFactory::buildUidTypeList() const
{
UidTypeList list;
std::vector<CSMWorld::UniversalId::Type> types = CSMWorld::UniversalId::listReferenceableTypes();
for (std::vector<CSMWorld::UniversalId::Type>::const_iterator iter (types.begin());
iter!=types.end(); ++iter)
{
CSMWorld::UniversalId id (*iter, "");
list.push_back (std::make_pair (id.getType(), id.getIcon().c_str()));
}
return list;
}

@ -0,0 +1,82 @@
#include "scenesubview.hpp"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include "../../model/doc/document.hpp"
#include "../filter/filterbox.hpp"
#include "tablebottombox.hpp"
#include "creator.hpp"
#include "scenetoolbar.hpp"
#include "scenetoolmode.hpp"
CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document)
: SubView (id)
{
QVBoxLayout *layout = new QVBoxLayout;
layout->setContentsMargins (QMargins (0, 0, 0, 0));
layout->addWidget (mBottom =
new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id,
this), 0);
QHBoxLayout *layout2 = new QHBoxLayout;
layout2->setContentsMargins (QMargins (0, 0, 0, 0));
SceneToolbar *toolbar = new SceneToolbar (48, this);
// test
SceneToolMode *tool = new SceneToolMode (toolbar);
tool->addButton (":door.png", "a");
tool->addButton (":GMST.png", "b");
tool->addButton (":Info.png", "c");
toolbar->addTool (tool);
toolbar->addTool (new SceneToolMode (toolbar));
toolbar->addTool (new SceneToolMode (toolbar));
toolbar->addTool (new SceneToolMode (toolbar));
layout2->addWidget (toolbar, 0);
/// \todo replace with rendering widget
QPalette palette2 (palette());
palette2.setColor (QPalette::Background, Qt::white);
QLabel *placeholder = new QLabel ("Here goes the 3D scene", this);
placeholder->setAutoFillBackground (true);
placeholder->setPalette (palette2);
placeholder->setAlignment (Qt::AlignHCenter);
layout2->addWidget (placeholder, 1);
layout->insertLayout (0, layout2, 1);
CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);
layout->insertWidget (0, filterBox);
QWidget *widget = new QWidget;
widget->setLayout (layout);
setWidget (widget);
}
void CSVWorld::SceneSubView::setEditLock (bool locked)
{
}
void CSVWorld::SceneSubView::updateEditorSetting(const QString &settingName, const QString &settingValue)
{
}
void CSVWorld::SceneSubView::setStatusBar (bool show)
{
mBottom->setStatusBar (show);
}

@ -0,0 +1,37 @@
#ifndef CSV_WORLD_SCENESUBVIEW_H
#define CSV_WORLD_SCENESUBVIEW_H
#include "../doc/subview.hpp"
class QModelIndex;
namespace CSMDoc
{
class Document;
}
namespace CSVWorld
{
class Table;
class TableBottomBox;
class CreatorFactoryBase;
class SceneSubView : public CSVDoc::SubView
{
Q_OBJECT
TableBottomBox *mBottom;
public:
SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
virtual void setEditLock (bool locked);
virtual void updateEditorSetting (const QString& key, const QString& value);
virtual void setStatusBar (bool show);
};
}
#endif

@ -0,0 +1,17 @@
#include "scenetool.hpp"
#include "scenetoolbar.hpp"
CSVWorld::SceneTool::SceneTool (SceneToolbar *parent) : QPushButton (parent)
{
setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
setFixedSize (parent->getButtonSize(), parent->getButtonSize());
connect (this, SIGNAL (clicked()), this, SLOT (openRequest()));
}
void CSVWorld::SceneTool::openRequest()
{
showPanel (parentWidget()->mapToGlobal (pos()));
}

@ -0,0 +1,27 @@
#ifndef CSV_WORLD_SCENETOOL_H
#define CSV_WORLD_SCENETOOL_H
#include <QPushButton>
namespace CSVWorld
{
class SceneToolbar;
///< \brief Tool base class
class SceneTool : public QPushButton
{
Q_OBJECT
public:
SceneTool (SceneToolbar *parent);
virtual void showPanel (const QPoint& position) = 0;
private slots:
void openRequest();
};
}
#endif

@ -0,0 +1,29 @@
#include "scenetoolbar.hpp"
#include <QVBoxLayout>
#include "scenetool.hpp"
CSVWorld::SceneToolbar::SceneToolbar (int buttonSize, QWidget *parent)
: QWidget (parent), mButtonSize (buttonSize)
{
setFixedWidth (mButtonSize);
mLayout = new QVBoxLayout (this);
mLayout->setAlignment (Qt::AlignTop);
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
setLayout (mLayout);
}
void CSVWorld::SceneToolbar::addTool (SceneTool *tool)
{
mLayout->addWidget (tool, 0, Qt::AlignTop);
}
int CSVWorld::SceneToolbar::getButtonSize() const
{
return mButtonSize;
}

@ -0,0 +1,29 @@
#ifndef CSV_WORLD_SCENETOOLBAR_H
#define CSV_WORLD_SCENETOOLBAR_H
#include <QWidget>
class QVBoxLayout;
namespace CSVWorld
{
class SceneTool;
class SceneToolbar : public QWidget
{
Q_OBJECT
QVBoxLayout *mLayout;
int mButtonSize;
public:
SceneToolbar (int buttonSize, QWidget *parent = 0);
void addTool (SceneTool *tool);
int getButtonSize() const;
};
}
#endif

@ -0,0 +1,56 @@
#include "scenetoolmode.hpp"
#include <QHBoxLayout>
#include <QFrame>
#include <QSignalMapper>
#include "scenetoolbar.hpp"
CSVWorld::SceneToolMode::SceneToolMode (SceneToolbar *parent)
: SceneTool (parent), mButtonSize (parent->getButtonSize())
{
mPanel = new QFrame (this, Qt::Popup);
mLayout = new QHBoxLayout (mPanel);
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
mPanel->setLayout (mLayout);
}
void CSVWorld::SceneToolMode::showPanel (const QPoint& position)
{
mPanel->move (position);
mPanel->show();
}
void CSVWorld::SceneToolMode::addButton (const std::string& icon, const std::string& id)
{
QPushButton *button = new QPushButton (QIcon (QPixmap (icon.c_str())), "", mPanel);
button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
button->setFixedSize (mButtonSize, mButtonSize);
mLayout->addWidget (button);
mButtons.insert (std::make_pair (button, id));
connect (button, SIGNAL (clicked()), this, SLOT (selected()));
if (mButtons.size()==1)
setIcon (button->icon());
}
void CSVWorld::SceneToolMode::selected()
{
std::map<QPushButton *, std::string>::const_iterator iter =
mButtons.find (dynamic_cast<QPushButton *> (sender()));
if (iter!=mButtons.end())
{
mPanel->hide();
setIcon (iter->first->icon());
emit modeChanged (iter->second);
}
}

@ -0,0 +1,42 @@
#ifndef CSV_WORLD_SCENETOOL_MODE_H
#define CSV_WORLD_SCENETOOL_MODE_H
#include "scenetool.hpp"
#include <map>
class QHBoxLayout;
namespace CSVWorld
{
class SceneToolbar;
///< \brief Mode selector tool
class SceneToolMode : public SceneTool
{
Q_OBJECT
QWidget *mPanel;
QHBoxLayout *mLayout;
std::map<QPushButton *, std::string> mButtons; // widget, id
int mButtonSize;
public:
SceneToolMode (SceneToolbar *parent);
virtual void showPanel (const QPoint& position);
void addButton (const std::string& icon, const std::string& id);
signals:
void modeChanged (const std::string& id);
private slots:
void selected();
};
}
#endif

@ -4,6 +4,7 @@
#include <sstream>
#include <components/compiler/scanner.hpp>
#include <components/compiler/extensions0.hpp>
bool CSVWorld::ScriptHighlighter::parseInt (int value, const Compiler::TokenLoc& loc,
Compiler::Scanner& scanner)
@ -22,7 +23,7 @@ bool CSVWorld::ScriptHighlighter::parseFloat (float value, const Compiler::Token
bool CSVWorld::ScriptHighlighter::parseName (const std::string& name, const Compiler::TokenLoc& loc,
Compiler::Scanner& scanner)
{
highlight (loc, Type_Name);
highlight (loc, mContext.isId (name) ? Type_Id : Type_Name);
return true;
}
@ -62,10 +63,10 @@ void CSVWorld::ScriptHighlighter::highlight (const Compiler::TokenLoc& loc, Type
setFormat (index, length, mScheme[type]);
}
CSVWorld::ScriptHighlighter::ScriptHighlighter (QTextDocument *parent)
: QSyntaxHighlighter (parent), Compiler::Parser (mErrorHandler, mContext)
CSVWorld::ScriptHighlighter::ScriptHighlighter (const CSMWorld::Data& data, QTextDocument *parent)
: QSyntaxHighlighter (parent), Compiler::Parser (mErrorHandler, mContext), mContext (data)
{
/// \ŧodo replace this with user settings
/// \todo replace this with user settings
{
QTextCharFormat format;
format.setForeground (Qt::darkMagenta);
@ -101,6 +102,16 @@ CSVWorld::ScriptHighlighter::ScriptHighlighter (QTextDocument *parent)
format.setForeground (Qt::green);
mScheme.insert (std::make_pair (Type_Comment, format));
}
{
QTextCharFormat format;
format.setForeground (Qt::blue);
mScheme.insert (std::make_pair (Type_Id, format));
}
// configure compiler
Compiler::registerExtensions (mExtensions);
mContext.setExtensions (&mExtensions);
}
void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text)
@ -114,5 +125,9 @@ void CSVWorld::ScriptHighlighter::highlightBlock (const QString& text)
scanner.scan (*this);
}
catch (...) {} // ignore syntax errors
}
void CSVWorld::ScriptHighlighter::invalidateIds()
{
mContext.invalidateIds();
}

@ -7,6 +7,7 @@
#include <components/compiler/nullerrorhandler.hpp>
#include <components/compiler/parser.hpp>
#include <components/compiler/extensions.hpp>
#include "../../model/world/scriptcontext.hpp"
@ -23,12 +24,14 @@ namespace CSVWorld
Type_Name,
Type_Keyword,
Type_Special,
Type_Comment
Type_Comment,
Type_Id
};
private:
Compiler::NullErrorHandler mErrorHandler;
Compiler::Extensions mExtensions;
CSMWorld::ScriptContext mContext;
std::map<Type, QTextCharFormat> mScheme;
@ -71,9 +74,11 @@ namespace CSVWorld
public:
ScriptHighlighter (QTextDocument *parent);
ScriptHighlighter (const CSMWorld::Data& data, QTextDocument *parent);
virtual void highlightBlock (const QString& text);
void invalidateIds();
};
}

@ -58,7 +58,13 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc:
connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int, int)));
new ScriptHighlighter (mEditor->document());
connect (&document.getData(), SIGNAL (idListChanged()), this, SLOT (idListChanged()));
mHighlighter = new ScriptHighlighter (document.getData(), mEditor->document());
connect (&mUpdateTimer, SIGNAL (timeout()), this, SLOT (updateHighlighting()));
mUpdateTimer.setSingleShot (true);
}
void CSVWorld::ScriptSubView::setEditLock (bool locked)
@ -66,8 +72,19 @@ void CSVWorld::ScriptSubView::setEditLock (bool locked)
mEditor->setReadOnly (locked);
}
void CSVWorld::ScriptSubView::idListChanged()
{
mHighlighter->invalidateIds();
if (!mUpdateTimer.isActive())
mUpdateTimer.start (0);
}
void CSVWorld::ScriptSubView::textChanged()
{
if (mChangeLocked)
return;
ChangeLock lock (*this);
mDocument.getUndoStack().push (new CSMWorld::ModifyCommand (*mModel,
@ -79,6 +96,8 @@ void CSVWorld::ScriptSubView::dataChanged (const QModelIndex& topLeft, const QMo
if (mChangeLocked)
return;
ChangeLock lock (*this);
QModelIndex index = mModel->getModelIndex (getUniversalId().getId(), mColumn);
if (index.row()>=topLeft.row() && index.row()<=bottomRight.row() &&
@ -96,4 +115,14 @@ void CSVWorld::ScriptSubView::rowsAboutToBeRemoved (const QModelIndex& parent, i
if (!parent.isValid() && index.row()>=start && index.row()<=end)
deleteLater();
}
void CSVWorld::ScriptSubView::updateHighlighting()
{
if (mChangeLocked)
return;
ChangeLock lock (*this);
mHighlighter->rehighlight();
}

@ -3,6 +3,8 @@
#include "../doc/subview.hpp"
#include <QTimer>
class QTextEdit;
class QModelIndex;
@ -18,6 +20,8 @@ namespace CSMWorld
namespace CSVWorld
{
class ScriptHighlighter;
class ScriptSubView : public CSVDoc::SubView
{
Q_OBJECT
@ -27,6 +31,8 @@ namespace CSVWorld
CSMWorld::IdTable *mModel;
int mColumn;
int mChangeLocked;
ScriptHighlighter *mHighlighter;
QTimer mUpdateTimer;
class ChangeLock
{
@ -49,13 +55,19 @@ namespace CSVWorld
virtual void setEditLock (bool locked);
private slots:
public slots:
void idListChanged();
void textChanged();
void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end);
private slots:
void updateHighlighting();
};
}

@ -13,6 +13,7 @@
#include "cellcreator.hpp"
#include "referenceablecreator.hpp"
#include "referencecreator.hpp"
#include "scenesubview.hpp"
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
{
@ -62,4 +63,5 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
new CSVDoc::SubViewFactoryWithCreator<TableSubView,
CreatorFactory<CSVFilter::FilterCreator> >);
manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>);
}

@ -12,8 +12,8 @@
#include "../../model/world/idtableproxymodel.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/record.hpp"
#include "recordstatusdelegate.hpp"
#include "refidtypedelegate.hpp"
#include "util.hpp"
void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)

@ -119,6 +119,10 @@ target_link_libraries(openmw
components
)
if (USE_SYSTEM_TINYXML)
target_link_libraries(openmw ${TINYXML_LIBRARIES})
endif()
if (NOT UNIX)
target_link_libraries(openmw ${SDL2MAIN_LIBRARY})
endif()

@ -399,8 +399,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding);
mEnvironment.setWindowManager (window);
if (mNewGame)
mEnvironment.getWindowManager()->setNewGame(true);
// Create the world
mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mMaster, mPlugins,
@ -410,6 +408,10 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
input->setPlayer(&mEnvironment.getWorld()->getPlayer());
window->initUI();
if (mNewGame)
// still redundant work here: recreate CharacterCreation(),
// double update visibility etc.
window->setNewGame(true);
window->renderWorldMap();
//Load translation data

@ -324,6 +324,7 @@ namespace MWBase
virtual void processChangedSettings (const Settings::CategorySettingVector& settings) = 0;
virtual bool isFlying(const MWWorld::Ptr &ptr) const = 0;
virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const = 0;
virtual bool isSwimming(const MWWorld::Ptr &object) const = 0;
///Is the head of the creature underwater?
virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0;
@ -389,6 +390,12 @@ namespace MWBase
/// Returns true if teleport spell effects are allowed.
virtual bool isTeleportingEnabled() const = 0;
/// Enables or disables use of levitation spell effect.
virtual void enableLevitation(bool enable) = 0;
/// Returns true if levitation spell effect is allowed.
virtual bool isLevitationEnabled() const = 0;
/// Turn actor into werewolf or normal form.
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf) = 0;
@ -396,6 +403,8 @@ namespace MWBase
/// It only applies to the current form the NPC is in.
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor) = 0;
virtual bool getGodModeState() = 0;
virtual bool toggleGodMode() = 0;
};
}

@ -7,6 +7,7 @@
#include <OgreSceneNode.h>
#include <components/esm/loadmgef.hpp>
#include <components/esm/loadnpc.hpp>
#include "../mwbase/environment.hpp"
@ -396,9 +397,10 @@ namespace MWClass
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
}
weapon.getCellRef().mCharge -= std::min(std::max(1,
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())),
weapon.getCellRef().mCharge);
if (!MWBase::Environment::get().getWorld()->getGodModeState())
weapon.getCellRef().mCharge -= std::min(std::max(1,
(int)(damage * gmst.find("fWeaponDamageMult")->getFloat())), weapon.getCellRef().mCharge);
}
healthdmg = true;
}
@ -769,6 +771,37 @@ namespace MWClass
return x;
}
float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
{
MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
const float fallDistanceMin = gmst.find("fFallDamageDistanceMin")->getFloat();
if (fallHeight >= fallDistanceMin)
{
const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude;
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
const float fallDistanceMult = gmst.find("fFallDistanceMult")->getFloat();
float x = fallHeight - fallDistanceMin;
x -= (1.5 * acrobaticsSkill) + jumpSpellBonus;
x = std::max(0.0f, x);
float a = fallAcroBase + fallAcroMult * (100 - acrobaticsSkill);
x = fallDistanceBase + fallDistanceMult * x;
x *= a;
return x;
}
return 0;
}
MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const
{
ensureCustomData (ptr);

@ -97,6 +97,9 @@ namespace MWClass
virtual float getJump(const MWWorld::Ptr &ptr) const;
///< Return jump velocity (not accounting for movement)
virtual float getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const;
///< Return amount of health points lost when falling
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
///< Return desired movement.

@ -250,6 +250,7 @@ namespace MWGui
// remove object from the container it was coming from
mDragAndDrop->mSourceModel->removeItem(mDragAndDrop->mItem, mDragAndDrop->mDraggedCount);
mDragAndDrop->finish();
mDragAndDrop->mSourceModel->update();
}
else
{

@ -23,6 +23,7 @@ namespace MWGui
, mLastWallpaperChangeTime(0.f)
, mFirstLoad(true)
, mProgress(0)
, mVSyncWasEnabled(false)
{
getWidget(mLoadingText, "LoadingText");
getWidget(mProgressBar, "ProgressBar");
@ -67,6 +68,14 @@ namespace MWGui
void LoadingScreen::loadingOn()
{
// Temporarily turn off VSync, we want to do actual loading rather than waiting for the screen to sync.
// Threaded loading would be even better, of course - especially because some drivers force VSync to on and we can't change it.
// In Ogre 1.8, the swapBuffers argument is useless and setVSyncEnabled is bugged with GLX, nothing we can do :/
mVSyncWasEnabled = mWindow->isVSyncEnabled();
#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0)
mWindow->setVSyncEnabled(false);
#endif
setVisible(true);
if (mFirstLoad)
@ -83,6 +92,12 @@ namespace MWGui
void LoadingScreen::loadingOff()
{
// Re-enable vsync now.
// In Ogre 1.8, the swapBuffers argument is useless and setVSyncEnabled is bugged with GLX, nothing we can do :/
#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0)
mWindow->setVSyncEnabled(mVSyncWasEnabled);
#endif
setVisible(false);
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Loading);
@ -212,7 +227,8 @@ namespace MWGui
// caused a sync / flush and would be expensive).
// We're doing this so we can do some actual loading while the GPU is busy with the render.
// This means the render is lagging a frame behind, but this is hardly noticable.
mWindow->swapBuffers(false); // never Vsync, makes no sense here
mWindow->swapBuffers();
mWindow->update(false);
if (!hasCompositor)

@ -57,6 +57,8 @@ namespace MWGui
Ogre::StringVector mResources;
bool mVSyncWasEnabled;
void changeWallpaper();
void draw();

@ -70,7 +70,10 @@ namespace MWGui
{
MWBase::Environment::get().getSoundManager()->playSound("Menu Click", 1.f, 1.f);
if (sender == mButtons["return"])
{
MWBase::Environment::get().getSoundManager ()->resumeSounds (MWBase::SoundManager::Play_TypeSfx);
MWBase::Environment::get().getWindowManager ()->removeGuiMode (GM_MainMenu);
}
else if (sender == mButtons["options"])
MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings);
else if (sender == mButtons["exitgame"])

@ -14,6 +14,7 @@ namespace MWGui
mMessageBoxSpeed = 0.1;
mInterMessageBoxe = NULL;
mStaticMessageBox = NULL;
mLastButtonPressed = -1;
}
void MessageBoxManager::onFrame (float frameDuration)
@ -62,6 +63,7 @@ namespace MWGui
}
if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) {
mLastButtonPressed = mInterMessageBoxe->readPressedButton();
delete mInterMessageBoxe;
mInterMessageBoxe = NULL;
MWBase::Environment::get().getInputManager()->changeInputMode(
@ -107,6 +109,7 @@ namespace MWGui
}
mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);
mLastButtonPressed = -1;
return true;
}
@ -154,11 +157,9 @@ namespace MWGui
int MessageBoxManager::readPressedButton ()
{
if(mInterMessageBoxe != NULL)
{
return mInterMessageBoxe->readPressedButton();
}
return -1;
int pressed = mLastButtonPressed;
mLastButtonPressed = -1;
return pressed;
}
@ -421,9 +422,7 @@ namespace MWGui
int InteractiveMessageBox::readPressedButton ()
{
int pressed = mButtonPressed;
mButtonPressed = -1;
return pressed;
return mButtonPressed;
}
}

@ -56,6 +56,7 @@ namespace MWGui
MessageBox* mStaticMessageBox;
std::vector<MessageBoxManagerTimer> mTimers;
float mMessageBoxSpeed;
int mLastButtonPressed;
};
class MessageBox : public OEngine::GUI::Layout

@ -363,8 +363,12 @@ namespace MWGui
else if (_sender == mVSyncButton)
{
Settings::Manager::setBool("vsync", "Video", newState);
// Ogre::Window::setVSyncEnabled is bugged in 1.8
#if OGRE_VERSION < (1 << 16 | 9 << 8 | 0)
MWBase::Environment::get().getWindowManager()->
messageBox("VSync will be applied after a restart", std::vector<std::string>());
#endif
apply();
}
else
{

@ -2,6 +2,9 @@
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <iomanip>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
@ -169,13 +172,34 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->getGameSettingString(
ESM::Attribute::sGmstAttributeIds[effectIt->mKey.mArg], "") + ")";
if (!(effect->mData.mFlags & ESM::MagicEffect::NoMagnitude))
ESM::MagicEffect::MagnitudeDisplayType displayType = effect->getMagnitudeDisplayType();
if (displayType == ESM::MagicEffect::MDT_TimesInt)
{
std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", "");
std::stringstream formatter;
formatter << std::fixed << std::setprecision(1) << " " << (effectIt->mMagnitude / 10.0f) << timesInt;
sourcesDescription += formatter.str();
}
else if ( displayType != ESM::MagicEffect::MDT_None )
{
std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", "");
std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", "");
sourcesDescription += ": " + boost::lexical_cast<std::string>(effectIt->mMagnitude);
sourcesDescription += " " + ((effectIt->mMagnitude > 1) ? pts : pt);
if ( displayType == ESM::MagicEffect::MDT_Percentage )
sourcesDescription += MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", "");
else if ( displayType == ESM::MagicEffect::MDT_Feet )
sourcesDescription += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", "");
else if ( displayType == ESM::MagicEffect::MDT_Level )
{
sourcesDescription += " " + ((effectIt->mMagnitude > 1) ?
MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", "") :
MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", "") );
}
else // ESM::MagicEffect::MDT_Points
{
sourcesDescription += " " + ((effectIt->mMagnitude > 1) ?
MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", "") :
MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", "") );
}
}
}

@ -2,6 +2,9 @@
#include <boost/lexical_cast.hpp>
#include <sstream>
#include <iomanip>
#include <MyGUI_ProgressBar.h>
#include <MyGUI_ImageBox.h>
#include <MyGUI_ControllerManager.h>
@ -405,6 +408,10 @@ namespace MWGui
std::string pt = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoint", "");
std::string pts = MWBase::Environment::get().getWindowManager()->getGameSettingString("spoints", "");
std::string pct = MWBase::Environment::get().getWindowManager()->getGameSettingString("spercent", "");
std::string ft = MWBase::Environment::get().getWindowManager()->getGameSettingString("sfeet", "");
std::string lvl = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevel", "");
std::string lvls = MWBase::Environment::get().getWindowManager()->getGameSettingString("sLevels", "");
std::string to = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "") + " ";
std::string sec = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("ssecond", "");
std::string secs = " " + MWBase::Environment::get().getWindowManager()->getGameSettingString("sseconds", "");
@ -421,13 +428,32 @@ namespace MWGui
spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Attribute::sGmstAttributeIds[mEffectParams.mAttribute], "");
}
if ((mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude))
{
if (mEffectParams.mMagnMin == mEffectParams.mMagnMax)
spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin) + " " + ((mEffectParams.mMagnMin == 1) ? pt : pts);
else
{
spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin) + to + boost::lexical_cast<std::string>(mEffectParams.mMagnMax) + " " + pts;
if (mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) {
ESM::MagicEffect::MagnitudeDisplayType displayType = magicEffect->getMagnitudeDisplayType();
if ( displayType == ESM::MagicEffect::MDT_TimesInt ) {
std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", "");
std::stringstream formatter;
formatter << std::fixed << std::setprecision(1) << " " << (mEffectParams.mMagnMin / 10.0f);
if (mEffectParams.mMagnMin != mEffectParams.mMagnMax)
formatter << to << (mEffectParams.mMagnMax / 10.0f);
formatter << timesInt;
spellLine += formatter.str();
}
else if ( displayType != ESM::MagicEffect::MDT_None ) {
spellLine += " " + boost::lexical_cast<std::string>(mEffectParams.mMagnMin);
if (mEffectParams.mMagnMin != mEffectParams.mMagnMax)
spellLine += to + boost::lexical_cast<std::string>(mEffectParams.mMagnMax);
if ( displayType == ESM::MagicEffect::MDT_Percentage )
spellLine += pct;
else if ( displayType == ESM::MagicEffect::MDT_Feet )
spellLine += " " + ft;
else if ( displayType == ESM::MagicEffect::MDT_Level )
spellLine += " " + ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? lvl : lvls );
else // ESM::MagicEffect::MDT_Points
spellLine += " " + ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? pt : pts );
}
}

@ -61,20 +61,23 @@ namespace MWGui
const Compiler::Extensions& extensions, int fpsLevel, OEngine::Render::OgreRenderer *ogre,
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts,
Translation::Storage& translationDataStorage, ToUTF8::FromType encoding)
: mGuiManager(NULL)
, mConsoleOnlyScripts(consoleOnlyScripts)
: mConsoleOnlyScripts(consoleOnlyScripts)
, mGuiManager(NULL)
, mRendering(ogre)
, mHud(NULL)
, mMap(NULL)
, mMenu(NULL)
, mStatsWindow(NULL)
, mToolTips(NULL)
, mStatsWindow(NULL)
, mMessageBoxManager(NULL)
, mConsole(NULL)
, mJournal(NULL)
, mDialogueWindow(NULL)
, mBookWindow(NULL)
, mContainerWindow(NULL)
, mDragAndDrop(NULL)
, mInventoryWindow(NULL)
, mScrollWindow(NULL)
, mBookWindow(NULL)
, mCountDialog(NULL)
, mTradeWindow(NULL)
, mSpellBuyingWindow(NULL)
@ -83,27 +86,37 @@ namespace MWGui
, mConfirmationDialog(NULL)
, mAlchemyWindow(NULL)
, mSpellWindow(NULL)
, mQuickKeysMenu(NULL)
, mLoadingScreen(NULL)
, mCharGen(NULL)
, mLevelupDialog(NULL)
, mWaitDialog(NULL)
, mSpellCreationDialog(NULL)
, mEnchantingDialog(NULL)
, mTrainingWindow(NULL)
, mMerchantRepair(NULL)
, mRepair(NULL)
, mSoulgemDialog(NULL)
, mRepair(NULL)
, mCompanionWindow(NULL)
, mTranslationDataStorage (translationDataStorage)
, mSoftwareCursor(NULL)
, mCharGen(NULL)
, mInputBlocker(NULL)
, mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD"))
, mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI"))
, mHudEnabled(true)
, mCursorVisible(true)
, mPlayerName()
, mPlayerRaceId()
, mPlayerAttributes()
, mPlayerMajorSkills()
, mPlayerMinorSkills()
, mPlayerMajorSkills()
, mPlayerSkillValues()
, mPlayerHealth()
, mPlayerMagicka()
, mPlayerFatigue()
, mGui(NULL)
, mGuiModes()
, mCursorManager(NULL)
, mGarbageDialogs()
, mShown(GW_ALL)
, mForceHidden(GW_None)
@ -113,13 +126,7 @@ namespace MWGui
, mFPS(0.0f)
, mTriangleCount(0)
, mBatchCount(0)
, mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD"))
, mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI"))
, mHudEnabled(true)
, mTranslationDataStorage (translationDataStorage)
, mCursorManager(NULL)
, mUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI"))
, mCursorVisible(true)
{
// Set up the GUI system
mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath);

@ -577,15 +577,15 @@ namespace MWInput
rot[0] = -y;
rot[1] = 0.0f;
rot[2] = x;
// Only actually turn player when we're not in vanity mode
// Only actually turn player when we're not in vanity mode
if(!MWBase::Environment::get().getWorld()->vanityRotateCamera(rot))
{
mPlayer->yaw(x/scale);
mPlayer->pitch(-y/scale);
}
if (arg.zrel)
if (arg.zrel && mControlSwitch["playerviewswitch"]) //Check to make sure you are allowed to zoomout and there is a change
{
MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.zrel);
MWBase::Environment::get().getWorld()->setCameraDistance(arg.zrel, true, true);
@ -617,9 +617,15 @@ namespace MWInput
if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video)
MWBase::Environment::get().getWorld ()->stopVideo ();
else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu))
{
MWBase::Environment::get().getWindowManager()->popGuiMode();
MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx);
}
else
{
MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu);
MWBase::Environment::get().getSoundManager()->pauseSounds (MWBase::SoundManager::Play_TypeSfx);
}
}
void InputManager::toggleSpell()

@ -31,11 +31,14 @@ namespace MWMechanics
calculateDynamicStats (ptr);
calculateCreatureStatModifiers (ptr);
// AI
if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
{
// AI
CreatureStats& creatureStats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
creatureStats.getAiSequence().execute (ptr);
// fatigue restoration
calculateRestoration(ptr, duration);
}
}
@ -93,39 +96,29 @@ namespace MWMechanics
void Actors::calculateRestoration (const MWWorld::Ptr& ptr, float duration)
{
CreatureStats& stats = MWWorld::Class::get (ptr).getCreatureStats (ptr);
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
float capacity = MWWorld::Class::get(ptr).getCapacity(ptr);
float encumbrance = MWWorld::Class::get(ptr).getEncumbrance(ptr);
float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity);
if (normalizedEncumbrance > 1)
normalizedEncumbrance = 1;
if (duration == 3600)
{
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0;
// the actor is sleeping, restore health and magicka
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0;
DynamicStat<float> health = stats.getHealth();
health.setCurrent (health.getCurrent() + 0.1 * endurance);
stats.setHealth (health);
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
float fFatigueReturnBase = store.get<ESM::GameSetting>().find("fFatigueReturnBase")->getFloat ();
float fFatigueReturnMult = store.get<ESM::GameSetting>().find("fFatigueReturnMult")->getFloat ();
float fEndFatigueMult = store.get<ESM::GameSetting>().find("fEndFatigueMult")->getFloat ();
float capacity = MWWorld::Class::get(ptr).getCapacity(ptr);
float encumbrance = MWWorld::Class::get(ptr).getEncumbrance(ptr);
float normalizedEncumbrance = (capacity == 0 ? 1 : encumbrance/capacity);
if (normalizedEncumbrance > 1)
normalizedEncumbrance = 1;
float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
x *= fEndFatigueMult * endurance;
DynamicStat<float> fatigue = stats.getFatigue();
fatigue.setCurrent (fatigue.getCurrent() + 3600 * x);
stats.setFatigue (fatigue);
if (!stunted)
{
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat ();
float fRestMagicMult = settings.find("fRestMagicMult")->getFloat ();
DynamicStat<float> magicka = stats.getMagicka();
magicka.setCurrent (magicka.getCurrent()
@ -133,6 +126,19 @@ namespace MWMechanics
stats.setMagicka (magicka);
}
}
// restore fatigue
float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
float fEndFatigueMult = settings.find("fEndFatigueMult")->getFloat ();
float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
x *= fEndFatigueMult * endurance;
DynamicStat<float> fatigue = stats.getFatigue();
fatigue.setCurrent (fatigue.getCurrent() + duration * x);
stats.setFatigue (fatigue);
}
void Actors::calculateCreatureStatModifiers (const MWWorld::Ptr& ptr)
@ -275,9 +281,9 @@ namespace MWMechanics
continue;
}
// workaround: always keep player alive for now
// \todo remove workaround, once player death can be handled
if(iter->first.getRefData().getHandle()=="player")
// If it's the player and God Mode is turned on, keep it alive
if(iter->first.getRefData().getHandle()=="player" &&
MWBase::Environment::get().getWorld()->getGodModeState())
{
MWMechanics::DynamicStat<float> stat(stats.getHealth());

@ -767,10 +767,25 @@ void CharacterController::update(float duration)
}
if(sneak || inwater || flying)
{
vec.z = 0.0f;
mFallHeight = mPtr.getRefData().getPosition().pos[2];
}
if(!onground && !flying && !inwater)
{
// The player is in the air (either getting up —ascending part of jump— or falling).
if (world->isSlowFalling(mPtr))
{
// SlowFalling spell effect is active, do not keep previous fall height
mFallHeight = mPtr.getRefData().getPosition().pos[2];
}
else
{
mFallHeight = std::max(mFallHeight, mPtr.getRefData().getPosition().pos[2]);
}
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
forcestateupdate = (mJumpState != JumpState_Falling);
@ -794,6 +809,8 @@ void CharacterController::update(float duration)
}
else if(vec.z > 0.0f && mJumpState == JumpState_None)
{
// The player has started a jump.
float z = cls.getJump(mPtr);
if(vec.x == 0 && vec.y == 0)
vec = Ogre::Vector3(0.0f, 0.0f, z);
@ -803,13 +820,49 @@ void CharacterController::update(float duration)
vec = Ogre::Vector3(lat.x, lat.y, 1.0f) * z * 0.707f;
}
//decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult;
// advance acrobatics
cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0);
// decrease fatigue
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
const float fatigueJumpBase = gmst.find("fFatigueJumpBase")->getFloat();
const float fatigueJumpMult = gmst.find("fFatigueJumpMult")->getFloat();
const float normalizedEncumbrance = cls.getEncumbrance(mPtr) / cls.getCapacity(mPtr);
const int fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult;
DynamicStat<float> fatigue = cls.getCreatureStats(mPtr).getFatigue();
fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease);
cls.getCreatureStats(mPtr).setFatigue(fatigue);
}
else if(mJumpState == JumpState_Falling)
{
// The player is landing.
forcestateupdate = true;
mJumpState = JumpState_Landing;
vec.z = 0.0f;
float healthLost = cls.getFallDamage(mPtr, mFallHeight - mPtr.getRefData().getPosition().pos[2]);
if (healthLost > 0.0f)
{
const float fatigueTerm = cls.getCreatureStats(mPtr).getFatigueTerm();
// inflict fall damages
DynamicStat<float> health = cls.getCreatureStats(mPtr).getHealth();
int realHealthLost = healthLost * (1.0f - 0.25 * fatigueTerm);
health.setCurrent(health.getCurrent() - realHealthLost);
cls.getCreatureStats(mPtr).setHealth(health);
// report acrobatics progression
cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1);
const float acrobaticsSkill = cls.getNpcStats(mPtr).getSkill(ESM::Skill::Acrobatics).getModified();
if (healthLost > (acrobaticsSkill * fatigueTerm))
{
//TODO: actor falls over
}
}
mFallHeight = mPtr.getRefData().getPosition().pos[2];
}
else
{

@ -3,6 +3,8 @@
#include <OgreVector3.h>
#include <components/esm/loadmgef.hpp>
#include "../mwworld/ptr.hpp"
namespace MWWorld
@ -154,6 +156,9 @@ class CharacterController
float mSecondsOfSwimming;
float mSecondsOfRunning;
// used for acrobatics progress and fall damages
float mFallHeight;
std::string mAttackType; // slash, chop or thrust
void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false);

@ -151,8 +151,7 @@ namespace MWMechanics
for (Collection::const_iterator iter (prev.begin()); iter!=prev.end(); ++iter)
{
Collection::const_iterator other = now.mCollection.find (iter->first);
if (other==prev.end())
if (other==now.end())
{
result.add (iter->first, EffectParam() - iter->second);
}

@ -187,6 +187,12 @@ namespace MWRender
rotateCamera(Ogre::Vector3(getPitch(), 0.f, getYaw()), false);
}
void Camera::setSneakOffset()
{
if(mAnimation)
mAnimation->addFirstPersonOffset(Ogre::Vector3(0.f, 0.f, -9.8f));
}
float Camera::getYaw()
{
if(mVanity.enabled || mPreviewMode)

@ -79,6 +79,12 @@ namespace MWRender
void togglePreviewMode(bool enable);
/// \brief Lowers the camera for sneak.
/// As animation is tied to the camera, this needs
/// to be set each frame after the animation is
/// applied.
void setSneakOffset();
bool isFirstPerson() const
{ return !(mVanity.enabled || mPreviewMode || !mFirstPersonView); }

@ -84,7 +84,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
mWeapon(inv.end()),
mShield(inv.end()),
mViewMode(viewMode),
mShowWeapons(false)
mShowWeapons(false),
mFirstPersonOffset(0.f, 0.f, 0.f)
{
mNpc = mPtr.get<ESM::NPC>()->mBase;
@ -392,6 +393,11 @@ void NpcAnimation::updateParts(bool forceupdate)
}
}
void NpcAnimation::addFirstPersonOffset(const Ogre::Vector3 &offset)
{
mFirstPersonOffset += offset;
}
class SetObjectGroup {
int mGroup;
@ -448,7 +454,12 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
float pitch = mCamera->getPitch();
Ogre::Node *node = baseinst->getBone("Bip01 Neck");
node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD);
// This has to be done before this function ends;
// updateSkeletonInstance, below, touches the hands.
node->translate(mFirstPersonOffset, Ogre::Node::TS_WORLD);
}
mFirstPersonOffset = 0.f; // reset the X, Y, Z offset for the next frame.
for(size_t i = 0;i < ESM::PRT_Count;i++)
{

@ -64,6 +64,8 @@ private:
int mPartslots[ESM::PRT_Count]; //Each part slot is taken by clothing, armor, or is empty
int mPartPriorities[ESM::PRT_Count];
Ogre::Vector3 mFirstPersonOffset;
void updateNpcBase();
NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename);
@ -89,6 +91,11 @@ public:
void updateParts(bool forceupdate = false);
/// \brief Applies a translation to the arms and hands.
/// This may be called multiple times before the animation
/// is updated to add additional offsets.
void addFirstPersonOffset(const Ogre::Vector3 &offset);
/// Rebuilds the NPC, updating their root model, animation sources, and equipment.
void rebuild();
};

@ -354,6 +354,15 @@ void RenderingManager::update (float duration, bool paused)
mCamera->setCameraDistance(test.second * orig.distance(dest), false, false);
}
// Sink the camera while sneaking
bool isSneaking = MWWorld::Class::get(player).getStance(player, MWWorld::Class::Sneak);
bool isInAir = !world->isOnGround(player);
bool isSwimming = world->isSwimming(player);
if(isSneaking && !(isSwimming || isInAir))
mCamera->setSneakOffset();
mOcclusionQuery->update(duration);
mVideoPlayer->update ();
@ -760,6 +769,13 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
|| it->second == "resolution y"
|| it->second == "fullscreen"))
changeRes = true;
else if (it->first == "Video" && it->second == "vsync")
{
// setVSyncEnabled is bugged in 1.8
#if OGRE_VERSION >= (1 << 16 | 9 << 8 | 0)
mRendering.getWindow()->setVSyncEnabled(Settings::Manager::getBool("vsync", "Video"));
#endif
}
else if (it->second == "field of view" && it->first == "General")
mRendering.setFov(Settings::Manager::getFloat("field of view", "General"));
else if ((it->second == "texture filtering" && it->first == "General")

@ -352,5 +352,7 @@ op 0x200021c: SetWerewolfAcrobaticsExplicit
op 0x200021d: ShowVars
op 0x200021e: ShowVarsExplicit
op 0x200021f: ToggleGodMode
op 0x2000220: DisableLevitation
op 0x2000221: EnableLevitation
opcodes 0x2000220-0x3ffffff unused
opcodes 0x2000222-0x3ffffff unused

@ -635,7 +635,18 @@ namespace MWScript
world->enableTeleporting(Enable);
}
};
template <bool Enable>
class OpEnableLevitation : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
world->enableLevitation(Enable);
}
};
template <class R>
class OpShowVars : public Interpreter::Opcode0
@ -726,8 +737,7 @@ namespace MWScript
bool enabled = MWBase::Environment::get().getWorld()->toggleGodMode();
// context.report (enabled ? "God Mode -> On" : "God Mode -> Off");
context.report("Unimplemented");
context.report (enabled ? "God Mode -> On" : "God Mode -> Off");
}
};
@ -790,6 +800,8 @@ namespace MWScript
interpreter.installSegment5 (Compiler::Misc::opcodeShowVars, new OpShowVars<ImplicitRef>);
interpreter.installSegment5 (Compiler::Misc::opcodeShowVarsExplicit, new OpShowVars<ExplicitRef>);
interpreter.installSegment5 (Compiler::Misc::opcodeToggleGodMode, new OpToggleGodMode);
interpreter.installSegment5 (Compiler::Misc::opcodeDisableLevitation, new OpEnableLevitation<false>);
interpreter.installSegment5 (Compiler::Misc::opcodeEnableLevitation, new OpEnableLevitation<true>);
}
}
}

@ -167,6 +167,11 @@ namespace MWWorld
throw std::runtime_error ("class does not support enchanting");
}
float Class::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
{
return 0;
}
MWMechanics::Movement& Class::getMovementSettings (const Ptr& ptr) const
{
throw std::runtime_error ("movement settings not supported by class");

@ -175,6 +175,9 @@ namespace MWWorld
virtual float getJump(const MWWorld::Ptr &ptr) const;
///< Return jump velocity (not accounting for movement)
virtual float getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const;
///< Return amount of health points lost when falling
virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const;
///< Return desired movement.

@ -656,26 +656,38 @@ namespace MWWorld
return iterator(mSharedExt.end());
}
/// \todo implement appropriate index
// Return the northernmost cell in the easternmost column.
const ESM::Cell *searchExtByName(const std::string &id) const {
ESM::Cell *cell = 0;
std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin();
for (; it != mSharedExt.end(); ++it) {
if (Misc::StringUtils::ciEqual((*it)->mName, id)) {
return *it;
if ( cell == 0 ||
( (*it)->mData.mX > cell->mData.mX ) ||
( (*it)->mData.mX == cell->mData.mX && (*it)->mData.mY > cell->mData.mY ) )
{
cell = *it;
}
}
}
return 0;
return cell;
}
/// \todo implement appropriate index
// Return the northernmost cell in the easternmost column.
const ESM::Cell *searchExtByRegion(const std::string &id) const {
ESM::Cell *cell = 0;
std::vector<ESM::Cell *>::const_iterator it = mSharedExt.begin();
for (; it != mSharedExt.end(); ++it) {
if (Misc::StringUtils::ciEqual((*it)->mRegion, id)) {
return *it;
if ( cell == 0 ||
( (*it)->mData.mX > cell->mData.mX ) ||
( (*it)->mData.mX == cell->mData.mX && (*it)->mData.mY > cell->mData.mY ) )
{
cell = *it;
}
}
}
return 0;
return cell;
}
size_t getSize() const {

@ -170,7 +170,7 @@ namespace MWWorld
mSky (true), mCells (mStore, mEsm),
mActivationDistanceOverride (mActivationDistanceOverride),
mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true),
mFacedDistance(FLT_MAX)
mFacedDistance(FLT_MAX), mGodMode(false)
{
mPhysics = new PhysicsSystem(renderer);
mPhysEngine = mPhysics->getEngine();
@ -225,8 +225,8 @@ namespace MWWorld
if (mEsm[0].getFormat() == 0)
ensureNeededRecords();
mStore.movePlayerRecord();
mStore.setUp();
mStore.movePlayerRecord();
mGlobalVariables = new Globals (mStore);
@ -1582,6 +1582,19 @@ namespace MWWorld
return false;
}
bool
World::isSlowFalling(const MWWorld::Ptr &ptr) const
{
if(!ptr.getClass().isActor())
return false;
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
if(stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::SlowFall)).mMagnitude > 0)
return true;
return false;
}
bool World::isSubmerged(const MWWorld::Ptr &object) const
{
float *fpos = object.getRefData().getPosition().pos;
@ -1877,6 +1890,16 @@ namespace MWWorld
return mTeleportEnabled;
}
void World::enableLevitation(bool enable)
{
mLevitationEnabled = enable;
}
bool World::isLevitationEnabled() const
{
return mLevitationEnabled;
}
void World::setWerewolf(const MWWorld::Ptr& actor, bool werewolf)
{
MWMechanics::NpcStats& npcStats = Class::get(actor).getNpcStats(actor);
@ -1948,9 +1971,16 @@ namespace MWWorld
stats.getSkill(ESM::Skill::Acrobatics).setModified(gmst.find("fWerewolfAcrobatics")->getFloat(), 0);
}
bool World::getGodModeState()
{
return mGodMode;
}
bool World::toggleGodMode()
{
return false;
mGodMode = !mGodMode;
return mGodMode;
}
}

@ -68,6 +68,8 @@ namespace MWWorld
OEngine::Physic::PhysicEngine* mPhysEngine;
bool mGodMode;
// not implemented
World (const World&);
World& operator= (const World&);
@ -114,6 +116,7 @@ namespace MWWorld
int mPlayIntro;
bool mTeleportEnabled;
bool mLevitationEnabled;
public:
@ -353,6 +356,7 @@ namespace MWWorld
virtual void processChangedSettings(const Settings::CategorySettingVector& settings);
virtual bool isFlying(const MWWorld::Ptr &ptr) const;
virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const;
///Is the head of the creature underwater?
virtual bool isSubmerged(const MWWorld::Ptr &object) const;
virtual bool isSwimming(const MWWorld::Ptr &object) const;
@ -436,10 +440,18 @@ namespace MWWorld
/// Returns true if teleport spell effects are allowed.
virtual bool isTeleportingEnabled() const;
/// Enables or disables use of levitation spell effect.
virtual void enableLevitation(bool enable);
/// Returns true if levitation spell effect is allowed.
virtual bool isLevitationEnabled() const;
virtual void setWerewolf(const MWWorld::Ptr& actor, bool werewolf);
virtual void applyWerewolfAcrobatics(const MWWorld::Ptr& actor);
virtual bool getGodModeState();
virtual bool toggleGodMode();
};
}

@ -260,6 +260,8 @@ namespace Compiler
extensions.registerInstruction ("sv", "", opcodeShowVars, opcodeShowVarsExplicit);
extensions.registerInstruction("tgm", "", opcodeToggleGodMode);
extensions.registerInstruction("togglegodmode", "", opcodeToggleGodMode);
extensions.registerInstruction ("disablelevitation", "", opcodeDisableLevitation);
extensions.registerInstruction ("enablelevitation", "", opcodeEnableLevitation);
}
}

@ -222,6 +222,8 @@ namespace Compiler
const int opcodeShowVars = 0x200021d;
const int opcodeShowVarsExplicit = 0x200021e;
const int opcodeToggleGodMode = 0x200021f;
const int opcodeDisableLevitation = 0x2000220;
const int opcodeEnableLevitation = 0x2000221;
}
namespace Sky

@ -274,5 +274,23 @@ short MagicEffect::effectStringToId(const std::string &effect)
return name->first;
}
MagicEffect::MagnitudeDisplayType MagicEffect::getMagnitudeDisplayType() const {
if ( mData.mFlags & NoMagnitude )
return MDT_None;
if ( mIndex == 84 )
return MDT_TimesInt;
if ( mIndex == 59 ||
( mIndex >= 64 && mIndex <= 66) )
return MDT_Feet;
if ( mIndex == 118 || mIndex == 119 )
return MDT_Level;
if ( ( mIndex >= 28 && mIndex <= 36 )
|| ( mIndex >= 90 && mIndex <= 99 )
|| mIndex == 40 || mIndex == 47
|| mIndex == 57 || mIndex == 68 )
return MDT_Percentage;
return MDT_Points;
}
}

@ -32,6 +32,15 @@ struct MagicEffect
Negative = 0x0800 // A harmful effect. Will determine whether
// eg. NPCs regard this spell as an attack. (same as 0x10?)
};
enum MagnitudeDisplayType
{
MDT_None,
MDT_Feet,
MDT_Level,
MDT_Percentage,
MDT_Points,
MDT_TimesInt
};
struct MEDTstruct
{
@ -47,6 +56,7 @@ struct MagicEffect
static const std::string &effectIdToString(short effectID);
static short effectStringToId(const std::string &effect);
MagnitudeDisplayType getMagnitudeDisplayType() const;
MEDTstruct mData;

@ -425,7 +425,7 @@ void Node::getProperties(const Nif::NiTexturingProperty *&texprop,
Ogre::Matrix4 Node::getLocalTransform() const
{
Ogre::Matrix4 mat4(Ogre::Matrix4::IDENTITY);
Ogre::Matrix4 mat4 = Ogre::Matrix4(Ogre::Matrix4::IDENTITY);
mat4.makeTransform(trafo.pos, Ogre::Vector3(trafo.scale), Ogre::Quaternion(trafo.rotation));
return mat4;
}

@ -12,6 +12,7 @@ Marc Zinnschlag (Zini) - Lead Programmer/Project Manager
Adam Hogan (aurix)
Aleksandar Jovanov
Alex Haddad (rainChu)
Alex McKibben (WeirdSexy)
Alexander Nadeau (wareya)
Alexander Olofsson (Ace)
@ -47,6 +48,7 @@ Marc Bouvier (CramitDeFrog)
Marcin Hulist (Gohan)
Mark Siewert (mark76)
Mateusz Kołaczek (PL_kolek)
Michael Hogan (Xethik)
Michael Mc Donnell
Michael Papageorgiou (werdanith)
Michał Bień (Glorf)
@ -61,6 +63,7 @@ Roman Proskuryakov (humbug)
Sandy Carter (bwrsandman)
Sebastian Wick (swick)
Sergey Shambir
sir_herrbatka
Sylvain Thesnieres (Garvek)
Tom Mason (wheybags)
Torben Leif Carrington (TorbenC)

@ -30,9 +30,6 @@ namespace SFO
InputWrapper::~InputWrapper()
{
if(mSDLWindow != NULL)
SDL_DestroyWindow(mSDLWindow);
mSDLWindow = NULL;
}
void InputWrapper::capture(bool windowEventsOnly)

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 615 B

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

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

Loading…
Cancel
Save