diff --git a/CMakeLists.txt b/CMakeLists.txt index 6fb0ee34c0..370b499e6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -434,7 +434,7 @@ if (APPLE) install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) - install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) + set(CPACK_GENERATOR "DragNDrop") set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION}) set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR}) diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index 319bbbc576..f0e5eba948 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -84,5 +84,5 @@ else() "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.qss") configure_file(${CMAKE_SOURCE_DIR}/files/launcher.cfg - "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.cfg") + "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}launcher.cfg") endif() diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index b88664f0cc..c954468080 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -1,8 +1,6 @@ #include #include -#include -#include #include #include "datafilespage.hpp" @@ -120,11 +118,12 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, QWidget *parent) connect(mPluginsTable, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(setCheckState(QModelIndex))); connect(mPluginsTable, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&))); + connect(mProfilesComboBox, SIGNAL(textChanged(const QString&, const QString&)), this, SLOT(profileChanged(const QString&, const QString&))); - + createActions(); setupConfig(); setupDataFiles(); - createActions(); + } void DataFilesPage::setupConfig() @@ -138,8 +137,7 @@ void DataFilesPage::setupConfig() // Open our config file mLauncherConfig = new QSettings(config, QSettings::IniFormat); - mLauncherConfig->sync(); - + file.close(); // Make sure we have no groups open while (!mLauncherConfig->group().isEmpty()) { @@ -162,13 +160,14 @@ void DataFilesPage::setupConfig() // No current profile selected currentProfile = "Default"; } - mProfilesComboBox->setCurrentIndex(mProfilesComboBox->findText(currentProfile)); + + const int currentIndex = mProfilesComboBox->findText(currentProfile); + if (currentIndex != -1) { + // Profile is found + mProfilesComboBox->setCurrentIndex(currentIndex); + } mLauncherConfig->endGroup(); - - // Now we connect the combobox to do something if the profile changes - // This prevents strange behaviour while reading and appending the profiles - connect(mProfilesComboBox, SIGNAL(textChanged(const QString&, const QString&)), this, SLOT(profileChanged(const QString&, const QString&))); } @@ -188,18 +187,56 @@ void DataFilesPage::setupDataFiles() // Put the paths in a boost::filesystem vector to use with Files::Collections Files::PathContainer dataDirs(variables["data"].as()); + mDataDirs = dataDirs; -// std::string local(variables["data-local"].as()); -// if (!local.empty()) -// { -// dataDirs.push_back(Files::PathContainer::value_type(local)); -// } +// std::string local = variables["data-local"].as(); +// if (!local.empty()) { +// mDataLocal.push_back(Files::PathContainer::value_type(local)); +// dataDirs.push_back(Files::PathContainer::value_type(local)); +// } if (dataDirs.size()>1) dataDirs.resize (1); mCfgMgr.processPaths(dataDirs); + while (dataDirs.empty()) { + // No valid data files directory found + + QMessageBox msgBox; + msgBox.setWindowTitle("Error detecting Morrowind installation"); + msgBox.setIcon(QMessageBox::Critical); + msgBox.setStandardButtons(QMessageBox::Cancel); + msgBox.setText(tr("
Could not find the Data Files location

\ + The directory containing the Data Files was not found.

\ + Press \"Browse...\" to specify the location manually.
")); + + QAbstractButton *dirSelectButton = + msgBox.addButton(tr("B&rowse..."), QMessageBox::ActionRole); + + msgBox.exec(); + + if (msgBox.clickedButton() == dirSelectButton) { + + QString dataDir = QFileDialog::getExistingDirectory( + this, tr("Select Data Files Directory"), + "/home", + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + dataDirs.push_back(Files::PathContainer::value_type(dataDir.toStdString())); + mDataDirs.push_back(Files::PathContainer::value_type(dataDir.toStdString())); + } else { + // Cancel + break; + } + } + + // Check if cancel was clicked because we can't exit from while loop + if (dataDirs.empty()) { + QApplication::exit(1); + return; + } + // Create a file collection for the dataDirs Files::Collections fileCollections(dataDirs, !variables["fs-strict"].as()); @@ -207,15 +244,13 @@ void DataFilesPage::setupDataFiles() const Files::MultiDirCollection &esm = fileCollections.getCollection(".esm"); unsigned int i = 0; // Row number - for (Files::MultiDirCollection::TIter iter(esm.begin()); iter!=esm.end(); ++iter) - { + for (Files::MultiDirCollection::TIter iter(esm.begin()); iter!=esm.end(); ++iter) { QString currentMaster = QString::fromStdString( boost::filesystem::path (iter->second.filename()).string()); const QList itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly); - if (itemList.isEmpty()) // Master is not yet in the widget - { + if (itemList.isEmpty()) { // Master is not yet in the widget mMastersWidget->insertRow(i); QTableWidgetItem *item = new QTableWidgetItem(currentMaster); mMastersWidget->setItem(i, 0, item); @@ -226,8 +261,7 @@ void DataFilesPage::setupDataFiles() // Now on to the plugins const Files::MultiDirCollection &esp = fileCollections.getCollection(".esp"); - for (Files::MultiDirCollection::TIter iter(esp.begin()); iter!=esp.end(); ++iter) - { + for (Files::MultiDirCollection::TIter iter(esp.begin()); iter!=esp.end(); ++iter) { ESMReader fileReader; QStringList availableMasters; // Will contain all found masters @@ -243,8 +277,7 @@ void DataFilesPage::setupDataFiles() const QList itemList = mMastersWidget->findItems(currentMaster, Qt::MatchExactly); - if (itemList.isEmpty()) // Master is not yet in the widget - { + if (itemList.isEmpty()) { // Master is not yet in the widget mMastersWidget->insertRow(i); QTableWidgetItem *item = new QTableWidgetItem(currentMaster); @@ -433,18 +466,18 @@ void DataFilesPage::deleteProfile() return; } - QMessageBox deleteMessageBox(this); - deleteMessageBox.setWindowTitle(tr("Delete Profile")); - deleteMessageBox.setText(tr("Are you sure you want to delete %0?").arg(profile)); - deleteMessageBox.setIcon(QMessageBox::Warning); + QMessageBox msgBox(this); + msgBox.setWindowTitle(tr("Delete Profile")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Cancel); + msgBox.setText(tr("Are you sure you want to delete %0?").arg(profile)); + QAbstractButton *deleteButton = - deleteMessageBox.addButton(tr("Delete"), QMessageBox::ActionRole); + msgBox.addButton(tr("Delete"), QMessageBox::ActionRole); - deleteMessageBox.addButton(QMessageBox::Cancel); + msgBox.exec(); - deleteMessageBox.exec(); - - if (deleteMessageBox.clickedButton() == deleteButton) { + if (msgBox.clickedButton() == deleteButton) { // Make sure we have no groups open while (!mLauncherConfig->group().isEmpty()) { mLauncherConfig->endGroup(); @@ -501,7 +534,6 @@ void DataFilesPage::moveUp() void DataFilesPage::moveDown() { // Shift the selected plugins down one row - if (!mPluginsTable->selectionModel()->hasSelection()) { return; } @@ -917,9 +949,18 @@ void DataFilesPage::filterChanged(const QString filter) void DataFilesPage::profileChanged(const QString &previous, const QString ¤t) { + // Prevent the deletion of the default profile + if (current == "Default") { + mDeleteProfileAction->setEnabled(false); + } else { + mDeleteProfileAction->setEnabled(true); + } + if (!previous.isEmpty()) { writeConfig(previous); mLauncherConfig->sync(); + } else { + return; } uncheckPlugins(); @@ -992,14 +1033,6 @@ void DataFilesPage::writeConfig(QString profile) return; } - if (profile.isEmpty()) { - profile = mProfilesComboBox->currentText(); - } - - if (profile.isEmpty()) { - return; - } - // Prepare the OpenMW config QString config = QString::fromStdString((mCfgMgr.getLocalPath() / "openmw.cfg").string()); QFile file(config); @@ -1028,10 +1061,14 @@ void DataFilesPage::writeConfig(QString profile) QTextStream in(&file); QByteArray buffer; - // Remove all previous master/plugin entries from config + // Remove all previous entries from config while (!in.atEnd()) { QString line = in.readLine(); - if (!line.contains("master") && !line.contains("plugin")) { + if (!line.startsWith("master") && + !line.startsWith("plugin") && + !line.startsWith("data") && + !line.startsWith("data-local")) + { buffer += line += "\n"; } } @@ -1052,9 +1089,52 @@ void DataFilesPage::writeConfig(QString profile) return; } - file.write(buffer); + if (!buffer.isEmpty()) { + file.write(buffer); + } + QTextStream gameConfig(&file); + // First write the list of data dirs + mCfgMgr.processPaths(mDataDirs); + mCfgMgr.processPaths(mDataLocal); + + QString path; + + // data= directories + for (Files::PathContainer::iterator it = mDataDirs.begin(); it != mDataDirs.end(); ++it) { + path = QString::fromStdString(it->string()); + path.remove(QChar('\"')); + + // Make sure the string is quoted when it contains spaces + if (path.contains(" ")) { + gameConfig << "data=\"" << path << "\"" << endl; + } else { + gameConfig << "data=" << path << endl; + } + } + + // data-local directory + if (!mDataLocal.empty()) { + path = QString::fromStdString(mDataLocal.front().string()); + path.remove(QChar('\"')); + + if (path.contains(" ")) { + gameConfig << "data-local=\"" << path << "\"" << endl; + } else { + gameConfig << "data-local=" << path << endl; + } + } + + + if (profile.isEmpty()) { + profile = mProfilesComboBox->currentText(); + } + + if (profile.isEmpty()) { + return; + } + // Make sure we have no groups open while (!mLauncherConfig->group().isEmpty()) { mLauncherConfig->endGroup(); @@ -1067,7 +1147,7 @@ void DataFilesPage::writeConfig(QString profile) mLauncherConfig->beginGroup(profile); mLauncherConfig->remove(""); // Clear the subgroup - // First write the masters to the configs + // Now write the masters to the configs const QStringList masters = selectedMasters(); // We don't use foreach because we need i @@ -1079,11 +1159,10 @@ void DataFilesPage::writeConfig(QString profile) } - // Now write all checked plugins + // And finally write all checked plugins const QStringList plugins = checkedPlugins(); - for (int i = 0; i < plugins.size(); ++i) - { + for (int i = 0; i < plugins.size(); ++i) { const QString currentPlugin = plugins.at(i); mLauncherConfig->setValue(QString("Plugin%1").arg(i), currentPlugin); gameConfig << "plugin=" << currentPlugin << endl; diff --git a/apps/launcher/datafilespage.hpp b/apps/launcher/datafilespage.hpp index a454fa871b..ad5e90511c 100644 --- a/apps/launcher/datafilespage.hpp +++ b/apps/launcher/datafilespage.hpp @@ -3,6 +3,9 @@ #include #include + +#include + #include "combobox.hpp" class QTableWidget; @@ -77,6 +80,8 @@ private: QAction *mUncheckAction; Files::ConfigurationManager &mCfgMgr; + Files::PathContainer mDataDirs; + Files::PathContainer mDataLocal; QSettings *mLauncherConfig; diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index aaa54dd7fc..b7d397f067 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -246,13 +246,7 @@ void GraphicsPage::setupOgre() if (mOpenGLRenderSystem) { mOGLRTTComboBox->addItems(getAvailableOptions(QString("RTT Preferred Mode"), mOpenGLRenderSystem)); mOGLAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mOpenGLRenderSystem)); - - QStringList videoModes = getAvailableOptions(QString("Video Mode"), mOpenGLRenderSystem); - // Remove extraneous spaces - videoModes.replaceInStrings(QRegExp("\\s{2,}"), QString(" ")); - videoModes.replaceInStrings(QRegExp("^\\s"), QString()); - - mOGLResolutionComboBox->addItems(videoModes); + mOGLResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mOpenGLRenderSystem)); mOGLFrequencyComboBox->addItems(getAvailableOptions(QString("Display Frequency"), mOpenGLRenderSystem)); } @@ -261,12 +255,7 @@ void GraphicsPage::setupOgre() mD3DRenderDeviceComboBox->addItems(getAvailableOptions(QString("Rendering Device"), mDirect3DRenderSystem)); mD3DAntiAliasingComboBox->addItems(getAvailableOptions(QString("FSAA"), mDirect3DRenderSystem)); mD3DFloatingPointComboBox->addItems(getAvailableOptions(QString("Floating-point mode"), mDirect3DRenderSystem)); - - QStringList videoModes = getAvailableOptions(QString("Video Mode"), mDirect3DRenderSystem); - // Remove extraneous spaces - videoModes.replaceInStrings(QRegExp("\\s{2,}"), QString(" ")); - videoModes.replaceInStrings(QRegExp("^\\s"), QString()); - mD3DResolutionComboBox->addItems(videoModes); + mD3DResolutionComboBox->addItems(getAvailableOptions(QString("Video Mode"), mDirect3DRenderSystem)); } } @@ -482,7 +471,7 @@ QStringList GraphicsPage::getAvailableOptions(const QString &key, Ogre::RenderSy { if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) - result << (*opt_it).c_str(); + result << QString::fromStdString((*opt_it).c_str()).simplified(); } } diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index b8bd588c4b..1b324459a5 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -658,9 +658,15 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) if (weather.mNight && mStarsOpacity != weather.mNightFade) { - for (int i=0; i<7; ++i) - mStarsMaterials[i]->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, weather.mNightFade); - mStarsOpacity = weather.mNightFade; + if (weather.mNightFade == 0) + mAtmosphereNight->setVisible(false); + else + { + mAtmosphereNight->setVisible(true); + for (int i=0; i<7; ++i) + mStarsMaterials[i]->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, weather.mNightFade); + mStarsOpacity = weather.mNightFade; + } } float strength; diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 76ef23bc2a..6795eff195 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -410,7 +410,12 @@ namespace MWSound if(useSound) { - mData = new SoundImpl(root, camera, store, dataDirs /* Sound */, dataDirs /* Music */, fsstrict); + Files::PathContainer soundDirs;; + for (Files::PathContainer::const_iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) + { + soundDirs.push_back( *it / std::string("Sound")); + } + mData = new SoundImpl(root, camera, store, soundDirs /* Sound */, dataDirs /* Music */, fsstrict); } test.name = ""; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 7cb9f3dfc6..059b0ec1e2 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -758,7 +758,7 @@ unsigned int WeatherManager::getWeatherID() const return 3; else if (mCurrentWeather == "rain") return 4; - else if (mCurrentWeather == "thunder") + else if (mCurrentWeather == "thunderstorm") return 5; else if (mCurrentWeather == "ashstorm") return 6; @@ -787,7 +787,7 @@ void WeatherManager::changeWeather(const std::string& region, const unsigned int else if (id==4) weather = "rain"; else if (id==5) - weather = "thunder"; + weather = "thunderstorm"; else if (id==6) weather = "ashstorm"; else if (id==7) diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 8b55400193..1c23b55c06 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -243,6 +243,8 @@ void NIFLoader::createMaterial(const String &name, /*TextureUnitState *txt =*/ pass->createTextureUnitState(texName); + pass->setVertexColourTracking(TVC_DIFFUSE); + // As of yet UNTESTED code from Chris: /*pass->setTextureFiltering(Ogre::TFO_ANISOTROPIC); pass->setDepthFunction(Ogre::CMPF_LESS_EQUAL);