diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bdd8b21c..e1b8e32e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ include (OpenMWMacros) # Version set (OPENMW_VERSION_MAJOR 0) -set (OPENMW_VERSION_MINOR 21) +set (OPENMW_VERSION_MINOR 22) set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") @@ -257,10 +257,10 @@ set_directory_properties(PROPERTIES COMPILE_DEFINITIONS_DEBUG DEBUG=1) # Set up Ogre plugin folder & debug suffix if (APPLE) - # Ogre on OS X doesn't use "_d" suffix (see Ogre's CMakeLists.txt) - add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="") + # Ogre on OS X doesn't use "_d" suffix (see Ogre's CMakeLists.txt) + add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="") else () - add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d") + add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d") endif() add_definitions(-DOGRE_PLUGIN_DIR_REL="${OGRE_PLUGIN_DIR_REL}") @@ -278,9 +278,9 @@ add_subdirectory(files/mygui) # Specify build paths if (APPLE) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS") else (APPLE) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}") endif (APPLE) # Other files @@ -334,7 +334,7 @@ if(DPKG_PROGRAM) #Install icon and desktop file INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "share/applications/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") - INSTALL(FILES "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.png" DESTINATION "share/pixmaps/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "share/pixmaps/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") #Install global configuration files INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "../etc/openmw/" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw") @@ -355,7 +355,7 @@ if(DPKG_PROGRAM) Data files from the original game is required to run it.") SET(CPACK_DEBIAN_PACKAGE_NAME "openmw") SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}") - SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW bsatool;Bsatool esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter") + SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW bsatool;Bsatool esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)") SET(CPACK_DEBIAN_PACKAGE_SECTION "Games") @@ -384,6 +384,7 @@ if(WIN32) "${OpenMW_SOURCE_DIR}/Daedric Font License.txt" "${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" + "${OpenMW_BINARY_DIR}/Release/mwiniimport.exe" "${OpenMW_BINARY_DIR}/Release/omwlauncher.exe" "${OpenMW_BINARY_DIR}/Release/openmw.exe" DESTINATION ".") @@ -409,8 +410,8 @@ if(WIN32) SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org") SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org") SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe") - SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.ico") - SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.ico") + SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.ico") + SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.ico") SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp") SET(VCREDIST32 "${OpenMW_BINARY_DIR}/vcredist_x86.exe") @@ -510,10 +511,10 @@ if (WIN32) 4986 # Undocumented warning that occurs in the crtdbg.h file 4996 # Function was declared deprecated - # cause by ogre extensivly - 4193 # #pragma warning(pop) : no matching '#pragma warning(push)' - 4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY' - 4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY' + # cause by ogre extensivly + 4193 # #pragma warning(pop) : no matching '#pragma warning(push)' + 4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY' + 4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY' # OpenMW specific warnings 4099 # Type mismatch, declared class or struct is defined with other type @@ -525,7 +526,7 @@ if (WIN32) 4309 # Variable overflow, trying to store 128 in a signed char for example 4355 # Using 'this' in member initialization list 4701 # Potentially uninitialized local variable used - 4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt + 4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt ) foreach(d ${WARNINGS_DISABLE}) @@ -536,12 +537,12 @@ if (WIN32) set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS}) if (BUILD_LAUNCHER) - set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS}) - endif (BUILD_LAUNCHER) + set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS}) + endif (BUILD_LAUNCHER) set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS}) - if (BUILD_BSATOOL) + if (BUILD_BSATOOL) set_target_properties(bsatool PROPERTIES COMPILE_FLAGS ${WARNINGS}) - endif (BUILD_BSATOOL) + endif (BUILD_BSATOOL) if (BUILD_ESMTOOL) set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS}) endif (BUILD_ESMTOOL) @@ -666,9 +667,9 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE) IF(BUILD_LAUNCHER) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" ) ENDIF(BUILD_LAUNCHER) - IF(BUILD_BSATOOL) + IF(BUILD_BSATOOL) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" ) - ENDIF(BUILD_BSATOOL) + ENDIF(BUILD_BSATOOL) IF(BUILD_ESMTOOL) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" ) ENDIF(BUILD_ESMTOOL) @@ -680,7 +681,7 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE) ENDIF(BUILD_OPENCS) # Install icon and .desktop - INSTALL(FILES "${OpenMW_SOURCE_DIR}/apps/launcher/resources/images/openmw.png" DESTINATION "${ICONDIR}") + INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications") # Install global configuration files diff --git a/apps/launcher/CMakeLists.txt b/apps/launcher/CMakeLists.txt index a63898c0e..eb93d71e7 100644 --- a/apps/launcher/CMakeLists.txt +++ b/apps/launcher/CMakeLists.txt @@ -12,7 +12,7 @@ set(LAUNCHER utils/checkablemessagebox.cpp utils/textinputdialog.cpp - launcher.rc + ${CMAKE_SOURCE_DIR}/files/launcher/launcher.rc ) set(LAUNCHER_HEADER @@ -43,10 +43,10 @@ set(LAUNCHER_HEADER_MOC ) set(LAUNCHER_UI - ../../files/ui/datafilespage.ui - ../../files/ui/graphicspage.ui - ../../files/ui/mainwindow.ui - ../../files/ui/playpage.ui + ${CMAKE_SOURCE_DIR}/files/ui/datafilespage.ui + ${CMAKE_SOURCE_DIR}/files/ui/graphicspage.ui + ${CMAKE_SOURCE_DIR}/files/ui/mainwindow.ui + ${CMAKE_SOURCE_DIR}/files/ui/playpage.ui ) source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 444d05b2a..add3dea40 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -1,6 +1,9 @@ #include "datafilespage.hpp" -#include +#include +#include +#include +#include #include @@ -97,7 +100,7 @@ DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, GameSettings &gam connect(mastersTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint))); connect(mDataFilesModel, SIGNAL(layoutChanged()), this, SLOT(updateViews())); - + connect(filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterChanged(QString))); connect(splitter, SIGNAL(splitterMoved(int,int)), this, SLOT(updateSplitter())); @@ -144,7 +147,7 @@ void DataFilesPage::setupDataFiles() profilesComboBox->addItems(profiles); // Add the current profile if empty - if (profilesComboBox->findText(profile) == -1) + if (profilesComboBox->findText(profile) == -1 && !profile.isEmpty()) profilesComboBox->addItem(profile); if (profilesComboBox->findText(QString("Default")) == -1) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index 3caae2c36..700ba3db9 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -1,6 +1,8 @@ #include "graphicspage.hpp" -#include +#include +#include +#include #include @@ -257,7 +259,7 @@ QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) for (opt_it = i->second.possibleValues.begin (); opt_it != i->second.possibleValues.end (); opt_it++, idx++) { - QRegExp resolutionRe(QString("(\\d+) x (\\d+)")); + QRegExp resolutionRe(QString("(\\d+) x (\\d+).*")); QString resolution = QString::fromStdString(*opt_it).simplified(); if (resolutionRe.exactMatch(resolution)) { @@ -266,16 +268,17 @@ QStringList GraphicsPage::getAvailableResolutions(Ogre::RenderSystem *renderer) int height = resolutionRe.cap(2).toInt(); QString aspect = getAspect(width, height); + QString cleanRes = resolutionRe.cap(1) + QString(" x ") + resolutionRe.cap(2); if (aspect == QLatin1String("16:9") || aspect == QLatin1String("16:10")) { - resolution.append(tr("\t(Wide ") + aspect + ")"); + cleanRes.append(tr("\t(Wide ") + aspect + ")"); } else if (aspect == QLatin1String("4:3")) { - resolution.append(tr("\t(Standard 4:3)")); + cleanRes.append(tr("\t(Standard 4:3)")); } // do not add duplicate resolutions - if (!result.contains(resolution)) - result.append(resolution); + if (!result.contains(cleanRes)) + result.append(cleanRes); } } } diff --git a/apps/launcher/launcher.rc b/apps/launcher/launcher.rc deleted file mode 100644 index efe86e4da..000000000 --- a/apps/launcher/launcher.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "resources/images/openmw.ico" diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 5d11421d0..e5da3431a 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -1,6 +1,15 @@ #include "maindialog.hpp" -#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include #include "utils/checkablemessagebox.hpp" @@ -113,6 +122,51 @@ void MainDialog::createPages() bool MainDialog::showFirstRunDialog() { + QStringList iniPaths; + + foreach (const QString &path, mGameSettings.getDataDirs()) { + QDir dir(path); + dir.setPath(dir.canonicalPath()); // Resolve symlinks + + if (!dir.cdUp()) + continue; // Cannot move from Data Files + + if (dir.exists(QString("Morrowind.ini"))) + iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini"))); + } + + // Ask the user where the Morrowind.ini is + if (iniPaths.empty()) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("Error detecting Morrowind configuration")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setStandardButtons(QMessageBox::Cancel); + msgBox.setText(QObject::tr("
Could not find Morrowind.ini

\ + OpenMW needs to import settings from this file.

\ + Press \"Browse...\" to specify the location manually.
")); + + QAbstractButton *dirSelectButton = + msgBox.addButton(QObject::tr("B&rowse..."), QMessageBox::ActionRole); + + msgBox.exec(); + + QString iniFile; + if (msgBox.clickedButton() == dirSelectButton) { + iniFile = QFileDialog::getOpenFileName( + NULL, + QObject::tr("Select configuration file"), + QDir::currentPath(), + QString(tr("Morrowind configuration file (*.ini)"))); + } + + if (iniFile.isEmpty()) + return false; // Cancel was clicked; + + QFileInfo info(iniFile); + iniPaths.clear(); + iniPaths.append(info.absoluteFilePath()); + } + CheckableMessageBox msgBox(this); msgBox.setWindowTitle(tr("Morrowind installation detected")); @@ -120,7 +174,6 @@ bool MainDialog::showFirstRunDialog() int size = QApplication::style()->pixelMetric(QStyle::PM_MessageBoxIconSize); msgBox.setIconPixmap(icon.pixmap(size, size)); - QAbstractButton *importerButton = msgBox.addButton(tr("Import"), QDialogButtonBox::AcceptRole); // ActionRole doesn't work?! QAbstractButton *skipButton = @@ -129,54 +182,28 @@ bool MainDialog::showFirstRunDialog() Q_UNUSED(skipButton); // Surpress compiler unused warning msgBox.setStandardButtons(QDialogButtonBox::NoButton); - - msgBox.setText(tr("
An existing Morrowind installation was detected

\ - Would you like to import settings from Morrowind.ini?
")); - + msgBox.setText(tr("
An existing Morrowind configuration was detected
\ +
Would you like to import settings from Morrowind.ini?
\ +
Warning: In most cases OpenMW needs these settings to run properly
")); msgBox.setCheckBoxText(tr("Include selected masters and plugins (creates a new profile)")); msgBox.exec(); if (msgBox.clickedButton() == importerButton) { - QStringList iniPaths; - - foreach (const QString &path, mGameSettings.getDataDirs()) { - QDir dir(path); - dir.setPath(dir.canonicalPath()); // Resolve symlinks - - if (!dir.cdUp()) - continue; // Cannot move from Data Files - - if (dir.exists(QString("Morrowind.ini"))) - iniPaths.append(dir.absoluteFilePath(QString("Morrowind.ini"))); - } - - if (iniPaths.isEmpty()) { - QMessageBox msgBox; - msgBox.setWindowTitle(tr("Error reading Morrowind configuration file")); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setText(QObject::tr("
Could not find Morrowind.ini

\ - The problem may be due to an incomplete installation of Morrowind.
\ - Reinstalling Morrowind may resolve the problem.")); - msgBox.exec(); - return false; - } - if (iniPaths.count() > 1) { // Multiple Morrowind.ini files found bool ok; - QString path = QInputDialog::getItem(this, tr("Multiple configurations found"), + QString path = QInputDialog::getItem(this, tr("Multiple configurations found"), tr("
There are multiple Morrowind.ini files found.

\ Please select the one you wish to import from:"), iniPaths, 0, false, &ok); - if (ok && !path.isEmpty()) { - iniPaths.clear(); - iniPaths.append(path); - } else { - // Cancel was clicked TODO: should we abort here? - return false; - } + if (ok && !path.isEmpty()) { + iniPaths.clear(); + iniPaths.append(path); + } else { + // Cancel was clicked + return false; + } } // Create the file if it doesn't already exist, else the importer will fail @@ -204,9 +231,13 @@ bool MainDialog::showFirstRunDialog() QStringList arguments; if (msgBox.isChecked()) - arguments.append(QString("-g")); + arguments.append(QString("--game-files")); + arguments.append(QString("--encoding")); + arguments.append(mGameSettings.value(QString("encoding"), QString("win1252"))); + arguments.append(QString("--ini")); arguments.append(iniPaths.first()); + arguments.append(QString("--cfg")); arguments.append(path); if (!startProgram(QString("mwiniimport"), arguments, false)) @@ -218,7 +249,7 @@ bool MainDialog::showFirstRunDialog() // Add a new profile if (msgBox.isChecked()) { - mLauncherSettings.setValue(QString("Profiles/CurrentProfile"), QString("Imported")); + mLauncherSettings.setValue(QString("Profiles/currentprofile"), QString("Imported")); mLauncherSettings.remove(QString("Profiles/Imported/master")); mLauncherSettings.remove(QString("Profiles/Imported/plugin")); @@ -659,7 +690,7 @@ bool MainDialog::startProgram(const QString &name, const QStringList &arguments, return false; } - if (process.exitCode() != 0) { + if (process.exitCode() != 0 || process.exitStatus() == QProcess::CrashExit) { QString error(process.readAllStandardError()); error.append(tr("\nArguments:\n")); error.append(arguments.join(" ")); diff --git a/apps/launcher/playpage.cpp b/apps/launcher/playpage.cpp index d6d25d71d..46900c595 100644 --- a/apps/launcher/playpage.cpp +++ b/apps/launcher/playpage.cpp @@ -1,6 +1,10 @@ #include "playpage.hpp" -#include +#include + +#ifdef Q_OS_MAC +#include +#endif PlayPage::PlayPage(QWidget *parent) : QWidget(parent) { diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 62ee09bdb..162819995 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -241,7 +241,7 @@ namespace MWDialogue } } - void DialogueManager::executeTopic (const std::string& topic) + void DialogueManager::executeTopic (const std::string& topic, bool randomResponse) { Filter filter (mActor, mChoice, mTalkedTo); @@ -256,7 +256,7 @@ namespace MWDialogue if (!infos.empty()) { - const ESM::DialInfo* info = infos[std::rand() % infos.size()]; + const ESM::DialInfo* info = infos[randomResponse ? std::rand() % infos.size() : 0]; parseText (info->mResponse); @@ -505,7 +505,7 @@ namespace MWDialogue text = "Bribe"; } - executeTopic (text + (success ? " Success" : " Fail")); + executeTopic (text + (success ? " Success" : " Fail"), true); } int DialogueManager::getTemporaryDispositionChange() const diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp index ad537b0ad..337cf6247 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.hpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.hpp @@ -48,7 +48,7 @@ namespace MWDialogue void printError (const std::string& error); - void executeTopic (const std::string& topic); + void executeTopic (const std::string& topic, bool randomResponse=false); public: diff --git a/apps/openmw/mwgui/charactercreation.cpp b/apps/openmw/mwgui/charactercreation.cpp index 0cc12170a..bcf3c335d 100644 --- a/apps/openmw/mwgui/charactercreation.cpp +++ b/apps/openmw/mwgui/charactercreation.cpp @@ -674,9 +674,6 @@ void CharacterCreation::showClassQuestionDialog() void CharacterCreation::onGenerateClassBack() { - if(mCreationStage < CSE_ClassChosen) - mCreationStage = CSE_ClassChosen; - mWM->removeDialog(mGenerateClassResultDialog); mGenerateClassResultDialog = 0; diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index 839586452..8a079e40c 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -454,10 +454,13 @@ namespace MWGui mAvailableEffectsList->clear (); + int i=0; for (std::vector::const_iterator it = knownEffects.begin(); it != knownEffects.end(); ++it) { mAvailableEffectsList->addItem(MWBase::Environment::get().getWorld ()->getStore ().get().find( ESM::MagicEffect::effectIdToString (*it))->getString()); + mButtonMapping[i] = *it; + ++i; } mAvailableEffectsList->adjustSize (); @@ -466,7 +469,6 @@ namespace MWGui std::string name = MWBase::Environment::get().getWorld ()->getStore ().get().find( ESM::MagicEffect::effectIdToString (*it))->getString(); MyGUI::Widget* w = mAvailableEffectsList->getItemWidget(name); - w->setUserData(*it); ToolTips::createMagicEffectToolTip (w, *it); } @@ -518,7 +520,8 @@ namespace MWGui return; } - short effectId = *sender->getUserData(); + int buttonId = *sender->getUserData(); + short effectId = mButtonMapping[buttonId]; for (std::vector::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) { diff --git a/apps/openmw/mwgui/spellcreationdialog.hpp b/apps/openmw/mwgui/spellcreationdialog.hpp index 4d27ec1c6..393d9c3ec 100644 --- a/apps/openmw/mwgui/spellcreationdialog.hpp +++ b/apps/openmw/mwgui/spellcreationdialog.hpp @@ -88,6 +88,8 @@ namespace MWGui protected: + std::map mButtonMapping; // maps button ID to effect ID + Widgets::MWList* mAvailableEffectsList; MyGUI::ScrollView* mUsedEffectsView; diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 586e407ff..f69f606b4 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -187,18 +187,20 @@ namespace MWWorld T item; item.mId = Misc::StringUtils::lowerCase(id); - // delete from the static part of mShared - typename std::vector::iterator sharedIter = mShared.begin(); - for (; sharedIter != (mShared.begin()+mStatic.size()); ++sharedIter) { - if((*sharedIter)->mId == item.mId) { - mShared.erase(sharedIter); - break; - } - } - typename std::map::iterator it = mStatic.find(item.mId); if (it != mStatic.end() && Misc::StringUtils::ciEqual(it->second.mId, id)) { + // delete from the static part of mShared + typename std::vector::iterator sharedIter = mShared.begin(); + typename std::vector::iterator end = sharedIter + mStatic.size(); + + while (sharedIter != mShared.end() && sharedIter != end) { + if((*sharedIter)->mId == item.mId) { + mShared.erase(sharedIter); + break; + } + ++sharedIter; + } mStatic.erase(it); } diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 5aaf40dc5..35b5b59cf 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -18,7 +18,18 @@ using namespace Ogre; using namespace MWWorld; using namespace MWSound; -#define lerp(x, y) (x * (1-factor) + y * factor) +namespace +{ + float lerp (float x, float y, float factor) + { + return x * (1-factor) + y * factor; + } + Ogre::ColourValue lerp (const Ogre::ColourValue& x, const Ogre::ColourValue& y, float factor) + { + return x * (1-factor) + y * factor; + } +} + void WeatherManager::setFallbackWeather(Weather& weather,const std::string& name) { std::string upper=name; @@ -66,7 +77,8 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering,MWWorld::Fa mSunsetTime = mFallback->getFallbackFloat("Weather_Sunset_Time"); mSunriseDuration = mFallback->getFallbackFloat("Weather_Sunrise_Duration"); mSunsetDuration = mFallback->getFallbackFloat("Weather_Sunset_Duration"); - mWeatherUpdateTime = mFallback->getFallbackFloat("Weather_Hours_Between_Weather_Changes"); + mHoursBetweenWeatherChanges = mFallback->getFallbackFloat("Weather_Hours_Between_Weather_Changes"); + mWeatherUpdateTime = mHoursBetweenWeatherChanges*3600; mThunderFrequency = mFallback->getFallbackFloat("Weather_Thunderstorm_Thunder_Frequency"); mThunderThreshold = mFallback->getFallbackFloat("Weather_Thunderstorm_Thunder_Threshold"); mThunderSoundDelay = 0.25; @@ -181,10 +193,10 @@ WeatherResult WeatherManager::getResult(const String& weather) // fade in float advance = 6-mHour; float factor = advance / 0.5f; - result.mFogColor = lerp(current.mFogSunriseColor, current.mFogNightColor); - result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientNightColor); - result.mSunColor = lerp(current.mSunSunriseColor, current.mSunNightColor); - result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyNightColor); + result.mFogColor = lerp(current.mFogSunriseColor, current.mFogNightColor, factor); + result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientNightColor, factor); + result.mSunColor = lerp(current.mSunSunriseColor, current.mSunNightColor, factor); + result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyNightColor, factor); result.mNightFade = factor; } else //if (mHour >= 6) @@ -192,10 +204,10 @@ WeatherResult WeatherManager::getResult(const String& weather) // fade out float advance = mHour-6; float factor = advance / 3.f; - result.mFogColor = lerp(current.mFogSunriseColor, current.mFogDayColor); - result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientDayColor); - result.mSunColor = lerp(current.mSunSunriseColor, current.mSunDayColor); - result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyDayColor); + result.mFogColor = lerp(current.mFogSunriseColor, current.mFogDayColor, factor); + result.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientDayColor, factor); + result.mSunColor = lerp(current.mSunSunriseColor, current.mSunDayColor, factor); + result.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyDayColor, factor); } } @@ -216,20 +228,20 @@ WeatherResult WeatherManager::getResult(const String& weather) // fade in float advance = 19-mHour; float factor = (advance / 2); - result.mFogColor = lerp(current.mFogSunsetColor, current.mFogDayColor); - result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientDayColor); - result.mSunColor = lerp(current.mSunSunsetColor, current.mSunDayColor); - result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyDayColor); + result.mFogColor = lerp(current.mFogSunsetColor, current.mFogDayColor, factor); + result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientDayColor, factor); + result.mSunColor = lerp(current.mSunSunsetColor, current.mSunDayColor, factor); + result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyDayColor, factor); } else //if (mHour >= 19) { // fade out float advance = mHour-19; float factor = advance / 2.f; - result.mFogColor = lerp(current.mFogSunsetColor, current.mFogNightColor); - result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientNightColor); - result.mSunColor = lerp(current.mSunSunsetColor, current.mSunNightColor); - result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyNightColor); + result.mFogColor = lerp(current.mFogSunsetColor, current.mFogNightColor, factor); + result.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientNightColor, factor); + result.mSunColor = lerp(current.mSunSunsetColor, current.mSunNightColor, factor); + result.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyNightColor, factor); result.mNightFade = factor; } } @@ -247,19 +259,19 @@ WeatherResult WeatherManager::transition(float factor) result.mNextCloudTexture = other.mCloudTexture; result.mCloudBlendFactor = factor; - result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity); - result.mFogColor = lerp(current.mFogColor, other.mFogColor); - result.mSunColor = lerp(current.mSunColor, other.mSunColor); - result.mSkyColor = lerp(current.mSkyColor, other.mSkyColor); + result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity, factor); + result.mFogColor = lerp(current.mFogColor, other.mFogColor, factor); + result.mSunColor = lerp(current.mSunColor, other.mSunColor, factor); + result.mSkyColor = lerp(current.mSkyColor, other.mSkyColor, factor); - result.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor); - result.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor); - result.mFogDepth = lerp(current.mFogDepth, other.mFogDepth); - result.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed); - result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed); - result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity); - result.mGlareView = lerp(current.mGlareView, other.mGlareView); - result.mNightFade = lerp(current.mNightFade, other.mNightFade); + result.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor, factor); + result.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor, factor); + result.mFogDepth = lerp(current.mFogDepth, other.mFogDepth, factor); + result.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed, factor); + result.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor); + result.mCloudOpacity = lerp(current.mCloudOpacity, other.mCloudOpacity, factor); + result.mGlareView = lerp(current.mGlareView, other.mGlareView, factor); + result.mNightFade = lerp(current.mNightFade, other.mNightFade, factor); result.mNight = current.mNight; @@ -283,7 +295,7 @@ void WeatherManager::update(float duration) if (mWeatherUpdateTime <= 0 || regionstr != mCurrentRegion) { mCurrentRegion = regionstr; - mWeatherUpdateTime = mWeatherUpdateTime*3600; + mWeatherUpdateTime = mHoursBetweenWeatherChanges*3600; std::string weather = "clear"; diff --git a/apps/openmw/mwworld/weather.hpp b/apps/openmw/mwworld/weather.hpp index 93d908ebe..f8c85b1fe 100644 --- a/apps/openmw/mwworld/weather.hpp +++ b/apps/openmw/mwworld/weather.hpp @@ -177,6 +177,7 @@ namespace MWWorld float mSunriseDuration; float mSunsetDuration; float mWeatherUpdateTime; + float mHoursBetweenWeatherChanges; float mThunderFrequency; float mThunderThreshold; float mThunderSoundDelay; diff --git a/components/fileorderlist/model/datafilesmodel.cpp b/components/fileorderlist/model/datafilesmodel.cpp index 824fbd565..9f2e470b2 100644 --- a/components/fileorderlist/model/datafilesmodel.cpp +++ b/components/fileorderlist/model/datafilesmodel.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include #include @@ -237,10 +239,6 @@ bool lessThanDate(const EsmFile *e1, const EsmFile *e2) } else { return false; } -// if (!e1->fileName().endsWith(".esm") && e2->fileName().endsWith(".esm")) -// return false; - -// return e1->fileName().toLower() < e2->fileName().toLower(); } void DataFilesModel::sort(int column, Qt::SortOrder order) @@ -270,18 +268,33 @@ void DataFilesModel::addFiles(const QString &path) filters << "*.esp" << "*.esm"; dir.setNameFilters(filters); + // Create a decoder for non-latin characters in esx metadata + QTextCodec *codec; + + if (mEncoding == QLatin1String("win1252")) { + codec = QTextCodec::codecForName("windows-1252"); + } else if (mEncoding == QLatin1String("win1251")) { + codec = QTextCodec::codecForName("windows-1251"); + } else if (mEncoding == QLatin1String("win1250")) { + codec = QTextCodec::codecForName("windows-1250"); + } else { + return; // This should never happen; + } + + QTextDecoder *decoder = codec->makeDecoder(); + foreach (const QString &path, dir.entryList()) { QFileInfo info(dir.absoluteFilePath(path)); EsmFile *file = new EsmFile(path); - try { ESM::ESMReader fileReader; - ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(mEncoding.toStdString())); + ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding.toStdString())); fileReader.setEncoder(&encoder); fileReader.open(dir.absoluteFilePath(path).toStdString()); std::vector mlist = fileReader.getMasters(); + QStringList masters; for (unsigned int i = 0; i < mlist.size(); ++i) { @@ -289,13 +302,13 @@ void DataFilesModel::addFiles(const QString &path) masters.append(master); } - file->setAuthor(QString::fromStdString(fileReader.getAuthor())); + file->setAuthor(decoder->toUnicode(fileReader.getAuthor().c_str())); file->setSize(info.size()); file->setDates(info.lastModified(), info.lastRead()); file->setVersion(fileReader.getFVer()); file->setPath(info.absoluteFilePath()); file->setMasters(masters); - file->setDescription(QString::fromStdString(fileReader.getDesc())); + file->setDescription(decoder->toUnicode(fileReader.getDesc().c_str())); // Put the file in the table @@ -308,6 +321,8 @@ void DataFilesModel::addFiles(const QString &path) } } + + delete decoder; } QModelIndex DataFilesModel::indexFromItem(EsmFile *item) const diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp index 3fc82f73a..5aa5ff80c 100644 --- a/components/nifogre/ogrenifloader.cpp +++ b/components/nifogre/ogrenifloader.cpp @@ -743,8 +743,6 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String blend_mode += getBlendFactor((alphaFlags>>5)&0xf); instance->setProperty("scene_blend", sh::makeProperty(new sh::StringValue(blend_mode))); } - else - instance->getMaterial()->setShadowCasterMaterial("openmw_shadowcaster_noalpha"); if((alphaFlags>>9)&1) { @@ -754,9 +752,12 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String reject += Ogre::StringConverter::toString(alphaTest); instance->setProperty("alpha_rejection", sh::makeProperty(new sh::StringValue(reject))); } + else + instance->getMaterial()->setShadowCasterMaterial("openmw_shadowcaster_noalpha"); // Ogre usually only sorts if depth write is disabled, so we want "force" instead of "on" - instance->setProperty("transparent_sorting", sh::makeProperty(new sh::StringValue(!((alphaFlags>>13)&1) ? "force" : "off"))); + instance->setProperty("transparent_sorting", sh::makeProperty(new sh::StringValue( + ((alphaFlags&1) && !((alphaFlags>>13)&1)) ? "force" : "off"))); instance->setProperty("depth_check", sh::makeProperty(new sh::StringValue((depthFlags&1) ? "on" : "off"))); instance->setProperty("depth_write", sh::makeProperty(new sh::StringValue(((depthFlags>>1)&1) ? "on" : "off"))); diff --git a/files/launcher/launcher.rc b/files/launcher/launcher.rc new file mode 100644 index 000000000..df2121f46 --- /dev/null +++ b/files/launcher/launcher.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "images/openmw.ico" diff --git a/files/materials/watersim_heightmap.shader b/files/materials/watersim_heightmap.shader index 50d375efe..ec8ae4174 100644 --- a/files/materials/watersim_heightmap.shader +++ b/files/materials/watersim_heightmap.shader @@ -14,12 +14,21 @@ SH_START_PROGRAM { +#if !SH_HLSL const float3 offset[4] = float3[4]( float3(-1.0, 0.0, 0.25), float3( 1.0, 0.0, 0.25), float3( 0.0,-1.0, 0.25), float3( 0.0, 1.0, 0.25) ); +#else + const float3 offset[4] = { + float3(-1.0, 0.0, 0.25), + float3( 1.0, 0.0, 0.25), + float3( 0.0,-1.0, 0.25), + float3( 0.0, 1.0, 0.25) + }; +#endif float fHeightPrev = DecodeHeightmap(heightPrevSampler, UV.xy + previousFrameOffset.xy + currentFrameOffset.xy); diff --git a/files/materials/watersim_heighttonormal.shader b/files/materials/watersim_heighttonormal.shader index 5402b6bb5..eaa4af498 100644 --- a/files/materials/watersim_heighttonormal.shader +++ b/files/materials/watersim_heighttonormal.shader @@ -8,12 +8,21 @@ SH_START_PROGRAM { - float2 offset[4] = float2[4] ( - vec2(-1.0, 0.0), - vec2( 1.0, 0.0), - vec2( 0.0,-1.0), - vec2( 0.0, 1.0) - ); +#if !SH_HLSL + float2 offset[4] = float2[4] ( + float2(-1.0, 0.0), + float2( 1.0, 0.0), + float2( 0.0,-1.0), + float2( 0.0, 1.0) + ); +#else + float2 offset[4] = { + float2(-1.0, 0.0), + float2( 1.0, 0.0), + float2( 0.0,-1.0), + float2( 0.0, 1.0) + }; +#endif float fHeightL = DecodeHeightmap(heightCurrentSampler, UV.xy + offset[0]*rippleTextureSize.xy); float fHeightR = DecodeHeightmap(heightCurrentSampler, UV.xy + offset[1]*rippleTextureSize.xy); diff --git a/files/ui/mainwindow.ui b/files/ui/mainwindow.ui index 8143fa24d..a1dfb172b 100644 --- a/files/ui/mainwindow.ui +++ b/files/ui/mainwindow.ui @@ -5,7 +5,7 @@ 575 - 525 + 535 diff --git a/files/ui/playpage.ui b/files/ui/playpage.ui index 6b8b66b20..c0320de1e 100644 --- a/files/ui/playpage.ui +++ b/files/ui/playpage.ui @@ -19,6 +19,9 @@ QFrame::Plain + + 0 + 30 @@ -40,10 +43,14 @@ border-color: rgba(0, 0, 0, 125); border-style: solid; border-radius: 2px; + + font-size: 12pt; + font-family: "EB Garamond", "EB Garamond 08"; + color: black; } /*QComboBox gets the "on" state when the popup is open */ -#profilesComboBox:!editable:on, #ProfilesComboBox::drop-down:editable:on { +#profilesComboBox:!editable:on { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0, 0, 0, 75), stop:0.1 rgba(0, 0, 0, 15), @@ -52,13 +59,9 @@ border: 1px solid rgba(0, 0, 0, 55); } -#profilesComboBox { /* shift the text when the popup opens */ +#profilesComboBox:on { /* shift the text when the popup opens */ padding-top: 3px; padding-left: 4px; - - font-size: 12pt; - font-family: "EB Garamond", "EB Garamond 08"; - color: black; } #profilesComboBox::drop-down { @@ -82,7 +85,6 @@ left: 1px; } - #profilesComboBox QAbstractItemView { border: 0px; } diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index c4f35e087..309ba8a06 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -229,15 +229,6 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& assert(mRoot); mRoot->initialise(false); - // create a hidden 1x1 background window to keep resources when recreating the secondary (real) window - NameValuePairList params_; - params_.insert(std::make_pair("title", title)); - params_.insert(std::make_pair("FSAA", "0")); - params_.insert(std::make_pair("vsync", "false")); - params_.insert(std::make_pair("hidden", "true")); - Ogre::RenderWindow* hiddenWindow = mRoot->createRenderWindow("InactiveHidden", 1, 1, false, ¶ms_); - hiddenWindow->setActive(false); - NameValuePairList params; params.insert(std::make_pair("title", title)); params.insert(std::make_pair("FSAA", settings.fsaa)); diff --git a/readme.txt b/readme.txt index 228278a91..8edb0c4b3 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ OpenMW: A reimplementation of The Elder Scrolls III: Morrowind OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. -Version: 0.21.0 +Version: 0.22.0 License: GPL (see GPL3.txt for more information) Website: http://www.openmw.org @@ -94,6 +94,82 @@ Allowed options: CHANGELOG +0.22.0 + +Bug #311: Potential infinite recursion in script compiler +Bug #355: Keyboard repeat rate (in Xorg) are left disabled after game exit. +Bug #382: Weird effect in 3rd person on water +Bug #387: Always use detailed shape for physics raycasts +Bug #420: Potion/ingredient effects do not stack +Bug #429: Parts of dwemer door not picked up correctly for activation/tooltips +Bug #434/Bug #605: Object movement between cells not properly implemented +Bug #502: Duplicate player collision model at origin +Bug #509: Dialogue topic list shifts inappropriately +Bug #513: Sliding stairs +Bug #515: Launcher does not support non-latin strings +Bug #525: Race selection preview camera wrong position +Bug #526: Attributes / skills should not go below zero +Bug #529: Class and Birthsign menus options should be preselected +Bug #530: Lock window button graphic missing +Bug #532: Missing map menu graphics +Bug #545: ESX selector does not list ESM files properly +Bug #547: Global variables of type short are read incorrectly +Bug #550: Invisible meshes collision and tooltip +Bug #551: Performance drop when loading multiple ESM files +Bug #552: Don't list CG in options if it is not available +Bug #555: Character creation windows "OK" button broken +Bug #558: Segmentation fault when Alt-tabbing with console opened +Bug #559: Dialog window should not be available before character creation is finished +Bug #560: Tooltip borders should be stretched +Bug #562: Sound should not be played when an object cannot be picked up +Bug #565: Water animation speed + timescale +Bug #572: Better Bodies' textures don't work +Bug #573: OpenMW doesn't load if TR_Mainland.esm is enabled (Tamriel Rebuilt mod) +Bug #574: Moving left/right should not cancel auto-run +Bug #575: Crash entering the Chamber of Song +Bug #576: Missing includes +Bug #577: Left Gloves Addon causes ESMReader exception +Bug #579: Unable to open container "Kvama Egg Sack" +Bug #581: Mimicking vanilla Morrowind water +Bug #583: Gender not recognized +Bug #586: Wrong char gen behaviour +Bug #587: "End" script statements with spaces don't work +Bug #589: Closing message boxes by pressing the activation key +Bug #590: Ugly Dagoth Ur rendering +Bug #591: Race selection issues +Bug #593: Persuasion response should be random +Bug #595: Footless guard +Bug #599: Waterfalls are invisible from a certain distance +Bug #600: Waterfalls rendered incorrectly, cut off by water +Bug #607: New beast bodies mod crashes +Bug #608: Crash in cell "Mournhold, Royal Palace" +Bug #611: OpenMW doesn't find some of textures used in Tamriel Rebuilt +Bug #613: Messagebox causing assert to fail +Bug #615: Meshes invisible from above water +Bug #617: Potion effects should be hidden until discovered +Bug #619: certain moss hanging from tree has rendering bug +Bug #621: Batching bloodmoon's trees +Bug #623: NiMaterialProperty alpha unhandled +Bug #628: Launcher in latest master crashes the game +Bug #633: Crash on startup: Better Heads +Bug #636: Incorrect Char Gen Menu Behavior +Feature #29: Allow ESPs and multiple ESMs +Feature #94: Finish class selection-dialogue +Feature #149: Texture Alphas +Feature #237: Run Morrowind-ini importer from launcher +Feature #286: Update Active Spell Icons +Feature #334: Swimming animation +Feature #335: Walking animation +Feature #360: Proper collision shapes for NPCs and creatures +Feature #367: Lights that behave more like original morrowind implementation +Feature #477: Special local scripting variables +Feature #528: Message boxes should close when enter is pressed under certain conditions. +Feature #543: Add bsa files to the settings imported by the ini importer +Feature #594: coordinate space and utility functions +Feature #625: Zoom in vanity mode +Task #464: Refactor launcher ESX selector into a re-usable component +Task #624: Unified implementation of type-variable sub-records + 0.21.0 Bug #253: Dialogs don't work for Russian version of Morrowind