diff --git a/README.md b/README.md index f62800e1fd..95380e39b5 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 1f16c9695b..a4fe98de9a 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 c75a3c2a12..dec9ee083d 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 4e608dbbde..24414db641 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 64d317bd41..d723ddaacd 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 7737e62c05..2cc6e43ea2 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 2a710a9400..e8bc0d632e 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 df77399417..85f6f8ac94 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 f63c451092..41f88e8683 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 970490828f..e2a794f2cc 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 836e8ac7dc..5de5f71d0b 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 14ad24b292..57b5b0312c 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 1da9878ea8..179f799c00 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);