diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 794ca3d7b..de3e23965 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -259,20 +259,36 @@ int CS::Editor::run() std::auto_ptr CS::Editor::setupGraphics() { - // TODO: setting - Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName("OpenGL Rendering Subsystem")); + std::string renderer = +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + "Direct3D9 Rendering Subsystem"; +#else + "OpenGL Rendering Subsystem"; +#endif + std::string renderSystem = mUserSettings.setting("Video/render system", renderer.c_str()).toStdString(); + + Ogre::Root::getSingleton().setRenderSystem(Ogre::Root::getSingleton().getRenderSystemByName(renderSystem)); Ogre::Root::getSingleton().initialise(false); // Create a hidden background window to keep resources Ogre::NameValuePairList params; params.insert(std::make_pair("title", "")); - params.insert(std::make_pair("FSAA", "0")); + + std::string antialiasing = mUserSettings.settingValue("Video/antialiasing").toStdString(); + if(antialiasing == "MSAA 16") antialiasing = "16"; + else if(antialiasing == "MSAA 8") antialiasing = "8"; + else if(antialiasing == "MSAA 4") antialiasing = "4"; + else if(antialiasing == "MSAA 2") antialiasing = "2"; + else antialiasing = "0"; + params.insert(std::make_pair("FSAA", antialiasing)); + params.insert(std::make_pair("vsync", "false")); params.insert(std::make_pair("hidden", "true")); #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE params.insert(std::make_pair("macAPI", "cocoa")); #endif + // NOTE: fullscreen mode not supported (doesn't really make sense for opencs) Ogre::RenderWindow* hiddenWindow = Ogre::Root::getSingleton().createRenderWindow("InactiveHidden", 1, 1, false, ¶ms); hiddenWindow->setActive(false); @@ -286,7 +302,28 @@ std::auto_ptr CS::Editor::setupGraphics() std::auto_ptr factory (new sh::Factory (platform)); - factory->setCurrentLanguage (sh::Language_GLSL); /// \todo make this configurable + QString shLang = mUserSettings.settingValue("General/shader mode"); + QString rend = renderSystem.c_str(); + bool openGL = rend.contains(QRegExp("^OpenGL", Qt::CaseInsensitive)); + bool glES = rend.contains(QRegExp("^OpenGL ES", Qt::CaseInsensitive)); + + // force shader language based on render system + if(shLang == "" + || (openGL && shLang == "hlsl") + || (!openGL && shLang == "glsl") + || (glES && shLang != "glsles")) + { + shLang = openGL ? (glES ? "glsles" : "glsl") : "hlsl"; + //no group means "General" group in the "ini" file standard + mUserSettings.setDefinitions("shader mode", (QStringList() << shLang)); + } + enum sh::Language lang; + if(shLang == "glsl") lang = sh::Language_GLSL; + else if(shLang == "glsles") lang = sh::Language_GLSLES; + else if(shLang == "hlsl") lang = sh::Language_HLSL; + else lang = sh::Language_CG; + + factory->setCurrentLanguage (lang); factory->setWriteSourceCache (true); factory->setReadSourceCache (true); factory->setReadMicrocodeCache (true); @@ -294,16 +331,27 @@ std::auto_ptr CS::Editor::setupGraphics() factory->loadAllFiles(); - sh::Factory::getInstance().setGlobalSetting ("fog", "true"); + bool shaders = mUserSettings.setting("Objects/shaders", QString("true")) == "true" ? true : false; + sh::Factory::getInstance ().setShadersEnabled (shaders); + + std::string fog = mUserSettings.setting("Shader/fog", QString("true")).toStdString(); + sh::Factory::getInstance().setGlobalSetting ("fog", fog); + + + std::string shadows = mUserSettings.setting("Shader/shadows", QString("false")).toStdString(); + sh::Factory::getInstance().setGlobalSetting ("shadows", shadows); - sh::Factory::getInstance().setGlobalSetting ("shadows", "false"); - sh::Factory::getInstance().setGlobalSetting ("shadows_pssm", "false"); + std::string shadows_pssm = mUserSettings.setting("Shader/shadows_pssm", QString("false")).toStdString(); + sh::Factory::getInstance().setGlobalSetting ("shadows_pssm", shadows_pssm); - sh::Factory::getInstance ().setGlobalSetting ("render_refraction", "false"); + std::string render_refraction = mUserSettings.setting("Shader/render_refraction", QString("false")).toStdString(); + sh::Factory::getInstance ().setGlobalSetting ("render_refraction", render_refraction); + // internal setting - may be switched on or off by the use of shader configurations sh::Factory::getInstance ().setGlobalSetting ("viewproj_fix", "false"); - sh::Factory::getInstance ().setGlobalSetting ("num_lights", "8"); + std::string num_lights = mUserSettings.setting("Objects/num_lights", QString("8")).toStdString(); + sh::Factory::getInstance ().setGlobalSetting ("num_lights", num_lights); /// \todo add more configurable shiny settings diff --git a/apps/opencs/model/settings/setting.cpp b/apps/opencs/model/settings/setting.cpp index 2f86d4ff8..404ec58f7 100644 --- a/apps/opencs/model/settings/setting.cpp +++ b/apps/opencs/model/settings/setting.cpp @@ -194,6 +194,16 @@ QString CSMSettings::Setting::page() const return property (Property_Page).at(0); } +void CSMSettings::Setting::setStyleSheet (const QString &value) +{ + setProperty (Property_StyleSheet, value); +} + +QString CSMSettings::Setting::styleSheet() const +{ + return property (Property_StyleSheet).at(0); +} + void CSMSettings::Setting::setPrefix (const QString &value) { setProperty (Property_Prefix, value); diff --git a/apps/opencs/model/settings/setting.hpp b/apps/opencs/model/settings/setting.hpp index e40302f00..0068fd158 100644 --- a/apps/opencs/model/settings/setting.hpp +++ b/apps/opencs/model/settings/setting.hpp @@ -80,6 +80,9 @@ namespace CSMSettings void setPage (const QString &value); QString page() const; + void setStyleSheet (const QString &value); + QString styleSheet() const; + void setPrefix (const QString &value); QString prefix() const; diff --git a/apps/opencs/model/settings/support.hpp b/apps/opencs/model/settings/support.hpp index 229e293b8..1e122a214 100644 --- a/apps/opencs/model/settings/support.hpp +++ b/apps/opencs/model/settings/support.hpp @@ -35,12 +35,13 @@ namespace CSMSettings Property_TickInterval = 19, Property_TicksAbove = 20, Property_TicksBelow = 21, + Property_StyleSheet = 22, //Stringlists should always be the last items - Property_DefaultValues = 22, - Property_DeclaredValues = 23, - Property_DefinedValues = 24, - Property_Proxies = 25 + Property_DefaultValues = 23, + Property_DeclaredValues = 24, + Property_DefinedValues = 25, + Property_Proxies = 26 }; ///Basic setting widget types. @@ -106,7 +107,7 @@ namespace CSMSettings "is_multi_line", "widget_width", "view_row", "view_column", "delimiter", "is_serializable","column_span", "row_span", "minimum", "maximum", "special_value_text", "prefix", "suffix", "single_step", "wrapping", - "tick_interval", "ticks_above", "ticks_below", + "tick_interval", "ticks_above", "ticks_below", "stylesheet", "defaults", "declarations", "definitions", "proxies" }; @@ -135,6 +136,7 @@ namespace CSMSettings "1", //tick interval "false", //ticks above "true", //ticks below + "", //StyleSheet "", //default values "", //declared values "", //defined values diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 04f98f0d6..11fdc54f4 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -4,12 +4,16 @@ #include #include +#include #include #include "setting.hpp" #include "support.hpp" +#include #include +#include + /** * Workaround for problems with whitespaces in paths in older versions of Boost library */ @@ -28,20 +32,111 @@ namespace boost CSMSettings::UserSettings *CSMSettings::UserSettings::mUserSettingsInstance = 0; -CSMSettings::UserSettings::UserSettings (const Files::ConfigurationManager& configurationManager) -: mCfgMgr (configurationManager) + CSMSettings::UserSettings::UserSettings (const Files::ConfigurationManager& configurationManager) + : mCfgMgr (configurationManager) + , mSettingDefinitions(NULL) + , mSettingCfgDefinitions(NULL) { assert(!mUserSettingsInstance); mUserSettingsInstance = this; - mSettingDefinitions = 0; - buildSettingModelDefaults(); + + // for overriding opencs.ini settings with those from settings.cfg + mSettingCfgDefinitions = new QSettings(QSettings::IniFormat, QSettings::UserScope, "", QString(), this); } void CSMSettings::UserSettings::buildSettingModelDefaults() { - QString section = "Window Size"; + QString section; + + section = "Objects"; + { + Setting *numLights = createSetting (Type_SpinBox, section, "num_lights"); + numLights->setDefaultValue(8); + numLights->setEditorSetting(true); + numLights->setColumnSpan (1); + numLights->setMinimum (0); + numLights->setMaximum (100); // FIXME: not sure what the max value should be + numLights->setWidgetWidth (10); + numLights->setViewLocation(1, 2); + + Setting *shaders = createSetting (Type_CheckBox, section, "shaders"); + shaders->setDeclaredValues(QStringList() << "true" << "false"); + shaders->setDefaultValue("true"); + shaders->setEditorSetting(true); + shaders->setSpecialValueText("Enable Shaders"); + shaders->setWidgetWidth(25); + shaders->setColumnSpan (3); + shaders->setStyleSheet ("QGroupBox { border: 0px; }"); + shaders->setViewLocation(2, 1); + } + + section = "Scene"; + { + Setting *fastFactor = createSetting (Type_SpinBox, section, "fast factor"); + fastFactor->setDefaultValue(4); + fastFactor->setEditorSetting(true); + fastFactor->setColumnSpan (1); + fastFactor->setMinimum (1); + fastFactor->setSpecialValueText ("1"); // FIXME: workaround + fastFactor->setMaximum (100); // FIXME: not sure what the max value should be + fastFactor->setWidgetWidth (10); + fastFactor->setViewLocation(1, 2); + + Setting *farClipDist = createSetting (Type_DoubleSpinBox, section, "far clip distance"); + farClipDist->setDefaultValue(300000); + farClipDist->setEditorSetting(true); + farClipDist->setColumnSpan (1); + farClipDist->setMinimum (0); + farClipDist->setMaximum (1000000); // FIXME: not sure what the max value should be + farClipDist->setWidgetWidth (10); + farClipDist->setViewLocation(2, 2); + + Setting *timerStart = createSetting (Type_SpinBox, section, "timer start"); + timerStart->setDefaultValue(20); + timerStart->setEditorSetting(true); + timerStart->setColumnSpan (1); + timerStart->setMinimum (0); + timerStart->setMaximum (100); // FIXME: not sure what the max value should be + timerStart->setWidgetWidth (10); + timerStart->setViewLocation(3, 2); + } + + section = "SubView"; + { + Setting *maxSubView = createSetting (Type_SpinBox, section, "max subviews"); + maxSubView->setDefaultValue(256); + maxSubView->setEditorSetting(true); + maxSubView->setColumnSpan (1); + maxSubView->setMinimum (1); + maxSubView->setSpecialValueText ("1"); + maxSubView->setMaximum (256); // FIXME: not sure what the max value should be + maxSubView->setWidgetWidth (10); + maxSubView->setViewLocation(1, 2); + + Setting *minWidth = createSetting (Type_SpinBox, section, "minimum width"); + minWidth->setDefaultValue(325); + minWidth->setEditorSetting(true); + minWidth->setColumnSpan (1); + minWidth->setMinimum (50); + minWidth->setSpecialValueText ("50"); + minWidth->setMaximum (10000); // FIXME: not sure what the max value should be + minWidth->setWidgetWidth (10); + minWidth->setViewLocation(2, 2); + + Setting *reuse = createSetting (Type_CheckBox, section, "reuse"); + reuse->setDeclaredValues(QStringList() << "true" << "false"); + reuse->setDefaultValue("true"); + reuse->setEditorSetting(true); + reuse->setSpecialValueText("Reuse SubView"); + reuse->setWidgetWidth(25); + reuse->setColumnSpan (3); + reuse->setStyleSheet ("QGroupBox { border: 0px; }"); + reuse->setViewLocation(3, 2); + } + + section = "Window Size"; { Setting *width = createSetting (Type_LineEdit, section, "Width"); Setting *height = createSetting (Type_LineEdit, section, "Height"); @@ -100,6 +195,17 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() ritd->setEditorSetting (true); } + section = "Video"; + { + QString defaultValue = "None"; + QStringList values = QStringList() + << defaultValue << "MSAA 2" << "MSAA 4" << "MSAA 8" << "MSAA 16"; + Setting *antialiasing = createSetting (Type_SpinBox, section, "antialiasing"); + antialiasing->setDeclaredValues (values); + antialiasing->setEditorSetting (true); + antialiasing->setWidgetWidth(15); + } + section = "Proxy Selection Test"; { /****************************************************************** @@ -305,10 +411,27 @@ void CSMSettings::UserSettings::loadSettings (const QString &fileName) mSettingDefinitions = new QSettings (QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this); + + // check if override entry exists (default: disabled) + if(!mSettingDefinitions->childGroups().contains("Video", Qt::CaseInsensitive)) + mSettingDefinitions->setValue("Video/use settings.cfg", "false"); } -bool CSMSettings::UserSettings::hasSettingDefinitions - (const QString &viewKey) const +// if the key is not found create one with a defaut value +QString CSMSettings::UserSettings::setting(const QString &viewKey, const QString &value) +{ + if(mSettingDefinitions->contains(viewKey)) + return settingValue(viewKey); + else if(value != QString()) + { + mSettingDefinitions->setValue (viewKey, QStringList() << value); + return value; + } + + return QString(); +} + +bool CSMSettings::UserSettings::hasSettingDefinitions (const QString &viewKey) const { return (mSettingDefinitions->contains (viewKey)); } @@ -326,10 +449,25 @@ void CSMSettings::UserSettings::saveDefinitions() const QString CSMSettings::UserSettings::settingValue (const QString &settingKey) { - if (!mSettingDefinitions->contains (settingKey)) - return QString(); + QStringList defs; + + // check if video settings are overriden + if(settingKey.contains(QRegExp("^Video\\b", Qt::CaseInsensitive)) && + mSettingDefinitions->value("Video/use settings.cfg") == "true" && + settingKey.contains(QRegExp("^Video/\\brender|antialiasing|vsync|fullscreen\\b", Qt::CaseInsensitive))) + { + if (!mSettingCfgDefinitions->contains (settingKey)) + return QString(); + else + defs = mSettingCfgDefinitions->value (settingKey).toStringList(); + } + else + { + if (!mSettingDefinitions->contains (settingKey)) + return QString(); - QStringList defs = mSettingDefinitions->value (settingKey).toStringList(); + defs = mSettingDefinitions->value (settingKey).toStringList(); + } if (defs.isEmpty()) return QString(); @@ -348,6 +486,15 @@ void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey, { mSettingDefinitions->setValue (settingKey ,list); + if(settingKey == "Objects/num_lights" && !list.empty()) + { + sh::Factory::getInstance ().setGlobalSetting ("num_lights", list.at(0).toStdString()); + } + else if(settingKey == "Objects/shaders" && !list.empty()) + { + sh::Factory::getInstance ().setShadersEnabled (list.at(0).toStdString() == "true" ? true : false); + } + emit userSettingUpdated (settingKey, list); } @@ -387,7 +534,6 @@ void CSMSettings::UserSettings::removeSetting } } - CSMSettings::SettingPageMap CSMSettings::UserSettings::settingPageMap() const { SettingPageMap pageMap; diff --git a/apps/opencs/model/settings/usersettings.hpp b/apps/opencs/model/settings/usersettings.hpp index 7e553caf6..0aabd66e5 100644 --- a/apps/opencs/model/settings/usersettings.hpp +++ b/apps/opencs/model/settings/usersettings.hpp @@ -33,8 +33,10 @@ namespace CSMSettings { const Files::ConfigurationManager& mCfgMgr; QSettings *mSettingDefinitions; + QSettings *mSettingCfgDefinitions; QList mSettings; + public: /// Singleton implementation @@ -75,6 +77,8 @@ namespace CSMSettings { ///Save any unsaved changes in the QSettings object void saveDefinitions() const; + QString setting(const QString &viewKey, const QString &value = QString()); + private: void buildSettingModelDefaults(); diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index 9c3c4e5e9..be03f91a5 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -1,5 +1,7 @@ #include "subview.hpp" +#include "view.hpp" + CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) { /// \todo add a button to the title bar that clones this sub view @@ -25,3 +27,10 @@ void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id) mUniversalId = id; setWindowTitle (mUniversalId.toString().c_str()); } + +void CSVDoc::SubView::closeEvent (QCloseEvent *event) +{ + // update title bars of view and subviews + if(mParent) + mParent->updateSubViewIndicies(this); +} diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index 733a75bb0..6a3ddd8bd 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -18,11 +18,14 @@ namespace CSMWorld namespace CSVDoc { + class View; + class SubView : public QDockWidget { Q_OBJECT CSMWorld::UniversalId mUniversalId; + View *mParent; // not implemented SubView (const SubView&); @@ -44,6 +47,12 @@ namespace CSVDoc virtual void useHint (const std::string& hint); ///< Default implementation: ignored + void setParent(View *parent) { mParent = parent; } + + private: + + void closeEvent (QCloseEvent *event); + signals: void focusId (const CSMWorld::UniversalId& universalId, const std::string& hint); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 1ed75b0b4..73beee60c 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "../../model/doc/document.hpp" #include "../../model/settings/usersettings.hpp" @@ -103,6 +104,10 @@ void CSVDoc::View::setupViewMenu() mShowStatusBar = new QAction (tr ("Show Status Bar"), this); mShowStatusBar->setCheckable (true); connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool))); + std::string showStatusBar = + CSMSettings::UserSettings::instance().settingValue("Display/show statusbar").toStdString(); + if(showStatusBar == "true") + mShowStatusBar->setChecked(true); view->addAction (mShowStatusBar); QAction *filters = new QAction (tr ("Filters"), this); @@ -283,7 +288,7 @@ void CSVDoc::View::setupUi() setupDebugMenu(); } -void CSVDoc::View::updateTitle() +void CSVDoc::View::updateTitle(const std::string subview) { std::ostringstream stream; @@ -295,9 +300,40 @@ void CSVDoc::View::updateTitle() if (mViewTotal>1) stream << " [" << (mViewIndex+1) << "/" << mViewTotal << "]"; + if (subview != "") + stream << " - " << subview; + setWindowTitle (stream.str().c_str()); } +void CSVDoc::View::updateSubViewIndicies(SubView *view) +{ + if(view && mSubViews.contains(view)) + mSubViews.removeOne(view); + + if(mSubViews.size() == 1) + { + if(!mSubViews.at(0)->isFloating()) + { + mSubViews.at(0)->setTitleBarWidget(new QWidget(this)); + updateTitle(mSubViews.at(0)->getUniversalId().getTypeName().c_str()); + } + } + else + { + updateTitle(); + if(mSubViews.size() > 1) + { + foreach(SubView * sb, mSubViews) + { + QWidget * tb = sb->titleBarWidget(); + if(tb) delete tb; + sb->setTitleBarWidget(0); + } + } + } +} + void CSVDoc::View::updateActions() { bool editing = !(mDocument->getState() & CSMDoc::State_Locked); @@ -326,7 +362,11 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to QString height = CSMSettings::UserSettings::instance().settingValue ("Window Size/Height"); - resize (width.toInt(), height.toInt()); + // trick to get the window decorations and their sizes + show(); + hide(); + resize (width.toInt() - (frameGeometry().width() - geometry().width()), + height.toInt() - (frameGeometry().height() - geometry().height())); mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks); @@ -400,31 +440,64 @@ void CSVDoc::View::updateProgress (int current, int max, int type, int threads) void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::string& hint) { - /// \todo add an user setting for limiting the number of sub views per top level view. Automatically open a new top level view if this - /// number is exceeded + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); - /// \todo if the sub view limit setting is one, the sub view title bar should be hidden and the text in the main title bar adjusted - /// accordingly + const std::vector referenceables(CSMWorld::UniversalId::listReferenceableTypes()); + bool isReferenceable = std::find(referenceables.begin(), referenceables.end(), id.getType()) != referenceables.end(); - /// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) + // User setting to reuse sub views (on a per top level view basis) + bool reuse = + userSettings.setting("SubView/reuse", QString("true")) == "true" ? true : false; + if(reuse) + { + foreach(SubView *sb, mSubViews) + { + if((isReferenceable && (CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Referenceable, id.getId()) == CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Referenceable, sb->getUniversalId().getId()))) + || (!isReferenceable && (id == sb->getUniversalId()))) + { + sb->setFocus(Qt::OtherFocusReason); // FIXME: focus not quite working + return; + } + } + } + + // User setting for limiting the number of sub views per top level view. + // Automatically open a new top level view if this number is exceeded + // + // If the sub view limit setting is one, the sub view title bar is hidden and the + // text in the main title bar is adjusted accordingly + int maxSubView = userSettings.setting("SubView/max subviews", QString("256")).toInt(); + if(mSubViews.size() >= maxSubView) // create a new top level view + { + mViewManager.addView(mDocument, id, hint); + + return; + } - const std::vector referenceables(CSMWorld::UniversalId::listReferenceableTypes()); SubView *view = NULL; if(std::find(referenceables.begin(), referenceables.end(), id.getType()) != referenceables.end()) { view = mSubViewFactory.makeSubView (CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Referenceable, id.getId()), *mDocument); - } else + } + else { view = mSubViewFactory.makeSubView (id, *mDocument); } assert(view); + view->setParent(this); + mSubViews.append(view); // only after assert if (!hint.empty()) view->useHint (hint); + int minWidth = userSettings.setting("SubView/minimum width", QString("325")).toInt(); + view->setMinimumWidth(minWidth); + view->setStatusBar (mShowStatusBar->isChecked()); mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view); + updateSubViewIndicies(); + connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&)), this, SLOT (addSubView (const CSMWorld::UniversalId&, const std::string&))); @@ -642,6 +715,11 @@ void CSVDoc::View::toggleShowStatusBar (bool show) } } +void CSVDoc::View::toggleStatusBar(bool checked) +{ + mShowStatusBar->setChecked(checked); +} + void CSVDoc::View::loadErrorLog() { addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_LoadErrorLog, 0)); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 9b4f2099b..eab274a59 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -35,6 +35,7 @@ namespace CSVDoc CSMDoc::Document *mDocument; int mViewIndex; int mViewTotal; + QList mSubViews; QAction *mUndo; QAction *mRedo; QAction *mSave; @@ -74,7 +75,7 @@ namespace CSVDoc void setupUi(); - void updateTitle(); + void updateTitle(const std::string subview = ""); void updateActions(); @@ -106,11 +107,16 @@ namespace CSVDoc void updateProgress (int current, int max, int type, int threads); + void toggleStatusBar(bool checked); + Operations *getOperations() const; /// Function called by view manager when user preferences are updated void updateEditorSetting (const QString &, const QString &); + // called when subviews are added or removed + void updateSubViewIndicies(SubView *view = 0); + signals: void newGameRequest(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 638b42d5f..2b46eecd2 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -9,6 +9,7 @@ #include "../../model/doc/documentmanager.hpp" #include "../../model/doc/document.hpp" #include "../../model/world/columns.hpp" +#include "../../model/world/universalid.hpp" #include "../world/util.hpp" #include "../world/enumdelegate.hpp" @@ -140,6 +141,10 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) mViews.push_back (view); + std::string showStatusBar = + CSMSettings::UserSettings::instance().settingValue("Display/show statusbar").toStdString(); + + view->toggleStatusBar (showStatusBar == "true"); view->show(); connect (view, SIGNAL (newGameRequest ()), this, SIGNAL (newGameRequest())); @@ -157,6 +162,14 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) return view; } +CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document, const CSMWorld::UniversalId& id, const std::string& hint) +{ + View* view = addView(document); + view->addSubView(id, hint); + + return view; +} + int CSVDoc::ViewManager::countViews (const CSMDoc::Document *document) const { int count = 0; diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 753d7f0cb..cdd5ac768 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -18,6 +18,11 @@ namespace CSVWorld class CommandDelegateFactoryCollection; } +namespace CSMWorld +{ + class UniversalId; +} + namespace CSVDoc { class View; @@ -52,6 +57,8 @@ namespace CSVDoc View *addView (CSMDoc::Document *document); ///< The ownership of the returned view is not transferred. + View *addView (CSMDoc::Document *document, const CSMWorld::UniversalId& id, const std::string& hint); + int countViews (const CSMDoc::Document *document) const; ///< Return number of views for \a document. diff --git a/apps/opencs/view/filter/recordfilterbox.cpp b/apps/opencs/view/filter/recordfilterbox.cpp index ef2aeb4d3..97490d508 100644 --- a/apps/opencs/view/filter/recordfilterbox.cpp +++ b/apps/opencs/view/filter/recordfilterbox.cpp @@ -11,7 +11,7 @@ CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *pare { QHBoxLayout *layout = new QHBoxLayout (this); - layout->setContentsMargins (0, 0, 0, 0); + layout->setContentsMargins (0, 6, 5, 0); QLabel *label = new QLabel("Record Filter", this); label->setIndent(2); diff --git a/apps/opencs/view/render/scenewidget.cpp b/apps/opencs/view/render/scenewidget.cpp index 06b041786..5ddb5e084 100644 --- a/apps/opencs/view/render/scenewidget.cpp +++ b/apps/opencs/view/render/scenewidget.cpp @@ -13,6 +13,7 @@ #include #include "../widget/scenetoolmode.hpp" +#include "../../model/settings/usersettings.hpp" #include "navigation.hpp" #include "lighting.hpp" @@ -27,7 +28,7 @@ namespace CSVRender , mKeyForward (false), mKeyBackward (false), mKeyLeft (false), mKeyRight (false) , mKeyRollLeft (false), mKeyRollRight (false) , mFast (false), mDragging (false), mMod1 (false) - , mFastFactor (4) /// \todo make this configurable + , mFastFactor (4) , mDefaultAmbient (0, 0, 0, 0), mHasDefaultAmbient (false) { setAttribute(Qt::WA_PaintOnScreen); @@ -44,7 +45,14 @@ namespace CSVRender mCamera->setPosition (300, 0, 0); mCamera->lookAt (0, 0, 0); mCamera->setNearClipDistance (0.1); - mCamera->setFarClipDistance (300000); ///< \todo make this configurable + + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); + + float farClipDist = userSettings.setting("Scene/far clip distance", QString("300000")).toFloat(); + mCamera->setFarClipDistance (farClipDist); + + mFastFactor = userSettings.setting("Scene/fast factor", QString("4")).toInt(); + mCamera->roll (Ogre::Degree (90)); setLighting (&mLightingDay); @@ -52,7 +60,9 @@ namespace CSVRender QTimer *timer = new QTimer (this); connect (timer, SIGNAL (timeout()), this, SLOT (update())); - timer->start (20); ///< \todo make this configurable + + int timerStart = userSettings.setting("Scene/timer start", QString("20")).toInt(); + timer->start (timerStart); /// \todo make shortcut configurable QShortcut *focusToolbar = new QShortcut (Qt::Key_T, this, 0, 0, Qt::WidgetWithChildrenShortcut); @@ -118,7 +128,16 @@ namespace CSVRender params.insert(std::make_pair("externalWindowHandle", windowHandle.str())); params.insert(std::make_pair("title", windowTitle.str())); - params.insert(std::make_pair("FSAA", "0")); // TODO setting + + std::string antialiasing = + CSMSettings::UserSettings::instance().settingValue("Video/antialiasing").toStdString(); + if(antialiasing == "MSAA 16") antialiasing = "16"; + else if(antialiasing == "MSAA 8") antialiasing = "8"; + else if(antialiasing == "MSAA 4") antialiasing = "4"; + else if(antialiasing == "MSAA 2") antialiasing = "2"; + else antialiasing = "0"; + params.insert(std::make_pair("FSAA", antialiasing)); + params.insert(std::make_pair("vsync", "false")); // TODO setting #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE params.insert(std::make_pair("macAPI", "cocoa")); @@ -382,4 +401,32 @@ namespace CSVRender else if (mode=="bright") setLighting (&mLightingBright); } + + void SceneWidget::updateUserSetting (const QString &key, const QStringList &list) + { + if(key.contains(QRegExp("^\\b(Objects|Shader|Scene)", Qt::CaseInsensitive))) + flagAsModified(); + + if(key == "Scene/far clip distance" && !list.empty()) + { + if(mCamera->getFarClipDistance() != list.at(0).toFloat()) + mCamera->setFarClipDistance(list.at(0).toFloat()); + } + + // minimise unnecessary ogre window creation by updating only when there is a change + if(key == "Video/antialiasing") + { + unsigned int aa = mWindow->getFSAA(); + unsigned int antialiasing = 0; + if(!list.empty()) + { + if(list.at(0) == "MSAA 16") antialiasing = 16; + else if(list.at(0) == "MSAA 8") antialiasing = 8; + else if(list.at(0) == "MSAA 4") antialiasing = 4; + else if(list.at(0) == "MSAA 2") antialiasing = 2; + } + if(aa != antialiasing) + updateOgreWindow(); + } + } } diff --git a/apps/opencs/view/render/scenewidget.hpp b/apps/opencs/view/render/scenewidget.hpp index 6361589a4..8301cd446 100644 --- a/apps/opencs/view/render/scenewidget.hpp +++ b/apps/opencs/view/render/scenewidget.hpp @@ -108,6 +108,10 @@ namespace CSVRender LightingNight mLightingNight; LightingBright mLightingBright; + public slots: + + void updateUserSetting (const QString &key, const QStringList &list); + private slots: void update(); diff --git a/apps/opencs/view/settings/booleanview.cpp b/apps/opencs/view/settings/booleanview.cpp index 2a3f0cba6..29f9775af 100644 --- a/apps/opencs/view/settings/booleanview.cpp +++ b/apps/opencs/view/settings/booleanview.cpp @@ -12,16 +12,27 @@ CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting, Page *parent) - : View (setting, parent) + : mType(setting->type()), View (setting, parent) { foreach (const QString &value, setting->declaredValues()) { QAbstractButton *button = 0; - switch (setting->type()) + switch (mType) { - case CSMSettings::Type_CheckBox: - button = new QCheckBox (value, this); + case CSMSettings::Type_CheckBox: { + if(mButtons.empty()) // show only one for checkboxes + { + button = new QCheckBox (value, this); + button->setChecked (setting->defaultValues().at(0) == "true" ? true : false); + + // special visual treatment option for checkboxes + if(setting->specialValueText() != "") { + Frame::setTitle(""); + button->setText(setting->specialValueText()); + } + } + } break; case CSMSettings::Type_RadioButton: @@ -32,14 +43,17 @@ CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting, break; } - connect (button, SIGNAL (clicked (bool)), - this, SLOT (slotToggled (bool))); + if(button && (mType != CSMSettings::Type_CheckBox || mButtons.empty())) + { + connect (button, SIGNAL (clicked (bool)), + this, SLOT (slotToggled (bool))); - button->setObjectName (value); + button->setObjectName (value); - addWidget (button); + addWidget (button); - mButtons[value] = button; + mButtons[value] = button; + } } } @@ -53,8 +67,14 @@ void CSVSettings::BooleanView::slotToggled (bool state) foreach (QString key, mButtons.keys()) { - if (mButtons.value(key)->isChecked()) - values.append (key); + // checkbox values are true/false unlike radio buttons + if(mType == CSMSettings::Type_CheckBox) + values.append(mButtons.value(key)->isChecked() ? "true" : "false"); + else + { + if (mButtons.value(key)->isChecked()) + values.append (key); + } } setSelectedValues (values, false); diff --git a/apps/opencs/view/settings/booleanview.hpp b/apps/opencs/view/settings/booleanview.hpp index 55ef0bb08..53198234a 100644 --- a/apps/opencs/view/settings/booleanview.hpp +++ b/apps/opencs/view/settings/booleanview.hpp @@ -16,6 +16,7 @@ namespace CSVSettings Q_OBJECT QMap mButtons; + enum CSMSettings::SettingType mType; public: explicit BooleanView (CSMSettings::Setting *setting, diff --git a/apps/opencs/view/settings/frame.cpp b/apps/opencs/view/settings/frame.cpp index 019024776..a3df2a993 100644 --- a/apps/opencs/view/settings/frame.cpp +++ b/apps/opencs/view/settings/frame.cpp @@ -3,7 +3,7 @@ #include const QString CSVSettings::Frame::sInvisibleBoxStyle = - QString::fromUtf8("Frame { border:2px; padding 2px; margin: 2px;}"); + QString::fromUtf8("Frame { border:2px; padding: 2px; margin: 2px;}"); CSVSettings::Frame::Frame (bool isVisible, const QString &title, QWidget *parent) @@ -14,7 +14,11 @@ CSVSettings::Frame::Frame (bool isVisible, const QString &title, mVisibleBoxStyle = styleSheet(); if (!isVisible) + { + // must be Page, not a View setStyleSheet (sInvisibleBoxStyle); + mLayout->setContentsMargins(10, 15, 10, 15); + } setLayout (mLayout); } diff --git a/apps/opencs/view/settings/page.cpp b/apps/opencs/view/settings/page.cpp index afd4bff5e..ed4cdd6bc 100644 --- a/apps/opencs/view/settings/page.cpp +++ b/apps/opencs/view/settings/page.cpp @@ -1,4 +1,7 @@ #include "page.hpp" + +#include + #include "view.hpp" #include "booleanview.hpp" #include "textview.hpp" @@ -38,7 +41,18 @@ void CSVSettings::Page::setupViews void CSVSettings::Page::addView (CSMSettings::Setting *setting) { if (setting->viewType() == ViewType_Undefined) - return; + { + if(setting->specialValueText() != "") + { + // hack to put a label + addWidget(new QLabel(setting->specialValueText()), + setting->viewRow(), setting->viewColumn(), + setting->rowSpan(), setting->columnSpan()); + return; + } + else + return; + } View *view = mViewFactories[setting->viewType()]->createView(setting, this); diff --git a/apps/opencs/view/settings/rangeview.cpp b/apps/opencs/view/settings/rangeview.cpp index 8ae6caca0..c96df9859 100644 --- a/apps/opencs/view/settings/rangeview.cpp +++ b/apps/opencs/view/settings/rangeview.cpp @@ -36,8 +36,11 @@ CSVSettings::RangeView::RangeView (CSMSettings::Setting *setting, break; } - mRangeWidget->setFixedWidth (widgetWidth (setting->widgetWidth())); - mRangeWidget->setObjectName (setting->name()); + if(mRangeWidget) + { + mRangeWidget->setFixedWidth (widgetWidth (setting->widgetWidth())); + mRangeWidget->setObjectName (setting->name()); + } addWidget (mRangeWidget); } @@ -75,13 +78,16 @@ void CSVSettings::RangeView::buildSlider (CSMSettings::Setting *setting) break; } - mRangeWidget->setProperty ("minimum", setting->minimum()); - mRangeWidget->setProperty ("maximum", setting->maximum()); - mRangeWidget->setProperty ("tracking", false); - mRangeWidget->setProperty ("singleStep", setting->singleStep()); + if(mRangeWidget) + { + mRangeWidget->setProperty ("minimum", setting->minimum()); + mRangeWidget->setProperty ("maximum", setting->maximum()); + mRangeWidget->setProperty ("tracking", false); + mRangeWidget->setProperty ("singleStep", setting->singleStep()); - connect (mRangeWidget, SIGNAL (valueChanged (int)), - this, SLOT (slotUpdateView (int))); + connect (mRangeWidget, SIGNAL (valueChanged (int)), + this, SLOT (slotUpdateView (int))); + } } void CSVSettings::RangeView::buildSpinBox (CSMSettings::Setting *setting) @@ -127,7 +133,10 @@ void CSVSettings::RangeView::buildSpinBox (CSMSettings::Setting *setting) mRangeWidget->setProperty ("prefix", setting->prefix()); mRangeWidget->setProperty ("suffix", setting->suffix()); mRangeWidget->setProperty ("wrapping", setting->wrapping()); + dynamic_cast (mRangeWidget)->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + if(setting->type() == CSMSettings::Type_SpinBox && setting->declaredValues().isEmpty()) + dynamic_cast (mRangeWidget)->setValue (setting->defaultValues().at(0).toInt()); } void CSVSettings::RangeView::slotUpdateView (int value) diff --git a/apps/opencs/view/settings/settingwindow.cpp b/apps/opencs/view/settings/settingwindow.cpp index 7cdf2bded..590b6f7a5 100644 --- a/apps/opencs/view/settings/settingwindow.cpp +++ b/apps/opencs/view/settings/settingwindow.cpp @@ -19,7 +19,7 @@ void CSVSettings::SettingWindow::createPages() QList connectedSettings; foreach (const QString &pageName, pageMap.keys()) - { + { QList pageSettings = pageMap.value (pageName); mPages.append (new Page (pageName, pageSettings, this)); @@ -129,7 +129,3 @@ void CSVSettings::SettingWindow::saveSettings() mModel->saveDefinitions(); } -void CSVSettings::SettingWindow::closeEvent (QCloseEvent *event) -{ - QApplication::focusWidget()->clearFocus(); -} diff --git a/apps/opencs/view/settings/settingwindow.hpp b/apps/opencs/view/settings/settingwindow.hpp index 2266f130d..11bceee96 100644 --- a/apps/opencs/view/settings/settingwindow.hpp +++ b/apps/opencs/view/settings/settingwindow.hpp @@ -36,8 +36,6 @@ namespace CSVSettings { protected: - virtual void closeEvent (QCloseEvent *event); - ///construct the pages to be displayed in the dialog void createPages(); diff --git a/apps/opencs/view/settings/spinbox.cpp b/apps/opencs/view/settings/spinbox.cpp index 4b1447f8f..c70fc36d1 100644 --- a/apps/opencs/view/settings/spinbox.cpp +++ b/apps/opencs/view/settings/spinbox.cpp @@ -24,7 +24,7 @@ QString CSVSettings::SpinBox::textFromValue(int val) const int CSVSettings::SpinBox::valueFromText(const QString &text) const { if (mValueList.isEmpty()) - return -1; + return text.toInt(); // TODO: assumed integer, untested error handling for alpha types if (mValueList.contains (text)) return mValueList.indexOf(text); diff --git a/apps/opencs/view/settings/view.cpp b/apps/opencs/view/settings/view.cpp index 69109e2b3..f95bb5c03 100644 --- a/apps/opencs/view/settings/view.cpp +++ b/apps/opencs/view/settings/view.cpp @@ -22,6 +22,9 @@ CSVSettings::View::View(CSMSettings::Setting *setting, setObjectName (setting->name()); buildView(); buildModel (setting); + // apply stylesheet to view's frame if exists + if(setting->styleSheet() != "") + Frame::setStyleSheet (setting->styleSheet()); } void CSVSettings::View::buildModel (const CSMSettings::Setting *setting) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 57069bec0..8790601ea 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -392,7 +392,6 @@ void CSVWorld::EditWidget::remake(int row) mWidgetMapper->setCurrentModelIndex(mTable->index(row, 0)); - this->setMinimumWidth(325); /// \todo replace hardcoded value with a user setting this->setWidget(mMainWidget); this->setWidgetResizable(true); } diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 52bd47b54..d10eebb30 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -247,6 +247,8 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW mToolbar = toolbar; connect (mScene, SIGNAL (focusToolbarRequest()), mToolbar, SLOT (setFocus())); + connect (this, SIGNAL (updateSceneUserSetting(const QString &, const QStringList &)), + mScene, SLOT (updateUserSetting(const QString &, const QStringList &))); connect (mToolbar, SIGNAL (focusSceneRequest()), mScene, SLOT (setFocus())); mLayout->addWidget (mToolbar, 0); @@ -254,4 +256,9 @@ void CSVWorld::SceneSubView::replaceToolbarAndWorldspace (CSVRender::WorldspaceW mScene->selectDefaultNavigationMode(); setFocusProxy (mScene); -} \ No newline at end of file +} + +void CSVWorld::SceneSubView::updateUserSetting (const QString &key, const QStringList &list) +{ + emit updateSceneUserSetting(key, list); +} diff --git a/apps/opencs/view/world/scenesubview.hpp b/apps/opencs/view/world/scenesubview.hpp index b9dcdd6a3..c0905f0d6 100644 --- a/apps/opencs/view/world/scenesubview.hpp +++ b/apps/opencs/view/world/scenesubview.hpp @@ -82,6 +82,14 @@ namespace CSVWorld void cellSelectionChanged (const CSMWorld::UniversalId& id); void handleDrop(const std::vector& data); + + public slots: + + void updateUserSetting (const QString &, const QStringList &); + + signals: + + void updateSceneUserSetting (const QString &, const QStringList &); }; }