diff --git a/README.md b/README.md index f62800e1f..95380e39b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,11 @@ Morrowind by Bethesda Softworks. You need to own and install the original game f Font Licenses: * DejaVuLGCSansMono.ttf: custom (see docs/license/DejaVu Font License.txt for more information) +Wrong Way, Go Back +------------------ + +This is a fork of an old version of OpenMW. This version is probably not what you are looking for. It is still stuck on Ogre 1.9 and hence does not have any of the recent graphics enhancements. I suggest you use the [official release](https://github.com/OpenMW/openmw) instead. + Getting Started --------------- @@ -97,3 +102,26 @@ Command line options --export-fonts [=arg(=1)] (=0) Export Morrowind .fnt fonts to PNG image and XML file in current directory --activate-dist arg (=-1) activation distance override + +Changes +------- + +Some of the differences with the official release are listed below. They are almost all to do with OpenCS. + +* Various minor bug fixes. +* Experimental support of loading TES4/TES5 records (coming soon). +* Experimental support of navMesh (coming soon). +* C++11 features are used (or at least those available on MSVC 2013 onwards). +* Loading time improvements. +* Loading progress bar changes. +* Pathgrid points supported. +* 3D editing retained, but does not have OSG enhancements or mouse modes. +* Modifying an object in the cell view should trigger the instances table to scroll to the corresponding record. +* Initial support for Land and Land Texture records. +* NPC stats autocalculation. +* Per-subview shortcuts for "added" and "modified" filters. +* Global filters + warning splash screen. +* User preferences setting to save the window state (position, geometry, etc) at the time of exit. +* User preferences setting to workaround some X window managers not keeping pre-maximised state. +* Use opencs.ini to store window states between sessions. + diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index 1f16c9695..a4fe98de9 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -103,7 +103,8 @@ bool CSMWorld::ColumnBase::isId (Display display) bool CSMWorld::ColumnBase::isText (Display display) { return display==Display_String || display==Display_LongString || - display==Display_String32 || display==Display_LongString256; + display==Display_String32 || display==Display_String64 || + display==Display_LongString256; } bool CSMWorld::ColumnBase::isScript (Display display) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index c75a3c2a1..dec9ee083 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -129,6 +129,7 @@ namespace CSMWorld Display_InfoCondVar, Display_InfoCondComp, Display_String32, + Display_String64, Display_LongString256, Display_EffectSkill, // must display at least one, unlike Display_Skill diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 4e608dbbd..24414db64 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -317,7 +317,8 @@ namespace CSMWorld template struct NameColumn : public Column { - NameColumn() : Column (Columns::ColumnId_Name, ColumnBase::Display_String) {} + NameColumn(ColumnBase::Display display = ColumnBase::Display_String) + : Column (Columns::ColumnId_Name, display) {} virtual QVariant get (const Record& record) const { diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 64d317bd4..d723ddaac 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -3,6 +3,8 @@ #include #include +#include + #include #include @@ -105,7 +107,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mFactions.addColumn (new StringIdColumn); mFactions.addColumn (new RecordStateColumn); mFactions.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Faction)); - mFactions.addColumn (new NameColumn); + // The savegame format limits the player faction string to 32 characters. + mFactions.addColumn (new NameColumn(ColumnBase::Display_String32)); mFactions.addColumn (new AttributesColumn (0)); mFactions.addColumn (new AttributesColumn (1)); mFactions.addColumn (new HiddenColumn); @@ -115,6 +118,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mFactions.addColumn (new NestedParentColumn (Columns::ColumnId_FactionReactions)); index = mFactions.getColumns()-1; mFactions.addAdapter (std::make_pair(&mFactions.getColumn(index), new FactionReactionsAdapter ())); + // NAME32 enforced in IdCompletionDelegate::createEditor() mFactions.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction)); mFactions.getNestableColumn(index)->addColumn( @@ -183,6 +187,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc index = mRegions.getColumns()-1; mRegions.addAdapter (std::make_pair(&mRegions.getColumn(index), new RegionSoundListAdapter ())); mRegions.getNestableColumn(index)->addColumn( + // NAME32 enforced in IdCompletionDelegate::createEditor() new NestedChildColumn (Columns::ColumnId_SoundName, ColumnBase::Display_Sound)); mRegions.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_SoundChance, ColumnBase::Display_Integer)); @@ -289,7 +294,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mCells.addColumn (new StringIdColumn); mCells.addColumn (new RecordStateColumn); mCells.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Cell)); - mCells.addColumn (new NameColumn); + // NAME64 enforced in IdCompletionDelegate::createEditor() + mCells.addColumn (new NameColumn(ColumnBase::Display_String64)); mCells.addColumn (new FlagColumn (Columns::ColumnId_SleepForbidden, ESM::Cell::NoSleep)); mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); @@ -905,9 +911,12 @@ int CSMWorld::Data::getTotalRecords (const std::vector& for (unsigned int i = 0; i < files.size(); ++i) { - reader->open(files[i].string()); - records += reader->getRecordCount(); - reader->close(); + if (boost::filesystem::exists(files[i].string())) + { + reader->open(files[i].string()); + records += reader->getRecordCount(); + reader->close(); + } } return records; @@ -1113,7 +1122,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) else { mTopics.load (record, mBase); - mDialogue = &mTopics.getRecord (record.mId).get(); + mDialogue = &mTopics.getRecord (record.mId).get(); } } diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 7737e62c0..2cc6e43ea 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -58,8 +58,11 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) NameColumns nameColumns (modelColumns); - mColumns.push_back (RefIdColumn (Columns::ColumnId_Name, ColumnBase::Display_String)); + // Only items that can be placed in a container have the 32 character limit, but enforce + // that for all referenceable types for now. + mColumns.push_back (RefIdColumn (Columns::ColumnId_Name, ColumnBase::Display_String32)); nameColumns.mName = &mColumns.back(); + // NAME32 enforced in IdCompletionDelegate::createEditor() mColumns.push_back (RefIdColumn (Columns::ColumnId_Script, ColumnBase::Display_Script)); nameColumns.mScript = &mColumns.back(); @@ -239,9 +242,9 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_AiWanderRepeat, CSMWorld::ColumnBase::Display_Boolean)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_AiActivateName, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_AiActivateName, CSMWorld::ColumnBase::Display_String32)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_AiTargetId, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_AiTargetId, CSMWorld::ColumnBase::Display_String32)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_AiTargetCell, CSMWorld::ColumnBase::Display_String)); mColumns.back().addColumn( @@ -486,6 +489,7 @@ CSMWorld::RefIdCollection::RefIdCollection(const CSMWorld::Data& data) mColumns.push_back (RefIdColumn (Columns::ColumnId_Class, ColumnBase::Display_Class)); npcColumns.mClass = &mColumns.back(); + // NAME32 enforced in IdCompletionDelegate::createEditor() mColumns.push_back (RefIdColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction)); npcColumns.mFaction = &mColumns.back(); diff --git a/apps/opencs/view/world/cellcreator.cpp b/apps/opencs/view/world/cellcreator.cpp index 2a710a940..e8bc0d632 100644 --- a/apps/opencs/view/world/cellcreator.cpp +++ b/apps/opencs/view/world/cellcreator.cpp @@ -84,6 +84,13 @@ void CSVWorld::CellCreator::setType (int index) mYLabel->setVisible (index==1); mY->setVisible (index==1); + // The cell name is limited to 64 characters. (ESM::Header::GMDT::mCurrentCell) + std::string text = mType->currentText().toStdString(); + if (text == "Interior Cell") + GenericCreator::setEditorMaxLength (64); + else + GenericCreator::setEditorMaxLength (32767); + update(); } @@ -92,7 +99,7 @@ void CSVWorld::CellCreator::valueChanged (int index) update(); } -void CSVWorld::CellCreator::cloneMode(const std::string& originId, +void CSVWorld::CellCreator::cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type) { CSVWorld::GenericCreator::cloneMode(originId, type); diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index df7739941..85f6f8ac9 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -174,6 +174,11 @@ CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undo connect (&mData, SIGNAL (idListChanged()), this, SLOT (dataIdListChanged())); } +void CSVWorld::GenericCreator::setEditorMaxLength (int length) +{ + mId->setMaxLength (length); +} + void CSVWorld::GenericCreator::setEditLock (bool locked) { mLocked = locked; diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index f63c45109..41f88e868 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -78,6 +78,8 @@ namespace CSVWorld std::string getNamespace() const; + void setEditorMaxLength(int length); + private: void updateNamespace(); diff --git a/apps/opencs/view/world/idcompletiondelegate.cpp b/apps/opencs/view/world/idcompletiondelegate.cpp index 970490828..e2a794f2c 100644 --- a/apps/opencs/view/world/idcompletiondelegate.cpp +++ b/apps/opencs/view/world/idcompletiondelegate.cpp @@ -30,11 +30,27 @@ QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager(); CSVWidget::DropLineEdit *editor = new CSVWidget::DropLineEdit(display, parent); editor->setCompleter(completionManager.getCompleter(display).get()); + // The savegame format limits the player faction string to 32 characters. + // The region sound name is limited to 32 characters. (ESM::Region::SoundRef::mSound) + // The script name is limited to 32 characters. (ESM::Script::SCHD::mName) + // The cell name is limited to 64 characters. (ESM::Header::GMDT::mCurrentCell) + if (display == CSMWorld::ColumnBase::Display_Faction || + display == CSMWorld::ColumnBase::Display_Sound || + display == CSMWorld::ColumnBase::Display_Script || + display == CSMWorld::ColumnBase::Display_Referenceable) + { + editor->setMaxLength (32); + } + else if (display == CSMWorld::ColumnBase::Display_Cell) + { + editor->setMaxLength (64); + } + return editor; } CSVWorld::CommandDelegate *CSVWorld::IdCompletionDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, - CSMDoc::Document& document, + CSMDoc::Document& document, QObject *parent) const { return new IdCompletionDelegate(dispatcher, document, parent); diff --git a/apps/opencs/view/world/referenceablecreator.cpp b/apps/opencs/view/world/referenceablecreator.cpp index 836e8ac7d..5de5f71d0 100644 --- a/apps/opencs/view/world/referenceablecreator.cpp +++ b/apps/opencs/view/world/referenceablecreator.cpp @@ -33,6 +33,8 @@ CSVWorld::ReferenceableCreator::ReferenceableCreator (CSMWorld::Data& data, QUnd } insertBeforeButtons (mType, false); + + connect (mType, SIGNAL (currentIndexChanged (int)), this, SLOT (setType (int))); } void CSVWorld::ReferenceableCreator::reset() @@ -53,3 +55,27 @@ void CSVWorld::ReferenceableCreator::toggleWidgets(bool active) CSVWorld::GenericCreator::toggleWidgets(active); mType->setEnabled(active); } + +void CSVWorld::ReferenceableCreator::setType (int index) +{ + // container items have name limit of 32 characters + std::string text = mType->currentText().toStdString(); + if (text == "Potion" || + text == "Apparatus" || + text == "Armor" || + text == "Book" || + text == "Clothing" || + text == "Ingredient" || + text == "ItemLevelledList" || + text == "Light" || + text == "Lockpick" || + text == "Miscellaneous" || + text == "Probe" || + text == "Repair" || + text == "Weapon") + { + GenericCreator::setEditorMaxLength (32); + } + else + GenericCreator::setEditorMaxLength (32767); +} diff --git a/apps/opencs/view/world/referenceablecreator.hpp b/apps/opencs/view/world/referenceablecreator.hpp index 14ad24b29..57b5b0312 100644 --- a/apps/opencs/view/world/referenceablecreator.hpp +++ b/apps/opencs/view/world/referenceablecreator.hpp @@ -29,6 +29,9 @@ namespace CSVWorld virtual void toggleWidgets(bool active = true); + private slots: + + void setType (int index); }; } diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 1da9878ea..179f799c0 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -261,7 +261,15 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO widget->setMaxLength (32); return widget; } - + + case CSMWorld::ColumnBase::Display_String64: + { + // For other Display types (that represent record IDs) with drop support IdCompletionDelegate is used + CSVWidget::DropLineEdit *widget = new CSVWidget::DropLineEdit(display, parent); + widget->setMaxLength (64); + return widget; + } + default: return QStyledItemDelegate::createEditor (parent, option, index);